21 static void validate_fetched_endorsement(
24 if (!is_self_endorsement(endorsement))
26 const auto [from, to] =
30 if (!from_txid.has_value())
32 throw std::logic_error(fmt::format(
33 "Cannot parse COSE endorsement header: {}",
34 ccf::crypto::COSE_PHEADER_KEY_RANGE_BEGIN));
38 if (!to_txid.has_value())
40 throw std::logic_error(fmt::format(
41 "Cannot parse COSE endorsement header: {}",
42 ccf::crypto::COSE_PHEADER_KEY_RANGE_END));
47 throw std::logic_error(
48 "COSE endorsement does not contain epoch end in the table entry");
54 throw std::logic_error(fmt ::format(
55 "COSE endorsement fetched but range is invalid, epoch begin {}, "
56 "epoch end {}, header epoch begin: {}, header epoch end: {}",
65 static void validate_chain_integrity(
70 throw std::logic_error(fmt::format(
71 "COSE endorsement chain integrity is violated, previous endorsement "
72 "from {} does not have an epoch end",
82 throw std::logic_error(fmt::format(
83 "COSE endorsement chain integrity is violated, previous endorsement "
84 "epoch end {} is not chained with newer endorsement epoch begin {}",
105 const std::unique_ptr<NetworkIdentity>& network_identity_,
106 std::shared_ptr<ccf::historical::StateCacheImpl> historical_cache_) :
119 const std::unique_ptr<NetworkIdentity>&
get()
override
124 [[nodiscard]] std::optional<CoseEndorsementsChain>
137 "Unset current_service_from when fetching endorsements chain");
150 "No endorsements found for seqno {}, earliest endorsed is {}",
159 result.push_back(it->second.endorsement);
161 std::reverse(result.begin(), result.end());
166 void retry_first_fetch()
168 using namespace std::chrono_literals;
169 static constexpr auto retry_after = 1s;
175 void fail_fetching(
const std::string& err =
"")
179 LOG_FAIL_FMT(
"Failed fetching network identity: {}", err);
184 void complete_fetching()
188 fail_fetching(
"Unset current_service_from when completing fetching");
200 validate_chain_integrity(next->second, prev->second);
205 const auto& last = prev->second;
206 if (!last.endorsement_epoch_end.has_value())
208 fail_fetching(fmt::format(
209 "The last fetched endorsement at {} has no epoch end",
210 last.endorsement_epoch_begin.seqno));
216 last.endorsement_epoch_end->view ||
218 last.endorsement_epoch_end->seqno)
220 fail_fetching(fmt::format(
221 "COSE endorsement chain integrity is violated, the current "
222 "service start at {} is not chained with previous endorsement "
225 last.endorsement_epoch_end->to_str()));
229 catch (
const std::exception& e)
231 fail_fetching(e.what());
244 "Retry fetching network identity as node is not part of the network "
251 auto tx = store->create_read_only_tx();
255 auto* service_info_handle =
256 tx.template ro<ccf::Service>(ccf::Tables::SERVICE);
257 auto service_info = service_info_handle->get();
260 !service_info->current_service_create_txid.has_value())
263 "Retrying fetching network identity as current service create txid "
264 "is not yet available");
272 auto* previous_identity_endorsement =
274 ccf::Tables::PREVIOUS_SERVICE_IDENTITY_ENDORSEMENT);
276 auto endorsement = previous_identity_endorsement->get();
277 if (!endorsement.has_value())
280 "Retrying fetching network identity as there is no previous service "
281 "identity endorsement yet");
286 if (is_self_endorsement(endorsement.value()))
290 endorsement->endorsement_epoch_begin.seqno)
292 fail_fetching(fmt::format(
293 "The first fetched endorsement is a self-endorsement with seqno {} "
294 "which is different from current_service_create_txid {}",
295 endorsement->endorsement_epoch_begin.seqno,
301 "The very first service endorsement is self-signed at {}, no "
302 "endorsement chain will be preloaded",
312 process_endorsement(endorsement.value());
318 if (is_self_endorsement(endorsement))
322 fail_fetching(fmt::format(
323 "Fetched self-endorsement with seqno {} which has not been seen",
327 LOG_INFO_FMT(
"Got self-endorsement at {}, stopping fetching", from);
334 fail_fetching(fmt::format(
335 "Fetched service endorsement with seqno {} which is greater than "
336 "the earliest known in the chain {}",
345 fmt::format(
"Fetched endorsement at {} has no epoch end", from));
352 fail_fetching(fmt::format(
353 "Fetched service endorsement with seqno {} which already exists",
359 "Fetched service endorsement from {} to {}",
381 retry_fetch_next(seq);
387 fail_fetching(fmt::format(
388 "Fetched historical state with seqno {} with missing store", seq));
391 auto htx = state->store->create_read_only_tx();
392 const auto endorsement =
394 .template ro<ccf::PreviousServiceIdentityEndorsement>(
395 ccf::Tables::PREVIOUS_SERVICE_IDENTITY_ENDORSEMENT)
398 if (!endorsement.has_value())
401 fmt::format(
"Fetched COSE endorsement for {} is invalid", seq));
407 validate_fetched_endorsement(endorsement.value());
409 catch (
const std::exception& e)
411 fail_fetching(e.what());
415 process_endorsement(endorsement.value());
420 using namespace std::chrono_literals;
421 static constexpr auto retry_after = 100ms;
424 [
this, seq]() { this->fetch_next_at(seq); }),
Definition node_interface.h:22
virtual bool is_part_of_network() const =0
virtual std::shared_ptr< ccf::kv::Store > get_store()=0
Definition network_identity_interface.h:26
Definition network_identity_subsystem.h:91
std::map< SeqNo, CoseEndorsement > endorsements
Definition network_identity_subsystem.h:96
FetchStatus endorsements_fetching_status() const override
Definition network_identity_subsystem.h:114
std::optional< CoseEndorsementsChain > get_cose_endorsements_chain(ccf::SeqNo seqno) const override
Definition network_identity_subsystem.h:125
const std::unique_ptr< NetworkIdentity > & network_identity
Definition network_identity_subsystem.h:94
std::atomic< FetchStatus > fetch_status
Definition network_identity_subsystem.h:99
SeqNo earliest_endorsed_seq
Definition network_identity_subsystem.h:98
AbstractNodeState & node_state
Definition network_identity_subsystem.h:93
std::shared_ptr< historical::StateCacheImpl > historical_cache
Definition network_identity_subsystem.h:95
const std::unique_ptr< NetworkIdentity > & get() override
Definition network_identity_subsystem.h:119
std::optional< TxID > current_service_from
Definition network_identity_subsystem.h:97
bool has_predecessors
Definition network_identity_subsystem.h:100
NetworkIdentitySubsystem(AbstractNodeState &node_state_, const std::unique_ptr< NetworkIdentity > &network_identity_, std::shared_ptr< ccf::historical::StateCacheImpl > historical_cache_)
Definition network_identity_subsystem.h:103
#define LOG_INFO_FMT
Definition internal_logger.h:15
#define LOG_FAIL_FMT
Definition internal_logger.h:16
COSEEndorsementValidity extract_cose_endorsement_validity(std::span< const uint8_t > cose_msg)
Definition cose_verifier.cpp:238
std::pair< RequestNamespace, RequestHandle > CompoundHandle
Definition historical_queries.h:36
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:14
FetchStatus
Definition network_identity_interface.h:19
std::vector< RawCoseEndorsement > CoseEndorsementsChain
Definition network_identity_interface.h:16
seqno
Definition signatures.h:54
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
ccf::TxID endorsement_epoch_begin
The transaction ID when the endorsed service was created.
Definition previous_service_identity.h:26
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