From 0b99d521646ff2fa6386cfae3696c73b34bcf99e Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 5 Feb 2020 08:03:21 +0000 Subject: [PATCH] Cannot trust or retire a retired node --- src/node/rpc/memberfrontend.h | 15 ++++++ src/node/rpc/test/membervoting_test.cpp | 64 +++++++++++++++++++++++++ src/runtime_config/default_whitelists.h | 1 - 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/node/rpc/memberfrontend.h b/src/node/rpc/memberfrontend.h index feb44ed7ba20..7d1cfc5d2db9 100644 --- a/src/node/rpc/memberfrontend.h +++ b/src/node/rpc/memberfrontend.h @@ -141,7 +141,14 @@ namespace ccf auto nodes = tx.get_view(this->network.nodes); auto info = nodes->get(id); if (!info) + { throw std::logic_error(fmt::format("Node {} does not exist", id)); + } + if (info->status == NodeStatus::RETIRED) + { + throw std::logic_error( + fmt::format("Node {} is already retired", id)); + } info->status = NodeStatus::TRUSTED; nodes->put(id, *info); LOG_INFO_FMT("Node {} is now {}", id, info->status); @@ -154,9 +161,17 @@ namespace ccf auto nodes = tx.get_view(this->network.nodes); auto info = nodes->get(id); if (!info) + { throw std::logic_error(fmt::format("Node {} does not exist", id)); + } + if (info->status == NodeStatus::RETIRED) + { + throw std::logic_error( + fmt::format("Node {} is already retired", id)); + } info->status = NodeStatus::RETIRED; nodes->put(id, *info); + LOG_INFO_FMT("Node {} is now {}", id, info->status); return true; }}, // accept new code diff --git a/src/node/rpc/test/membervoting_test.cpp b/src/node/rpc/test/membervoting_test.cpp index e861cd27db79..c59d915aa43c 100644 --- a/src/node/rpc/test/membervoting_test.cpp +++ b/src/node/rpc/test/membervoting_test.cpp @@ -625,6 +625,70 @@ TEST_CASE("Accept node") frontend_process(frontend, read_values_j, member_0_cert); CHECK(r.result.status == NodeStatus::TRUSTED); } + + // m0 proposes retire node + { + Script proposal(R"xxx( + local tables, node_id = ... + return Calls:call("retire_node", node_id) + )xxx"); + json proposej = create_json_req(Propose::In{proposal, node_id}, "propose"); + Response r = + frontend_process(frontend, proposej, member_0_cert); + + CHECK(!r.result.completed); + CHECK(r.result.id == 1); + } + + // m1 votes for retiring node + { + const Script vote_ballot("return true"); + json votej = create_json_req_signed(Vote{1, vote_ballot}, "vote", kp); + check_success(frontend_process(frontend, votej, member_1_cert)); + } + + // check that node exists with status retired + { + auto read_values_j = + create_json_req(read_params(node_id, Tables::NODES), "read"); + Response r = + frontend_process(frontend, read_values_j, member_0_cert); + CHECK(r.result.status == NodeStatus::RETIRED); + } + + // check that retired node cannot be trusted + { + Script proposal(R"xxx( + local tables, node_id = ... + return Calls:call("trust_node", node_id) + )xxx"); + json proposej = create_json_req(Propose::In{proposal, node_id}, "propose"); + Response r = + frontend_process(frontend, proposej, member_0_cert); + + const Script vote_ballot("return true"); + json votej = create_json_req_signed(Vote{2, vote_ballot}, "vote", kp); + check_error( + frontend_process(frontend, votej, member_1_cert), + StandardErrorCodes::INTERNAL_ERROR); + } + + // check that retired node cannot be retired again + { + Script proposal(R"xxx( + local tables, node_id = ... + return Calls:call("retire_node", node_id) + )xxx"); + json proposej = create_json_req(Propose::In{proposal, node_id}, "propose"); + Response r = + frontend_process(frontend, proposej, member_0_cert); + + const Script vote_ballot("return true"); + json votej = create_json_req_signed(Vote{3, vote_ballot}, "vote", kp); + check_error( + frontend_process(frontend, votej, member_1_cert), + StandardErrorCodes::INTERNAL_ERROR); + } } bool test_raw_writes( diff --git a/src/runtime_config/default_whitelists.h b/src/runtime_config/default_whitelists.h index a7b18fe3f9c3..2001c8e2eee4 100644 --- a/src/runtime_config/default_whitelists.h +++ b/src/runtime_config/default_whitelists.h @@ -32,7 +32,6 @@ namespace ccf Tables::MEMBER_CERTS, Tables::USERS, Tables::USER_CERTS, - Tables::NODES, Tables::VALUES, Tables::WHITELISTS, Tables::GOV_SCRIPTS,