diff --git a/validator/impl/liteserver.cpp b/validator/impl/liteserver.cpp index 70330c6d1..6601e7fc6 100644 --- a/validator/impl/liteserver.cpp +++ b/validator/impl/liteserver.cpp @@ -359,7 +359,7 @@ static bool visit(Ref cs_ref) { return cs_ref.is_null() || visit(*cs_ref); } -void LiteQuery::continue_lookupBlockWithProof_getHeaderProof(BlockIdExt blkid, BlockIdExt client_mc_blkid, int mode, Ref block) { +void LiteQuery::continue_getBlockHeader(BlockIdExt blkid, int mode, Ref block) { LOG(INFO) << "obtained data for getBlockHeader(" << blkid.to_str() << ", " << mode << ")"; CHECK(block.not_null()); CHECK(block->block_id() == blkid); @@ -423,436 +423,152 @@ void LiteQuery::continue_lookupBlockWithProof_getHeaderProof(BlockIdExt blkid, B fatal_error(proof_data.move_as_error()); return; } + // send answer + auto b = ton::create_serialize_tl_object(ton::create_tl_lite_block_id(blkid), + mode, proof_data.move_as_ok()); + finish_query(std::move(b)); +} - if (!blkid.is_masterchain()) { - block::gen::ExtBlkRef::Record mcref; - if (!tlb::unpack_cell(info.master_ref, mcref)) { - fatal_error("cannot unpack masterchain block reference"); - return; - } - ton::BlockIdExt mc_blkid{ton::masterchainId, ton::shardIdAll, mcref.seq_no, mcref.root_hash, mcref.file_hash}; - - get_block_handle_checked(mc_blkid, [blkid, client_mc_blkid, header_proof=proof_data.move_as_ok(), manager = manager_, Self = actor_id(this)](td::Result R) mutable { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), - [blkid, client_mc_blkid, header_proof=std::move(header_proof), Self](td::Result> res) mutable { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - return; - } - td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock, blkid, client_mc_blkid, - std::move(header_proof), res.move_as_ok(), 10); - }); - }); - } else { - td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, - proof_data.move_as_ok(), blkid, td::BufferSlice(), std::vector>()); +void LiteQuery::perform_getState(BlockIdExt blkid) { + LOG(INFO) << "started a getState(" << blkid.to_str() << ") liteserver query"; + if (!blkid.is_valid_full()) { + fatal_error("invalid BlockIdExt"); return; } -} - -bool LiteQuery::check_mc_block_contains_shard_block(td::Ref mcref_block_data, BlockIdExt blkid, BlockIdExt& shard_top_blkid) { - block::gen::Block::Record blk; - block::gen::BlockExtra::Record extra; - block::gen::McBlockExtra::Record mc_extra; - if (!tlb::unpack_cell(mcref_block_data, blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() || - !tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra)) { - fatal_error("cannot unpack header of block "s + mc_block_->block_id().to_str()); - return false; + if (blkid.id.seqno > 1000) { + fatal_error("cannot request total state: possibly too large"); + return; } - vm::Dictionary shards_dict(std::move(mc_extra.shard_hashes), 32); - - vm::CellSlice cs; - ton::ShardIdFull true_shard; - // Here I assume that eventually mc block contains exact shard hash for the requested block. TODO: check if it's true for all cases - // e.g. can it be that shard split and merge happen between consequent mc blocks? - bool found = block::ShardConfig::get_shard_hash_raw_from(shards_dict, cs, blkid.shard_full(), true_shard, true, nullptr); - if (found) { - auto info = block::McShardHash::unpack(cs, true_shard); - if (info.is_null()) { - return false; + get_block_handle_checked(blkid, [=, manager = manager_, Self = actor_id(this)](td::Result R) { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); + return; } - if (info->top_block_id().id.seqno < blkid.id.seqno) { - return false; + if (blkid.id.seqno) { + td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, R.move_as_ok(), + [=](td::Result> res) { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + } else { + td::actor::send_closure_later(Self, &LiteQuery::continue_getState, blkid, + res.move_as_ok()); + } + }); + } else { + td::actor::send_closure_later(manager, &ValidatorManager::get_zero_state, blkid, + [=](td::Result res) { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + } else { + td::actor::send_closure_later(Self, &LiteQuery::continue_getZeroState, blkid, + res.move_as_ok()); + } + }); } - shard_top_blkid = info->top_block_id(); - return true; - } - return false; + }); } -void LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, td::Ref mc_block_data, int limit) { - if (!limit) { - fatal_error("checked 10 blocks after block.mcref and couldn't find shard block"); +void LiteQuery::continue_getState(BlockIdExt blkid, Ref state) { + LOG(INFO) << "obtained data for getState(" << blkid.to_str() << ")"; + CHECK(state.not_null()); + auto res = state->serialize(); + if (res.is_error()) { + abort_query(res.move_as_error()); return; } + auto data = res.move_as_ok(); + FileHash file_hash; + td::sha256(data, file_hash.as_slice()); + auto b = ton::create_serialize_tl_object( + ton::create_tl_lite_block_id(blkid), state->root_hash(), file_hash, std::move(data)); + finish_query(std::move(b)); +} - auto mc_block = Ref(std::move(mc_block_data)); - vm::MerkleProofBuilder mpb{mc_block->root_cell()}; - BlockIdExt shard_top_blkid; - if (!check_mc_block_contains_shard_block(mpb.root(), blkid, shard_top_blkid)) { - // try next mc block - ton::AccountIdPrefixFull pfx{ton::masterchainId, ton::shardIdAll}; - td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db, pfx, mc_block->block_id().id.seqno + 1, - [blkid, client_mc_blkid, limit, header_proof=std::move(header_proof), manager = manager_, Self = actor_id(this)](td::Result R) mutable { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), - [blkid, client_mc_blkid, limit, header_proof=std::move(header_proof), Self](td::Result> res) mutable { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - return; +void LiteQuery::continue_getZeroState(BlockIdExt blkid, td::BufferSlice state) { + LOG(INFO) << "obtained data for getZeroState(" << blkid.to_str() << ")"; + CHECK(!state.empty()); + auto b = ton::create_serialize_tl_object( + ton::create_tl_lite_block_id(blkid), blkid.root_hash, blkid.file_hash, std::move(state)); + finish_query(std::move(b)); +} + +void LiteQuery::perform_sendMessage(td::BufferSlice data) { + LOG(INFO) << "started a sendMessage(<" << data.size() << " bytes>) liteserver query"; + auto copy = data.clone(); + td::actor::send_closure_later( + manager_, &ValidatorManager::check_external_message, std::move(copy), + [Self = actor_id(this), data = std::move(data), manager = manager_](td::Result> res) mutable { + if(res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, + res.move_as_error_prefix("cannot apply external message to current state : "s)); + } else { + LOG(INFO) << "sending an external message to validator manager"; + td::actor::send_closure_later(manager, &ValidatorManager::send_external_message, res.move_as_ok()); + auto b = ton::create_serialize_tl_object(1); + td::actor::send_closure(Self, &LiteQuery::finish_query, std::move(b)); } - td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock, blkid, client_mc_blkid, - std::move(header_proof), res.move_as_ok(), limit - 1); }); - }); - return; - } - - auto mc_shard_proof_data = mpb.extract_proof_boc(); - if (mc_shard_proof_data.is_error()) { - fatal_error(mc_shard_proof_data.move_as_error()); - return; - } +} - continue_lookupBlockWithProof_getShardBlockData(blkid, client_mc_blkid, std::move(header_proof), mc_block->block_id(), mc_shard_proof_data.move_as_ok(), shard_top_blkid); +void LiteQuery::get_block_handle_checked(BlockIdExt blkid, td::Promise promise) { + auto P = td::PromiseCreator::lambda( + [promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(R.move_as_error()); + } else { + auto handle = R.move_as_ok(); + if (handle->is_applied()) { + promise.set_result(std::move(handle)); + } else { + promise.set_error(td::Status::Error(ErrorCode::notready, "block is not applied")); + } + } + }); + td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, blkid, false, std::move(P)); } -void LiteQuery::continue_lookupBlockWithProof_getShardBlockData(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, BlockIdExt shard_top_blkid) { - if (shard_top_blkid == blkid) { - td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, - std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::vector>()); - return; +bool LiteQuery::request_mc_block_data(BlockIdExt blkid) { + if (!blkid.is_masterchain() || !blkid.is_valid_full()) { + return fatal_error("reference block must belong to the masterchain"); } - get_block_handle_checked(shard_top_blkid, [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data), - manager = manager_, Self = actor_id(this)](td::Result R) mutable { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), - [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data)](td::Result> res) mutable { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - return; - } - td::actor::send_closure(Self, &LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks, blkid, client_mc_blkid, - std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::vector>(), res.move_as_ok()); - }); - }); + if (!cont_set_) { + return fatal_error("continuation not set"); + } + base_blk_id_ = blkid; + ++pending_; + td::actor::send_closure_later( + manager_, &ValidatorManager::get_block_data_from_db_short, blkid, + [Self = actor_id(this), blkid](td::Result> res) { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, + res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : ")); + } else { + td::actor::send_closure_later(Self, &LiteQuery::got_mc_block_data, blkid, res.move_as_ok()); + } + }); + return true; } -void LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, - std::vector> shard_prev_blocks_proofs, td::Ref shard_block_data) { - if (shard_block_data->block_id() == blkid) { - td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, - std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::move(shard_prev_blocks_proofs)); - return; +bool LiteQuery::request_mc_proof(BlockIdExt blkid, int mode) { + if (!blkid.is_masterchain() || !blkid.is_valid_full()) { + return fatal_error("reference block must belong to the masterchain"); } - auto block_root = shard_block_data->root_cell(); - vm::MerkleProofBuilder mpb{block_root}; - std::vector prev; - ton::BlockIdExt mc_ref_blkid; - bool after_split; - auto res = block::unpack_block_prev_blk_ext(block_root, shard_block_data->block_id(), prev, mc_ref_blkid, after_split); - if (res.is_error()) { - fatal_error(res.move_as_error()); - return; + if (!cont_set_) { + return fatal_error("continuation not set"); } - auto prev_blk_proof = mpb.extract_proof(); - if (prev_blk_proof.is_error()) { - fatal_error(prev_blk_proof.move_as_error()); - return; + if (mode) { + base_blk_id_alt_ = blkid; + } else { + base_blk_id_ = blkid; } - shard_prev_blocks_proofs.push_back(prev_blk_proof.move_as_ok()); - - for (const auto& prev_block : prev) { - get_block_handle_checked(prev_block, [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data), - shard_prev_blocks_proofs=std::move(shard_prev_blocks_proofs), manager = manager_, Self = actor_id(this)](td::Result R) mutable { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), - [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data), - shard_prev_blocks_proofs=std::move(shard_prev_blocks_proofs)](td::Result> res) mutable { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - return; - } - td::actor::send_closure(Self, &LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks, blkid, client_mc_blkid, std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::move(shard_prev_blocks_proofs), res.move_as_ok()); - }); - }); - } -} - -void LiteQuery::continue_lookupBlock_getClientMcBlockState(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, - std::vector> shard_prev_blocks_proofs) { - get_block_handle_checked(client_mc_blkid, [=, header_proof = std::move(header_proof), mc_shard_proof_data = std::move(mc_shard_proof_data), Self = actor_id(this), manager = manager_](td::Result R) mutable { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, R.move_as_ok(), - [=, header_proof = std::move(header_proof), mc_shard_proof_data = std::move(mc_shard_proof_data), - shard_prev_blocks_proofs = std::move(shard_prev_blocks_proofs)](td::Result> res) mutable { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - } else { - td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlock_getMcBlockPrev, blkid, client_mc_blkid, - std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), - std::move(shard_prev_blocks_proofs), res.move_as_ok()); - } - }); - }); -} - -void LiteQuery::continue_lookupBlock_getMcBlockPrev(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, - std::vector> shard_prev_blocks_proofs, Ref client_mc_state) { - auto mc_state_r = Ref(std::move(client_mc_state)); - vm::MerkleProofBuilder mpb{mc_state_r->root_cell()}; - - auto prev_blocks_dict = block::get_prev_blocks_dict(mpb.root()); - if (!prev_blocks_dict) { - fatal_error(td::Status::Error("cannot extract prev_blocks from mc state")); - return; - } - if (!block::check_old_mc_block_id(*prev_blocks_dict, mc_blkid)) { - fatal_error(td::Status::Error("client mc blkid is not in prev_blocks")); - return; - } - auto client_mc_blk_proof = mpb.extract_proof_boc(); - if (client_mc_blk_proof.is_error()) { - fatal_error(client_mc_blk_proof.move_as_error()); - return; - } - auto prev_block_proof = vm::std_boc_serialize_multi(std::move(shard_prev_blocks_proofs)); - if (prev_block_proof.is_error()) { - fatal_error(prev_block_proof.move_as_error()); - return; - } - // liteServer.lookupBlockResult id:tonNode.blockIdExt mode:# mc_block_proof:bytes shard_proof:bytes prev_block_proof:bytes header:bytes = liteServer.LookupBlockResult; - auto b = ton::create_serialize_tl_object(ton::create_tl_lite_block_id(blkid), - mode_, client_mc_blk_proof.move_as_ok(), std::move(mc_shard_proof_data), prev_block_proof.move_as_ok(), std::move(header_proof)); - finish_query(std::move(b)); -} - -void LiteQuery::continue_getBlockHeader(BlockIdExt blkid, int mode, Ref block) { - LOG(INFO) << "obtained data for getBlockHeader(" << blkid.to_str() << ", " << mode << ")"; - CHECK(block.not_null()); - CHECK(block->block_id() == blkid); - auto block_root = block->root_cell(); - if (block_root.is_null()) { - fatal_error("block has no valid root cell"); - return; - } - // create block header proof - RootHash rhash{block_root->get_hash().bits()}; - CHECK(rhash == blkid.root_hash); - vm::MerkleProofBuilder mpb{block_root}; - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(mpb.root(), blk) && tlb::unpack_cell(blk.info, info))) { - fatal_error("cannot unpack block header"); - return; - } - if (mode & 1) { - // with state_update - vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; - if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update - && upd_cs.size_ext() == 0x20228)) { - fatal_error("invalid Merkle update in block"); - return; - } - } - visit(info.master_ref); - visit(info.prev_ref); - visit(info.prev_vert_ref); - if (mode & 2) { - // with value flow - visit(blk.value_flow); - } - if (mode & 16) { - // with extra - block::gen::BlockExtra::Record extra; - if (!tlb::unpack_cell(blk.extra, extra)) { - fatal_error("cannot unpack BlockExtra in block"); - return; - } - if (blkid.is_masterchain()) { - auto mc_extra_root = extra.custom->prefetch_ref(); - block::gen::McBlockExtra::Record mc_extra; - if (!(mc_extra_root.not_null() && tlb::unpack_cell(std::move(mc_extra_root), mc_extra))) { - fatal_error("cannot unpack McBlockExtra in block"); - return; - } - if (mode & 32) { - // with ShardHashes - visit(mc_extra.shard_hashes); - } - if (mode & 64) { - // with PrevBlkSignatures - visit(mc_extra.r1.prev_blk_signatures); - } - } - } - auto proof_data = mpb.extract_proof_boc(); - if (proof_data.is_error()) { - fatal_error(proof_data.move_as_error()); - return; - } - // send answer - auto b = ton::create_serialize_tl_object(ton::create_tl_lite_block_id(blkid), - mode, proof_data.move_as_ok()); - finish_query(std::move(b)); -} - -void LiteQuery::perform_getState(BlockIdExt blkid) { - LOG(INFO) << "started a getState(" << blkid.to_str() << ") liteserver query"; - if (!blkid.is_valid_full()) { - fatal_error("invalid BlockIdExt"); - return; - } - if (blkid.id.seqno > 1000) { - fatal_error("cannot request total state: possibly too large"); - return; - } - get_block_handle_checked(blkid, [=, manager = manager_, Self = actor_id(this)](td::Result R) { - if (R.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); - return; - } - if (blkid.id.seqno) { - td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, R.move_as_ok(), - [=](td::Result> res) { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - } else { - td::actor::send_closure_later(Self, &LiteQuery::continue_getState, blkid, - res.move_as_ok()); - } - }); - } else { - td::actor::send_closure_later(manager, &ValidatorManager::get_zero_state, blkid, - [=](td::Result res) { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - } else { - td::actor::send_closure_later(Self, &LiteQuery::continue_getZeroState, blkid, - res.move_as_ok()); - } - }); - } - }); -} - -void LiteQuery::continue_getState(BlockIdExt blkid, Ref state) { - LOG(INFO) << "obtained data for getState(" << blkid.to_str() << ")"; - CHECK(state.not_null()); - auto res = state->serialize(); - if (res.is_error()) { - abort_query(res.move_as_error()); - return; - } - auto data = res.move_as_ok(); - FileHash file_hash; - td::sha256(data, file_hash.as_slice()); - auto b = ton::create_serialize_tl_object( - ton::create_tl_lite_block_id(blkid), state->root_hash(), file_hash, std::move(data)); - finish_query(std::move(b)); -} - -void LiteQuery::continue_getZeroState(BlockIdExt blkid, td::BufferSlice state) { - LOG(INFO) << "obtained data for getZeroState(" << blkid.to_str() << ")"; - CHECK(!state.empty()); - auto b = ton::create_serialize_tl_object( - ton::create_tl_lite_block_id(blkid), blkid.root_hash, blkid.file_hash, std::move(state)); - finish_query(std::move(b)); -} - -void LiteQuery::perform_sendMessage(td::BufferSlice data) { - LOG(INFO) << "started a sendMessage(<" << data.size() << " bytes>) liteserver query"; - auto copy = data.clone(); - td::actor::send_closure_later( - manager_, &ValidatorManager::check_external_message, std::move(copy), - [Self = actor_id(this), data = std::move(data), manager = manager_](td::Result> res) mutable { - if(res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, - res.move_as_error_prefix("cannot apply external message to current state : "s)); - } else { - LOG(INFO) << "sending an external message to validator manager"; - td::actor::send_closure_later(manager, &ValidatorManager::send_external_message, res.move_as_ok()); - auto b = ton::create_serialize_tl_object(1); - td::actor::send_closure(Self, &LiteQuery::finish_query, std::move(b)); - } - }); -} - -void LiteQuery::get_block_handle_checked(BlockIdExt blkid, td::Promise promise) { - auto P = td::PromiseCreator::lambda( - [promise = std::move(promise)](td::Result R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - } else { - auto handle = R.move_as_ok(); - if (handle->is_applied()) { - promise.set_result(std::move(handle)); - } else { - promise.set_error(td::Status::Error(ErrorCode::notready, "block is not applied")); - } - } - }); - td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, blkid, false, std::move(P)); -} - -bool LiteQuery::request_mc_block_data(BlockIdExt blkid) { - if (!blkid.is_masterchain() || !blkid.is_valid_full()) { - return fatal_error("reference block must belong to the masterchain"); - } - if (!cont_set_) { - return fatal_error("continuation not set"); - } - base_blk_id_ = blkid; - ++pending_; - td::actor::send_closure_later( - manager_, &ValidatorManager::get_block_data_from_db_short, blkid, - [Self = actor_id(this), blkid](td::Result> res) { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, - res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : ")); - } else { - td::actor::send_closure_later(Self, &LiteQuery::got_mc_block_data, blkid, res.move_as_ok()); - } - }); - return true; -} - -bool LiteQuery::request_mc_proof(BlockIdExt blkid, int mode) { - if (!blkid.is_masterchain() || !blkid.is_valid_full()) { - return fatal_error("reference block must belong to the masterchain"); - } - if (!cont_set_) { - return fatal_error("continuation not set"); - } - if (mode) { - base_blk_id_alt_ = blkid; - } else { - base_blk_id_ = blkid; - } - ++pending_; - td::actor::send_closure( - manager_, &ValidatorManager::get_key_block_proof, blkid, - [Self = actor_id(this), manager = manager_, blkid, mode](td::Result R) { - if (R.is_ok()) { - auto proof = create_proof(blkid, R.move_as_ok()); - proof.ensure(); - td::actor::send_closure_later(Self, &LiteQuery::got_mc_block_proof, blkid, mode, proof.move_as_ok()); + ++pending_; + td::actor::send_closure( + manager_, &ValidatorManager::get_key_block_proof, blkid, + [Self = actor_id(this), manager = manager_, blkid, mode](td::Result R) { + if (R.is_ok()) { + auto proof = create_proof(blkid, R.move_as_ok()); + proof.ensure(); + td::actor::send_closure_later(Self, &LiteQuery::got_mc_block_proof, blkid, mode, proof.move_as_ok()); return; } td::actor::send_closure_later( @@ -2129,119 +1845,400 @@ void LiteQuery::continue_getShardInfo(ShardIdFull shard, bool exact) { if (!make_shard_info_proof(proof2, shard_info, shard, true_shard, leaf, found, exact)) { return; } - auto proof = vm::std_boc_serialize_multi({std::move(proof1), std::move(proof2)}); - if (proof.is_error()) { - fatal_error(proof.move_as_error()); + auto proof = vm::std_boc_serialize_multi({std::move(proof1), std::move(proof2)}); + if (proof.is_error()) { + fatal_error(proof.move_as_error()); + return; + } + BlockIdExt true_id; + td::BufferSlice data; + if (found) { + if (shard_info.is_null()) { + fatal_error("cannot unpack a leaf entry from ShardHashes"); + return; + } + true_id = shard_info->top_block_id(); + auto res = vm::std_boc_serialize(std::move(leaf)); + if (res.is_error()) { + fatal_error(res.move_as_error()); + return; + } + data = res.move_as_ok(); + } else { + true_id.invalidate_clear(); + } + LOG(INFO) << "getShardInfo() query completed"; + auto b = ton::create_serialize_tl_object( + ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(true_id), proof.move_as_ok(), + std::move(data)); + finish_query(std::move(b)); +} + +void LiteQuery::continue_getAllShardsInfo() { + LOG(INFO) << "completing getAllShardsInfo() query"; + vm::MerkleProofBuilder mpb{mc_block_->root_cell()}; + block::gen::Block::Record blk; + block::gen::BlockExtra::Record extra; + block::gen::McBlockExtra::Record mc_extra; + if (!tlb::unpack_cell(mpb.root(), blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() || + !tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra)) { + fatal_error("cannot unpack header of block "s + mc_block_->block_id().to_str()); + return; + } + vm::Dictionary shards_dict(std::move(mc_extra.shard_hashes), 32); + Ref proof; + if (!mpb.extract_proof_to(proof)) { + fatal_error("cannot construct Merkle proof for all shards dictionary"); + return; + } + auto proof_boc = vm::std_boc_serialize(std::move(proof)); + if (proof_boc.is_error()) { + fatal_error(proof_boc.move_as_error()); + return; + } + vm::CellBuilder cb; + Ref cell; + if (!(shards_dict.append_dict_to_bool(cb) && cb.finalize_to(cell))) { + fatal_error("cannot store ShardHashes from last mc block into a new cell"); + return; + } + auto data = vm::std_boc_serialize(std::move(cell)); + if (data.is_error()) { + fatal_error(data.move_as_error()); + return; + } + LOG(INFO) << "getAllShardInfo() query completed"; + auto b = ton::create_serialize_tl_object( + ton::create_tl_lite_block_id(base_blk_id_), proof_boc.move_as_ok(), data.move_as_ok()); + finish_query(std::move(b)); +} + +void LiteQuery::perform_lookupBlockWithProof(BlockId blkid, BlockIdExt mc_blkid, int mode, LogicalTime lt, UnixTime utime) { + if (!((1 << (mode & 7)) & 0x16)) { + fatal_error("exactly one of mode.0, mode.1 and mode.2 bits must be set"); + return; + } + if (!(mode & 2)) { + lt = 0; + } + if (!(mode & 4)) { + utime = 0; + } + mode_ = mode; + LOG(INFO) << "started a lookupBlockWithProof(" << blkid.to_str() << ", " << mc_blkid.to_str() << ", " << mode << ", " + << lt << ", " << utime << ") liteserver query"; + auto P = td::PromiseCreator::lambda( + [Self = actor_id(this), mc_blkid, manager = manager_, mode = (mode >> 4)](td::Result res) { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + } else { + auto handle = res.move_as_ok(); + if (!handle->is_applied()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error(ErrorCode::notready, "block is not applied")); + return; + } + LOG(DEBUG) << "requesting data for block " << handle->id().to_str(); + td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, handle, + [Self, blkid = handle->id(), mc_blkid, mode](td::Result> res) { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + } else { + td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlockWithProof_getHeaderProof, + blkid, mc_blkid, mode, res.move_as_ok()); + } + }); + } + }); + + ton::AccountIdPrefixFull pfx{blkid.workchain, blkid.shard}; + if (mode & 2) { + td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_lt_from_db, pfx, lt, std::move(P)); + } else if (mode & 4) { + td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_unix_time_from_db, pfx, utime, std::move(P)); + } else { + td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db, pfx, blkid.seqno, std::move(P)); + } +} + +void LiteQuery::continue_lookupBlockWithProof_getHeaderProof(BlockIdExt blkid, BlockIdExt client_mc_blkid, int mode, Ref block) { + LOG(INFO) << "obtained data for getBlockHeader(" << blkid.to_str() << ", " << mode << ")"; + CHECK(block.not_null()); + CHECK(block->block_id() == blkid); + auto block_root = block->root_cell(); + if (block_root.is_null()) { + fatal_error("block has no valid root cell"); + return; + } + // create block header proof + RootHash rhash{block_root->get_hash().bits()}; + CHECK(rhash == blkid.root_hash); + vm::MerkleProofBuilder mpb{block_root}; + block::gen::Block::Record blk; + block::gen::BlockInfo::Record info; + if (!(tlb::unpack_cell(mpb.root(), blk) && tlb::unpack_cell(blk.info, info))) { + fatal_error("cannot unpack block header"); + return; + } + if (mode & 1) { + // with state_update + vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; + if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update + && upd_cs.size_ext() == 0x20228)) { + fatal_error("invalid Merkle update in block"); + return; + } + } + visit(info.master_ref); + visit(info.prev_ref); + visit(info.prev_vert_ref); + if (mode & 2) { + // with value flow + visit(blk.value_flow); + } + if (mode & 16) { + // with extra + block::gen::BlockExtra::Record extra; + if (!tlb::unpack_cell(blk.extra, extra)) { + fatal_error("cannot unpack BlockExtra in block"); + return; + } + if (blkid.is_masterchain()) { + auto mc_extra_root = extra.custom->prefetch_ref(); + block::gen::McBlockExtra::Record mc_extra; + if (!(mc_extra_root.not_null() && tlb::unpack_cell(std::move(mc_extra_root), mc_extra))) { + fatal_error("cannot unpack McBlockExtra in block"); + return; + } + if (mode & 32) { + // with ShardHashes + visit(mc_extra.shard_hashes); + } + if (mode & 64) { + // with PrevBlkSignatures + visit(mc_extra.r1.prev_blk_signatures); + } + } + } + auto proof_data = mpb.extract_proof_boc(); + if (proof_data.is_error()) { + fatal_error(proof_data.move_as_error()); return; } - BlockIdExt true_id; - td::BufferSlice data; - if (found) { - if (shard_info.is_null()) { - fatal_error("cannot unpack a leaf entry from ShardHashes"); - return; - } - true_id = shard_info->top_block_id(); - auto res = vm::std_boc_serialize(std::move(leaf)); - if (res.is_error()) { - fatal_error(res.move_as_error()); + + if (!blkid.is_masterchain()) { + block::gen::ExtBlkRef::Record mcref; + if (!tlb::unpack_cell(info.master_ref, mcref)) { + fatal_error("cannot unpack masterchain block reference"); return; } - data = res.move_as_ok(); + ton::BlockIdExt mc_ref_blkid{ton::masterchainId, ton::shardIdAll, mcref.seq_no, mcref.root_hash, mcref.file_hash}; + + get_block_handle_checked(mc_ref_blkid, [blkid, client_mc_blkid, header_proof=proof_data.move_as_ok(), manager = manager_, Self = actor_id(this)](td::Result R) mutable { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); + return; + } + td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), + [blkid, client_mc_blkid, header_proof=std::move(header_proof), Self](td::Result> res) mutable { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + return; + } + td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock, blkid, client_mc_blkid, + std::move(header_proof), res.move_as_ok(), 10); + }); + }); } else { - true_id.invalidate_clear(); + td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, + proof_data.move_as_ok(), blkid, td::BufferSlice(), std::vector>()); + return; } - LOG(INFO) << "getShardInfo() query completed"; - auto b = ton::create_serialize_tl_object( - ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(true_id), proof.move_as_ok(), - std::move(data)); - finish_query(std::move(b)); } -void LiteQuery::continue_getAllShardsInfo() { - LOG(INFO) << "completing getAllShardsInfo() query"; - vm::MerkleProofBuilder mpb{mc_block_->root_cell()}; +bool LiteQuery::check_mc_block_contains_shard_block(td::Ref mcref_block_data, BlockIdExt blkid, BlockIdExt& shard_top_blkid) { block::gen::Block::Record blk; block::gen::BlockExtra::Record extra; block::gen::McBlockExtra::Record mc_extra; - if (!tlb::unpack_cell(mpb.root(), blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() || + if (!tlb::unpack_cell(mcref_block_data, blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() || !tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra)) { fatal_error("cannot unpack header of block "s + mc_block_->block_id().to_str()); - return; + return false; } vm::Dictionary shards_dict(std::move(mc_extra.shard_hashes), 32); - Ref proof; - if (!mpb.extract_proof_to(proof)) { - fatal_error("cannot construct Merkle proof for all shards dictionary"); + + vm::CellSlice cs; + ton::ShardIdFull true_shard; + // Here I assume that eventually mc block contains exact shard hash for the requested block. TODO: check if it's true for all cases + // e.g. can it be that shard split and merge happen between consequent mc blocks? + bool found = block::ShardConfig::get_shard_hash_raw_from(shards_dict, cs, blkid.shard_full(), true_shard, true, nullptr); + if (found) { + auto info = block::McShardHash::unpack(cs, true_shard); + if (info.is_null()) { + return false; + } + if (info->top_block_id().id.seqno < blkid.id.seqno) { + return false; + } + shard_top_blkid = info->top_block_id(); + return true; + } + return false; +} + +void LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, td::Ref mc_block_data, int limit) { + if (!limit) { + fatal_error("checked 10 blocks after block.mcref and couldn't find shard block"); return; } - auto proof_boc = vm::std_boc_serialize(std::move(proof)); - if (proof_boc.is_error()) { - fatal_error(proof_boc.move_as_error()); + + auto mc_block = Ref(std::move(mc_block_data)); + vm::MerkleProofBuilder mpb{mc_block->root_cell()}; + BlockIdExt shard_top_blkid; + if (!check_mc_block_contains_shard_block(mpb.root(), blkid, shard_top_blkid)) { + // try next mc block + ton::AccountIdPrefixFull pfx{ton::masterchainId, ton::shardIdAll}; + td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db, pfx, mc_block->block_id().id.seqno + 1, + [blkid, client_mc_blkid, limit, header_proof=std::move(header_proof), manager = manager_, Self = actor_id(this)](td::Result R) mutable { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); + return; + } + td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), + [blkid, client_mc_blkid, limit, header_proof=std::move(header_proof), Self](td::Result> res) mutable { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + return; + } + td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_findContainingMcBlock, blkid, client_mc_blkid, + std::move(header_proof), res.move_as_ok(), limit - 1); + }); + }); return; } - vm::CellBuilder cb; - Ref cell; - if (!(shards_dict.append_dict_to_bool(cb) && cb.finalize_to(cell))) { - fatal_error("cannot store ShardHashes from last mc block into a new cell"); + + auto mc_shard_proof_data = mpb.extract_proof_boc(); + if (mc_shard_proof_data.is_error()) { + fatal_error(mc_shard_proof_data.move_as_error()); return; } - auto data = vm::std_boc_serialize(std::move(cell)); - if (data.is_error()) { - fatal_error(data.move_as_error()); + + if (shard_top_blkid == blkid) { + td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, + std::move(header_proof), mc_block->block_id(), mc_shard_proof_data.move_as_ok(), std::vector>()); return; } - LOG(INFO) << "getAllShardInfo() query completed"; - auto b = ton::create_serialize_tl_object( - ton::create_tl_lite_block_id(base_blk_id_), proof_boc.move_as_ok(), data.move_as_ok()); - finish_query(std::move(b)); + + get_block_handle_checked(shard_top_blkid, [=, header_proof=std::move(header_proof), mc_shard_proof_data=mc_shard_proof_data.move_as_ok(), + manager = manager_, Self = actor_id(this)](td::Result R) mutable { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); + return; + } + td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), + [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data)](td::Result> res) mutable { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + return; + } + td::actor::send_closure(Self, &LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks, blkid, client_mc_blkid, + std::move(header_proof), mc_block->block_id(), std::move(mc_shard_proof_data), std::vector>(), res.move_as_ok()); + }); + }); } -void LiteQuery::perform_lookupBlockWithProof(BlockId blkid, BlockIdExt mc_blkid, int mode, LogicalTime lt, UnixTime utime) { - if (!((1 << (mode & 7)) & 0x16)) { - fatal_error("exactly one of mode.0, mode.1 and mode.2 bits must be set"); +void LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, + std::vector> shard_prev_blocks_proofs, td::Ref shard_block_data) { + if (shard_block_data->block_id() == blkid) { + td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlock_getClientMcBlockState, blkid, client_mc_blkid, + std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::move(shard_prev_blocks_proofs)); return; } - if (!(mode & 2)) { - lt = 0; + auto block_root = shard_block_data->root_cell(); + vm::MerkleProofBuilder mpb{block_root}; + std::vector prev; + ton::BlockIdExt mc_ref_blkid; + bool after_split; + auto res = block::unpack_block_prev_blk_ext(block_root, shard_block_data->block_id(), prev, mc_ref_blkid, after_split); + if (res.is_error()) { + fatal_error(res.move_as_error()); + return; } - if (!(mode & 4)) { - utime = 0; + auto prev_blk_proof = mpb.extract_proof(); + if (prev_blk_proof.is_error()) { + fatal_error(prev_blk_proof.move_as_error()); + return; } - mode_ = mode; - LOG(INFO) << "started a lookupBlockWithProof(" << blkid.to_str() << ", " << mc_blkid.to_str() << ", " << mode << ", " - << lt << ", " << utime << ") liteserver query"; - auto P = td::PromiseCreator::lambda( - [Self = actor_id(this), mc_blkid, manager = manager_, mode = (mode >> 4)](td::Result res) { - if (res.is_error()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - } else { - auto handle = res.move_as_ok(); - if (!handle->is_applied()) { - td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error(ErrorCode::notready, "block is not applied")); + shard_prev_blocks_proofs.push_back(prev_blk_proof.move_as_ok()); + + for (const auto& prev_block : prev) { + get_block_handle_checked(prev_block, [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data), + shard_prev_blocks_proofs=std::move(shard_prev_blocks_proofs), manager = manager_, Self = actor_id(this)](td::Result R) mutable { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); return; } - LOG(DEBUG) << "requesting data for block " << handle->id().to_str(); - td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, handle, - [Self, blkid = handle->id(), mc_blkid, mode](td::Result> res) { + td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(), + [=, header_proof=std::move(header_proof), mc_shard_proof_data=std::move(mc_shard_proof_data), + shard_prev_blocks_proofs=std::move(shard_prev_blocks_proofs)](td::Result> res) mutable { if (res.is_error()) { td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); - } else { - td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlockWithProof_getHeaderProof, - blkid, mc_blkid, mode, res.move_as_ok()); + return; } + td::actor::send_closure(Self, &LiteQuery::continue_lookupBlock_findTargetBlockInShardPrevBlocks, blkid, client_mc_blkid, std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), std::move(shard_prev_blocks_proofs), res.move_as_ok()); }); + }); + } +} + +void LiteQuery::continue_lookupBlock_getClientMcBlockState(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, + std::vector> shard_prev_blocks_proofs) { + get_block_handle_checked(client_mc_blkid, [=, header_proof = std::move(header_proof), mc_shard_proof_data = std::move(mc_shard_proof_data), Self = actor_id(this), manager = manager_](td::Result R) mutable { + if (R.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error()); + return; + } + td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, R.move_as_ok(), + [=, header_proof = std::move(header_proof), mc_shard_proof_data = std::move(mc_shard_proof_data), + shard_prev_blocks_proofs = std::move(shard_prev_blocks_proofs)](td::Result> res) mutable { + if (res.is_error()) { + td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error()); + } else { + td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlock_getMcBlockPrev, blkid, client_mc_blkid, + std::move(header_proof), mc_blkid, std::move(mc_shard_proof_data), + std::move(shard_prev_blocks_proofs), res.move_as_ok()); } + }); }); +} - ton::AccountIdPrefixFull pfx{blkid.workchain, blkid.shard}; - if (mode & 2) { - td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_lt_from_db, pfx, lt, std::move(P)); - } else if (mode & 4) { - td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_unix_time_from_db, pfx, utime, std::move(P)); - } else { - td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db, pfx, blkid.seqno, std::move(P)); +void LiteQuery::continue_lookupBlock_getMcBlockPrev(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, + std::vector> shard_prev_blocks_proofs, Ref client_mc_state) { + auto mc_state_r = Ref(std::move(client_mc_state)); + vm::MerkleProofBuilder mpb{mc_state_r->root_cell()}; + + auto prev_blocks_dict = block::get_prev_blocks_dict(mpb.root()); + if (!prev_blocks_dict) { + fatal_error(td::Status::Error("cannot extract prev_blocks from mc state")); + return; + } + if (!block::check_old_mc_block_id(*prev_blocks_dict, mc_blkid)) { + fatal_error(td::Status::Error("client mc blkid is not in prev_blocks")); + return; + } + auto client_mc_blk_proof = mpb.extract_proof_boc(); + if (client_mc_blk_proof.is_error()) { + fatal_error(client_mc_blk_proof.move_as_error()); + return; + } + auto prev_block_proof = vm::std_boc_serialize_multi(std::move(shard_prev_blocks_proofs)); + if (prev_block_proof.is_error()) { + fatal_error(prev_block_proof.move_as_error()); + return; } + + auto b = ton::create_serialize_tl_object(ton::create_tl_lite_block_id(blkid), + mode_, client_mc_blk_proof.move_as_ok(), std::move(mc_shard_proof_data), prev_block_proof.move_as_ok(), std::move(header_proof)); + finish_query(std::move(b)); } void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime) { diff --git a/validator/impl/liteserver.hpp b/validator/impl/liteserver.hpp index 38df8009c..ddd2e1535 100644 --- a/validator/impl/liteserver.hpp +++ b/validator/impl/liteserver.hpp @@ -136,7 +136,6 @@ class LiteQuery : public td::actor::Actor { void perform_lookupBlockWithProof(BlockId blkid, BlockIdExt client_mc_blkid, int mode, LogicalTime lt, UnixTime utime); void continue_lookupBlockWithProof_getHeaderProof(BlockIdExt blkid, BlockIdExt client_mc_blkid, int mode, Ref block); void continue_lookupBlockWithProof_findContainingMcBlock(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, td::Ref mc_block_data, int limit); - void continue_lookupBlockWithProof_getShardBlockData(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, BlockIdExt shard_top_blkid); void continue_lookupBlock_findTargetBlockInShardPrevBlocks(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data, std::vector> prev_blocks_proofs, td::Ref shard_block_data); bool check_mc_block_contains_shard_block(td::Ref mcref_block_data, BlockIdExt blkid, BlockIdExt& shard_top_blkid); void continue_lookupBlock_getClientMcBlockState(BlockIdExt blkid, BlockIdExt client_mc_blkid, td::BufferSlice header_proof, BlockIdExt mc_blkid, td::BufferSlice mc_shard_proof_data,