зеркало из https://github.com/microsoft/CCF.git
Make `GenesisGenerator` methods static (#5333)
This commit is contained in:
Родитель
8b6232b6ed
Коммит
705f0e9faf
|
@ -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())
|
||||
{
|
Загрузка…
Ссылка в новой задаче