diff --git a/scripts/ci-checks.sh b/scripts/ci-checks.sh index ebb29ff34..5c3168b17 100755 --- a/scripts/ci-checks.sh +++ b/scripts/ci-checks.sh @@ -87,7 +87,7 @@ npx tsp compile . if [ -n "$(git status --porcelain)" ]; then echo "TypeSpec compile produced git diff - that should be checked in" git status - git diff + git diff --raw exit 1 fi popd > /dev/null diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 2ae6aaaed..0cf81059d 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -45,7 +45,6 @@ namespace ccf std::unique_ptr writer_factory; RingbufferLogger* ringbuffer_logger = nullptr; ccf::NetworkState network; - ccf::ShareManager share_manager; std::shared_ptr rpc_map; std::shared_ptr rpcsessions; std::unique_ptr node; @@ -90,7 +89,6 @@ namespace ccf writer_factory(std::move(writer_factory_)), ringbuffer_logger(ringbuffer_logger_), network(), - share_manager(network), rpc_map(std::make_shared()), rpcsessions(std::make_shared(*writer_factory, rpc_map)) { @@ -118,7 +116,7 @@ namespace ccf LOG_TRACE_FMT("Creating node"); node = std::make_unique( - *writer_factory, network, rpcsessions, share_manager, curve_id); + *writer_factory, network, rpcsessions, curve_id); LOG_TRACE_FMT("Creating context"); context = std::make_unique(node->get_node_id()); @@ -159,8 +157,7 @@ namespace ccf LOG_TRACE_FMT("Creating RPC actors / ffi"); rpc_map->register_frontend( - std::make_unique( - network, *context, share_manager)); + std::make_unique(network, *context)); rpc_map->register_frontend( std::make_unique( diff --git a/src/indexing/test/indexing.cpp b/src/indexing/test/indexing.cpp index 916ed0ed7..b209bc2c6 100644 --- a/src/indexing/test/indexing.cpp +++ b/src/indexing/test/indexing.cpp @@ -256,11 +256,7 @@ kv::Version rekey( kv::Store& kv_store, const std::shared_ptr& ledger_secrets) { - // This isn't really used, but is needed for ShareManager, so can be recreated - // each time here - ccf::NetworkState network; - network.ledger_secrets = ledger_secrets; - ccf::ShareManager share_manager(network); + ccf::ShareManager share_manager(ledger_secrets); auto tx = kv_store.create_tx(); auto new_ledger_secret = ccf::make_ledger_secret(); diff --git a/src/node/node_state.h b/src/node/node_state.h index 13f5b2005..9565e0d43 100644 --- a/src/node/node_state.h +++ b/src/node/node_state.h @@ -37,7 +37,7 @@ #include "rpc/frontend.h" #include "rpc/serialization.h" #include "secret_broadcast.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include "share_manager.h" #include "uvm_endorsements.h" @@ -134,7 +134,7 @@ namespace ccf std::shared_ptr history; std::shared_ptr encryptor; - ShareManager& share_manager; + ShareManager share_manager; std::shared_ptr snapshotter; // @@ -224,7 +224,6 @@ namespace ccf ringbuffer::AbstractWriterFactory& writer_factory, NetworkState& network, std::shared_ptr rpcsessions, - ShareManager& share_manager, crypto::CurveID curve_id_) : sm("NodeState", NodeStartupState::uninitialized), curve_id(curve_id_), @@ -235,7 +234,7 @@ namespace ccf to_host(writer_factory.create_writer_to_outside()), network(network), rpcsessions(rpcsessions), - share_manager(share_manager) + share_manager(network.ledger_secrets) {} QuoteVerificationResult verify_quote( @@ -1184,14 +1183,13 @@ namespace ccf // Clear recovery shares that were submitted to initiate the recovery // procedure - share_manager.clear_submitted_recovery_shares(tx); + ShareManager::clear_submitted_recovery_shares(tx); // Shares for the new ledger secret can only be issued now, once the // previous ledger secrets have been recovered share_manager.issue_recovery_shares(tx); - GenesisGenerator g(network, tx); - if (!g.open_service()) + if (!InternalTablesAccess::open_service(tx)) { throw std::logic_error("Service could not be opened"); } @@ -1493,7 +1491,7 @@ namespace ccf { // If the node is in public mode, start accepting member recovery // shares - share_manager.clear_submitted_recovery_shares(tx); + ShareManager::clear_submitted_recovery_shares(tx); service_info->status = ServiceStatus::WAITING_FOR_RECOVERY_SHARES; service->put(service_info.value()); return; @@ -1513,8 +1511,7 @@ namespace ccf fmt::format("Failed to issue recovery shares: {}", e.what())); } - GenesisGenerator g(network, tx); - g.open_service(); + InternalTablesAccess::open_service(tx); trigger_snapshot(tx); return; } @@ -1708,8 +1705,10 @@ namespace ccf // startup of the first recovery node // - On recovery, historical ledger secrets can only be looked up in the // ledger once all ledger secrets have been restored - GenesisGenerator g(network, tx); - if (g.get_service_status().value() != ServiceStatus::OPEN) + const auto service_status = InternalTablesAccess::get_service_status(tx); + if ( + !service_status.has_value() || + service_status.value() != ServiceStatus::OPEN) { LOG_FAIL_FMT("Cannot rekey ledger while the service is not open"); return false; diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index 341f9326a..a25f76341 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -23,7 +23,7 @@ #include "node/rpc/serialization.h" #include "node/share_manager.h" #include "node_interface.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include "service/tables/config.h" #include "service/tables/endpoints.h" @@ -591,16 +591,14 @@ namespace ccf } NetworkState& network; - ShareManager& share_manager; + ShareManager share_manager; public: MemberEndpoints( - NetworkState& network_, - ccfapp::AbstractNodeContext& context_, - ShareManager& share_manager_) : + NetworkState& network_, ccfapp::AbstractNodeContext& context_) : CommonEndpointRegistry(get_actor_prefix(ActorsType::members), context_), network(network_), - share_manager(share_manager_) + share_manager(network_.ledger_secrets) { openapi_info.title = "CCF Governance API"; openapi_info.description = @@ -737,10 +735,9 @@ namespace ccf } // update member status to ACTIVE - GenesisGenerator g(this->network, ctx.tx); try { - g.activate_member(member_id.value()); + InternalTablesAccess::activate_member(ctx.tx, member_id.value()); } catch (const std::logic_error& e) { @@ -752,7 +749,7 @@ namespace ccf return; } - auto service_status = g.get_service_status(); + auto service_status = InternalTablesAccess::get_service_status(ctx.tx); if (!service_status.has_value()) { set_gov_error( @@ -767,7 +764,7 @@ namespace ccf auto member_info = members->get(member_id.value()); if ( service_status.value() == ServiceStatus::OPEN && - g.is_recovery_member(member_id.value())) + InternalTablesAccess::is_recovery_member(ctx.tx, member_id.value())) { // When the service is OPEN and the new active member is a recovery // member, all recovery members are allocated new recovery shares @@ -979,9 +976,9 @@ namespace ccf cose_auth_id ? cose_auth_id->content : ctx.rpc_ctx->get_request_body()); - GenesisGenerator g(this->network, ctx.tx); if ( - g.get_service_status() != ServiceStatus::WAITING_FOR_RECOVERY_SHARES) + InternalTablesAccess::get_service_status(ctx.tx) != + ServiceStatus::WAITING_FOR_RECOVERY_SHARES) { set_gov_error( ctx.rpc_ctx, @@ -1032,14 +1029,16 @@ namespace ccf } OPENSSL_cleanse(raw_recovery_share.data(), raw_recovery_share.size()); - if (submitted_shares_count < g.get_recovery_threshold()) + if ( + submitted_shares_count < + InternalTablesAccess::get_recovery_threshold(ctx.tx)) { // The number of shares required to re-assemble the secret has not yet // been reached auto recovery_share = SubmitRecoveryShare::Out{fmt::format( "{}/{} recovery shares successfully submitted.", submitted_shares_count, - g.get_recovery_threshold())}; + InternalTablesAccess::get_recovery_threshold(ctx.tx))}; ctx.rpc_ctx->set_response_header( http::headers::CONTENT_TYPE, http::headervalues::contenttype::JSON); ctx.rpc_ctx->set_response_body(nlohmann::json(recovery_share).dump()); @@ -1048,7 +1047,8 @@ namespace ccf } GOV_DEBUG_FMT( - "Reached recovery threshold {}", g.get_recovery_threshold()); + "Reached recovery threshold {}", + InternalTablesAccess::get_recovery_threshold(ctx.tx)); try { @@ -1061,7 +1061,7 @@ namespace ccf constexpr auto error_msg = "Failed to initiate private recovery."; GOV_FAIL_FMT(error_msg); GOV_DEBUG_FMT("Error: {}", e.what()); - share_manager.clear_submitted_recovery_shares(ctx.tx); + ShareManager::clear_submitted_recovery_shares(ctx.tx); ctx.rpc_ctx->set_apply_writes(true); set_gov_error( ctx.rpc_ctx, @@ -1075,7 +1075,7 @@ namespace ccf "{}/{} recovery shares successfully submitted. End of recovery " "procedure initiated.", submitted_shares_count, - g.get_recovery_threshold())}; + InternalTablesAccess::get_recovery_threshold(ctx.tx))}; ctx.rpc_ctx->set_response_header( http::headers::CONTENT_TYPE, http::headervalues::contenttype::JSON); ctx.rpc_ctx->set_response_body(nlohmann::json(recovery_share).dump()); @@ -1896,11 +1896,9 @@ namespace ccf public: MemberRpcFrontend( - NetworkState& network, - ccfapp::AbstractNodeContext& context, - ShareManager& share_manager) : + NetworkState& network, ccfapp::AbstractNodeContext& context) : RpcFrontend(*network.tables, member_endpoints, context), - member_endpoints(network, context, share_manager) + member_endpoints(network, context) {} }; } // namespace ccf diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index c1a5e3c4a..9680f76e3 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -22,7 +22,7 @@ #include "node/rpc/serialization.h" #include "node/session_metrics.h" #include "node_interface.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include "service/tables/previous_service_identity.h" namespace ccf @@ -1449,8 +1449,7 @@ namespace ccf const auto in = params.get(); - GenesisGenerator g(this->network, ctx.tx); - if (g.is_service_created(in.service_cert)) + if (InternalTablesAccess::is_service_created(ctx.tx, in.service_cert)) { return make_error( HTTP_STATUS_FORBIDDEN, @@ -1458,11 +1457,11 @@ namespace ccf "Service is already created."); } - g.create_service( - in.service_cert, in.create_txid, in.service_data, recovering); + InternalTablesAccess::create_service( + ctx.tx, in.service_cert, in.create_txid, in.service_data, recovering); // Retire all nodes, in case there are any (i.e. post recovery) - g.retire_active_nodes(); + InternalTablesAccess::retire_active_nodes(ctx.tx); // Genesis transaction (i.e. not after recovery) if (in.genesis_info.has_value()) @@ -1472,11 +1471,13 @@ namespace ccf // recovery member is added before the service is opened. for (const auto& info : in.genesis_info->members) { - g.add_member(info); + InternalTablesAccess::add_member(ctx.tx, info); } - g.init_configuration(in.genesis_info->service_configuration); - g.set_constitution(in.genesis_info->constitution); + InternalTablesAccess::init_configuration( + ctx.tx, in.genesis_info->service_configuration); + InternalTablesAccess::set_constitution( + ctx.tx, in.genesis_info->constitution); } else { @@ -1503,21 +1504,24 @@ namespace ccf in.certificate_signing_request, in.public_key, in.node_data}; - g.add_node(in.node_id, node_info); + InternalTablesAccess::add_node(ctx.tx, in.node_id, node_info); if ( in.quote_info.format != QuoteFormat::amd_sev_snp_v1 || !in.snp_uvm_endorsements.has_value()) { // For improved serviceability on SNP, do not record trusted // measurements if UVM endorsements are available - g.trust_node_measurement(in.measurement, in.quote_info.format); + InternalTablesAccess::trust_node_measurement( + ctx.tx, in.measurement, in.quote_info.format); } if (in.quote_info.format == QuoteFormat::amd_sev_snp_v1) { auto host_data = AttestationProvider::get_host_data(in.quote_info).value(); - g.trust_node_host_data(host_data, in.snp_security_policy); - g.trust_node_uvm_endorsements(in.snp_uvm_endorsements); + InternalTablesAccess::trust_node_host_data( + ctx.tx, host_data, in.snp_security_policy); + InternalTablesAccess::trust_node_uvm_endorsements( + ctx.tx, in.snp_uvm_endorsements); } LOG_INFO_FMT("Created service"); diff --git a/src/node/rpc/test/frontend_test.cpp b/src/node/rpc/test/frontend_test.cpp index 9c94bd3a5..86e5d8ac9 100644 --- a/src/node/rpc/test/frontend_test.cpp +++ b/src/node/rpc/test/frontend_test.cpp @@ -20,7 +20,7 @@ #include "node/rpc/node_frontend.h" #include "node/test/channel_stub.h" #include "node_stub.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include #include @@ -265,10 +265,8 @@ class TestMemberFrontend : public MemberRpcFrontend { public: TestMemberFrontend( - ccf::NetworkState& network, - ccf::StubNodeContext& context, - ccf::ShareManager& share_manager) : - MemberRpcFrontend(network, context, share_manager) + ccf::NetworkState& network, ccf::StubNodeContext& context) : + MemberRpcFrontend(network, context) { open(); @@ -391,10 +389,8 @@ class TestForwardingMemberFrontEnd : public MemberRpcFrontend, { public: TestForwardingMemberFrontEnd( - ccf::NetworkState& network, - ccf::StubNodeContext& context, - ccf::ShareManager& share_manager) : - MemberRpcFrontend(network, context, share_manager) + ccf::NetworkState& network, ccf::StubNodeContext& context) : + MemberRpcFrontend(network, context) { open(); @@ -482,11 +478,10 @@ void prepare_callers(NetworkState& network) init_network(network); - GenesisGenerator g(network, tx); - g.create_service(network.identity->cert, ccf::TxID{}); - user_id = g.add_user({user_caller}); - member_id = g.add_member(member_cert); - invalid_member_id = g.add_member(invalid_caller); + InternalTablesAccess::create_service(tx, network.identity->cert, ccf::TxID{}); + user_id = InternalTablesAccess::add_user(tx, {user_caller}); + member_id = InternalTablesAccess::add_member(tx, member_cert); + invalid_member_id = InternalTablesAccess::add_member(tx, invalid_caller); CHECK(tx.commit() == kv::CommitResult::SUCCESS); } @@ -625,12 +620,11 @@ TEST_CASE("Member caller") NetworkState network; prepare_callers(network); - ShareManager share_manager(network); StubNodeContext context; auto simple_call = create_simple_request(); std::vector serialized_call = simple_call.build_request(); - TestMemberFrontend frontend(network, context, share_manager); + TestMemberFrontend frontend(network, context); SUBCASE("valid caller") { @@ -1197,7 +1191,6 @@ TEST_CASE("Nodefrontend forwarding" * doctest::test_suite("forwarding")) NetworkState network_backup; prepare_callers(network_backup); - ShareManager share_manager(network_primary); StubNodeContext context; TestForwardingNodeFrontEnd node_frontend_primary(network_primary, context); @@ -1292,13 +1285,11 @@ TEST_CASE("Memberfrontend forwarding" * doctest::test_suite("forwarding")) NetworkState network_backup; prepare_callers(network_backup); - ShareManager share_manager(network_primary); StubNodeContext context; TestForwardingMemberFrontEnd member_frontend_primary( - network_primary, context, share_manager); - TestForwardingMemberFrontEnd member_frontend_backup( - network_backup, context, share_manager); + network_primary, context); + TestForwardingMemberFrontEnd member_frontend_backup(network_backup, context); auto channel_stub = std::make_shared(); auto primary_consensus = std::make_shared(); @@ -1705,8 +1696,7 @@ TEST_CASE("Manual conflicts") run_test( [&]() { auto tx = network.tables->create_tx(); - GenesisGenerator g(network, tx); - g.remove_user(user_id); + InternalTablesAccess::remove_user(tx, user_id); CHECK(tx.commit() == kv::CommitResult::SUCCESS); }, user_session, diff --git a/src/node/rpc/test/frontend_test_infra.h b/src/node/rpc/test/frontend_test_infra.h index 3fb89e910..9b3ae51b7 100644 --- a/src/node/rpc/test/frontend_test_infra.h +++ b/src/node/rpc/test/frontend_test_infra.h @@ -14,7 +14,6 @@ #include "node/rpc/member_frontend.h" #include "node/rpc/user_frontend.h" #include "node_stub.h" -#include "service/genesis_gen.h" #include #include @@ -118,24 +117,6 @@ auto get_cert(uint64_t member_id, crypto::KeyPairPtr& kp_mem) "CN=new member" + to_string(member_id), valid_from, valid_to); } -auto init_frontend( - NetworkState& network, - GenesisGenerator& gen, - StubNodeContext& context, - ShareManager& share_manager, - const int n_members, - std::vector& member_certs) -{ - // create members - for (uint8_t i = 0; i < n_members; i++) - { - member_certs.push_back(get_cert(i, kp)); - gen.activate_member(gen.add_member(member_certs.back())); - } - - return MemberRpcFrontend(network, context, share_manager); -} - std::unique_ptr make_test_network_ident() { using namespace std::literals; diff --git a/src/node/rpc/test/node_frontend_test.cpp b/src/node/rpc/test/node_frontend_test.cpp index b21819e37..7ca871485 100644 --- a/src/node/rpc/test/node_frontend_test.cpp +++ b/src/node/rpc/test/node_frontend_test.cpp @@ -10,7 +10,7 @@ #include "nlohmann/json.hpp" #include "node/rpc/node_frontend.h" #include "node_stub.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" using namespace ccf; using namespace nlohmann; @@ -67,18 +67,17 @@ TEST_CASE("Add a node to an opening service") auto encryptor = std::make_shared(); network.tables->set_encryptor(encryptor); auto gen_tx = network.tables->create_tx(); - GenesisGenerator gen(network, gen_tx); - gen.init_configuration({0, ConsensusType::CFT, std::nullopt}); - - ShareManager share_manager(network); - StubNodeContext context; - NodeRpcFrontend frontend(network, context); - frontend.open(); + InternalTablesAccess::init_configuration( + gen_tx, {0, ConsensusType::CFT, std::nullopt}); network.identity = make_test_network_ident(); network.ledger_secrets = std::make_shared(); network.ledger_secrets->init(); + StubNodeContext context; + NodeRpcFrontend frontend(network, context); + frontend.open(); + // New node should not be given ledger secret past this one via join request kv::Version up_to_ledger_secret_seqno = 4; network.ledger_secrets->set_secret( @@ -101,7 +100,8 @@ TEST_CASE("Add a node to an opening service") check_error_message(response, "No service is available to accept new node"); } - gen.create_service(network.identity->cert, ccf::TxID{}); + InternalTablesAccess::create_service( + gen_tx, network.identity->cert, ccf::TxID{}); REQUIRE(gen_tx.commit() == kv::CommitResult::SUCCESS); auto tx = network.tables->create_tx(); @@ -185,28 +185,29 @@ TEST_CASE("Add a node to an open service") auto gen_tx = network.tables->create_tx(); auto encryptor = std::make_shared(); network.tables->set_encryptor(encryptor); - GenesisGenerator gen(network, gen_tx); - - ShareManager share_manager(network); - StubNodeContext context; - context.node_operation->is_public = true; - NodeRpcFrontend frontend(network, context); - frontend.open(); network.identity = make_test_network_ident(); network.ledger_secrets = std::make_shared(); network.ledger_secrets->init(); + StubNodeContext context; + context.node_operation->is_public = true; + NodeRpcFrontend frontend(network, context); + frontend.open(); + // New node should not be given ledger secret past this one via join request kv::Version up_to_ledger_secret_seqno = 4; network.ledger_secrets->set_secret( up_to_ledger_secret_seqno, make_ledger_secret()); - gen.create_service(network.identity->cert, ccf::TxID{}); - gen.init_configuration({1}); - gen.activate_member(gen.add_member( - {member_cert, crypto::make_rsa_key_pair()->public_key_pem()})); - REQUIRE(gen.open_service()); + InternalTablesAccess::create_service( + gen_tx, network.identity->cert, ccf::TxID{}); + InternalTablesAccess::init_configuration(gen_tx, {1}); + InternalTablesAccess::activate_member( + gen_tx, + InternalTablesAccess::add_member( + gen_tx, {member_cert, crypto::make_rsa_key_pair()->public_key_pem()})); + REQUIRE(InternalTablesAccess::open_service(gen_tx)); REQUIRE(gen_tx.commit() == kv::CommitResult::SUCCESS); // Node certificate @@ -276,9 +277,9 @@ TEST_CASE("Add a node to an open service") INFO("Trust node and attempt to join"); { // In a real scenario, nodes are trusted via member governance. - GenesisGenerator g(network, tx); auto joining_node_id = ccf::compute_node_id_from_kp(kp); - g.trust_node(joining_node_id, network.ledger_secrets->get_latest(tx).first); + InternalTablesAccess::trust_node( + tx, joining_node_id, network.ledger_secrets->get_latest(tx).first); const auto dummy_endorsed_certificate = crypto::make_key_pair()->self_sign( "CN=dummy endorsed certificate", valid_from, valid_to); auto endorsed_certificate = tx.rw(network.node_endorsed_certificates); diff --git a/src/node/rpc/test/node_stub.h b/src/node/rpc/test/node_stub.h index d7fd35eb1..e2ec9459e 100644 --- a/src/node/rpc/test/node_stub.h +++ b/src/node/rpc/test/node_stub.h @@ -8,7 +8,6 @@ #include "node/rpc/gov_effects_interface.h" #include "node/rpc/node_interface.h" #include "node/rpc/node_operation_interface.h" -#include "node/share_manager.h" namespace ccf { diff --git a/src/node/secret_broadcast.h b/src/node/secret_broadcast.h index a1dddd315..92d0e62e6 100644 --- a/src/node/secret_broadcast.h +++ b/src/node/secret_broadcast.h @@ -6,7 +6,7 @@ #include "ccf/crypto/rsa_key_pair.h" #include "ledger_secrets.h" #include "network_state.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include @@ -21,12 +21,11 @@ namespace ccf kv::Tx& tx, const LedgerSecretsMap& some_ledger_secrets) { - GenesisGenerator g(network, tx); auto secrets = tx.rw(network.secrets); LedgerSecretsForNodes secrets_for_nodes; - for (auto [nid, ni] : g.get_trusted_nodes(self)) + for (auto [nid, ni] : InternalTablesAccess::get_trusted_nodes(tx, self)) { std::vector ledger_secrets_for_node; @@ -49,12 +48,11 @@ namespace ccf static void broadcast_new( NetworkState& network, kv::Tx& tx, LedgerSecretPtr&& new_ledger_secret) { - GenesisGenerator g(network, tx); auto secrets = tx.rw(network.secrets); LedgerSecretsForNodes secrets_for_nodes; - for (auto [nid, ni] : g.get_trusted_nodes()) + for (auto [nid, ni] : InternalTablesAccess::get_trusted_nodes(tx)) { std::vector ledger_secrets_for_node; diff --git a/src/node/share_manager.h b/src/node/share_manager.h index e9aa67dee..44f07cc18 100644 --- a/src/node/share_manager.h +++ b/src/node/share_manager.h @@ -10,7 +10,7 @@ #include "ledger_secrets.h" #include "network_state.h" #include "secret_share.h" -#include "service/genesis_gen.h" +#include "service/internal_tables_access.h" #include #include @@ -107,7 +107,7 @@ namespace ccf class ShareManager { private: - NetworkState& network; + std::shared_ptr ledger_secrets; EncryptedSharesMap compute_encrypted_shares( kv::Tx& tx, const LedgerSecretWrappingKey& ls_wrapping_key) @@ -117,9 +117,10 @@ namespace ccf auto secret_to_split = ls_wrapping_key.get_raw_data(); - GenesisGenerator g(network, tx); - auto active_recovery_members_info = g.get_active_recovery_members(); - size_t recovery_threshold = g.get_recovery_threshold(); + auto active_recovery_members_info = + InternalTablesAccess::get_active_recovery_members(tx); + size_t recovery_threshold = + InternalTablesAccess::get_recovery_threshold(tx); if (active_recovery_members_info.empty()) { @@ -171,7 +172,7 @@ namespace ccf { auto ls_wrapping_key = LedgerSecretWrappingKey(); auto wrapped_latest_ls = ls_wrapping_key.wrap(latest_ledger_secret); - auto recovery_shares = tx.rw(network.shares); + auto recovery_shares = tx.rw(Tables::SHARES); recovery_shares->put( {wrapped_latest_ls, compute_encrypted_shares(tx, ls_wrapping_key), @@ -194,7 +195,8 @@ namespace ccf shuffle_recovery_shares(tx, latest_ledger_secret); - auto encrypted_ls = tx.rw(network.encrypted_ledger_secrets); + auto encrypted_ls = tx.rw( + Tables::ENCRYPTED_PAST_LEDGER_SECRET); std::vector encrypted_previous_secret = {}; kv::Version version_previous_secret = kv::NoVersion; @@ -266,9 +268,9 @@ namespace ccf LedgerSecretWrappingKey combine_from_encrypted_submitted_shares(kv::Tx& tx) { - auto encrypted_submitted_shares = - tx.rw(network.encrypted_submitted_shares); - auto config = tx.rw(network.config); + auto encrypted_submitted_shares = tx.rw( + Tables::ENCRYPTED_SUBMITTED_SHARES); + auto config = tx.rw(Tables::CONFIGURATION); std::vector shares = {}; encrypted_submitted_shares->foreach( @@ -276,7 +278,7 @@ namespace ccf const MemberId, const EncryptedSubmittedShare& encrypted_share) { SecretSharing::Share share; auto decrypted_share = decrypt_submitted_share( - encrypted_share, network.ledger_secrets->get_latest(tx).second); + encrypted_share, ledger_secrets->get_latest(tx).second); std::copy_n( decrypted_share.begin(), SecretSharing::SHARE_LENGTH, @@ -301,7 +303,9 @@ namespace ccf } public: - ShareManager(NetworkState& network_) : network(network_) {} + ShareManager(const std::shared_ptr& ledger_secrets_) : + ledger_secrets(ledger_secrets_) + {} /** Issue new recovery shares for the current ledger secret, recording the * wrapped new ledger secret and encrypted previous ledger secret in the @@ -312,7 +316,7 @@ namespace ccf void issue_recovery_shares(kv::Tx& tx) { auto [latest, penultimate] = - network.ledger_secrets->get_latest_and_penultimate(tx); + ledger_secrets->get_latest_and_penultimate(tx); set_recovery_shares_info(tx, latest.second, penultimate, latest.first); } @@ -331,7 +335,7 @@ namespace ccf void issue_recovery_shares(kv::Tx& tx, LedgerSecretPtr new_ledger_secret) { set_recovery_shares_info( - tx, new_ledger_secret, network.ledger_secrets->get_latest(tx)); + tx, new_ledger_secret, ledger_secrets->get_latest(tx)); } /** Issue new recovery shares of the same current ledger secret to all @@ -342,14 +346,14 @@ namespace ccf */ void shuffle_recovery_shares(kv::Tx& tx) { - shuffle_recovery_shares( - tx, network.ledger_secrets->get_latest(tx).second); + shuffle_recovery_shares(tx, ledger_secrets->get_latest(tx).second); } - std::optional get_encrypted_share( + static std::optional get_encrypted_share( kv::Tx& tx, const MemberId& member_id) { - auto recovery_shares_info = tx.rw(network.shares)->get(); + auto recovery_shares_info = + tx.rw(Tables::SHARES)->get(); if (!recovery_shares_info.has_value()) { throw std::logic_error( @@ -378,7 +382,8 @@ namespace ccf throw std::logic_error("No recovery ledger secrets"); } - auto recovery_shares_info = tx.ro(network.shares)->get(); + auto recovery_shares_info = + tx.ro(Tables::SHARES)->get(); if (!recovery_shares_info.has_value()) { throw std::logic_error( @@ -403,7 +408,8 @@ namespace ccf } auto encrypted_previous_ledger_secret = - tx.ro(network.encrypted_ledger_secrets); + tx.ro( + Tables::ENCRYPTED_PAST_LEDGER_SECRET); LedgerSecretsMap restored_ledger_secrets = {}; auto s = restored_ledger_secrets.emplace( @@ -442,9 +448,9 @@ namespace ccf MemberId member_id, const std::vector& submitted_recovery_share) { - auto service = tx.rw(network.service); - auto encrypted_submitted_shares = - tx.rw(network.encrypted_submitted_shares); + auto service = tx.rw(Tables::SERVICE); + auto encrypted_submitted_shares = tx.rw( + Tables::ENCRYPTED_SUBMITTED_SHARES); auto active_service = service->get(); if (!active_service.has_value()) { @@ -454,16 +460,15 @@ namespace ccf encrypted_submitted_shares->put( member_id, encrypt_submitted_share( - submitted_recovery_share, - network.ledger_secrets->get_latest(tx).second)); + submitted_recovery_share, ledger_secrets->get_latest(tx).second)); return encrypted_submitted_shares->size(); } - void clear_submitted_recovery_shares(kv::Tx& tx) + static void clear_submitted_recovery_shares(kv::Tx& tx) { - auto encrypted_submitted_shares = - tx.rw(network.encrypted_submitted_shares); + auto encrypted_submitted_shares = tx.rw( + Tables::ENCRYPTED_SUBMITTED_SHARES); encrypted_submitted_shares->clear(); } }; diff --git a/src/node/test/historical_queries.cpp b/src/node/test/historical_queries.cpp index 1231aa6bf..548276233 100644 --- a/src/node/test/historical_queries.cpp +++ b/src/node/test/historical_queries.cpp @@ -148,11 +148,7 @@ kv::Version rekey( kv::Store& kv_store, const std::shared_ptr& ledger_secrets) { - // This isn't really used, but is needed for ShareManager, so can be recreated - // each time here - ccf::NetworkState network; - network.ledger_secrets = ledger_secrets; - ccf::ShareManager share_manager(network); + ccf::ShareManager share_manager(ledger_secrets); auto tx = kv_store.create_tx(); auto new_ledger_secret = ccf::make_ledger_secret(); diff --git a/src/service/genesis_gen.h b/src/service/internal_tables_access.h similarity index 71% rename from src/service/genesis_gen.h rename to src/service/internal_tables_access.h index 2e4cb387d..16525120e 100644 --- a/src/service/genesis_gen.h +++ b/src/service/internal_tables_access.h @@ -9,7 +9,6 @@ #include "ccf/service/tables/nodes.h" #include "ccf/service/tables/snp_measurements.h" #include "ccf/tx.h" -#include "network_tables.h" #include "node/ledger_secrets.h" #include "node/uvm_endorsements.h" #include "service/tables/previous_service_identity.h" @@ -19,21 +18,22 @@ namespace ccf { - class GenesisGenerator + // This class provides functions for interacting with various internal + // service-governance tables. Specifically, it aims to maintain some + // invariants amongst these tables (eg - keys being present in multiple + // tables) despite access by distinct callers. These tables may be accessed + // directly with a Tx object, but it is recommended to use these methods where + // available. + class InternalTablesAccess { - NetworkTables& tables; - - kv::Tx& tx; - public: - GenesisGenerator(NetworkTables& tables_, kv::Tx& tx_) : - tables(tables_), - tx(tx_) - {} + // This class is purely a container for static methods, should not be + // instantiated + InternalTablesAccess() = delete; - void retire_active_nodes() + static void retire_active_nodes(kv::Tx& tx) { - auto nodes = tx.rw(tables.nodes); + auto nodes = tx.rw(Tables::NODES); std::map nodes_to_delete; nodes->foreach([&nodes_to_delete](const NodeId& nid, const NodeInfo& ni) { @@ -50,17 +50,19 @@ namespace ccf } } - bool is_recovery_member(const MemberId& member_id) + static bool is_recovery_member( + kv::ReadOnlyTx& tx, const MemberId& member_id) { auto member_encryption_public_keys = - tx.ro(tables.member_encryption_public_keys); + tx.ro( + Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS); return member_encryption_public_keys->get(member_id).has_value(); } - bool is_active_member(const MemberId& member_id) + static bool is_active_member(kv::ReadOnlyTx& tx, const MemberId& member_id) { - auto member_info = tx.ro(tables.member_info); + auto member_info = tx.ro(Tables::MEMBER_INFO); auto mi = member_info->get(member_id); if (!mi.has_value()) { @@ -70,11 +72,13 @@ namespace ccf return mi->status == MemberStatus::ACTIVE; } - std::map get_active_recovery_members() + static std::map get_active_recovery_members( + kv::ReadOnlyTx& tx) { - auto member_info = tx.ro(tables.member_info); + auto member_info = tx.ro(Tables::MEMBER_INFO); auto member_encryption_public_keys = - tx.ro(tables.member_encryption_public_keys); + tx.ro( + Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS); std::map active_recovery_members; @@ -97,12 +101,12 @@ namespace ccf return active_recovery_members; } - MemberId add_member(const NewMember& member_pub_info) + static MemberId add_member(kv::Tx& tx, const NewMember& member_pub_info) { - auto member_certs = tx.rw(tables.member_certs); - auto member_info = tx.rw(tables.member_info); - auto member_acks = tx.rw(tables.member_acks); - auto signatures = tx.ro(tables.signatures); + auto member_certs = tx.rw(Tables::MEMBER_CERTS); + auto member_info = tx.rw(Tables::MEMBER_INFO); + auto member_acks = tx.rw(Tables::MEMBER_ACKS); + auto signatures = tx.ro(Tables::SIGNATURES); auto member_cert_der = crypto::make_verifier(member_pub_info.cert)->cert_der(); @@ -122,7 +126,8 @@ namespace ccf if (member_pub_info.encryption_pub_key.has_value()) { auto member_encryption_public_keys = - tx.rw(tables.member_encryption_public_keys); + tx.rw( + Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS); member_encryption_public_keys->put( id, member_pub_info.encryption_pub_key.value()); } @@ -139,9 +144,9 @@ namespace ccf return id; } - void activate_member(const MemberId& member_id) + static void activate_member(kv::Tx& tx, const MemberId& member_id) { - auto member_info = tx.rw(tables.member_info); + auto member_info = tx.rw(Tables::MEMBER_INFO); auto member = member_info->get(member_id); if (!member.has_value()) @@ -152,8 +157,8 @@ namespace ccf member->status = MemberStatus::ACTIVE; if ( - is_recovery_member(member_id) && - (get_active_recovery_members().size() >= max_active_recovery_members)) + is_recovery_member(tx, member_id) && + (get_active_recovery_members(tx).size() >= max_active_recovery_members)) { throw std::logic_error(fmt::format( "Cannot activate new recovery member {}: no more than {} active " @@ -164,14 +169,16 @@ namespace ccf member_info->put(member_id, member.value()); } - bool remove_member(const MemberId& member_id) + static bool remove_member(kv::Tx& tx, const MemberId& member_id) { - auto member_certs = tx.rw(tables.member_certs); + auto member_certs = tx.rw(Tables::MEMBER_CERTS); auto member_encryption_public_keys = - tx.rw(tables.member_encryption_public_keys); - auto member_info = tx.rw(tables.member_info); - auto member_acks = tx.rw(tables.member_acks); - auto member_gov_history = tx.rw(tables.governance_history); + tx.rw( + Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS); + auto member_info = tx.rw(Tables::MEMBER_INFO); + auto member_acks = tx.rw(Tables::MEMBER_ACKS); + auto member_gov_history = + tx.rw(Tables::GOV_HISTORY); auto member_to_remove = member_info->get(member_id); if (!member_to_remove.has_value()) @@ -188,13 +195,13 @@ namespace ccf // recovery if ( member_to_remove->status == MemberStatus::ACTIVE && - is_recovery_member(member_id)) + is_recovery_member(tx, member_id)) { // Because the member to remove is active, there is at least one active // member (i.e. get_active_recovery_members_count_after >= 0) size_t get_active_recovery_members_count_after = - get_active_recovery_members().size() - 1; - auto recovery_threshold = get_recovery_threshold(); + get_active_recovery_members(tx).size() - 1; + auto recovery_threshold = get_recovery_threshold(tx); if (get_active_recovery_members_count_after < recovery_threshold) { LOG_FAIL_FMT( @@ -216,9 +223,9 @@ namespace ccf return true; } - UserId add_user(const NewUser& new_user) + static UserId add_user(kv::Tx& tx, const NewUser& new_user) { - auto user_certs = tx.rw(tables.user_certs); + auto user_certs = tx.rw(Tables::USER_CERTS); auto user_cert_der = crypto::make_verifier(new_user.cert)->cert_der(); auto id = crypto::Sha256Hash(user_cert_der).hex_str(); @@ -234,7 +241,7 @@ namespace ccf if (new_user.user_data != nullptr) { - auto user_info = tx.rw(tables.user_info); + auto user_info = tx.rw(Tables::USER_INFO); auto ui = user_info->get(id); if (ui.has_value()) { @@ -248,29 +255,31 @@ namespace ccf return id; } - void remove_user(const UserId& user_id) + static void remove_user(kv::Tx& tx, const UserId& user_id) { // Has no effect if the user does not exist - auto user_certs = tx.rw(tables.user_certs); - auto user_info = tx.rw(tables.user_info); + auto user_certs = tx.rw(Tables::USER_CERTS); + auto user_info = tx.rw(Tables::USER_INFO); user_certs->remove(user_id); user_info->remove(user_id); } - void add_node(const NodeId& id, const NodeInfo& node_info) + static void add_node( + kv::Tx& tx, const NodeId& id, const NodeInfo& node_info) { - auto node = tx.rw(tables.nodes); + auto node = tx.rw(Tables::NODES); node->put(id, node_info); } - auto get_trusted_nodes(std::optional self_to_exclude = std::nullopt) + static auto get_trusted_nodes( + kv::ReadOnlyTx& tx, std::optional self_to_exclude = std::nullopt) { // Returns the list of trusted nodes. If self_to_exclude is set, // self_to_exclude is not included in the list of returned nodes. std::map active_nodes; - auto nodes = tx.ro(tables.nodes); + auto nodes = tx.ro(Tables::NODES); nodes->foreach([&active_nodes, self_to_exclude](const NodeId& nid, const NodeInfo& ni) { @@ -287,13 +296,14 @@ namespace ccf } // Service status should use a state machine, very much like NodeState. - void create_service( + static void create_service( + kv::Tx& tx, const crypto::Pem& service_cert, ccf::TxID create_txid, nlohmann::json service_data = nullptr, bool recovering = false) { - auto service = tx.rw(tables.service); + auto service = tx.rw(Tables::SERVICE); size_t recovery_count = 0; @@ -319,24 +329,26 @@ namespace ccf create_txid}); } - bool is_service_created(const crypto::Pem& expected_service_cert) + static bool is_service_created( + kv::ReadOnlyTx& tx, const crypto::Pem& expected_service_cert) { - auto service = tx.ro(tables.service)->get(); + auto service = tx.ro(Tables::SERVICE)->get(); return service.has_value() && service->cert == expected_service_cert; } - bool open_service() + static bool open_service(kv::Tx& tx) { - auto service = tx.rw(tables.service); + auto service = tx.rw(Tables::SERVICE); - auto active_recovery_members_count = get_active_recovery_members().size(); - if (active_recovery_members_count < get_recovery_threshold()) + auto active_recovery_members_count = + get_active_recovery_members(tx).size(); + if (active_recovery_members_count < get_recovery_threshold(tx)) { LOG_FAIL_FMT( "Cannot open network as number of active recovery members ({}) is " "less than recovery threshold ({})", active_recovery_members_count, - get_recovery_threshold()); + get_recovery_threshold(tx)); return false; } @@ -371,9 +383,9 @@ namespace ccf return true; } - std::optional get_service_status() + static std::optional get_service_status(kv::ReadOnlyTx& tx) { - auto service = tx.ro(tables.service); + auto service = tx.ro(Tables::SERVICE); auto active_service = service->get(); if (!active_service.has_value()) { @@ -384,10 +396,10 @@ namespace ccf return active_service->status; } - void trust_node( - const NodeId& node_id, kv::Version latest_ledger_secret_seqno) + static void trust_node( + kv::Tx& tx, const NodeId& node_id, kv::Version latest_ledger_secret_seqno) { - auto nodes = tx.rw(tables.nodes); + auto nodes = tx.rw(Tables::NODES); auto node_info = nodes->get(node_id); if (!node_info.has_value()) @@ -407,12 +419,13 @@ namespace ccf LOG_INFO_FMT("Node {} is now {}", node_id, node_info->status); } - void set_constitution(const std::string& constitution) + static void set_constitution(kv::Tx& tx, const std::string& constitution) { - tx.rw(tables.constitution)->put(constitution); + tx.rw(Tables::CONSTITUTION)->put(constitution); } - void trust_node_measurement( + static void trust_node_measurement( + kv::Tx& tx, const pal::PlatformAttestationMeasurement& node_measurement, const QuoteFormat& platform) { @@ -445,11 +458,12 @@ namespace ccf } } - void trust_node_host_data( + static void trust_node_host_data( + kv::Tx& tx, const HostData& host_data, const std::optional& security_policy = std::nullopt) { - auto host_data_table = tx.rw(tables.host_data); + auto host_data_table = tx.rw(Tables::HOST_DATA); if (security_policy.has_value()) { auto raw_security_policy = @@ -464,8 +478,8 @@ namespace ccf } } - void trust_node_uvm_endorsements( - const std::optional& uvm_endorsements) + static void trust_node_uvm_endorsements( + kv::Tx& tx, const std::optional& uvm_endorsements) { if (!uvm_endorsements.has_value()) { @@ -473,15 +487,17 @@ namespace ccf return; } - auto uvme = tx.rw(tables.snp_uvm_endorsements); + auto uvme = + tx.rw(Tables::NODE_SNP_UVM_ENDORSEMENTS); uvme->put( uvm_endorsements->did, {{uvm_endorsements->feed, {uvm_endorsements->svn}}}); } - void init_configuration(const ServiceConfiguration& configuration) + static void init_configuration( + kv::Tx& tx, const ServiceConfiguration& configuration) { - auto config = tx.rw(tables.config); + auto config = tx.rw(Tables::CONFIGURATION); if (config->has()) { throw std::logic_error( @@ -492,9 +508,9 @@ namespace ccf config->put(configuration); } - bool set_recovery_threshold(size_t threshold) + static bool set_recovery_threshold(kv::Tx& tx, size_t threshold) { - auto config = tx.rw(tables.config); + auto config = tx.rw(Tables::CONFIGURATION); if (threshold == 0) { @@ -502,7 +518,7 @@ namespace ccf return false; } - auto service_status = get_service_status(); + auto service_status = get_service_status(tx); if (!service_status.has_value()) { LOG_FAIL_FMT("Failed to get active service"); @@ -522,7 +538,7 @@ namespace ccf else if (service_status.value() == ServiceStatus::OPEN) { auto get_active_recovery_members_count = - get_active_recovery_members().size(); + get_active_recovery_members(tx).size(); if (threshold > get_active_recovery_members_count) { LOG_FAIL_FMT( @@ -545,9 +561,9 @@ namespace ccf return true; } - size_t get_recovery_threshold() + static size_t get_recovery_threshold(kv::ReadOnlyTx& tx) { - auto config = tx.ro(tables.config); + auto config = tx.ro(Tables::CONFIGURATION); auto current_config = config->get(); if (!current_config.has_value()) {