21 #include "scale/scale.hpp" 27 case E::INVALID_BLOCK:
28 return "Invalid block";
29 case E::PARENT_NOT_FOUND:
30 return "Parent not found";
31 case E::INTERNAL_ERROR:
32 return "Internal error";
34 return "Unknown error";
38 constexpr
const char *kBlockExecutionTime =
39 "kagome_block_verification_and_import_time";
45 std::shared_ptr<blockchain::BlockTree> block_tree,
46 std::shared_ptr<runtime::Core> core,
47 std::shared_ptr<consensus::babe::BabeConfigRepository> babe_config_repo,
48 std::shared_ptr<BlockValidator> block_validator,
49 std::shared_ptr<grandpa::Environment> grandpa_environment,
50 std::shared_ptr<transaction_pool::TransactionPool> tx_pool,
51 std::shared_ptr<crypto::Hasher> hasher,
52 std::shared_ptr<blockchain::DigestTracker> digest_tracker,
53 std::shared_ptr<BabeUtil> babe_util,
54 std::shared_ptr<runtime::OffchainWorkerApi> offchain_worker_api,
55 std::shared_ptr<babe::ConsistencyKeeper> consistency_keeper)
56 : block_tree_{std::move(block_tree)},
57 core_{std::move(core)},
70 BOOST_ASSERT(
core_ !=
nullptr);
75 BOOST_ASSERT(
hasher_ !=
nullptr);
80 BOOST_ASSERT(
logger_ !=
nullptr);
85 kBlockExecutionTime,
"Time taken to verify and import blocks");
88 {0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10});
93 if (not b.header.has_value()) {
94 logger_->warn(
"Skipping a block without header");
97 auto &header = b.header.value();
99 auto block_hash =
hasher_->blake2b_256(scale::encode(header).value());
103 if (
auto header_res =
block_tree_->getBlockHeader(header.parent_hash);
104 header_res.has_error()
106 logger_->warn(
"Skipping a block {} with unknown parent", block_info);
108 }
else if (header_res.has_error()) {
109 return header_res.as_failure();
113 auto t_start = std::chrono::high_resolution_clock::now();
115 bool block_already_exists =
false;
118 if (
auto body_res =
block_tree_->getBlockBody(block_hash);
119 body_res.has_value()) {
120 SL_DEBUG(
logger_,
"Skip existing block: {}", block_info);
122 OUTCOME_TRY(
block_tree_->addExistingBlock(block_hash, header));
123 block_already_exists =
true;
125 return body_res.as_failure();
128 if (not b.body.has_value()) {
129 logger_->warn(
"Skipping a block without body.");
132 auto &body = b.body.value();
135 .body = std::move(body)};
139 const auto &babe_header = babe_digests.second;
141 auto slot_number = babe_header.slot_number;
145 if (res.has_error()) {
146 if (block.header.number == 1) {
148 "First block slot is {}: it is first block (at executing)",
150 return std::tuple(slot_number,
false);
153 "First block slot is {}: no first block (at executing)",
155 return std::tuple(
babe_util_->getCurrentSlot(),
false);
159 const auto &first_block_header = res.value();
161 BOOST_ASSERT_MSG(babe_digest_res.has_value(),
162 "Any non genesis block must contain babe digest");
163 auto first_slot_number = babe_digest_res.value().second.slot_number;
165 auto is_first_block_finalized =
170 "First block slot is {}: by {}finalized first block (at executing)",
172 is_first_block_finalized ?
"" :
"non-");
173 return std::tuple(first_slot_number, is_first_block_finalized);
176 auto epoch_number =
babe_util_->slotToEpoch(slot_number);
180 "Applying block {} ({} in slot {}, epoch {}, authority #{})",
185 babe_header.authority_index);
191 auto digest_tracking_res =
193 if (digest_tracking_res.has_error()) {
195 "Error while tracking digest of block {}: {}",
197 digest_tracking_res.error().message());
198 return digest_tracking_res.as_failure();
202 if (babe_config ==
nullptr) {
207 "Actual epoch digest to apply block {} (slot {}, epoch {}). " 212 babe_config->randomness);
215 babe_config->authorities,
216 babe_header.authority_index);
221 babe_config->authorities[babe_header.authority_index].id,
225 auto block_without_seal_digest = block;
228 block_without_seal_digest.header.digest.pop_back();
230 auto parent =
block_tree_->getBlockHeader(block.header.parent_hash).value();
232 auto last_finalized_block =
block_tree_->getLastFinalized();
233 auto previous_best_block_res =
234 block_tree_->getBestContaining(last_finalized_block.hash, std::nullopt);
235 BOOST_ASSERT(previous_best_block_res.has_value());
236 const auto &previous_best_block = previous_best_block_res.value();
238 if (not block_already_exists) {
239 auto exec_start = std::chrono::high_resolution_clock::now();
241 "Execute block {}, state {}, a child of block {}, state {}",
243 block.header.state_root,
247 OUTCOME_TRY(
core_->execute_block(block_without_seal_digest));
249 auto exec_end = std::chrono::high_resolution_clock::now();
250 auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
251 exec_end - exec_start)
253 SL_DEBUG(
logger_,
"Core_execute_block: {} ms", duration_ms);
264 if (b.justification.has_value()) {
265 SL_VERBOSE(
logger_,
"Justification received for block {}", block_info);
269 std::vector<primitives::BlockInfo> to_remove;
270 for (
const auto &[block_justified_for, justification] :
274 to_remove.push_back(block_justified_for);
277 if (not to_remove.empty()) {
278 for (
const auto &item : to_remove) {
279 justifications_.erase(item);
285 if (res.has_error()) {
290 return res.as_failure();
299 for (
const auto &extrinsic : block.body) {
305 return res.as_failure();
309 auto t_end = std::chrono::high_resolution_clock::now();
312 "Imported block {} within {} ms",
314 std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start)
317 last_finalized_block =
block_tree_->getLastFinalized();
318 telemetry_->notifyBlockFinalized(last_finalized_block);
319 auto current_best_block_res =
320 block_tree_->getBestContaining(last_finalized_block.hash, std::nullopt);
321 BOOST_ASSERT(current_best_block_res.has_value());
322 const auto ¤t_best_block = current_best_block_res.value();
327 if (current_best_block.number > previous_best_block.number) {
329 block.header.parent_hash, block.header);
330 if (ocw_res.has_failure()) {
331 logger_->error(
"Can't spawn offchain worker for block {}: {}",
333 ocw_res.error().message());
337 consistency_guard.commit();
339 return outcome::success();
std::shared_ptr< transaction_pool::TransactionPool > tx_pool_
std::shared_ptr< TelemetryService > createTelemetryService()
Returns preliminary initialized instance of telemetry service.
OUTCOME_CPP_DEFINE_CATEGORY(kagome::consensus, BlockExecutorImpl::Error, e)
std::map< primitives::BlockInfo, primitives::Justification > justifications_
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::shared_ptr< runtime::OffchainWorkerApi > offchain_worker_api_
metrics::Histogram * metric_block_execution_time_
Block is part of the initial sync with the network.
Threshold calculateThreshold(const std::pair< uint64_t, uint64_t > &ratio, const primitives::AuthorityList &authorities, primitives::AuthorityIndex authority_index)
std::shared_ptr< consensus::babe::BabeConfigRepository > babe_config_repo_
metrics::RegistryPtr metrics_registry_
telemetry::Telemetry telemetry_
virtual void observe(const double value)=0
Observe the given amount.
std::shared_ptr< grandpa::Environment > grandpa_environment_
std::shared_ptr< runtime::Core > core_
std::shared_ptr< crypto::Hasher > hasher_
std::shared_ptr< blockchain::DigestTracker > digest_tracker_
std::shared_ptr< BabeUtil > babe_util_
BlockExecutorImpl(std::shared_ptr< blockchain::BlockTree > block_tree, std::shared_ptr< runtime::Core > core, 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< transaction_pool::TransactionPool > tx_pool, std::shared_ptr< crypto::Hasher > hasher, std::shared_ptr< blockchain::DigestTracker > digest_tracker, std::shared_ptr< BabeUtil > babe_util, std::shared_ptr< runtime::OffchainWorkerApi > offchain_worker_api, std::shared_ptr< babe::ConsistencyKeeper > consistency_keeper)
std::shared_ptr< blockchain::BlockTree > block_tree_
outcome::result< void > applyJustification(const primitives::BlockInfo &block_info, const primitives::Justification &justification) override
BlockHeader header
block header
Logger createLogger(const std::string &tag)
std::shared_ptr< babe::ConsistencyKeeper > consistency_keeper_
outcome::result< void > applyBlock(primitives::BlockData &&block) override
std::shared_ptr< BlockValidator > block_validator_