2
This file is part of TON Blockchain Library.
4
TON Blockchain Library is free software: you can redistribute it and/or modify
5
it under the terms of the GNU Lesser General Public License as published by
6
the Free Software Foundation, either version 2 of the License, or
7
(at your option) any later version.
9
TON Blockchain Library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
17
Copyright 2017-2020 Telegram Systems LLP
19
#include "download-block-new.hpp"
20
#include "ton/ton-tl.hpp"
21
#include "adnl/utils.hpp"
22
#include "ton/ton-shard.h"
23
#include "td/utils/overloaded.h"
24
#include "ton/ton-io.hpp"
25
#include "validator/full-node.h"
26
#include "full-node-serializer.hpp"
34
DownloadBlockNew::DownloadBlockNew(BlockIdExt block_id, adnl::AdnlNodeIdShort local_id,
35
overlay::OverlayIdShort overlay_id, adnl::AdnlNodeIdShort download_from,
36
td::uint32 priority, td::Timestamp timeout,
37
td::actor::ActorId<ValidatorManagerInterface> validator_manager,
38
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays,
39
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<adnl::AdnlExtClient> client,
40
td::Promise<ReceivedBlock> promise)
43
, overlay_id_(overlay_id)
44
, download_from_(download_from)
47
, validator_manager_(validator_manager)
52
, promise_(std::move(promise))
53
, block_{block_id_, td::BufferSlice()}
54
, allow_partial_proof_{!block_id_.is_masterchain()} {
57
DownloadBlockNew::DownloadBlockNew(adnl::AdnlNodeIdShort local_id, overlay::OverlayIdShort overlay_id,
58
BlockIdExt prev_id, adnl::AdnlNodeIdShort download_from, td::uint32 priority,
59
td::Timestamp timeout,
60
td::actor::ActorId<ValidatorManagerInterface> validator_manager,
61
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays,
62
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<adnl::AdnlExtClient> client,
63
td::Promise<ReceivedBlock> promise)
65
, overlay_id_(overlay_id)
67
, download_from_(download_from)
70
, validator_manager_(validator_manager)
75
, promise_(std::move(promise))
76
, block_{BlockIdExt{}, td::BufferSlice()} {
79
void DownloadBlockNew::abort_query(td::Status reason) {
81
if (reason.code() == ErrorCode::notready || reason.code() == ErrorCode::timeout) {
82
VLOG(FULL_NODE_DEBUG) << "failed to download block " << block_id_ << "from " << download_from_ << ": " << reason;
84
VLOG(FULL_NODE_NOTICE) << "failed to download block " << block_id_ << " from " << download_from_ << ": "
87
promise_.set_error(std::move(reason));
92
void DownloadBlockNew::alarm() {
93
abort_query(td::Status::Error(ErrorCode::timeout, "timeout"));
96
void DownloadBlockNew::finish_query() {
98
promise_.set_value(std::move(block_));
103
void DownloadBlockNew::start_up() {
104
alarm_timestamp() = timeout_;
106
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
108
td::actor::send_closure(SelfId, &DownloadBlockNew::got_block_handle, R.move_as_ok());
111
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_block_handle,
112
block_id_.is_valid() ? block_id_ : prev_id_, true, std::move(P));
115
void DownloadBlockNew::got_block_handle(BlockHandle handle) {
116
handle_ = std::move(handle);
118
if (!block_id_.is_valid()) {
119
CHECK(prev_id_.is_valid());
120
if (handle_->inited_next_left()) {
121
block_id_ = handle_->one_next(true);
122
block_.id = block_id_;
129
if (block_id_.is_valid() &&
130
(handle_->inited_proof() || (handle_->inited_proof_link() && allow_partial_proof_) || skip_proof_) &&
131
handle_->received()) {
132
CHECK(block_.id == block_id_);
133
CHECK(handle_->id() == block_id_);
134
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<BlockData>> R) {
136
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query,
137
R.move_as_error_prefix("failed to get from db: "));
139
td::actor::send_closure(SelfId, &DownloadBlockNew::got_data_from_db, R.move_as_ok()->data());
142
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_block_data_from_db, handle_,
147
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::unique_ptr<DownloadToken>> R) {
149
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query,
150
R.move_as_error_prefix("failed to get download token: "));
152
td::actor::send_closure(SelfId, &DownloadBlockNew::got_download_token, R.move_as_ok());
155
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_download_token, 1, priority_, timeout_,
159
void DownloadBlockNew::got_download_token(std::unique_ptr<DownloadToken> token) {
160
token_ = std::move(token);
162
if (download_from_.is_zero() && client_.empty()) {
163
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<adnl::AdnlNodeIdShort>> R) {
165
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query, R.move_as_error());
167
auto vec = R.move_as_ok();
168
if (vec.size() == 0) {
169
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query,
170
td::Status::Error(ErrorCode::notready, "no nodes"));
172
td::actor::send_closure(SelfId, &DownloadBlockNew::got_node_to_download, vec[0]);
177
td::actor::send_closure(overlays_, &overlay::Overlays::get_overlay_random_peers, local_id_, overlay_id_, 1,
180
got_node_to_download(download_from_);
184
void DownloadBlockNew::got_node_to_download(adnl::AdnlNodeIdShort node) {
185
download_from_ = node;
187
VLOG(FULL_NODE_DEBUG) << "downloading proof for " << block_id_;
189
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) mutable {
191
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query, R.move_as_error());
193
td::actor::send_closure(SelfId, &DownloadBlockNew::got_data, R.move_as_ok());
198
if (block_id_.is_valid()) {
199
q = create_serialize_tl_object<ton_api::tonNode_downloadBlockFull>(create_tl_block_id(block_id_));
201
q = create_serialize_tl_object<ton_api::tonNode_downloadNextBlockFull>(create_tl_block_id(prev_id_));
203
if (client_.empty()) {
204
td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, download_from_, local_id_, overlay_id_,
205
"get_proof", std::move(P), td::Timestamp::in(15.0), std::move(q),
206
FullNode::max_proof_size() + FullNode::max_block_size() + 128, rldp_);
208
td::actor::send_closure(client_, &adnl::AdnlExtClient::send_query, "get_prepare",
209
create_serialize_tl_object_suffix<ton_api::tonNode_query>(std::move(q)),
210
td::Timestamp::in(15.0), std::move(P));
214
void DownloadBlockNew::got_data(td::BufferSlice data) {
215
auto F = fetch_tl_object<ton_api::tonNode_DataFull>(std::move(data), true);
218
abort_query(F.move_as_error_prefix("received invalid answer: "));
222
auto f = F.move_as_ok();
223
if (f->get_id() == ton_api::tonNode_dataFullEmpty::ID) {
224
abort_query(td::Status::Error(ErrorCode::notready, "node doesn't have this block"));
228
td::BufferSlice proof, block_data;
230
td::Status S = deserialize_block_full(*f, id, proof, block_data, is_link, overlay::Overlays::max_fec_broadcast_size());
232
abort_query(S.move_as_error_prefix("cannot deserialize block: "));
236
if (!allow_partial_proof_ && is_link) {
237
abort_query(td::Status::Error(ErrorCode::notready, "node doesn't have proof for this block"));
240
if (block_id_.is_valid() && id != block_id_) {
241
abort_query(td::Status::Error(ErrorCode::notready, "received data for wrong block"));
245
block_.data = std::move(block_data);
246
if (td::sha256_bits256(block_.data.as_slice()) != id.file_hash) {
247
abort_query(td::Status::Error(ErrorCode::notready, "received data with bad hash"));
251
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
253
td::actor::send_closure(SelfId, &DownloadBlockNew::abort_query, R.move_as_error_prefix("received bad proof: "));
255
td::actor::send_closure(SelfId, &DownloadBlockNew::checked_block_proof);
258
if (block_id_.is_valid()) {
260
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::validate_block_proof_link, block_id_,
261
std::move(proof), std::move(P));
263
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::validate_block_proof, block_id_,
264
std::move(proof), std::move(P));
268
td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::validate_block_is_next_proof, prev_id_, id,
269
std::move(proof), std::move(P));
273
void DownloadBlockNew::got_data_from_db(td::BufferSlice data) {
274
block_.data = std::move(data);
278
void DownloadBlockNew::checked_block_proof() {
282
} // namespace fullnode
284
} // namespace validator