mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-15 04:32:21 +00:00
Out msg queue proof: send only the required part
This commit is contained in:
parent
597fd8443d
commit
81d32ba5d6
2 changed files with 68 additions and 11 deletions
|
@ -852,6 +852,10 @@ void FullNodeShardImpl::download_out_msg_queue_proof(BlockIdExt block_id, ShardI
|
|||
// TODO: maybe more complex download (like other requests here)
|
||||
// TODO: estimate max size
|
||||
auto &b = choose_neighbour(true);
|
||||
if (b.adnl_id == adnl::AdnlNodeIdShort::zero()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "no nodes"));
|
||||
return;
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[=, promise = create_neighbour_promise(b, std::move(promise), true)](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "vm/cells/MerkleProof.h"
|
||||
#include "common/delay.h"
|
||||
#include "interfaces/validator-manager.h"
|
||||
#include "block/block-parse.h"
|
||||
#include "block/block-auto.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -51,9 +53,31 @@ td::Result<td::Ref<OutMsgQueueProof>> OutMsgQueueProof::fetch(BlockIdExt block_i
|
|||
// Validate proof
|
||||
auto state_root = vm::CellSlice(vm::NoVm(), queue_proof).prefetch_ref(0);
|
||||
TRY_RESULT_PREFIX(state, ShardStateQ::fetch(block_id, {}, state_root), "invalid proof: ");
|
||||
TRY_RESULT_PREFIX(queue, state->message_queue(), "invalid proof: ");
|
||||
auto queue_root = queue->root_cell();
|
||||
if (queue_root->get_level() != 0) {
|
||||
TRY_RESULT_PREFIX(outq_descr, state->message_queue(), "invalid proof: ");
|
||||
|
||||
block::gen::OutMsgQueueInfo::Record qinfo;
|
||||
if (!tlb::unpack_cell(outq_descr->root_cell(), qinfo)) {
|
||||
return td::Status::Error("invalid proof: invalid message queue");
|
||||
}
|
||||
td::Ref<vm::Cell> proc_info = qinfo.proc_info->prefetch_ref(0);
|
||||
if (proc_info.not_null() && proc_info->get_level() != 0) {
|
||||
return td::Status::Error("invalid proof: proc_info has prunned branches");
|
||||
}
|
||||
td::Ref<vm::Cell> ihr_pending = qinfo.ihr_pending->prefetch_ref(0);
|
||||
if (ihr_pending.not_null() && ihr_pending->get_level() != 0) {
|
||||
return td::Status::Error("invalid proof: ihr_pending has prunned branches");
|
||||
}
|
||||
auto queue =
|
||||
std::make_unique<vm::AugmentedDictionary>(qinfo.out_queue->prefetch_ref(0), 352, block::tlb::aug_OutMsgQueue);
|
||||
td::BitArray<96> prefix;
|
||||
td::BitPtr ptr = prefix.bits();
|
||||
ptr.store_int(dst_shard.workchain, 32);
|
||||
ptr.advance(32);
|
||||
ptr.store_uint(dst_shard.shard, 64);
|
||||
if (!queue->cut_prefix_subdict(prefix.bits(), 32 + dst_shard.pfx_len())) {
|
||||
return td::Status::Error("invalid proof: failed to cut queue dict");
|
||||
}
|
||||
if (queue->get_root_cell().not_null() && queue->get_root_cell()->get_level() != 0) {
|
||||
return td::Status::Error("invalid proof: msg queue has prunned branches");
|
||||
}
|
||||
|
||||
|
@ -64,14 +88,20 @@ td::Result<tl_object_ptr<ton_api::tonNode_outMsgQueueProof>> OutMsgQueueProof::s
|
|||
ShardIdFull dst_shard,
|
||||
Ref<vm::Cell> state_root,
|
||||
Ref<vm::Cell> block_root) {
|
||||
if (!dst_shard.is_valid_ext()) {
|
||||
return td::Status::Error("invalid shard");
|
||||
}
|
||||
vm::MerkleProofBuilder mpb{std::move(state_root)};
|
||||
TRY_RESULT(state, ShardStateQ::fetch(block_id, {}, mpb.root()));
|
||||
TRY_RESULT(outq_descr, state->message_queue());
|
||||
block::gen::OutMsgQueueInfo::Record qinfo;
|
||||
if (!tlb::unpack_cell(outq_descr->root_cell(), qinfo)) {
|
||||
return td::Status::Error("invalid message queue");
|
||||
}
|
||||
|
||||
// TODO: add only required part of msg queue
|
||||
td::HashSet<vm::Cell::Hash> visited;
|
||||
std::function<void(Ref<vm::Cell>)> dfs = [&](Ref<vm::Cell> cell) {
|
||||
if (!visited.insert(cell->get_hash()).second) {
|
||||
if (cell.is_null() || !visited.insert(cell->get_hash()).second) {
|
||||
return;
|
||||
}
|
||||
vm::CellSlice cs(vm::NoVm(), cell);
|
||||
|
@ -79,16 +109,32 @@ td::Result<tl_object_ptr<ton_api::tonNode_outMsgQueueProof>> OutMsgQueueProof::s
|
|||
dfs(cs.prefetch_ref(i));
|
||||
}
|
||||
};
|
||||
dfs(outq_descr->root_cell());
|
||||
auto dfs_cs = [&](const vm::CellSlice &cs) {
|
||||
for (unsigned i = 0; i < cs.size_refs(); i++) {
|
||||
dfs(cs.prefetch_ref(i));
|
||||
}
|
||||
};
|
||||
dfs_cs(*qinfo.proc_info);
|
||||
dfs_cs(*qinfo.ihr_pending);
|
||||
|
||||
auto queue =
|
||||
std::make_unique<vm::AugmentedDictionary>(qinfo.out_queue->prefetch_ref(0), 352, block::tlb::aug_OutMsgQueue);
|
||||
td::BitArray<96> prefix;
|
||||
td::BitPtr ptr = prefix.bits();
|
||||
ptr.store_int(dst_shard.workchain, 32);
|
||||
ptr.advance(32);
|
||||
ptr.store_uint(dst_shard.shard, 64);
|
||||
if (!queue->cut_prefix_subdict(prefix.bits(), 32 + dst_shard.pfx_len())) {
|
||||
return td::Status::Error("invalid message queue");
|
||||
}
|
||||
dfs(queue->get_root_cell());
|
||||
|
||||
TRY_RESULT(queue_proof, vm::std_boc_serialize(mpb.extract_proof()));
|
||||
|
||||
td::BufferSlice block_state_proof;
|
||||
if (block_id.seqno() != 0) {
|
||||
TRY_RESULT(proof, create_block_state_proof(std::move(block_root)));
|
||||
TRY_RESULT_ASSIGN(block_state_proof, vm::std_boc_serialize(std::move(proof), 31));
|
||||
}
|
||||
|
||||
return create_tl_object<ton_api::tonNode_outMsgQueueProof>(std::move(queue_proof), std::move(block_state_proof));
|
||||
}
|
||||
|
||||
|
@ -183,7 +229,11 @@ void WaitOutMsgQueueProof::run_net() {
|
|||
auto P =
|
||||
td::PromiseCreator::lambda([SelfId = actor_id(this), block_id = block_id_](td::Result<Ref<OutMsgQueueProof>> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(DEBUG) << "failed to get msg queue for " << block_id.to_str() << " from net: " << R.move_as_error();
|
||||
if (R.error().code() == ErrorCode::notready) {
|
||||
LOG(DEBUG) << "failed to get msg queue for " << block_id.to_str() << " from net: " << R.move_as_error();
|
||||
} else {
|
||||
LOG(WARNING) << "failed to get msg queue for " << block_id.to_str() << " from net: " << R.move_as_error();
|
||||
}
|
||||
delay_action([SelfId]() mutable { td::actor::send_closure(SelfId, &WaitOutMsgQueueProof::run_net); },
|
||||
td::Timestamp::in(0.1));
|
||||
} else {
|
||||
|
@ -246,8 +296,11 @@ void BuildOutMsgQueueProof::got_block_root(Ref<vm::Cell> root) {
|
|||
}
|
||||
|
||||
void BuildOutMsgQueueProof::build_proof() {
|
||||
promise_.set_result(
|
||||
OutMsgQueueProof::serialize(block_id_, dst_shard_, std::move(state_root_), std::move(block_root_)));
|
||||
auto result = OutMsgQueueProof::serialize(block_id_, dst_shard_, std::move(state_root_), std::move(block_root_));
|
||||
if (result.is_error()) {
|
||||
LOG(ERROR) << "Failed to build msg queue proof: " << result.error();
|
||||
}
|
||||
promise_.set_result(std::move(result));
|
||||
stop();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue