|
37 | 37 | #include "net/download-proof.hpp"
|
38 | 38 | #include "net/get-next-key-blocks.hpp"
|
39 | 39 | #include "net/download-archive-slice.hpp"
|
| 40 | +#include "impl/out-msg-queue-proof.hpp" |
40 | 41 |
|
41 | 42 | #include "td/utils/Random.h"
|
42 | 43 |
|
@@ -669,6 +670,62 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod
|
669 | 670 | query.offset_, query.max_size_, std::move(promise));
|
670 | 671 | }
|
671 | 672 |
|
| 673 | +void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getOutMsgQueueProof &query, |
| 674 | + td::Promise<td::BufferSlice> promise) { |
| 675 | + std::vector<BlockIdExt> blocks; |
| 676 | + for (const auto &x : query.blocks_) { |
| 677 | + BlockIdExt id = create_block_id(x); |
| 678 | + if (!id.is_valid_ext()) { |
| 679 | + promise.set_error(td::Status::Error("invalid block_id")); |
| 680 | + return; |
| 681 | + } |
| 682 | + if (!shard_is_ancestor(shard_, id.shard_full())) { |
| 683 | + promise.set_error(td::Status::Error("query in wrong overlay")); |
| 684 | + return; |
| 685 | + } |
| 686 | + blocks.push_back(create_block_id(x)); |
| 687 | + } |
| 688 | + ShardIdFull dst_shard = create_shard_id(query.dst_shard_); |
| 689 | + if (!dst_shard.is_valid_ext()) { |
| 690 | + promise.set_error(td::Status::Error("invalid shard")); |
| 691 | + return; |
| 692 | + } |
| 693 | + block::ImportedMsgQueueLimits limits{(td::uint32)query.limits_->max_bytes_, (td::uint32)query.limits_->max_msgs_}; |
| 694 | + if (limits.max_msgs > 512) { |
| 695 | + promise.set_error(td::Status::Error("max_msgs is too big")); |
| 696 | + return; |
| 697 | + } |
| 698 | + if (limits.max_bytes > (1 << 21)) { |
| 699 | + promise.set_error(td::Status::Error("max_bytes is too big")); |
| 700 | + return; |
| 701 | + } |
| 702 | + FLOG(DEBUG) { |
| 703 | + sb << "Got query getOutMsgQueueProof to shard " << dst_shard.to_str() << " from blocks"; |
| 704 | + for (const BlockIdExt &id : blocks) { |
| 705 | + sb << " " << id.id.to_str(); |
| 706 | + } |
| 707 | + sb << " from " << src; |
| 708 | + }; |
| 709 | + td::actor::send_closure( |
| 710 | + full_node_, &FullNode::get_out_msg_queue_query_token, |
| 711 | + [=, manager = validator_manager_, blocks = std::move(blocks), |
| 712 | + promise = std::move(promise)](td::Result<std::unique_ptr<ActionToken>> R) mutable { |
| 713 | + TRY_RESULT_PROMISE(promise, token, std::move(R)); |
| 714 | + auto P = |
| 715 | + td::PromiseCreator::lambda([promise = std::move(promise), token = std::move(token)]( |
| 716 | + td::Result<tl_object_ptr<ton_api::tonNode_outMsgQueueProof>> R) mutable { |
| 717 | + if (R.is_error()) { |
| 718 | + promise.set_result(create_serialize_tl_object<ton_api::tonNode_outMsgQueueProofEmpty>()); |
| 719 | + } else { |
| 720 | + promise.set_result(serialize_tl_object(R.move_as_ok(), true)); |
| 721 | + } |
| 722 | + }); |
| 723 | + td::actor::create_actor<BuildOutMsgQueueProof>("buildqueueproof", dst_shard, std::move(blocks), limits, manager, |
| 724 | + std::move(P)) |
| 725 | + .release(); |
| 726 | + }); |
| 727 | +} |
| 728 | + |
672 | 729 | void FullNodeShardImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice query,
|
673 | 730 | td::Promise<td::BufferSlice> promise) {
|
674 | 731 | if (!active_) {
|
@@ -944,6 +1001,47 @@ void FullNodeShardImpl::download_archive(BlockSeqno masterchain_seqno, ShardIdFu
|
944 | 1001 | .release();
|
945 | 1002 | }
|
946 | 1003 |
|
| 1004 | +void FullNodeShardImpl::download_out_msg_queue_proof(ShardIdFull dst_shard, std::vector<BlockIdExt> blocks, |
| 1005 | + block::ImportedMsgQueueLimits limits, td::Timestamp timeout, |
| 1006 | + td::Promise<std::vector<td::Ref<OutMsgQueueProof>>> promise) { |
| 1007 | + // TODO: maybe more complex download (like other requests here) |
| 1008 | + auto &b = choose_neighbour(); |
| 1009 | + if (b.adnl_id == adnl::AdnlNodeIdShort::zero()) { |
| 1010 | + promise.set_error(td::Status::Error(ErrorCode::notready, "no nodes")); |
| 1011 | + return; |
| 1012 | + } |
| 1013 | + std::vector<tl_object_ptr<ton_api::tonNode_blockIdExt>> blocks_tl; |
| 1014 | + for (const BlockIdExt &id : blocks) { |
| 1015 | + blocks_tl.push_back(create_tl_block_id(id)); |
| 1016 | + } |
| 1017 | + td::BufferSlice query = create_serialize_tl_object<ton_api::tonNode_getOutMsgQueueProof>( |
| 1018 | + create_tl_shard_id(dst_shard), std::move(blocks_tl), |
| 1019 | + create_tl_object<ton_api::tonNode_importedMsgQueueLimits>(limits.max_bytes, limits.max_msgs)); |
| 1020 | + |
| 1021 | + auto P = td::PromiseCreator::lambda( |
| 1022 | + [=, promise = std::move(promise), blocks = std::move(blocks)](td::Result<td::BufferSlice> R) mutable { |
| 1023 | + if (R.is_error()) { |
| 1024 | + promise.set_result(R.move_as_error()); |
| 1025 | + return; |
| 1026 | + } |
| 1027 | + TRY_RESULT_PROMISE(promise, f, fetch_tl_object<ton_api::tonNode_OutMsgQueueProof>(R.move_as_ok(), true)); |
| 1028 | + ton_api::downcast_call( |
| 1029 | + *f, td::overloaded( |
| 1030 | + [&](ton_api::tonNode_outMsgQueueProofEmpty &x) { |
| 1031 | + promise.set_error(td::Status::Error("node doesn't have this block")); |
| 1032 | + }, |
| 1033 | + [&](ton_api::tonNode_outMsgQueueProof &x) { |
| 1034 | + delay_action( |
| 1035 | + [=, promise = std::move(promise), blocks = std::move(blocks), x = std::move(x)]() mutable { |
| 1036 | + promise.set_result(OutMsgQueueProof::fetch(dst_shard, blocks, limits, x)); |
| 1037 | + }, |
| 1038 | + td::Timestamp::now()); |
| 1039 | + })); |
| 1040 | + }); |
| 1041 | + td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, b.adnl_id, adnl_id_, overlay_id_, |
| 1042 | + "get_msg_queue", std::move(P), timeout, std::move(query), 1 << 22, rldp_); |
| 1043 | +} |
| 1044 | + |
947 | 1045 | void FullNodeShardImpl::set_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
948 | 1046 | CHECK(!handle_);
|
949 | 1047 | handle_ = std::move(handle);
|
|
0 commit comments