From 87c4b4a5d4d5c6a12f12d446aff8b40d36223245 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Mon, 13 Jan 2025 17:41:50 +0300 Subject: [PATCH] Fix handling small out-of-sync in validate-query --- validator/downloaders/wait-block-state.cpp | 5 +- validator/impl/validate-query.cpp | 59 ++++++++++++---------- validator/impl/validate-query.hpp | 1 + validator/manager.cpp | 2 +- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/validator/downloaders/wait-block-state.cpp b/validator/downloaders/wait-block-state.cpp index b61b94922..c80e7d896 100644 --- a/validator/downloaders/wait-block-state.cpp +++ b/validator/downloaders/wait-block-state.cpp @@ -67,7 +67,8 @@ void WaitBlockState::start() { if (reading_from_db_) { return; } - if (handle_->received_state()) { + bool inited_proof = handle_->id().is_masterchain() ? handle_->inited_proof() : handle_->inited_proof_link(); + if (handle_->received_state() && inited_proof) { reading_from_db_ = true; auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result> R) { @@ -107,7 +108,7 @@ void WaitBlockState::start() { }); td::actor::send_closure(manager_, &ValidatorManager::send_get_zero_state_request, handle_->id(), priority_, std::move(P)); - } else if (check_persistent_state_desc()) { + } else if (check_persistent_state_desc() && !handle_->received_state()) { auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result> R) { if (R.is_error()) { LOG(WARNING) << "failed to get persistent state: " << R.move_as_error(); diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index 8490567e8..9a66ea81f 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -346,16 +346,7 @@ void ValidateQuery::start_up() { // return; } } - // 2. learn latest masterchain state and block id - LOG(DEBUG) << "sending get_top_masterchain_state_block() to Manager"; - ++pending; - td::actor::send_closure_later(manager, &ValidatorManager::get_top_masterchain_state_block, - [self = get_self()](td::Result, BlockIdExt>> res) { - LOG(DEBUG) << "got answer to get_top_masterchain_state_block"; - td::actor::send_closure_later( - std::move(self), &ValidateQuery::after_get_latest_mc_state, std::move(res)); - }); - // 3. load state(s) corresponding to previous block(s) + // 2. load state(s) corresponding to previous block(s) prev_states.resize(prev_blocks.size()); for (int i = 0; (unsigned)i < prev_blocks.size(); i++) { // 3.1. load state @@ -368,21 +359,13 @@ void ValidateQuery::start_up() { std::move(self), &ValidateQuery::after_get_shard_state, i, std::move(res)); }); } - // 4. unpack block candidate (while necessary data is being loaded) + // 3. unpack block candidate (while necessary data is being loaded) if (!unpack_block_candidate()) { reject_query("error unpacking block candidate"); return; } - // 5. request masterchain state referred to in the block + // 4. request masterchain handle and state referred to in the block if (!is_masterchain()) { - ++pending; - td::actor::send_closure_later(manager, &ValidatorManager::wait_block_state_short, mc_blkid_, priority(), timeout, - [self = get_self()](td::Result> res) { - LOG(DEBUG) << "got answer to wait_block_state() query for masterchain block"; - td::actor::send_closure_later(std::move(self), &ValidateQuery::after_get_mc_state, - std::move(res)); - }); - // 5.1. request corresponding block handle ++pending; td::actor::send_closure_later(manager, &ValidatorManager::get_block_handle, mc_blkid_, true, [self = get_self()](td::Result res) { @@ -663,6 +646,19 @@ bool ValidateQuery::extract_collated_data() { return true; } +/** + * Send get_top_masterchain_state_block to manager, call after_get_latest_mc_state afterwards + */ +void ValidateQuery::request_latest_mc_state() { + ++pending; + td::actor::send_closure_later(manager, &ValidatorManager::get_top_masterchain_state_block, + [self = get_self()](td::Result, BlockIdExt>> res) { + LOG(DEBUG) << "got answer to get_top_masterchain_state_block"; + td::actor::send_closure_later( + std::move(self), &ValidateQuery::after_get_latest_mc_state, std::move(res)); + }); +} + /** * Callback function called after retrieving the latest masterchain state. * @@ -710,6 +706,7 @@ void ValidateQuery::after_get_latest_mc_state(td::Result> res) { + CHECK(!is_masterchain()); LOG(WARNING) << "in ValidateQuery::after_get_mc_state() for " << mc_blkid_.to_str(); --pending; if (res.is_error()) { @@ -720,6 +717,7 @@ void ValidateQuery::after_get_mc_state(td::Result> res) { fatal_error("cannot process masterchain state for "s + mc_blkid_.to_str()); return; } + request_latest_mc_state(); if (!pending) { if (!try_validate()) { fatal_error("cannot validate new block"); @@ -734,17 +732,21 @@ void ValidateQuery::after_get_mc_state(td::Result> res) { */ void ValidateQuery::got_mc_handle(td::Result res) { LOG(DEBUG) << "in ValidateQuery::got_mc_handle() for " << mc_blkid_.to_str(); - --pending; if (res.is_error()) { fatal_error(res.move_as_error()); return; } - auto handle = res.move_as_ok(); - if (!handle->inited_proof() && mc_blkid_.seqno()) { - fatal_error(-666, "reference masterchain block "s + mc_blkid_.to_str() + " for block " + id_.to_str() + - " does not have a valid proof"); - return; - } + auto mc_handle = res.move_as_ok(); + td::actor::send_closure_later( + manager, &ValidatorManager::wait_block_state, mc_handle, priority(), timeout, + [self = get_self(), id = id_, mc_handle](td::Result> res) { + LOG(DEBUG) << "got answer to wait_block_state() query for masterchain block"; + if (res.is_ok() && mc_handle->id().seqno() > 0 && !mc_handle->inited_proof()) { + res = td::Status::Error(-666, "reference masterchain block "s + mc_handle->id().to_str() + " for block " + + id.to_str() + " does not have a valid proof"); + } + td::actor::send_closure_later(std::move(self), &ValidateQuery::after_get_mc_state, std::move(res)); + }); } /** @@ -778,6 +780,9 @@ void ValidateQuery::after_get_shard_state(int idx, td::Result> r return; } } + if (is_masterchain()) { + request_latest_mc_state(); + } if (!pending) { if (!try_validate()) { fatal_error("cannot validate new block"); diff --git a/validator/impl/validate-query.hpp b/validator/impl/validate-query.hpp index 52d4968ad..98cd2493b 100644 --- a/validator/impl/validate-query.hpp +++ b/validator/impl/validate-query.hpp @@ -284,6 +284,7 @@ class ValidateQuery : public td::actor::Actor { return actor_id(this); } + void request_latest_mc_state(); void after_get_latest_mc_state(td::Result, BlockIdExt>> res); void after_get_mc_state(td::Result> res); void got_mc_handle(td::Result res); diff --git a/validator/manager.cpp b/validator/manager.cpp index a631bd093..068ea5eb1 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -1343,7 +1343,7 @@ void ValidatorManagerImpl::written_handle(BlockHandle handle, td::Promisesecond.actor_, &WaitBlockData::force_read_from_db); } } - if (inited_state) { + if (inited_state && inited_proof) { auto it = wait_state_.find(handle->id()); if (it != wait_state_.end()) { td::actor::send_closure(it->second.actor_, &WaitBlockState::force_read_from_db);