16 static std::string format_epoch(
const std::optional<ccf::TxID>& epoch_end)
18 return epoch_end.has_value() ? epoch_end->to_str() :
"null";
33 static void validate_fetched_endorsement(
37 "Validating fetched endorsement from {} to {}",
41 if (!is_self_endorsement(endorsement))
43 const auto [from, to] =
47 if (!from_txid.has_value())
49 throw std::logic_error(fmt::format(
50 "Cannot parse COSE endorsement header: {}",
51 ccf::cose::header::custom::TX_RANGE_BEGIN));
55 if (!to_txid.has_value())
57 throw std::logic_error(fmt::format(
58 "Cannot parse COSE endorsement header: {}",
59 ccf::cose::header::custom::TX_RANGE_END));
64 throw std::logic_error(
65 "COSE endorsement does not contain epoch end in the table entry");
71 throw std::logic_error(fmt::format(
72 "COSE endorsement fetched but range is invalid, epoch begin {}, "
73 "epoch end {}, header epoch begin: {}, header epoch end: {}",
82 static void validate_chain_integrity(
87 throw std::logic_error(fmt::format(
88 "COSE endorsement chain integrity is violated, previous endorsement "
89 "from {} does not have an epoch end",
99 throw std::logic_error(fmt::format(
100 "COSE endorsement chain integrity is violated, previous endorsement "
101 "epoch end {} is not chained with newer endorsement epoch begin {}",
123 const std::unique_ptr<NetworkIdentity>& network_identity_,
124 std::shared_ptr<ccf::historical::StateCacheImpl> historical_cache_) :
137 const std::unique_ptr<NetworkIdentity>&
get()
override
142 [[nodiscard]] std::optional<CoseEndorsementsChain>
148 "COSE endorsements chain requested for seqno {} but identity "
149 "history fetching has not been completed yet",
156 "Unset current_service_from when fetching endorsements chain");
169 "No endorsements found for seqno {}, earliest endorsed is {}",
178 result.push_back(it->second.endorsement);
180 std::reverse(result.begin(), result.end());
190 "Trusted key requested for seqno {} but identity history "
191 "fetching has not been completed yet",
196 throw std::logic_error(fmt::format(
197 "No trusted keys fetched when requested one for seqno {}", seqno));
205 const auto& [key_seqno, key_ptr] = *(--it);
206 if (key_seqno > seqno)
208 throw std::logic_error(fmt::format(
209 "Resolved trusted key for {} with wrong starting seqno {}",
221 "Trusted keys requested but identity history fetching has not "
228 void retry_first_fetch()
230 using namespace std::chrono_literals;
231 static constexpr auto retry_after = 1s;
237 void fail_fetching(
const std::string& err =
"")
241 LOG_FAIL_FMT(
"Failed fetching network identity: {}", err);
250 throw std::runtime_error(
"Failed fetching network identity: " + err);
253 void complete_fetching()
257 fail_fetching(
"Unset current_service_from when completing fetching");
269 validate_chain_integrity(next->second, prev->second);
274 catch (
const std::exception& e)
276 fail_fetching(e.what());
279 const auto& last = prev->second;
280 if (!last.endorsement_epoch_end.has_value())
282 fail_fetching(fmt::format(
283 "The last fetched endorsement at {} has no epoch end",
284 last.endorsement_epoch_begin.seqno));
290 last.endorsement_epoch_end->view ||
293 fail_fetching(fmt::format(
294 "COSE endorsement chain integrity is violated, the current "
295 "service start at {} is not chained with previous endorsement "
298 last.endorsement_epoch_end->to_str()));
304 build_trusted_key_chain();
306 catch (
const std::exception& e)
308 fail_fetching(e.what());
319 "Retry fetching network identity as node is not part of the network "
326 auto tx = store->create_read_only_tx();
330 auto* service_info_handle =
331 tx.template ro<ccf::Service>(ccf::Tables::SERVICE);
332 auto service_info = service_info_handle->get();
335 !service_info->current_service_create_txid.has_value())
338 "Retrying fetching network identity as current service create txid "
339 "is not yet available");
352 "Retrying fetching network identity as service is not yet open");
360 auto* previous_identity_endorsement =
362 ccf::Tables::PREVIOUS_SERVICE_IDENTITY_ENDORSEMENT);
364 auto endorsement = previous_identity_endorsement->get();
365 if (!endorsement.has_value())
368 "Retrying fetching network identity as there is no previous service "
369 "identity endorsement yet");
374 if (is_self_endorsement(endorsement.value()))
378 endorsement->endorsement_epoch_begin.seqno)
380 fail_fetching(fmt::format(
381 "The first fetched endorsement is a self-endorsement with seqno {} "
382 "which is different from current_service_create_txid {}",
383 endorsement->endorsement_epoch_begin.seqno,
388 "The very first service endorsement is self-signed at {}, no "
389 "endorsement chain will be preloaded",
399 process_endorsement(endorsement.value());
404 if (is_ill_formed(endorsement))
413 "Fetched endorsement for {} - {} is ill-formed but has a "
414 "predecessor, so skipping this entry",
420 fail_fetching(fmt::format(
421 "Found an ill-formed endorsement for {} - {} which has no "
428 if (is_self_endorsement(endorsement))
432 fail_fetching(fmt::format(
433 "Fetched self-endorsement with seqno {} which has not been seen",
436 LOG_INFO_FMT(
"Got self-endorsement at {}, stopping fetching", from);
443 fail_fetching(fmt::format(
444 "Fetched service endorsement with seqno {} which is greater than "
445 "the earliest known in the chain {}",
453 fmt::format(
"Fetched endorsement at {} has no epoch end", from));
460 fail_fetching(fmt::format(
461 "Fetched service endorsement with seqno {} which already exists",
466 "Fetched service endorsement from {} to {}",
480 void build_trusted_key_chain()
484 throw std::logic_error(
485 "Attempting to build trusted key chain but no current service "
486 "created seqno fetched");
489 std::span<const uint8_t> previous_key_der{};
494 std::span<uint8_t> endorsed_key;
495 if (!verifier->verify(endorsement.
endorsement, endorsed_key))
497 throw std::logic_error(fmt::format(
498 "COSE endorsement chain integrity is violated, endorsement from {} "
499 "to {} failed signature verification",
505 "Adding trusted seq {} key {}",
513 !previous_key_der.empty() &&
515 previous_key_der.begin(),
516 previous_key_der.end(),
517 endorsed_key.begin(),
520 throw std::logic_error(fmt::format(
521 "Endorsement from {} to {} over public key {} doesn't chain with "
522 "the previous endorsement with key {}",
525 ccf::ds::to_hex(endorsed_key),
526 ccf::ds::to_hex(previous_key_der)));
532 const auto& current_pkey =
535 !previous_key_der.empty() &&
537 previous_key_der.begin(),
538 previous_key_der.end(),
539 current_pkey.begin(),
542 throw std::logic_error(fmt::format(
543 "Current service identity public key {} does not match the last "
545 ccf::ds::to_hex(current_pkey),
546 ccf::ds::to_hex(previous_key_der)));
550 "Adding trusted seq {} key {}",
566 retry_fetch_next(seq);
572 fail_fetching(fmt::format(
573 "Fetched historical state with seqno {} with missing store", seq));
575 auto htx = state->store->create_read_only_tx();
576 const auto endorsement =
578 .template ro<ccf::PreviousServiceIdentityEndorsement>(
579 ccf::Tables::PREVIOUS_SERVICE_IDENTITY_ENDORSEMENT)
582 if (!endorsement.has_value())
585 fmt::format(
"Fetched COSE endorsement for {} is invalid", seq));
591 validate_fetched_endorsement(endorsement.value());
593 catch (
const std::exception& e)
595 fail_fetching(e.what());
598 process_endorsement(endorsement.value());
603 using namespace std::chrono_literals;
604 static constexpr auto retry_after = 100ms;
607 [
this, seq]() { this->fetch_next_at(seq); }),
Definition node_interface.h:23
virtual bool is_part_of_network() const =0
virtual std::shared_ptr< ccf::kv::Store > get_store()=0
Definition network_identity_interface.h:53
Definition network_identity_subsystem.h:108
ccf::crypto::ECPublicKeyPtr get_trusted_identity_for(ccf::SeqNo seqno) const override
Definition network_identity_subsystem.h:184
std::map< SeqNo, CoseEndorsement > endorsements
Definition network_identity_subsystem.h:113
FetchStatus endorsements_fetching_status() const override
Returns the current status of endorsement fetching.
Definition network_identity_subsystem.h:132
std::optional< CoseEndorsementsChain > get_cose_endorsements_chain(ccf::SeqNo seqno) const override
Definition network_identity_subsystem.h:143
const std::unique_ptr< NetworkIdentity > & network_identity
Definition network_identity_subsystem.h:111
std::atomic< FetchStatus > fetch_status
Definition network_identity_subsystem.h:117
SeqNo earliest_endorsed_seq
Definition network_identity_subsystem.h:116
AbstractNodeState & node_state
Definition network_identity_subsystem.h:110
std::shared_ptr< historical::StateCacheImpl > historical_cache
Definition network_identity_subsystem.h:112
const std::unique_ptr< NetworkIdentity > & get() override
Returns a reference to the current network identity.
Definition network_identity_subsystem.h:137
std::optional< TxID > current_service_from
Definition network_identity_subsystem.h:115
bool has_predecessors
Definition network_identity_subsystem.h:118
std::map< SeqNo, ccf::crypto::ECPublicKeyPtr > trusted_keys
Definition network_identity_subsystem.h:114
NetworkIdentitySubsystem(AbstractNodeState &node_state_, const std::unique_ptr< NetworkIdentity > &network_identity_, std::shared_ptr< ccf::historical::StateCacheImpl > historical_cache_)
Definition network_identity_subsystem.h:121
TrustedKeys get_trusted_keys() const override
Definition network_identity_subsystem.h:216
#define LOG_INFO_FMT
Definition internal_logger.h:15
#define LOG_FAIL_FMT
Definition internal_logger.h:16
std::string b64_from_raw(const uint8_t *data, size_t size)
Definition base64.cpp:41
std::shared_ptr< ECPublicKey > ECPublicKeyPtr
Definition ec_public_key.h:158
COSEVerifierUniquePtr make_cose_verifier_from_key(const Pem &public_key)
Definition cose_verifier.cpp:291
ECPublicKeyPtr make_ec_public_key(const Pem &pem)
Definition ec_public_key.cpp:331
COSEEndorsementValidity extract_cose_endorsement_validity(std::span< const uint8_t > cose_msg)
Definition cose_verifier.cpp:302
std::pair< RequestNamespace, RequestHandle > CompoundHandle
Definition historical_queries.h:38
Task make_basic_task(Ts &&... ts)
Definition basic_task.h:33
void add_delayed_task(Task task, std::chrono::milliseconds delay)
Definition task_system.cpp:70
Definition app_interface.h:13
FetchStatus
Status of the network identity endorsement fetching process.
Definition network_identity_interface.h:26
@ Retry
Fetching should be retried.
@ Done
Fetching completed successfully.
std::map< ccf::SeqNo, ccf::crypto::ECPublicKeyPtr > TrustedKeys
Definition network_identity_interface.h:34
std::vector< RawCoseEndorsement > CoseEndorsementsChain
An ordered chain of raw COSE endorsements.
Definition network_identity_interface.h:22
uint64_t SeqNo
Definition tx_id.h:36
Definition previous_service_identity.h:18
std::optional< ccf::TxID > endorsement_epoch_end
Definition previous_service_identity.h:31
std::optional< ccf::kv::Version > previous_version
Definition previous_service_identity.h:35
std::vector< uint8_t > endorsement
COSE-sign of the a previous service identity's public key.
Definition previous_service_identity.h:20
std::vector< uint8_t > endorsing_key
Service key at the moment of endorsing.
Definition previous_service_identity.h:23
ccf::TxID endorsement_epoch_begin
The transaction ID when the endorsed service was created.
Definition previous_service_identity.h:26
Definition network_identity_interface.h:39
SeqNo seqno
Definition tx_id.h:46
View view
Definition tx_id.h:45
std::string to_str() const
Definition tx_id.h:48
static std::optional< TxID > from_str(const std::string_view &sv)
Definition tx_id.h:53