mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Tonlib method getShardBlockProof (#465)
* Tonlib method getShardBlockProof * Clarify limit of result.size() in getShardBlockProof
This commit is contained in:
parent
9c6787d2ff
commit
2512f0287b
8 changed files with 337 additions and 0 deletions
|
@ -201,6 +201,9 @@ void LiteQuery::start_up() {
|
|||
[&](lite_api::liteServer_getLibraries& q) {
|
||||
this->perform_getLibraries(q.library_list_);
|
||||
},
|
||||
[&](lite_api::liteServer_getShardBlockProof& q) {
|
||||
this->perform_getShardBlockProof(create_block_id(q.id_));
|
||||
},
|
||||
[&](auto& obj) { this->abort_query(td::Status::Error(ErrorCode::protoviolation, "unknown query")); }));
|
||||
}
|
||||
|
||||
|
@ -2432,5 +2435,135 @@ void LiteQuery::continue_getValidatorStats(int mode, int limit, Bits256 start_af
|
|||
finish_query(std::move(b));
|
||||
}
|
||||
|
||||
void LiteQuery::perform_getShardBlockProof(BlockIdExt blkid) {
|
||||
LOG(INFO) << "started a getMasterchainInfo(" << blkid.to_str() << ") liteserver query";
|
||||
if (!blkid.is_valid_ext()) {
|
||||
fatal_error("invalid block id");
|
||||
return;
|
||||
}
|
||||
if (blkid.is_masterchain()) {
|
||||
LOG(INFO) << "getShardBlockProof() query completed";
|
||||
auto b = create_serialize_tl_object<lite_api::liteServer_shardBlockProof>(
|
||||
create_tl_lite_block_id(blkid), std::vector<tl_object_ptr<lite_api::liteServer_shardBlockLink>>());
|
||||
finish_query(std::move(b));
|
||||
return;
|
||||
}
|
||||
blk_id_ = blkid;
|
||||
get_block_handle_checked(blkid, [manager = manager_, Self = actor_id(this)](td::Result<ConstBlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||
return;
|
||||
}
|
||||
ConstBlockHandle handle = R.move_as_ok();
|
||||
if (!handle->inited_masterchain_ref_block()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error("block doesn't have masterchain ref"));
|
||||
return;
|
||||
}
|
||||
AccountIdPrefixFull pfx{masterchainId, shardIdAll};
|
||||
td::actor::send_closure_later(
|
||||
manager, &ValidatorManager::get_block_by_seqno_from_db, pfx, handle->masterchain_ref_block(),
|
||||
[Self, manager](td::Result<ConstBlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||
} else {
|
||||
ConstBlockHandle handle = R.move_as_ok();
|
||||
td::actor::send_closure_later(
|
||||
manager, &ValidatorManager::get_block_data_from_db, handle, [Self](td::Result<Ref<BlockData>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getShardBlockProof, R.move_as_ok(),
|
||||
std::vector<std::pair<BlockIdExt, td::BufferSlice>>());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void LiteQuery::continue_getShardBlockProof(Ref<BlockData> cur_block,
|
||||
std::vector<std::pair<BlockIdExt, td::BufferSlice>> result) {
|
||||
BlockIdExt cur_id = cur_block->block_id();
|
||||
BlockIdExt prev_id;
|
||||
vm::MerkleProofBuilder mpb{cur_block->root_cell()};
|
||||
if (cur_id.is_masterchain()) {
|
||||
base_blk_id_ = cur_id;
|
||||
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 + cur_id.to_str());
|
||||
return;
|
||||
}
|
||||
block::ShardConfig shards(mc_extra.shard_hashes->prefetch_ref());
|
||||
ShardIdFull shard_id = blk_id_.shard_full();
|
||||
shard_id.shard = (shard_id.shard & ~(1 << (63 - shard_id.pfx_len()))) | 1;
|
||||
Ref<block::McShardHash> shard_hash = shards.get_shard_hash(shard_id, false);
|
||||
if (shard_hash.is_null()) {
|
||||
fatal_error("shard not found");
|
||||
return;
|
||||
}
|
||||
prev_id = shard_hash->top_block_id();
|
||||
} else {
|
||||
std::vector<BlockIdExt> prev;
|
||||
BlockIdExt mc_blkid;
|
||||
bool after_split;
|
||||
td::Status S = block::unpack_block_prev_blk_try(mpb.root(), cur_id, prev, mc_blkid, after_split);
|
||||
if (S.is_error()) {
|
||||
fatal_error(std::move(S));
|
||||
return;
|
||||
}
|
||||
bool found = false;
|
||||
for (const BlockIdExt& id : prev) {
|
||||
if (shard_intersects(id.shard_full(), blk_id_.shard_full())) {
|
||||
found = true;
|
||||
prev_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fatal_error("failed to find block chain");
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto proof = mpb.extract_proof_boc();
|
||||
if (proof.is_error()) {
|
||||
fatal_error(proof.move_as_error_prefix("cannot serialize Merkle proof : "));
|
||||
return;
|
||||
}
|
||||
result.emplace_back(prev_id, proof.move_as_ok());
|
||||
|
||||
if (prev_id == blk_id_) {
|
||||
CHECK(base_blk_id_.is_masterchain());
|
||||
std::vector<tl_object_ptr<lite_api::liteServer_shardBlockLink>> links;
|
||||
for (auto& p : result) {
|
||||
links.push_back(
|
||||
create_tl_object<lite_api::liteServer_shardBlockLink>(create_tl_lite_block_id(p.first), std::move(p.second)));
|
||||
}
|
||||
LOG(INFO) << "getShardBlockProof() query completed";
|
||||
auto b = create_serialize_tl_object<lite_api::liteServer_shardBlockProof>(create_tl_lite_block_id(base_blk_id_),
|
||||
std::move(links));
|
||||
finish_query(std::move(b));
|
||||
return;
|
||||
}
|
||||
if (result.size() == 8) {
|
||||
// Chains of shardblocks between masterchain blocks can't be longer than 8 (see collator.cpp:991)
|
||||
fatal_error("proof chain is too long");
|
||||
return;
|
||||
}
|
||||
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, prev_id,
|
||||
[Self = actor_id(this), result = std::move(result)](td::Result<Ref<BlockData>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getShardBlockProof, R.move_as_ok(),
|
||||
std::move(result));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
} // namespace ton
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue