Ton

Форк
0
/
download-state.cpp 
245 строк · 9.7 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

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.
8

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.
13

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/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "download-state.hpp"
20
#include "ton/ton-tl.hpp"
21
#include "ton/ton-io.hpp"
22
#include "td/utils/overloaded.h"
23
#include "full-node.h"
24

25
namespace ton {
26

27
namespace validator {
28

29
namespace fullnode {
30

31
DownloadState::DownloadState(BlockIdExt block_id, BlockIdExt masterchain_block_id, adnl::AdnlNodeIdShort local_id,
32
                             overlay::OverlayIdShort overlay_id, adnl::AdnlNodeIdShort download_from,
33
                             td::uint32 priority, td::Timestamp timeout,
34
                             td::actor::ActorId<ValidatorManagerInterface> validator_manager,
35
                             td::actor::ActorId<adnl::AdnlSenderInterface> rldp,
36
                             td::actor::ActorId<overlay::Overlays> overlays, td::actor::ActorId<adnl::Adnl> adnl,
37
                             td::actor::ActorId<adnl::AdnlExtClient> client, td::Promise<td::BufferSlice> promise)
38
    : block_id_(block_id)
39
    , masterchain_block_id_(masterchain_block_id)
40
    , local_id_(local_id)
41
    , overlay_id_(overlay_id)
42
    , download_from_(download_from)
43
    , priority_(priority)
44
    , timeout_(timeout)
45
    , validator_manager_(validator_manager)
46
    , rldp_(rldp)
47
    , overlays_(overlays)
48
    , adnl_(adnl)
49
    , client_(client)
50
    , promise_(std::move(promise)) {
51
}
52

53
void DownloadState::abort_query(td::Status reason) {
54
  if (promise_) {
55
    if (reason.code() == ErrorCode::notready || reason.code() == ErrorCode::timeout) {
56
      VLOG(FULL_NODE_DEBUG) << "failed to download state " << block_id_ << " from " << download_from_ << ": " << reason;
57
    } else {
58
      VLOG(FULL_NODE_NOTICE) << "failed to download state " << block_id_ << " from " << download_from_ << ": "
59
                             << reason;
60
    }
61
    promise_.set_error(std::move(reason));
62
  }
63
  stop();
64
}
65

66
void DownloadState::alarm() {
67
  abort_query(td::Status::Error(ErrorCode::timeout, "timeout"));
68
}
69

70
void DownloadState::finish_query() {
71
  if (promise_) {
72
    promise_.set_value(std::move(state_));
73
  }
74
  stop();
75
}
76

77
void DownloadState::start_up() {
78
  alarm_timestamp() = timeout_;
79

80
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
81
    if (R.is_error()) {
82
      td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error());
83
    } else {
84
      td::actor::send_closure(SelfId, &DownloadState::got_block_handle, R.move_as_ok());
85
    }
86
  });
87

88
  td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_block_handle, block_id_, true,
89
                          std::move(P));
90
}
91

92
void DownloadState::got_block_handle(BlockHandle handle) {
93
  handle_ = std::move(handle);
94
  if (!download_from_.is_zero() || !client_.empty()) {
95
    got_node_to_download(download_from_);
96
  } else {
97
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<adnl::AdnlNodeIdShort>> R) {
98
      if (R.is_error()) {
99
        td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error());
100
      } else {
101
        auto vec = R.move_as_ok();
102
        if (vec.size() == 0) {
103
          td::actor::send_closure(SelfId, &DownloadState::abort_query,
104
                                  td::Status::Error(ErrorCode::notready, "no nodes"));
105
        } else {
106
          td::actor::send_closure(SelfId, &DownloadState::got_node_to_download, vec[0]);
107
        }
108
      }
109
    });
110

111
    td::actor::send_closure(overlays_, &overlay::Overlays::get_overlay_random_peers, local_id_, overlay_id_, 1,
112
                            std::move(P));
113
  }
114
}
115

116
void DownloadState::got_node_to_download(adnl::AdnlNodeIdShort node) {
117
  download_from_ = node;
118
  LOG(INFO) << "downloading state " << block_id_.to_str() << " from " << download_from_;
119

120
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) mutable {
121
    if (R.is_error()) {
122
      td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error());
123
    } else {
124
      td::actor::send_closure(SelfId, &DownloadState::got_block_state_description, R.move_as_ok());
125
    }
126
  });
127

128
  td::BufferSlice query;
129
  if (masterchain_block_id_.is_valid()) {
130
    query = create_serialize_tl_object<ton_api::tonNode_preparePersistentState>(
131
        create_tl_block_id(block_id_), create_tl_block_id(masterchain_block_id_));
132
  } else {
133
    query = create_serialize_tl_object<ton_api::tonNode_prepareZeroState>(create_tl_block_id(block_id_));
134
  }
135

136
  if (client_.empty()) {
137
    td::actor::send_closure(overlays_, &overlay::Overlays::send_query, download_from_, local_id_, overlay_id_,
138
                            "get_prepare", std::move(P), td::Timestamp::in(1.0), std::move(query));
139
  } else {
140
    td::actor::send_closure(client_, &adnl::AdnlExtClient::send_query, "get_prepare",
141
                            create_serialize_tl_object_suffix<ton_api::tonNode_query>(std::move(query)),
142
                            td::Timestamp::in(1.0), std::move(P));
143
  }
144
}
145

146
void DownloadState::got_block_state_description(td::BufferSlice data) {
147
  auto F = fetch_tl_object<ton_api::tonNode_PreparedState>(std::move(data), true);
148
  if (F.is_error()) {
149
    abort_query(F.move_as_error());
150
    return;
151
  }
152
  prev_logged_timer_ = td::Timer();
153

154
  ton_api::downcast_call(
155
      *F.move_as_ok().get(),
156
      td::overloaded(
157
          [&](ton_api::tonNode_notFoundState &f) {
158
            abort_query(td::Status::Error(ErrorCode::notready, "state not found"));
159
          },
160
          [&, self = this](ton_api::tonNode_preparedState &f) {
161
            if (masterchain_block_id_.is_valid()) {
162
              got_block_state_part(td::BufferSlice{}, 0);
163
              return;
164
            }
165
            auto P = td::PromiseCreator::lambda([SelfId = actor_id(self)](td::Result<td::BufferSlice> R) {
166
              if (R.is_error()) {
167
                td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error());
168
              } else {
169
                td::actor::send_closure(SelfId, &DownloadState::got_block_state, R.move_as_ok());
170
              }
171
            });
172

173
            td::BufferSlice query =
174
                create_serialize_tl_object<ton_api::tonNode_downloadZeroState>(create_tl_block_id(block_id_));
175
            if (client_.empty()) {
176
              td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, download_from_, local_id_,
177
                                      overlay_id_, "download state", std::move(P), td::Timestamp::in(3.0),
178
                                      std::move(query), FullNode::max_state_size(), rldp_);
179
            } else {
180
              td::actor::send_closure(client_, &adnl::AdnlExtClient::send_query, "download state",
181
                                      create_serialize_tl_object_suffix<ton_api::tonNode_query>(std::move(query)),
182
                                      td::Timestamp::in(3.0), std::move(P));
183
            }
184
          }));
185
}
186

187
void DownloadState::got_block_state_part(td::BufferSlice data, td::uint32 requested_size) {
188
  bool last_part = data.size() < requested_size;
189
  sum_ += data.size();
190
  parts_.push_back(std::move(data));
191

192
  double elapsed = prev_logged_timer_.elapsed();
193
  if (elapsed > 10.0) {
194
    prev_logged_timer_ = td::Timer();
195
    LOG(INFO) << "downloading state " << block_id_.to_str() << ": total=" << sum_ << " ("
196
              << td::format::as_size((td::uint64)(double(sum_ - prev_logged_sum_) / elapsed)) << "/s)";
197
    prev_logged_sum_ = sum_;
198
  }
199

200
  if (last_part) {
201
    td::BufferSlice res{td::narrow_cast<std::size_t>(sum_)};
202
    auto S = res.as_slice();
203
    for (auto &p : parts_) {
204
      S.copy_from(p.as_slice());
205
      S.remove_prefix(p.size());
206
    }
207
    parts_.clear();
208
    CHECK(!S.size());
209
    got_block_state(std::move(res));
210
    return;
211
  }
212

213
  td::uint32 part_size = 1 << 21;
214
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), part_size](td::Result<td::BufferSlice> R) {
215
    if (R.is_error()) {
216
      td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error());
217
    } else {
218
      td::actor::send_closure(SelfId, &DownloadState::got_block_state_part, R.move_as_ok(), part_size);
219
    }
220
  });
221

222
  td::BufferSlice query = create_serialize_tl_object<ton_api::tonNode_downloadPersistentStateSlice>(
223
      create_tl_block_id(block_id_), create_tl_block_id(masterchain_block_id_), sum_, part_size);
224
  if (client_.empty()) {
225
    td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, download_from_, local_id_, overlay_id_,
226
                            "download state", std::move(P), td::Timestamp::in(20.0), std::move(query),
227
                            FullNode::max_state_size(), rldp_);
228
  } else {
229
    td::actor::send_closure(client_, &adnl::AdnlExtClient::send_query, "download state",
230
                            create_serialize_tl_object_suffix<ton_api::tonNode_query>(std::move(query)),
231
                            td::Timestamp::in(20.0), std::move(P));
232
  }
233
}
234

235
void DownloadState::got_block_state(td::BufferSlice data) {
236
  state_ = std::move(data);
237
  LOG(INFO) << "finished downloading state " << block_id_.to_str() << ": total=" << sum_;
238
  finish_query();
239
}
240

241
}  // namespace fullnode
242

243
}  // namespace validator
244

245
}  // namespace ton
246

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.