20 #include "scale/scale.hpp" 25 case E::INVALID_BLOCK:
26 return "Invalid block";
27 case E::PARENT_NOT_FOUND:
28 return "Parent not found";
30 return "Unknown error";
36 std::shared_ptr<blockchain::BlockTree> block_tree,
37 std::shared_ptr<consensus::babe::BabeConfigRepository> babe_config_repo,
38 std::shared_ptr<BlockValidator> block_validator,
39 std::shared_ptr<grandpa::Environment> grandpa_environment,
40 std::shared_ptr<crypto::Hasher> hasher,
41 std::shared_ptr<blockchain::DigestTracker> digest_tracker,
42 std::shared_ptr<BabeUtil> babe_util,
43 std::shared_ptr<babe::ConsistencyKeeper> consistency_keeper)
44 : block_tree_{std::move(block_tree)},
57 BOOST_ASSERT(
hasher_ !=
nullptr);
61 BOOST_ASSERT(
logger_ !=
nullptr);
66 if (not b.header.has_value()) {
67 logger_->warn(
"Skipping a block without header");
70 auto &header = b.header.value();
72 auto block_hash =
hasher_->blake2b_256(scale::encode(header).value());
79 logger_,
"Skip early appended header of block: {}", block_info);
80 return outcome::success();
83 SL_TRACE(
logger_,
"Skip just appended header of block: {}", block_info);
84 return outcome::success();
90 if (
auto header_res =
block_tree_->getBlockHeader(header.parent_hash);
91 header_res.has_error()
94 logger_->warn(
"Skipping a block {} with unknown parent", block_info);
96 }
else if (header_res.has_error()) {
97 return header_res.as_failure();
102 auto t_start = std::chrono::high_resolution_clock::now();
107 if (
auto header_res =
block_tree_->getBlockHeader(block_hash);
108 header_res.has_value()) {
109 SL_DEBUG(
logger_,
"Skip existing header of block: {}", block_info);
111 OUTCOME_TRY(
block_tree_->addExistingBlock(block_hash, block.header));
112 }
else if (header_res.error()
114 return header_res.as_failure();
116 OUTCOME_TRY(
block_tree_->addBlockHeader(block.header));
121 const auto &babe_header = babe_digests.second;
123 auto slot_number = babe_header.slot_number;
127 if (res.has_error()) {
128 if (block.header.number == 1) {
130 "First block slot is {}: it is first block (at executing)",
132 return std::tuple(slot_number,
false);
135 "First block slot is {}: no first block (at executing)",
137 return std::tuple(
babe_util_->getCurrentSlot(),
false);
141 const auto &first_block_header = res.value();
143 BOOST_ASSERT_MSG(babe_digest_res.has_value(),
144 "Any non genesis block must contain babe digest");
145 auto first_slot_number = babe_digest_res.value().second.slot_number;
147 auto is_first_block_finalized =
152 "First block slot is {}: by {}finalized first block (at executing)",
154 is_first_block_finalized ?
"" :
"non-");
155 return std::tuple(first_slot_number, is_first_block_finalized);
158 auto epoch_number =
babe_util_->slotToEpoch(slot_number);
162 "Appending header of block {} ({} in slot {}, epoch {}, authority #{})",
167 babe_header.authority_index);
173 auto digest_tracking_res =
175 if (digest_tracking_res.has_error()) {
177 "Error while tracking digest of block {}: {}",
179 digest_tracking_res.error().message());
180 return digest_tracking_res.as_failure();
184 if (babe_config ==
nullptr) {
189 "Actual epoch digest to apply block {} (slot {}, epoch {}). " 194 babe_config->randomness);
197 babe_config->authorities,
198 babe_header.authority_index);
203 babe_config->authorities[babe_header.authority_index].id,
209 if (b.justification.has_value()) {
210 SL_VERBOSE(
logger_,
"Justification received for block {}", block_info);
214 std::vector<primitives::BlockInfo> to_remove;
215 for (
const auto &[block_justified_for, justification] :
219 to_remove.push_back(block_justified_for);
222 if (not to_remove.empty()) {
223 for (
const auto &item : to_remove) {
224 justifications_.erase(item);
230 if (res.has_error()) {
236 "Error while applying of block {} justification: {}",
238 res.error().message());
239 return res.as_failure();
247 auto now = std::chrono::high_resolution_clock::now();
251 "Imported header of block {} within {} us",
253 std::chrono::duration_cast<std::chrono::microseconds>(now - t_start)
258 if (block_delta >= 10000 or time_delta >= std::chrono::minutes(1)) {
260 "Imported {} more headers of blocks. Average speed is {} bps",
263 / std::chrono::duration_cast<std::chrono::seconds>(time_delta)
269 consistency_guard.commit();
273 return outcome::success();
std::shared_ptr< BabeUtil > babe_util_
BlockAppenderImpl(std::shared_ptr< blockchain::BlockTree > block_tree, std::shared_ptr< consensus::babe::BabeConfigRepository > babe_config_repo, std::shared_ptr< BlockValidator > block_validator, std::shared_ptr< grandpa::Environment > grandpa_environment, std::shared_ptr< crypto::Hasher > hasher, std::shared_ptr< blockchain::DigestTracker > digest_tracker, std::shared_ptr< BabeUtil > babe_util, std::shared_ptr< babe::ConsistencyKeeper > consistency_keeper)
outcome::result< std::pair< Seal, BabeBlockHeader > > getBabeDigests(const primitives::BlockHeader &block_header)
Block class represents polkadot block primitive.
std::string_view to_string(SlotType s)
std::map< primitives::BlockInfo, primitives::Justification > justifications_
Threshold calculateThreshold(const std::pair< uint64_t, uint64_t > &ratio, const primitives::AuthorityList &authorities, primitives::AuthorityIndex authority_index)
OUTCOME_CPP_DEFINE_CATEGORY(kagome::consensus, BlockAppenderImpl::Error, e)
std::shared_ptr< crypto::Hasher > hasher_
std::shared_ptr< grandpa::Environment > grandpa_environment_
std::shared_ptr< blockchain::BlockTree > block_tree_
std::optional< primitives::BlockInfo > last_appended_
std::shared_ptr< consensus::babe::BabeConfigRepository > babe_config_repo_
outcome::result< void > appendBlock(primitives::BlockData &&b) override
std::shared_ptr< BlockValidator > block_validator_
BlockHeader header
block header
Logger createLogger(const std::string &tag)
outcome::result< void > applyJustification(const primitives::BlockInfo &block_info, const primitives::Justification &justification) override
std::shared_ptr< babe::ConsistencyKeeper > consistency_keeper_
struct kagome::consensus::BlockAppenderImpl::@2 speed_data_
std::shared_ptr< blockchain::DigestTracker > digest_tracker_