Make `GenesisGenerator` methods static (#5333)

This commit is contained in:
Eddy Ashton 2023-06-09 11:33:00 +01:00 коммит произвёл GitHub
Родитель 8b6232b6ed
Коммит 705f0e9faf
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 219 добавлений и 239 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -45,7 +45,6 @@ namespace ccf
std::unique_ptr<oversized::WriterFactory> writer_factory;
RingbufferLogger* ringbuffer_logger = nullptr;
ccf::NetworkState network;
ccf::ShareManager share_manager;
std::shared_ptr<RPCMap> rpc_map;
std::shared_ptr<RPCSessions> rpcsessions;
std::unique_ptr<ccf::NodeState> 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<RPCMap>()),
rpcsessions(std::make_shared<RPCSessions>(*writer_factory, rpc_map))
{
@ -118,7 +116,7 @@ namespace ccf
LOG_TRACE_FMT("Creating node");
node = std::make_unique<ccf::NodeState>(
*writer_factory, network, rpcsessions, share_manager, curve_id);
*writer_factory, network, rpcsessions, curve_id);
LOG_TRACE_FMT("Creating context");
context = std::make_unique<NodeContext>(node->get_node_id());
@ -159,8 +157,7 @@ namespace ccf
LOG_TRACE_FMT("Creating RPC actors / ffi");
rpc_map->register_frontend<ccf::ActorsType::members>(
std::make_unique<ccf::MemberRpcFrontend>(
network, *context, share_manager));
std::make_unique<ccf::MemberRpcFrontend>(network, *context));
rpc_map->register_frontend<ccf::ActorsType::users>(
std::make_unique<ccf::UserRpcFrontend>(

Просмотреть файл

@ -256,11 +256,7 @@ kv::Version rekey(
kv::Store& kv_store,
const std::shared_ptr<ccf::LedgerSecrets>& 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();

Просмотреть файл

@ -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<kv::TxHistory> history;
std::shared_ptr<kv::AbstractTxEncryptor> encryptor;
ShareManager& share_manager;
ShareManager share_manager;
std::shared_ptr<Snapshotter> snapshotter;
//
@ -224,7 +224,6 @@ namespace ccf
ringbuffer::AbstractWriterFactory& writer_factory,
NetworkState& network,
std::shared_ptr<RPCSessions> 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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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<CreateNetworkNodeToNode::In>();
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");

Просмотреть файл

@ -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 <doctest/doctest.h>
#include <iostream>
@ -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<uint8_t> 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<ChannelStubProxy>();
auto primary_consensus = std::make_shared<kv::test::PrimaryStubConsensus>();
@ -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,

Просмотреть файл

@ -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 <doctest/doctest.h>
#include <iostream>
@ -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<crypto::Pem>& 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<ccf::NetworkIdentity> make_test_network_ident()
{
using namespace std::literals;

Просмотреть файл

@ -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<kv::NullTxEncryptor>();
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<ccf::LedgerSecrets>();
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<kv::NullTxEncryptor>();
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<ccf::LedgerSecrets>();
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);

Просмотреть файл

@ -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
{

Просмотреть файл

@ -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 <optional>
@ -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<EncryptedLedgerSecret> 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<EncryptedLedgerSecret> ledger_secrets_for_node;

Просмотреть файл

@ -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 <openssl/crypto.h>
#include <vector>
@ -107,7 +107,7 @@ namespace ccf
class ShareManager
{
private:
NetworkState& network;
std::shared_ptr<LedgerSecrets> 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<SecretSharing::SplitSecret>();
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<ccf::RecoveryShares>(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<ccf::EncryptedLedgerSecretsInfo>(
Tables::ENCRYPTED_PAST_LEDGER_SECRET);
std::vector<uint8_t> 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<ccf::EncryptedSubmittedShares>(
Tables::ENCRYPTED_SUBMITTED_SHARES);
auto config = tx.rw<ccf::Configuration>(Tables::CONFIGURATION);
std::vector<SecretSharing::Share> 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<LedgerSecrets>& 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<EncryptedShare> get_encrypted_share(
static std::optional<EncryptedShare> 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<ccf::RecoveryShares>(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<ccf::RecoveryShares>(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<ccf::EncryptedLedgerSecretsInfo>(
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<uint8_t>& submitted_recovery_share)
{
auto service = tx.rw(network.service);
auto encrypted_submitted_shares =
tx.rw(network.encrypted_submitted_shares);
auto service = tx.rw<ccf::Service>(Tables::SERVICE);
auto encrypted_submitted_shares = tx.rw<ccf::EncryptedSubmittedShares>(
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<ccf::EncryptedSubmittedShares>(
Tables::ENCRYPTED_SUBMITTED_SHARES);
encrypted_submitted_shares->clear();
}
};

Просмотреть файл

@ -148,11 +148,7 @@ kv::Version rekey(
kv::Store& kv_store,
const std::shared_ptr<ccf::LedgerSecrets>& 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();

Просмотреть файл

@ -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<ccf::Nodes>(Tables::NODES);
std::map<NodeId, NodeInfo> 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<ccf::MemberPublicEncryptionKeys>(
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<ccf::MemberInfo>(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<MemberId, crypto::Pem> get_active_recovery_members()
static std::map<MemberId, crypto::Pem> get_active_recovery_members(
kv::ReadOnlyTx& tx)
{
auto member_info = tx.ro(tables.member_info);
auto member_info = tx.ro<ccf::MemberInfo>(Tables::MEMBER_INFO);
auto member_encryption_public_keys =
tx.ro(tables.member_encryption_public_keys);
tx.ro<ccf::MemberPublicEncryptionKeys>(
Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS);
std::map<MemberId, crypto::Pem> 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<ccf::MemberCerts>(Tables::MEMBER_CERTS);
auto member_info = tx.rw<ccf::MemberInfo>(Tables::MEMBER_INFO);
auto member_acks = tx.rw<ccf::MemberAcks>(Tables::MEMBER_ACKS);
auto signatures = tx.ro<ccf::Signatures>(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<ccf::MemberPublicEncryptionKeys>(
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<ccf::MemberInfo>(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<ccf::MemberCerts>(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<ccf::MemberPublicEncryptionKeys>(
Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS);
auto member_info = tx.rw<ccf::MemberInfo>(Tables::MEMBER_INFO);
auto member_acks = tx.rw<ccf::MemberAcks>(Tables::MEMBER_ACKS);
auto member_gov_history =
tx.rw<ccf::GovernanceHistory>(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<ccf::UserCerts>(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<ccf::UserInfo>(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<ccf::UserCerts>(Tables::USER_CERTS);
auto user_info = tx.rw<ccf::UserInfo>(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<ccf::Nodes>(Tables::NODES);
node->put(id, node_info);
}
auto get_trusted_nodes(std::optional<NodeId> self_to_exclude = std::nullopt)
static auto get_trusted_nodes(
kv::ReadOnlyTx& tx, std::optional<NodeId> 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<NodeId, NodeInfo> active_nodes;
auto nodes = tx.ro(tables.nodes);
auto nodes = tx.ro<ccf::Nodes>(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<ccf::Service>(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<ccf::Service>(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<ccf::Service>(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<ServiceStatus> get_service_status()
static std::optional<ServiceStatus> get_service_status(kv::ReadOnlyTx& tx)
{
auto service = tx.ro(tables.service);
auto service = tx.ro<ccf::Service>(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<ccf::Nodes>(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<ccf::Constitution>(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<HostDataMetadata>& security_policy = std::nullopt)
{
auto host_data_table = tx.rw(tables.host_data);
auto host_data_table = tx.rw<ccf::SnpHostDataMap>(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<UVMEndorsements>& uvm_endorsements)
static void trust_node_uvm_endorsements(
kv::Tx& tx, const std::optional<UVMEndorsements>& 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<ccf::SNPUVMEndorsements>(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<ccf::Configuration>(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<ccf::Configuration>(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<ccf::Configuration>(Tables::CONFIGURATION);
auto current_config = config->get();
if (!current_config.has_value())
{