Kagome
Polkadot Runtime Engine in C++17
babe_digests_util.cpp
Go to the documentation of this file.
1 
7 
8 #include "scale/scale.hpp"
9 
12  switch (e) {
13  case E::REQUIRED_DIGESTS_NOT_FOUND:
14  return "the block must contain at least BABE "
15  "header and seal digests";
16  case E::NO_TRAILING_SEAL_DIGEST:
17  return "the block must contain a seal digest as the last digest";
18  case E::MULTIPLE_EPOCH_CHANGE_DIGESTS:
19  return "the block contains multiple epoch change digests";
20  case E::NEXT_EPOCH_DIGEST_DOES_NOT_EXIST:
21  return "next epoch digest does not exist";
22  }
23  return "unknown error";
24 }
25 
26 namespace kagome::consensus {
27 
28  outcome::result<std::pair<Seal, BabeBlockHeader>> getBabeDigests(
29  const primitives::BlockHeader &block_header) {
30  // valid BABE block has at least two digests: BabeHeader and a seal
31  if (block_header.digest.size() < 2) {
33  }
34  const auto &digests = block_header.digest;
35 
36  // last digest of the block must be a seal - signature
37  auto seal_opt = getFromVariant<primitives::Seal>(digests.back());
38  if (not seal_opt.has_value()) {
40  }
41 
42  OUTCOME_TRY(babe_seal_res, scale::decode<Seal>(seal_opt->get().data));
43 
44  for (const auto &digest :
45  gsl::make_span(digests).subspan(0, digests.size() - 1)) {
46  if (auto pre_runtime_opt = getFromVariant<primitives::PreRuntime>(digest);
47  pre_runtime_opt.has_value()) {
48  if (auto header =
49  scale::decode<BabeBlockHeader>(pre_runtime_opt->get().data);
50  header) {
51  // found the BabeBlockHeader digest; return
52  return {babe_seal_res, header.value()};
53  }
54  }
55  }
56 
58  }
59 
60  outcome::result<EpochDigest> getNextEpochDigest(
61  const primitives::BlockHeader &header) {
62  // https://github.com/paritytech/substrate/blob/d8df977d024ebeb5330bacac64cf7193a7c242ed/core/consensus/babe/src/lib.rs#L497
63  outcome::result<EpochDigest> epoch_digest =
65 
66  for (const auto &log : header.digest) {
67  visit_in_place(
68  log,
69  [&epoch_digest](const primitives::Consensus &consensus) {
71  auto consensus_log_res =
72  scale::decode<primitives::BabeDigest>(consensus.data);
73  if (not consensus_log_res) {
74  return;
75  }
76 
77  visit_in_place(
78  consensus_log_res.value(),
79  [&epoch_digest](const primitives::NextEpochData &next_epoch) {
80  if (not epoch_digest) {
81  epoch_digest = static_cast<EpochDigest>(next_epoch);
82  } else {
84  }
85  },
86  [](const auto &) {});
87  }
88  },
89  [](const auto &) {});
90  }
91  return epoch_digest;
92  }
93 } // namespace kagome::consensus
outcome::result< std::pair< Seal, BabeBlockHeader > > getBabeDigests(const primitives::BlockHeader &block_header)
Data are corresponding to the epoch.
outcome::result< EpochDigest > getNextEpochDigest(const primitives::BlockHeader &header)
Digest digest
chain-specific auxiliary data
gsl::span< const uint8_t > make_span(const rocksdb::Slice &s)
OUTCOME_CPP_DEFINE_CATEGORY(kagome::consensus, DigestError, e)
const auto kBabeEngineId
Definition: digest.hpp:25