Ton

Форк
0
/
manager.cpp 
3176 строк · 130.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 "manager.hpp"
20
#include "checksum.h"
21
#include "td/utils/buffer.h"
22
#include "validator-group.hpp"
23
#include "adnl/utils.hpp"
24
#include "downloaders/wait-block-state.hpp"
25
#include "downloaders/wait-block-state-merge.hpp"
26
#include "downloaders/wait-block-data.hpp"
27
#include "validator-group.hpp"
28
#include "fabric.h"
29
#include "manager.h"
30
#include "validate-broadcast.hpp"
31
#include "ton/ton-tl.hpp"
32
#include "ton/ton-io.hpp"
33
#include "state-serializer.hpp"
34
#include "get-next-key-blocks.h"
35
#include "import-db-slice.hpp"
36

37
#include "auto/tl/lite_api.h"
38
#include "tl-utils/lite-utils.hpp"
39
#include "auto/tl/ton_api_json.h"
40
#include "tl/tl_json.h"
41

42
#include "td/utils/Random.h"
43
#include "td/utils/port/path.h"
44
#include "td/utils/JsonBuilder.h"
45

46
#include "common/delay.h"
47

48
#include "validator/stats-merger.h"
49

50
#include <fstream>
51

52
namespace ton {
53

54
namespace validator {
55

56
void ValidatorManagerImpl::validate_block_is_next_proof(BlockIdExt prev_block_id, BlockIdExt next_block_id,
57
                                                        td::BufferSlice proof, td::Promise<td::Unit> promise) {
58
  if (!prev_block_id.is_masterchain() || !next_block_id.is_masterchain()) {
59
    VLOG(VALIDATOR_NOTICE) << "prev=" << prev_block_id << " next=" << next_block_id;
60
    promise.set_error(
61
        td::Status::Error(ErrorCode::protoviolation, "validate_block_is_next_proof() can only work for masterchain"));
62
    return;
63
  }
64
  if (prev_block_id.seqno() + 1 != next_block_id.seqno()) {
65
    VLOG(VALIDATOR_NOTICE) << "prev=" << prev_block_id << " next=" << next_block_id;
66
    promise.set_error(td::Status::Error(ErrorCode::protoviolation, "validate_block_is_next_proof(): bad seqno"));
67
    return;
68
  }
69
  CHECK(last_masterchain_state_.not_null());
70
  auto pp = create_proof(next_block_id, std::move(proof));
71
  if (pp.is_error()) {
72
    promise.set_error(pp.move_as_error_prefix("failed to create proof: "));
73
    return;
74
  }
75

76
  if (last_masterchain_seqno_ == prev_block_id.seqno()) {
77
    CHECK(last_masterchain_block_id_ == prev_block_id);
78

79
    auto P = td::PromiseCreator::lambda(
80
        [promise = std::move(promise), id = prev_block_id](td::Result<BlockHandle> R) mutable {
81
          if (R.is_error()) {
82
            promise.set_error(R.move_as_error());
83
            return;
84
          }
85
          auto handle = R.move_as_ok();
86
          CHECK(!handle->merge_before());
87
          if (handle->one_prev(true) != id) {
88
            promise.set_error(td::Status::Error(ErrorCode::protoviolation, "prev block mismatch"));
89
            return;
90
          }
91
          promise.set_value(td::Unit());
92
        });
93

94
    run_check_proof_query(next_block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P),
95
                          last_masterchain_state_, opts_->is_hardfork(next_block_id));
96
  } else {
97
    auto P =
98
        td::PromiseCreator::lambda([promise = std::move(promise), next_block_id](td::Result<BlockHandle> R) mutable {
99
          R.ensure();
100
          auto handle = R.move_as_ok();
101
          CHECK(handle->inited_next_left());
102
          if (handle->one_next(true) == next_block_id) {
103
            promise.set_value(td::Unit());
104
          } else {
105
            promise.set_error(td::Status::Error("next block id mismatch"));
106
          }
107
        });
108
    get_block_handle(prev_block_id, false, std::move(P));
109
  }
110
}
111

112
void ValidatorManagerImpl::validate_block_proof(BlockIdExt block_id, td::BufferSlice proof,
113
                                                td::Promise<td::Unit> promise) {
114
  auto pp = create_proof(block_id, std::move(proof));
115
  if (pp.is_error()) {
116
    promise.set_error(pp.move_as_error_prefix(PSTRING() << "failed to create proof for " << block_id << ": "));
117
    return;
118
  }
119

120
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
121
    if (R.is_error()) {
122
      promise.set_error(R.move_as_error());
123
    } else {
124
      promise.set_value(td::Unit());
125
    }
126
  });
127
  run_check_proof_query(block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P),
128
                        opts_->is_hardfork(block_id));
129
}
130

131
void ValidatorManagerImpl::validate_block_proof_link(BlockIdExt block_id, td::BufferSlice proof,
132
                                                     td::Promise<td::Unit> promise) {
133
  auto pp = create_proof_link(block_id, std::move(proof));
134
  if (pp.is_error()) {
135
    promise.set_error(pp.move_as_error_prefix(PSTRING() << "failed to create proof link for " << block_id << ": "));
136
    return;
137
  }
138

139
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
140
    if (R.is_error()) {
141
      promise.set_error(R.move_as_error());
142
    } else {
143
      promise.set_value(td::Unit());
144
    }
145
  });
146
  run_check_proof_link_query(block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P));
147
}
148

149
void ValidatorManagerImpl::validate_block_proof_rel(BlockIdExt block_id, BlockIdExt rel_block_id, td::BufferSlice proof,
150
                                                    td::Promise<td::Unit> promise) {
151
  auto pp = create_proof(block_id, std::move(proof));
152
  if (pp.is_error()) {
153
    promise.set_error(pp.move_as_error_prefix(PSTRING() << "failed to create proof for " << block_id << ": "));
154
    return;
155
  }
156

157
  auto Q = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
158
    if (R.is_error()) {
159
      promise.set_error(R.move_as_error());
160
    } else {
161
      promise.set_value(td::Unit());
162
    }
163
  });
164

165
  if (rel_block_id.id.seqno == 0) {
166
    auto P = td::PromiseCreator::lambda(
167
        [block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), promise = std::move(Q),
168
         skip_sig = opts_->is_hardfork(block_id)](td::Result<td::Ref<ShardState>> R) mutable {
169
          if (R.is_error()) {
170
            promise.set_error(R.move_as_error());
171
          } else {
172
            auto s = td::Ref<MasterchainState>{R.move_as_ok()};
173

174
            run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise),
175
                                  std::move(s), skip_sig);
176
          }
177
        });
178
    get_shard_state_from_db_short(rel_block_id, std::move(P));
179
  } else {
180
    auto P =
181
        td::PromiseCreator::lambda([block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), promise = std::move(Q),
182
                                    skip_sig = opts_->is_hardfork(block_id)](td::Result<td::Ref<ProofLink>> R) mutable {
183
          if (R.is_error()) {
184
            promise.set_error(R.move_as_error());
185
          } else {
186
            run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise),
187
                                  R.move_as_ok(), skip_sig);
188
          }
189
        });
190
    get_block_proof_link_from_db_short(rel_block_id, std::move(P));
191
  }
192
}
193

194
void ValidatorManagerImpl::validate_block(ReceivedBlock block, td::Promise<BlockHandle> promise) {
195
  auto blkid = block.id;
196
  auto pp = create_block(std::move(block));
197
  if (pp.is_error()) {
198
    promise.set_error(pp.move_as_error_prefix(PSTRING() << "failed to create block for " << blkid << ": "));
199
    return;
200
  }
201
  CHECK(blkid.is_masterchain());
202

203
  auto P = td::PromiseCreator::lambda(
204
      [SelfId = actor_id(this), promise = std::move(promise), id = block.id](td::Result<td::Unit> R) mutable {
205
        if (R.is_error()) {
206
          promise.set_error(R.move_as_error());
207
        } else {
208
          td::actor::send_closure(SelfId, &ValidatorManager::get_block_handle, id, true, std::move(promise));
209
        }
210
      });
211
  run_apply_block_query(block.id, pp.move_as_ok(), block.id, actor_id(this), td::Timestamp::in(10.0), std::move(P));
212
}
213

214
void ValidatorManagerImpl::prevalidate_block(BlockBroadcast broadcast, td::Promise<td::Unit> promise) {
215
  if (!started_) {
216
    promise.set_error(td::Status::Error(ErrorCode::notready, "node not started"));
217
    return;
218
  }
219
  td::actor::create_actor<ValidateBroadcast>("broadcast", std::move(broadcast), last_masterchain_block_handle_,
220
                                             last_masterchain_state_, last_known_key_block_handle_, actor_id(this),
221
                                             td::Timestamp::in(2.0), std::move(promise))
222
      .release();
223
}
224

225
void ValidatorManagerImpl::sync_complete(td::Promise<td::Unit> promise) {
226
  started_ = true;
227

228
  VLOG(VALIDATOR_WARNING) << "completed sync. Validating " << validator_groups_.size() << " groups";
229
  for (auto &v : validator_groups_) {
230
    if (!v.second.actor.empty()) {
231
      td::actor::send_closure(v.second.actor, &ValidatorGroup::create_session);
232
    }
233
  }
234
  for (auto &v : next_validator_groups_) {
235
    if (!v.second.actor.empty()) {
236
      td::actor::send_closure(v.second.actor, &ValidatorGroup::create_session);
237
    }
238
  }
239
}
240

241
void ValidatorManagerImpl::get_next_block(BlockIdExt block_id, td::Promise<BlockHandle> promise) {
242
  auto P = td::PromiseCreator::lambda(
243
      [SelfId = actor_id(this), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
244
        if (R.is_error()) {
245
          promise.set_error(R.move_as_error());
246
          return;
247
        }
248
        auto handle = R.move_as_ok();
249
        if (!handle->inited_next_left()) {
250
          promise.set_error(td::Status::Error(ErrorCode::notready, "next block not known"));
251
          return;
252
        }
253

254
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::get_block_handle, handle->one_next(true), true,
255
                                std::move(promise));
256
      });
257

258
  get_block_handle(block_id, false, std::move(P));
259
}
260

261
void ValidatorManagerImpl::get_next_key_blocks(BlockIdExt block_id, td::uint32 cnt,
262
                                               td::Promise<std::vector<BlockIdExt>> promise) {
263
  if (!last_masterchain_block_handle_ || !last_key_block_handle_) {
264
    promise.set_error(td::Status::Error(ErrorCode::notready, "not inited"));
265
    return;
266
  }
267

268
  td::actor::create_actor<GetNextKeyBlocks>("nextkeyblocks", block_id, cnt, last_key_block_handle_,
269
                                            last_masterchain_state_, actor_id(this), td::Timestamp::in(2.0),
270
                                            std::move(promise))
271
      .release();
272
}
273

274
void ValidatorManagerImpl::get_block_data(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
275
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<BlockData>> R) mutable {
276
    if (R.is_error()) {
277
      promise.set_error(R.move_as_error());
278
    } else {
279
      auto B = R.move_as_ok();
280
      promise.set_value(B->data());
281
    }
282
  });
283

284
  td::actor::send_closure(db_, &Db::get_block_data, std::move(handle), std::move(P));
285
}
286

287
void ValidatorManagerImpl::check_zero_state_exists(BlockIdExt block_id, td::Promise<bool> promise) {
288
  td::actor::send_closure(db_, &Db::check_zero_state_file_exists, block_id, std::move(promise));
289
}
290
void ValidatorManagerImpl::get_zero_state(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
291
  td::actor::send_closure(db_, &Db::get_zero_state_file, block_id, std::move(promise));
292
}
293

294
void ValidatorManagerImpl::check_persistent_state_exists(BlockIdExt block_id, BlockIdExt masterchain_block_id,
295
                                                         td::Promise<bool> promise) {
296
  td::actor::send_closure(db_, &Db::check_persistent_state_file_exists, block_id, masterchain_block_id,
297
                          std::move(promise));
298
}
299
void ValidatorManagerImpl::get_persistent_state(BlockIdExt block_id, BlockIdExt masterchain_block_id,
300
                                                td::Promise<td::BufferSlice> promise) {
301
  td::actor::send_closure(db_, &Db::get_persistent_state_file, block_id, masterchain_block_id, std::move(promise));
302
}
303

304
void ValidatorManagerImpl::get_persistent_state_slice(BlockIdExt block_id, BlockIdExt masterchain_block_id,
305
                                                      td::int64 offset, td::int64 max_length,
306
                                                      td::Promise<td::BufferSlice> promise) {
307
  td::actor::send_closure(db_, &Db::get_persistent_state_file_slice, block_id, masterchain_block_id, offset, max_length,
308
                          std::move(promise));
309
}
310

311
void ValidatorManagerImpl::get_block_proof(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
312
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
313
    if (R.is_error()) {
314
      promise.set_error(R.move_as_error());
315
    } else {
316
      auto B = R.move_as_ok();
317
      promise.set_value(B->data());
318
    }
319
  });
320

321
  td::actor::send_closure(db_, &Db::get_block_proof, std::move(handle), std::move(P));
322
}
323

324
void ValidatorManagerImpl::get_block_proof_link(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
325
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<ProofLink>> R) mutable {
326
    if (R.is_error()) {
327
      promise.set_error(R.move_as_error());
328
    } else {
329
      auto B = R.move_as_ok();
330
      promise.set_value(B->data());
331
    }
332
  });
333

334
  td::actor::send_closure(db_, &Db::get_block_proof_link, std::move(handle), std::move(P));
335
}
336

337
void ValidatorManagerImpl::get_key_block_proof(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
338
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
339
    if (R.is_error()) {
340
      promise.set_error(R.move_as_error());
341
    } else {
342
      auto B = R.move_as_ok();
343
      promise.set_value(B->data());
344
    }
345
  });
346

347
  td::actor::send_closure(db_, &Db::get_key_block_proof, block_id, std::move(P));
348
}
349

350
void ValidatorManagerImpl::get_key_block_proof_link(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
351
  auto P = td::PromiseCreator::lambda(
352
      [promise = std::move(promise), block_id, db = db_.get()](td::Result<td::Ref<Proof>> R) mutable {
353
        if (R.is_error()) {
354
          auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<ProofLink>> R) mutable {
355
            if (R.is_error()) {
356
              promise.set_error(R.move_as_error());
357
            } else {
358
              auto B = R.move_as_ok();
359
              promise.set_value(B->data());
360
            }
361
          });
362

363
          td::actor::send_closure(db, &Db::get_key_block_proof_link, block_id, std::move(P));
364
        } else {
365
          auto B = R.move_as_ok()->export_as_proof_link().move_as_ok();
366
          promise.set_value(B->data());
367
        }
368
      });
369

370
  td::actor::send_closure(db_, &Db::get_key_block_proof, block_id, std::move(P));
371
}
372

373
void ValidatorManagerImpl::new_external_message(td::BufferSlice data, int priority) {
374
  if (!is_validator()) {
375
    return;
376
  }
377
  if (last_masterchain_state_.is_null()) {
378
    VLOG(VALIDATOR_NOTICE) << "dropping ext message: validator is not ready";
379
    return;
380
  }
381
  if (ext_msgs_[priority].ext_messages_.size() > (size_t)max_mempool_num()) {
382
    return;
383
  }
384
  auto R = create_ext_message(std::move(data), last_masterchain_state_->get_ext_msg_limits());
385
  if (R.is_error()) {
386
    VLOG(VALIDATOR_NOTICE) << "dropping bad ext message: " << R.move_as_error();
387
    return;
388
  }
389
  add_external_message(R.move_as_ok(), priority);
390
}
391

392
void ValidatorManagerImpl::add_external_message(td::Ref<ExtMessage> msg, int priority) {
393
  auto &msgs = ext_msgs_[priority];
394
  auto message = std::make_unique<MessageExt<ExtMessage>>(msg);
395
  auto id = message->ext_id();
396
  auto address = message->address();
397
  unsigned long per_address_limit = 256;
398
  auto it = msgs.ext_addr_messages_.find(address);
399
  if (it != msgs.ext_addr_messages_.end() && it->second.size() >= per_address_limit) {
400
    return;
401
  }
402
  auto it2 = ext_messages_hashes_.find(id.hash);
403
  if (it2 != ext_messages_hashes_.end()) {
404
    int old_priority = it2->second.first;
405
    if (old_priority >= priority) {
406
      return;
407
    }
408
    ext_msgs_[old_priority].erase(id);
409
  }
410
  msgs.ext_messages_.emplace(id, std::move(message));
411
  msgs.ext_addr_messages_[address].emplace(id.hash, id);
412
  ext_messages_hashes_[id.hash] = {priority, id};
413
}
414
void ValidatorManagerImpl::check_external_message(td::BufferSlice data, td::Promise<td::Ref<ExtMessage>> promise) {
415
  auto state = do_get_last_liteserver_state();
416
  if (state.is_null()) {
417
    promise.set_error(td::Status::Error(ErrorCode::notready, "not ready"));
418
    return;
419
  }
420
  auto R = create_ext_message(std::move(data), state->get_ext_msg_limits());
421
  if (R.is_error()) {
422
    promise.set_error(R.move_as_error_prefix("failed to parse external message: "));
423
    return;
424
  }
425
  auto message = R.move_as_ok();
426
  WorkchainId wc = message->wc();
427
  StdSmcAddress addr = message->addr();
428
  if (checked_ext_msg_counter_.get_msg_count(wc, addr) >= max_ext_msg_per_addr()) {
429
    promise.set_error(
430
        td::Status::Error(PSTRING() << "too many external messages to address " << wc << ":" << addr.to_hex()));
431
    return;
432
  }
433

434
  promise = [self = this, wc, addr, promise = std::move(promise),
435
             SelfId = actor_id(this)](td::Result<td::Ref<ExtMessage>> R) mutable {
436
    if (R.is_error()) {
437
      promise.set_error(R.move_as_error());
438
      return;
439
    }
440
    td::actor::send_lambda(SelfId, [=, promise = std::move(promise), message = R.move_as_ok()]() mutable {
441
      if (self->checked_ext_msg_counter_.inc_msg_count(wc, addr) > max_ext_msg_per_addr()) {
442
        promise.set_error(
443
            td::Status::Error(PSTRING() << "too many external messages to address " << wc << ":" << addr.to_hex()));
444
        return;
445
      }
446
      promise.set_result(std::move(message));
447
    });
448
  };
449
  ++ls_stats_check_ext_messages_;
450
  run_check_external_message(std::move(message), actor_id(this), std::move(promise));
451
}
452

453
void ValidatorManagerImpl::new_ihr_message(td::BufferSlice data) {
454
  if (!is_validator()) {
455
    return;
456
  }
457
  auto R = create_ihr_message(std::move(data));
458
  if (R.is_error()) {
459
    VLOG(VALIDATOR_NOTICE) << "dropping bad ihr message: " << R.move_as_error();
460
    return;
461
  }
462
  auto M = std::make_unique<MessageExt<IhrMessage>>(R.move_as_ok());
463
  auto id = M->ext_id();
464
  if (ihr_messages_hashes_.count(id.hash) == 0) {
465
    ihr_messages_.emplace(id, std::move(M));
466
    ihr_messages_hashes_.emplace(id.hash, id);
467
  }
468
}
469

470
void ValidatorManagerImpl::new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) {
471
  if (!is_validator()) {
472
    return;
473
  }
474
  if (!last_masterchain_block_handle_) {
475
    VLOG(VALIDATOR_DEBUG) << "dropping top shard block broadcast: not inited";
476
    return;
477
  }
478
  if (!started_) {
479
    return;
480
  }
481
  auto it = shard_blocks_.find(ShardTopBlockDescriptionId{block_id.shard_full(), cc_seqno});
482
  if (it != shard_blocks_.end() && block_id.id.seqno <= it->second->block_id().id.seqno) {
483
    VLOG(VALIDATOR_DEBUG) << "dropping duplicate shard block broadcast";
484
    return;
485
  }
486
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardTopBlockDescription>> R) {
487
    if (R.is_error()) {
488
      VLOG(VALIDATOR_NOTICE) << "dropping invalid new shard block description: " << R.move_as_error();
489
    } else {
490
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::add_shard_block_description, R.move_as_ok());
491
    }
492
  });
493
  run_validate_shard_block_description(std::move(data), last_masterchain_block_handle_, last_masterchain_state_,
494
                                       actor_id(this), td::Timestamp::in(2.0), std::move(P));
495
}
496

497
void ValidatorManagerImpl::new_block_candidate(BlockIdExt block_id, td::BufferSlice data) {
498
  if (!last_masterchain_block_handle_) {
499
    VLOG(VALIDATOR_DEBUG) << "dropping top shard block broadcast: not inited";
500
    return;
501
  }
502
  if (!started_) {
503
    return;
504
  }
505
  add_cached_block_candidate(ReceivedBlock{block_id, std::move(data)});
506
}
507

508
void ValidatorManagerImpl::add_shard_block_description(td::Ref<ShardTopBlockDescription> desc) {
509
  if (desc->may_be_valid(last_masterchain_block_handle_, last_masterchain_state_)) {
510
    auto it = shard_blocks_.find(ShardTopBlockDescriptionId{desc->shard(), desc->catchain_seqno()});
511
    if (it != shard_blocks_.end() && desc->block_id().id.seqno <= it->second->block_id().id.seqno) {
512
      VLOG(VALIDATOR_DEBUG) << "dropping duplicate shard block broadcast";
513
      return;
514
    }
515
    shard_blocks_[ShardTopBlockDescriptionId{desc->block_id().shard_full(), desc->catchain_seqno()}] = desc;
516
    VLOG(VALIDATOR_DEBUG) << "new shard block descr for " << desc->block_id();
517
    if (last_masterchain_block_handle_ && last_masterchain_seqno_ > 0 &&
518
        desc->generated_at() < last_masterchain_block_handle_->unix_time() + 60) {
519
      delay_action(
520
          [SelfId = actor_id(this), desc]() {
521
            auto P = td::PromiseCreator::lambda([](td::Result<td::Ref<ShardState>> R) {
522
              if (R.is_error()) {
523
                auto S = R.move_as_error();
524
                if (S.code() != ErrorCode::timeout && S.code() != ErrorCode::notready) {
525
                  VLOG(VALIDATOR_NOTICE) << "failed to get shard state: " << S;
526
                } else {
527
                  VLOG(VALIDATOR_DEBUG) << "failed to get shard state: " << S;
528
                }
529
              }
530
            });
531
            td::actor::send_closure(SelfId, &ValidatorManager::wait_block_state_short, desc->block_id(), 0,
532
                                    td::Timestamp::in(60.0), std::move(P));
533
          },
534
          td::Timestamp::in(1.0));
535
    }
536
  }
537
}
538

539
void ValidatorManagerImpl::add_cached_block_candidate(ReceivedBlock block) {
540
  BlockIdExt id = block.id;
541
  if (block.id.is_masterchain()) {
542
    return;
543
  }
544
  if (cached_block_candidates_.emplace(id, std::move(block)).second) {
545
    cached_block_candidates_lru_.push_back(id);
546
    {
547
      auto it = wait_block_data_.find(id);
548
      if (it != wait_block_data_.end()) {
549
        auto r_block = create_block(cached_block_candidates_[id].clone());
550
        if (r_block.is_ok()) {
551
          td::actor::send_closure(it->second.actor_, &WaitBlockData::got_block_data_from_net, r_block.move_as_ok());
552
        }
553
      }
554
    }
555
    {
556
      auto it = wait_state_.find(id);
557
      if (it != wait_state_.end()) {
558
        // Proof link is not ready at this point, but this will force WaitBlockState to redo send_get_proof_link_request
559
        td::actor::send_closure(it->second.actor_, &WaitBlockState::after_get_proof_link);
560
      }
561
    }
562
  }
563
  if (cached_block_candidates_lru_.size() > max_cached_candidates()) {
564
    CHECK(cached_block_candidates_.erase(cached_block_candidates_lru_.front()));
565
    cached_block_candidates_lru_.pop_front();
566
  }
567
}
568

569
void ValidatorManagerImpl::add_ext_server_id(adnl::AdnlNodeIdShort id) {
570
  class Cb : public adnl::Adnl::Callback {
571
   private:
572
    td::actor::ActorId<ValidatorManagerImpl> id_;
573

574
    void receive_message(adnl::AdnlNodeIdShort src, adnl::AdnlNodeIdShort dst, td::BufferSlice data) override {
575
    }
576
    void receive_query(adnl::AdnlNodeIdShort src, adnl::AdnlNodeIdShort dst, td::BufferSlice data,
577
                       td::Promise<td::BufferSlice> promise) override {
578
      td::actor::send_closure(id_, &ValidatorManagerImpl::run_ext_query, std::move(data), std::move(promise));
579
    }
580

581
   public:
582
    Cb(td::actor::ActorId<ValidatorManagerImpl> id) : id_(id) {
583
    }
584
  };
585

586
  td::actor::send_closure(adnl_, &adnl::Adnl::subscribe, id,
587
                          adnl::Adnl::int_to_bytestring(lite_api::liteServer_query::ID),
588
                          std::make_unique<Cb>(actor_id(this)));
589

590
  if (lite_server_.empty()) {
591
    pending_ext_ids_.push_back(id);
592
  } else {
593
    td::actor::send_closure(lite_server_, &adnl::AdnlExtServer::add_local_id, id);
594
  }
595
}
596

597
void ValidatorManagerImpl::add_ext_server_port(td::uint16 port) {
598
  if (lite_server_.empty()) {
599
    pending_ext_ports_.push_back(port);
600
  } else {
601
    td::actor::send_closure(lite_server_, &adnl::AdnlExtServer::add_tcp_port, port);
602
  }
603
}
604

605
void ValidatorManagerImpl::created_ext_server(td::actor::ActorOwn<adnl::AdnlExtServer> server) {
606
  lite_server_ = std::move(server);
607
  for (auto &id : pending_ext_ids_) {
608
    td::actor::send_closure(lite_server_, &adnl::AdnlExtServer::add_local_id, id);
609
  }
610
  for (auto port : pending_ext_ports_) {
611
    td::actor::send_closure(lite_server_, &adnl::AdnlExtServer::add_tcp_port, port);
612
  }
613
  pending_ext_ids_.clear();
614
  pending_ext_ports_.clear();
615
}
616

617
void ValidatorManagerImpl::run_ext_query(td::BufferSlice data, td::Promise<td::BufferSlice> promise) {
618
  if (!started_) {
619
    promise.set_error(td::Status::Error(ErrorCode::notready, "node not synced"));
620
    return;
621
  }
622
  auto F = fetch_tl_object<lite_api::liteServer_query>(data.clone(), true);
623
  if (F.is_ok()) {
624
    data = std::move(F.move_as_ok()->data_);
625
  } else {
626
    auto G = fetch_tl_prefix<lite_api::liteServer_queryPrefix>(data, true);
627
    if (G.is_error()) {
628
      promise.set_error(G.move_as_error());
629
      return;
630
    }
631
  }
632

633
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
634
    td::BufferSlice data;
635
    if (R.is_error()) {
636
      auto S = R.move_as_error();
637
      data = create_serialize_tl_object<lite_api::liteServer_error>(S.code(), S.message().c_str());
638
    } else {
639
      data = R.move_as_ok();
640
    }
641
    promise.set_value(std::move(data));
642
  });
643

644
  auto E = fetch_tl_prefix<lite_api::liteServer_waitMasterchainSeqno>(data, true);
645
  if (E.is_error()) {
646
    run_liteserver_query(std::move(data), actor_id(this), lite_server_cache_.get(), std::move(P));
647
  } else {
648
    auto e = E.move_as_ok();
649
    if (static_cast<BlockSeqno>(e->seqno_) <= min_confirmed_masterchain_seqno_) {
650
      run_liteserver_query(std::move(data), actor_id(this), lite_server_cache_.get(), std::move(P));
651
    } else {
652
      auto t = e->timeout_ms_ < 10000 ? e->timeout_ms_ * 0.001 : 10.0;
653
      auto Q =
654
          td::PromiseCreator::lambda([data = std::move(data), SelfId = actor_id(this), cache = lite_server_cache_.get(),
655
                                      promise = std::move(P)](td::Result<td::Unit> R) mutable {
656
            if (R.is_error()) {
657
              promise.set_error(R.move_as_error());
658
              return;
659
            }
660
            run_liteserver_query(std::move(data), SelfId, cache, std::move(promise));
661
          });
662
      wait_shard_client_state(e->seqno_, td::Timestamp::in(t), std::move(Q));
663
    }
664
  }
665
}
666

667
void ValidatorManagerImpl::wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
668
                                            td::Promise<td::Ref<ShardState>> promise) {
669
  auto it0 = block_state_cache_.find(handle->id());
670
  if (it0 != block_state_cache_.end()) {
671
    it0->second.ttl_ = td::Timestamp::in(30.0);
672
    promise.set_result(it0->second.state_);
673
    return;
674
  }
675
  auto it = wait_state_.find(handle->id());
676
  if (it == wait_state_.end()) {
677
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
678
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_state, handle, std::move(R));
679
    });
680
    auto id = td::actor::create_actor<WaitBlockState>("waitstate", handle, priority, actor_id(this),
681
                                                      td::Timestamp::in(10.0), std::move(P))
682
                  .release();
683
    wait_state_[handle->id()].actor_ = id;
684
    it = wait_state_.find(handle->id());
685
  }
686

687
  it->second.waiting_.emplace_back(timeout, priority, std::move(promise));
688
  auto X = it->second.get_timeout();
689
  td::actor::send_closure(it->second.actor_, &WaitBlockState::update_timeout, X.first, X.second);
690
}
691

692
void ValidatorManagerImpl::wait_block_state_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout,
693
                                                  td::Promise<td::Ref<ShardState>> promise) {
694
  auto P = td::PromiseCreator::lambda(
695
      [SelfId = actor_id(this), priority, timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
696
        if (R.is_error()) {
697
          promise.set_error(R.move_as_error());
698
          return;
699
        }
700
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_state, R.move_as_ok(), priority, timeout,
701
                                std::move(promise));
702
      });
703
  get_block_handle(block_id, true, std::move(P));
704
}
705

706
void ValidatorManagerImpl::wait_block_data(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
707
                                           td::Promise<td::Ref<BlockData>> promise) {
708
  auto it = wait_block_data_.find(handle->id());
709
  if (it == wait_block_data_.end()) {
710
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<BlockData>> R) {
711
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_data, handle, std::move(R));
712
    });
713
    auto id = td::actor::create_actor<WaitBlockData>("waitdata", handle, priority, actor_id(this),
714
                                                     td::Timestamp::in(10.0), std::move(P))
715
                  .release();
716
    wait_block_data_[handle->id()].actor_ = id;
717
    it = wait_block_data_.find(handle->id());
718
  }
719

720
  it->second.waiting_.emplace_back(timeout, priority, std::move(promise));
721
  auto X = it->second.get_timeout();
722
  td::actor::send_closure(it->second.actor_, &WaitBlockData::update_timeout, X.first, X.second);
723
}
724

725
void ValidatorManagerImpl::wait_block_data_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout,
726
                                                 td::Promise<td::Ref<BlockData>> promise) {
727
  auto P = td::PromiseCreator::lambda(
728
      [SelfId = actor_id(this), priority, timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
729
        if (R.is_error()) {
730
          promise.set_error(R.move_as_error());
731
          return;
732
        }
733
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_data, R.move_as_ok(), priority, timeout,
734
                                std::move(promise));
735
      });
736
  get_block_handle(block_id, true, std::move(P));
737
}
738

739
void ValidatorManagerImpl::wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority,
740
                                                  td::Timestamp timeout, td::Promise<td::Ref<ShardState>> promise) {
741
  td::actor::create_actor<WaitBlockStateMerge>("merge", left_id, right_id, priority, actor_id(this), timeout,
742
                                               std::move(promise))
743
      .release();
744
}
745

746
void ValidatorManagerImpl::wait_prev_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
747
                                                 td::Promise<td::Ref<ShardState>> promise) {
748
  CHECK(handle);
749
  CHECK(!handle->is_zero());
750
  if (!handle->merge_before()) {
751
    auto shard = handle->id().shard_full();
752
    auto prev_shard = handle->one_prev(true).shard_full();
753
    if (shard == prev_shard) {
754
      wait_block_state_short(handle->one_prev(true), priority, timeout, std::move(promise));
755
    } else {
756
      CHECK(shard_parent(shard) == prev_shard);
757
      bool left = shard_child(prev_shard, true) == shard;
758
      auto P =
759
          td::PromiseCreator::lambda([promise = std::move(promise), left](td::Result<td::Ref<ShardState>> R) mutable {
760
            if (R.is_error()) {
761
              promise.set_error(R.move_as_error());
762
            } else {
763
              auto s = R.move_as_ok();
764
              auto r = s->split();
765
              if (r.is_error()) {
766
                promise.set_error(r.move_as_error());
767
              } else {
768
                auto v = r.move_as_ok();
769
                promise.set_value(left ? std::move(v.first) : std::move(v.second));
770
              }
771
            }
772
          });
773
      wait_block_state_short(handle->one_prev(true), priority, timeout, std::move(P));
774
    }
775
  } else {
776
    wait_block_state_merge(handle->one_prev(true), handle->one_prev(false), priority, timeout, std::move(promise));
777
  }
778
}
779

780
void ValidatorManagerImpl::wait_block_proof(BlockHandle handle, td::Timestamp timeout,
781
                                            td::Promise<td::Ref<Proof>> promise) {
782
  td::actor::send_closure(db_, &Db::get_block_proof, std::move(handle), std::move(promise));
783
}
784

785
void ValidatorManagerImpl::wait_block_proof_short(BlockIdExt block_id, td::Timestamp timeout,
786
                                                  td::Promise<td::Ref<Proof>> promise) {
787
  auto P = td::PromiseCreator::lambda(
788
      [SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
789
        if (R.is_error()) {
790
          promise.set_error(R.move_as_error());
791
          return;
792
        }
793
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_proof, R.move_as_ok(), timeout,
794
                                std::move(promise));
795
      });
796
  get_block_handle(block_id, true, std::move(P));
797
}
798

799
void ValidatorManagerImpl::wait_block_proof_link(BlockHandle handle, td::Timestamp timeout,
800
                                                 td::Promise<td::Ref<ProofLink>> promise) {
801
  td::actor::send_closure(db_, &Db::get_block_proof_link, std::move(handle), std::move(promise));
802
}
803

804
void ValidatorManagerImpl::wait_block_proof_link_short(BlockIdExt block_id, td::Timestamp timeout,
805
                                                       td::Promise<td::Ref<ProofLink>> promise) {
806
  auto P = td::PromiseCreator::lambda(
807
      [SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
808
        if (R.is_error()) {
809
          promise.set_error(R.move_as_error());
810
          return;
811
        }
812
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_proof_link, R.move_as_ok(), timeout,
813
                                std::move(promise));
814
      });
815
  get_block_handle(block_id, true, std::move(P));
816
}
817

818
void ValidatorManagerImpl::wait_block_signatures(BlockHandle handle, td::Timestamp timeout,
819
                                                 td::Promise<td::Ref<BlockSignatureSet>> promise) {
820
  td::actor::send_closure(db_, &Db::get_block_signatures, handle, std::move(promise));
821
}
822

823
void ValidatorManagerImpl::wait_block_signatures_short(BlockIdExt block_id, td::Timestamp timeout,
824
                                                       td::Promise<td::Ref<BlockSignatureSet>> promise) {
825
  auto P = td::PromiseCreator::lambda(
826
      [SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
827
        if (R.is_error()) {
828
          promise.set_error(R.move_as_error());
829
          return;
830
        }
831
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_signatures, R.move_as_ok(), timeout,
832
                                std::move(promise));
833
      });
834
  get_block_handle(block_id, true, std::move(P));
835
}
836

837
void ValidatorManagerImpl::wait_block_message_queue(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
838
                                                    td::Promise<td::Ref<MessageQueue>> promise) {
839
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<ShardState>> R) mutable {
840
    if (R.is_error()) {
841
      promise.set_error(R.move_as_error());
842
    } else {
843
      auto state = R.move_as_ok();
844
      promise.set_result(state->message_queue());
845
    }
846
  });
847

848
  wait_block_state(handle, priority, timeout, std::move(P));
849
}
850

851
void ValidatorManagerImpl::wait_block_message_queue_short(BlockIdExt block_id, td::uint32 priority,
852
                                                          td::Timestamp timeout,
853
                                                          td::Promise<td::Ref<MessageQueue>> promise) {
854
  auto P = td::PromiseCreator::lambda(
855
      [SelfId = actor_id(this), priority, timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
856
        if (R.is_error()) {
857
          promise.set_error(R.move_as_error());
858
          return;
859
        }
860
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_message_queue, R.move_as_ok(), priority,
861
                                timeout, std::move(promise));
862
      });
863
  get_block_handle(block_id, true, std::move(P));
864
}
865

866
void ValidatorManagerImpl::get_external_messages(
867
    ShardIdFull shard, td::Promise<std::vector<std::pair<td::Ref<ExtMessage>, int>>> promise) {
868
  td::Timer t;
869
  size_t processed = 0, deleted = 0;
870
  std::vector<std::pair<td::Ref<ExtMessage>, int>> res;
871
  MessageId<ExtMessage> left{AccountIdPrefixFull{shard.workchain, shard.shard & (shard.shard - 1)}, Bits256::zero()};
872
  size_t total_msgs = 0;
873
  td::Random::Fast rnd;
874
  for (auto iter = ext_msgs_.rbegin(); iter != ext_msgs_.rend(); ++iter) {
875
    std::vector<std::pair<td::Ref<ExtMessage>, int>> cur_res;
876
    int priority = iter->first;
877
    auto &msgs = iter->second;
878
    auto it = msgs.ext_messages_.lower_bound(left);
879
    while (it != msgs.ext_messages_.end()) {
880
      auto s = it->first;
881
      if (!shard_contains(shard, s.dst)) {
882
        break;
883
      }
884
      ++processed;
885
      if (it->second->expired()) {
886
        msgs.ext_addr_messages_[it->second->address()].erase(it->first.hash);
887
        ext_messages_hashes_.erase(it->first.hash);
888
        it = msgs.ext_messages_.erase(it);
889
        ++deleted;
890
        continue;
891
      }
892
      if (it->second->is_active()) {
893
        cur_res.emplace_back(it->second->message(), priority);
894
      }
895
      it++;
896
    }
897
    td::random_shuffle(td::as_mutable_span(cur_res), rnd);
898
    res.insert(res.end(), cur_res.begin(), cur_res.end());
899
    total_msgs += msgs.ext_messages_.size();
900
  }
901
  LOG(WARNING) << "get_external_messages to shard " << shard.to_str() << " : time=" << t.elapsed()
902
               << " result_size=" << res.size() << " processed=" << processed << " expired=" << deleted
903
               << " total_size=" << total_msgs;
904
  promise.set_value(std::move(res));
905
}
906

907
void ValidatorManagerImpl::get_ihr_messages(ShardIdFull shard, td::Promise<std::vector<td::Ref<IhrMessage>>> promise) {
908
  std::vector<td::Ref<IhrMessage>> res;
909
  MessageId<IhrMessage> left{AccountIdPrefixFull{shard.workchain, shard.shard & (shard.shard - 1)}, Bits256::zero()};
910
  auto it = ihr_messages_.lower_bound(left);
911
  while (it != ihr_messages_.end()) {
912
    auto s = it->first;
913
    if (!shard_contains(shard, s.dst)) {
914
      break;
915
    }
916
    if (it->second->expired()) {
917
      ihr_messages_hashes_.erase(it->first.hash);
918
      it = ihr_messages_.erase(it);
919
      continue;
920
    }
921
    if (it->second->is_active()) {
922
      res.push_back(it->second->message());
923
    }
924
    it++;
925
  }
926
  promise.set_value(std::move(res));
927
}
928

929
void ValidatorManagerImpl::get_shard_blocks(BlockIdExt masterchain_block_id,
930
                                            td::Promise<std::vector<td::Ref<ShardTopBlockDescription>>> promise) {
931
  std::vector<td::Ref<ShardTopBlockDescription>> v;
932
  for (auto &b : shard_blocks_) {
933
    v.push_back(b.second);
934
  }
935
  promise.set_value(std::move(v));
936
}
937

938
void ValidatorManagerImpl::complete_external_messages(std::vector<ExtMessage::Hash> to_delay,
939
                                                      std::vector<ExtMessage::Hash> to_delete) {
940
  for (auto &hash : to_delete) {
941
    auto it = ext_messages_hashes_.find(hash);
942
    if (it != ext_messages_hashes_.end()) {
943
      int priority = it->second.first;
944
      auto msg_id = it->second.second;
945
      ext_msgs_[priority].erase(msg_id);
946
      ext_messages_hashes_.erase(it);
947
    }
948
  }
949
  unsigned long soft_mempool_limit = 1024;
950
  for (auto &hash : to_delay) {
951
    auto it = ext_messages_hashes_.find(hash);
952
    if (it != ext_messages_hashes_.end()) {
953
      int priority = it->second.first;
954
      auto msg_id = it->second.second;
955
      auto &msgs = ext_msgs_[priority];
956
      auto it2 = msgs.ext_messages_.find(msg_id);
957
      if ((msgs.ext_messages_.size() < soft_mempool_limit) && it2->second->can_postpone()) {
958
        it2->second->postpone();
959
      } else {
960
        msgs.erase(msg_id);
961
        ext_messages_hashes_.erase(it);
962
      }
963
    }
964
  }
965
}
966

967
void ValidatorManagerImpl::complete_ihr_messages(std::vector<IhrMessage::Hash> to_delay,
968
                                                 std::vector<IhrMessage::Hash> to_delete) {
969
  for (auto &hash : to_delete) {
970
    auto it = ihr_messages_hashes_.find(hash);
971
    if (it != ihr_messages_hashes_.end()) {
972
      ihr_messages_.erase(it->second);
973
      ihr_messages_hashes_.erase(it);
974
    }
975
  }
976
  for (auto &hash : to_delay) {
977
    auto it = ihr_messages_hashes_.find(hash);
978
    if (it != ihr_messages_hashes_.end()) {
979
      auto it2 = ihr_messages_.find(it->second);
980
      CHECK(it2 != ihr_messages_.end());
981
      if (it2->second->can_postpone()) {
982
        it2->second->postpone();
983
      } else {
984
        ihr_messages_.erase(it2);
985
        ihr_messages_hashes_.erase(it);
986
      }
987
    }
988
  }
989
}
990

991
void ValidatorManagerImpl::get_block_data_from_db(ConstBlockHandle handle, td::Promise<td::Ref<BlockData>> promise) {
992
  td::actor::send_closure(db_, &Db::get_block_data, std::move(handle), std::move(promise));
993
}
994

995
void ValidatorManagerImpl::get_block_data_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<BlockData>> promise) {
996
  auto P =
997
      td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
998
        if (R.is_error()) {
999
          promise.set_error(R.move_as_error());
1000
        } else {
1001
          auto handle = R.move_as_ok();
1002
          td::actor::send_closure(db, &Db::get_block_data, std::move(handle), std::move(promise));
1003
        }
1004
      });
1005
  get_block_handle(block_id, false, std::move(P));
1006
}
1007

1008
void ValidatorManagerImpl::get_shard_state_from_db(ConstBlockHandle handle, td::Promise<td::Ref<ShardState>> promise) {
1009
  td::actor::send_closure(db_, &Db::get_block_state, handle, std::move(promise));
1010
}
1011

1012
void ValidatorManagerImpl::get_shard_state_from_db_short(BlockIdExt block_id,
1013
                                                         td::Promise<td::Ref<ShardState>> promise) {
1014
  auto P =
1015
      td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
1016
        if (R.is_error()) {
1017
          promise.set_error(R.move_as_error());
1018
        } else {
1019
          auto handle = R.move_as_ok();
1020
          td::actor::send_closure(db, &Db::get_block_state, std::move(handle), std::move(promise));
1021
        }
1022
      });
1023
  get_block_handle(block_id, false, std::move(P));
1024
}
1025

1026
void ValidatorManagerImpl::get_block_candidate_from_db(PublicKey source, BlockIdExt id,
1027
                                                       FileHash collated_data_file_hash,
1028
                                                       td::Promise<BlockCandidate> promise) {
1029
  td::actor::send_closure(db_, &Db::get_block_candidate, source, id, collated_data_file_hash, std::move(promise));
1030
}
1031

1032
void ValidatorManagerImpl::get_block_proof_from_db(ConstBlockHandle handle, td::Promise<td::Ref<Proof>> promise) {
1033
  td::actor::send_closure(db_, &Db::get_block_proof, std::move(handle), std::move(promise));
1034
}
1035

1036
void ValidatorManagerImpl::get_block_proof_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<Proof>> promise) {
1037
  auto P =
1038
      td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
1039
        if (R.is_error()) {
1040
          promise.set_error(R.move_as_error());
1041
        } else {
1042
          auto handle = R.move_as_ok();
1043
          td::actor::send_closure(db, &Db::get_block_proof, std::move(handle), std::move(promise));
1044
        }
1045
      });
1046
  get_block_handle(block_id, false, std::move(P));
1047
}
1048

1049
void ValidatorManagerImpl::get_block_proof_link_from_db(ConstBlockHandle handle,
1050
                                                        td::Promise<td::Ref<ProofLink>> promise) {
1051
  if (handle->inited_proof_link()) {
1052
    td::actor::send_closure(db_, &Db::get_block_proof_link, std::move(handle), std::move(promise));
1053
  } else if (handle->inited_proof()) {
1054
    auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
1055
      if (R.is_error()) {
1056
        promise.set_error(R.move_as_error());
1057
      } else {
1058
        promise.set_result(R.move_as_ok()->export_as_proof_link());
1059
      }
1060
    });
1061
    td::actor::send_closure(db_, &Db::get_block_proof, std::move(handle), std::move(P));
1062
  } else {
1063
    promise.set_error(td::Status::Error(ErrorCode::notready, "not in db"));
1064
  }
1065
}
1066

1067
void ValidatorManagerImpl::get_block_proof_link_from_db_short(BlockIdExt block_id,
1068
                                                              td::Promise<td::Ref<ProofLink>> promise) {
1069
  auto P = td::PromiseCreator::lambda(
1070
      [SelfId = actor_id(this), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
1071
        if (R.is_error()) {
1072
          promise.set_error(R.move_as_error());
1073
        } else {
1074
          auto handle = R.move_as_ok();
1075
          td::actor::send_closure(SelfId, &ValidatorManager::get_block_proof_link_from_db, std::move(handle),
1076
                                  std::move(promise));
1077
        }
1078
      });
1079
  get_block_handle(block_id, false, std::move(P));
1080
}
1081

1082
void ValidatorManagerImpl::get_block_by_lt_from_db(AccountIdPrefixFull account, LogicalTime lt,
1083
                                                   td::Promise<ConstBlockHandle> promise) {
1084
  td::actor::send_closure(db_, &Db::get_block_by_lt, account, lt, std::move(promise));
1085
}
1086

1087
void ValidatorManagerImpl::get_block_by_unix_time_from_db(AccountIdPrefixFull account, UnixTime ts,
1088
                                                          td::Promise<ConstBlockHandle> promise) {
1089
  td::actor::send_closure(db_, &Db::get_block_by_unix_time, account, ts, std::move(promise));
1090
}
1091

1092
void ValidatorManagerImpl::get_block_by_seqno_from_db(AccountIdPrefixFull account, BlockSeqno seqno,
1093
                                                      td::Promise<ConstBlockHandle> promise) {
1094
  td::actor::send_closure(db_, &Db::get_block_by_seqno, account, seqno, std::move(promise));
1095
}
1096

1097
void ValidatorManagerImpl::finished_wait_state(BlockHandle handle, td::Result<td::Ref<ShardState>> R) {
1098
  if (R.is_ok()) {
1099
    block_state_cache_[handle->id()] = {R.ok(), td::Timestamp::in(30.0)};
1100
  }
1101
  auto it = wait_state_.find(handle->id());
1102
  if (it != wait_state_.end()) {
1103
    if (R.is_error()) {
1104
      auto S = R.move_as_error();
1105
      if (S.code() != ErrorCode::timeout) {
1106
        for (auto &X : it->second.waiting_) {
1107
          X.promise.set_error(S.clone());
1108
        }
1109
      } else if (it->second.waiting_.size() != 0) {
1110
        auto X = it->second.get_timeout();
1111
        auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
1112
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_state, handle, std::move(R));
1113
        });
1114
        auto id = td::actor::create_actor<WaitBlockState>("waitstate", handle, X.second, actor_id(this), X.first,
1115
                                                          std::move(P))
1116
                      .release();
1117
        it->second.actor_ = id;
1118
        return;
1119
      }
1120
    } else {
1121
      auto r = R.move_as_ok();
1122
      for (auto &X : it->second.waiting_) {
1123
        X.promise.set_result(r);
1124
      }
1125
    }
1126
    wait_state_.erase(it);
1127
  }
1128
}
1129

1130
void ValidatorManagerImpl::finished_wait_data(BlockHandle handle, td::Result<td::Ref<BlockData>> R) {
1131
  auto it = wait_block_data_.find(handle->id());
1132
  if (it != wait_block_data_.end()) {
1133
    if (R.is_error()) {
1134
      auto S = R.move_as_error();
1135
      if (S.code() != ErrorCode::timeout) {
1136
        for (auto &X : it->second.waiting_) {
1137
          X.promise.set_error(S.clone());
1138
        }
1139
      } else {
1140
        auto X = it->second.get_timeout();
1141
        auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<BlockData>> R) {
1142
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_data, handle, std::move(R));
1143
        });
1144
        auto id =
1145
            td::actor::create_actor<WaitBlockData>("waitdata", handle, X.second, actor_id(this), X.first, std::move(P))
1146
                .release();
1147
        it->second.actor_ = id;
1148
        return;
1149
      }
1150
    } else {
1151
      auto r = R.move_as_ok();
1152
      for (auto &X : it->second.waiting_) {
1153
        X.promise.set_result(r);
1154
      }
1155
    }
1156
    wait_block_data_.erase(it);
1157
  }
1158
}
1159

1160
void ValidatorManagerImpl::set_block_state(BlockHandle handle, td::Ref<ShardState> state,
1161
                                           td::Promise<td::Ref<ShardState>> promise) {
1162
  auto P = td::PromiseCreator::lambda(
1163
      [SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result<td::Ref<ShardState>> R) mutable {
1164
        if (R.is_error()) {
1165
          promise.set_error(R.move_as_error());
1166
        } else {
1167
          promise.set_value(R.move_as_ok());
1168
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_handle, std::move(handle), [](td::Unit) {});
1169
        }
1170
      });
1171
  td::actor::send_closure(db_, &Db::store_block_state, handle, state, std::move(P));
1172
}
1173

1174
void ValidatorManagerImpl::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise) {
1175
  td::actor::send_closure(db_, &Db::get_cell_db_reader, std::move(promise));
1176
}
1177

1178
void ValidatorManagerImpl::store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id,
1179
                                                       td::BufferSlice state, td::Promise<td::Unit> promise) {
1180
  td::actor::send_closure(db_, &Db::store_persistent_state_file, block_id, masterchain_block_id, std::move(state),
1181
                          std::move(promise));
1182
}
1183

1184
void ValidatorManagerImpl::store_persistent_state_file_gen(BlockIdExt block_id, BlockIdExt masterchain_block_id,
1185
                                                           std::function<td::Status(td::FileFd&)> write_data,
1186
                                                           td::Promise<td::Unit> promise) {
1187
  td::actor::send_closure(db_, &Db::store_persistent_state_file_gen, block_id, masterchain_block_id,
1188
                          std::move(write_data), std::move(promise));
1189
}
1190

1191
void ValidatorManagerImpl::store_zero_state_file(BlockIdExt block_id, td::BufferSlice state,
1192
                                                 td::Promise<td::Unit> promise) {
1193
  td::actor::send_closure(db_, &Db::store_zero_state_file, block_id, std::move(state), std::move(promise));
1194
}
1195

1196
void ValidatorManagerImpl::set_block_data(BlockHandle handle, td::Ref<BlockData> data, td::Promise<td::Unit> promise) {
1197
  auto P = td::PromiseCreator::lambda(
1198
      [SelfId = actor_id(this), data, handle, promise = std::move(promise)](td::Result<td::Unit> R) mutable {
1199
        if (R.is_error()) {
1200
          promise.set_error(R.move_as_error());
1201
        } else {
1202
          promise.set_value(td::Unit());
1203
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_handle, std::move(handle), [](td::Unit) {});
1204
        }
1205
      });
1206
  td::actor::send_closure(db_, &Db::store_block_data, handle, std::move(data), std::move(P));
1207
}
1208

1209
void ValidatorManagerImpl::set_block_proof(BlockHandle handle, td::Ref<Proof> proof, td::Promise<td::Unit> promise) {
1210
  auto P = td::PromiseCreator::lambda(
1211
      [SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result<td::Unit> R) mutable {
1212
        if (R.is_error()) {
1213
          promise.set_error(R.move_as_error());
1214
        } else {
1215
          promise.set_value(td::Unit());
1216
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_handle, std::move(handle), [](td::Unit) {});
1217
        }
1218
      });
1219
  td::actor::send_closure(db_, &Db::store_block_proof, handle, std::move(proof), std::move(P));
1220
}
1221

1222
void ValidatorManagerImpl::set_block_proof_link(BlockHandle handle, td::Ref<ProofLink> proof,
1223
                                                td::Promise<td::Unit> promise) {
1224
  auto P = td::PromiseCreator::lambda(
1225
      [SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result<td::Unit> R) mutable {
1226
        if (R.is_error()) {
1227
          promise.set_error(R.move_as_error());
1228
        } else {
1229
          promise.set_value(td::Unit());
1230
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_handle, std::move(handle), [](td::Unit) {});
1231
        }
1232
      });
1233
  td::actor::send_closure(db_, &Db::store_block_proof_link, handle, std::move(proof), std::move(P));
1234
}
1235

1236
/*void ValidatorManagerImpl::set_zero_state(ZeroStateIdExt id, td::Ref<ShardState> state, td::Promise<td::Unit> promise) {
1237
  td::actor::send_closure(db_, &Db::store_zero_state, id, std::move(state), std::move(promise));
1238
}*/
1239

1240
void ValidatorManagerImpl::set_block_signatures(BlockHandle handle, td::Ref<BlockSignatureSet> signatures,
1241
                                                td::Promise<td::Unit> promise) {
1242
  td::actor::send_closure(db_, &Db::store_block_signatures, handle, std::move(signatures), std::move(promise));
1243
}
1244

1245
void ValidatorManagerImpl::set_next_block(BlockIdExt block_id, BlockIdExt next, td::Promise<td::Unit> promise) {
1246
  auto P = td::PromiseCreator::lambda(
1247
      [SelfId = actor_id(this), next, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
1248
        if (R.is_error()) {
1249
          promise.set_error(R.move_as_error());
1250
        } else {
1251
          auto handle = R.move_as_ok();
1252
          handle->set_next(next);
1253
          if (handle->need_flush()) {
1254
            handle->flush(SelfId, handle, std::move(promise));
1255
          } else {
1256
            promise.set_value(td::Unit());
1257
          }
1258
        }
1259
      });
1260
  get_block_handle(block_id, true, std::move(P));
1261
}
1262

1263
void ValidatorManagerImpl::set_block_candidate(BlockIdExt id, BlockCandidate candidate, CatchainSeqno cc_seqno,
1264
                                               td::uint32 validator_set_hash, td::Promise<td::Unit> promise) {
1265
  if (!candidates_buffer_.empty()) {
1266
    td::actor::send_closure(candidates_buffer_, &CandidatesBuffer::add_new_candidate, id,
1267
                            PublicKey{pubkeys::Ed25519{candidate.pubkey.as_bits256()}}, candidate.collated_file_hash);
1268
  }
1269
  if (!id.is_masterchain()) {
1270
    add_cached_block_candidate(ReceivedBlock{id, candidate.data.clone()});
1271
    callback_->send_block_candidate(id, cc_seqno, validator_set_hash, candidate.data.clone());
1272
  }
1273
  td::actor::send_closure(db_, &Db::store_block_candidate, std::move(candidate), std::move(promise));
1274
}
1275

1276
void ValidatorManagerImpl::write_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
1277
  auto P = td::PromiseCreator::lambda(
1278
      [SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result<td::Unit> R) mutable {
1279
        if (R.is_error()) {
1280
          promise.set_error(R.move_as_error());
1281
        } else {
1282
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_handle, std::move(handle), std::move(promise));
1283
        }
1284
      });
1285
  td::actor::send_closure(db_, &Db::store_block_handle, std::move(handle), std::move(P));
1286
}
1287

1288
void ValidatorManagerImpl::written_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
1289
  bool received = handle->received();
1290
  bool inited_state = handle->received_state();
1291
  bool inited_proof = handle->id().is_masterchain() ? handle->inited_proof() : handle->inited_proof_link();
1292

1293
  if (handle->need_flush()) {
1294
    handle->flush(actor_id(this), handle, std::move(promise));
1295
    return;
1296
  }
1297

1298
  if (received && inited_proof) {
1299
    auto it = wait_block_data_.find(handle->id());
1300
    if (it != wait_block_data_.end()) {
1301
      td::actor::send_closure(it->second.actor_, &WaitBlockData::force_read_from_db);
1302
    }
1303
  }
1304
  if (inited_state) {
1305
    auto it = wait_state_.find(handle->id());
1306
    if (it != wait_state_.end()) {
1307
      td::actor::send_closure(it->second.actor_, &WaitBlockState::force_read_from_db);
1308
    }
1309
  } else {
1310
    if (handle->inited_proof_link()) {
1311
      auto it = wait_state_.find(handle->id());
1312
      if (it != wait_state_.end()) {
1313
        td::actor::send_closure(it->second.actor_, &WaitBlockState::after_get_proof_link);
1314
      }
1315
    }
1316
    if (handle->id().is_masterchain() && handle->inited_proof()) {
1317
      auto it = wait_state_.find(handle->id());
1318
      if (it != wait_state_.end()) {
1319
        td::actor::send_closure(it->second.actor_, &WaitBlockState::after_get_proof);
1320
      }
1321
    }
1322
  }
1323

1324
  promise.set_value(td::Unit());
1325
}
1326

1327
void ValidatorManagerImpl::new_block_cont(BlockHandle handle, td::Ref<ShardState> state,
1328
                                          td::Promise<td::Unit> promise) {
1329
  if (state->get_shard().is_masterchain() && handle->id().id.seqno > last_masterchain_seqno_) {
1330
    if (handle->id().id.seqno == last_masterchain_seqno_ + 1) {
1331
      last_masterchain_seqno_ = handle->id().id.seqno;
1332
      last_masterchain_state_ = td::Ref<MasterchainState>{state};
1333
      last_masterchain_block_id_ = handle->id();
1334
      last_masterchain_block_handle_ = handle;
1335
      last_masterchain_block_handle_->set_processed();
1336

1337
      new_masterchain_block();
1338

1339
      promise.set_value(td::Unit());
1340

1341
      while (true) {
1342
        auto it = pending_masterchain_states_.find(last_masterchain_seqno_ + 1);
1343
        if (it != pending_masterchain_states_.end()) {
1344
          CHECK(it == pending_masterchain_states_.begin());
1345
          last_masterchain_block_handle_ = std::move(std::get<0>(it->second));
1346
          last_masterchain_state_ = std::move(std::get<1>(it->second));
1347
          last_masterchain_block_id_ = last_masterchain_block_handle_->id();
1348
          last_masterchain_seqno_ = last_masterchain_block_id_.id.seqno;
1349
          CHECK(it->first == last_masterchain_seqno_);
1350

1351
          auto l_promise = std::move(std::get<2>(it->second));
1352
          last_masterchain_block_handle_->set_processed();
1353

1354
          pending_masterchain_states_.erase(it);
1355

1356
          new_masterchain_block();
1357

1358
          for (auto &p : l_promise) {
1359
            p.set_value(td::Unit());
1360
          }
1361
        } else {
1362
          break;
1363
        }
1364
      }
1365
    } else {
1366
      auto it = pending_masterchain_states_.find(handle->id().id.seqno);
1367
      if (it != pending_masterchain_states_.end()) {
1368
        std::get<2>(it->second).emplace_back(std::move(promise));
1369
      } else {
1370
        std::vector<td::Promise<td::Unit>> v;
1371
        v.emplace_back(std::move(promise));
1372
        pending_masterchain_states_.emplace(
1373
            handle->id().id.seqno,
1374
            std::forward_as_tuple(handle, td::Ref<MasterchainState>{std::move(state)}, std::move(v)));
1375
      }
1376
    }
1377
  } else {
1378
    handle->set_processed();
1379
    promise.set_value(td::Unit());
1380
  }
1381
}
1382

1383
void ValidatorManagerImpl::new_block(BlockHandle handle, td::Ref<ShardState> state, td::Promise<td::Unit> promise) {
1384
  if (handle->is_applied()) {
1385
    return new_block_cont(std::move(handle), std::move(state), std::move(promise));
1386
  } else {
1387
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle, state = std::move(state),
1388
                                         promise = std::move(promise)](td::Result<td::Unit> R) mutable {
1389
      if (R.is_error()) {
1390
        promise.set_error(R.move_as_error());
1391
      } else {
1392
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::new_block_cont, std::move(handle), std::move(state),
1393
                                std::move(promise));
1394
      }
1395
    });
1396
    td::actor::send_closure(db_, &Db::apply_block, handle, std::move(P));
1397
  }
1398
}
1399

1400
void ValidatorManagerImpl::get_block_handle(BlockIdExt id, bool force, td::Promise<BlockHandle> promise) {
1401
  if (!id.is_valid()) {
1402
    promise.set_error(td::Status::Error(ErrorCode::protoviolation, "bad block id"));
1403
    return;
1404
  }
1405
  {
1406
    // updates LRU position if found
1407
    auto B = get_handle_from_lru(id);
1408
    if (B) {
1409
      CHECK(B->id() == id);
1410
      promise.set_value(std::move(B));
1411
      return;
1412
    }
1413
  }
1414
  auto it = handles_.find(id);
1415
  if (it != handles_.end()) {
1416
    auto handle = it->second.lock();
1417
    if (handle) {
1418
      CHECK(handle->id() == id);
1419
      promise.set_value(std::move(handle));
1420
      return;
1421
    } else {
1422
      handles_.erase(it);
1423
    }
1424
  }
1425

1426
  auto it2 = wait_block_handle_.find(id);
1427
  if (it2 != wait_block_handle_.end()) {
1428
    it2->second.waiting_.emplace_back(std::move(promise));
1429
    return;
1430
  }
1431

1432
  wait_block_handle_.emplace(id, WaitBlockHandle{});
1433
  wait_block_handle_[id].waiting_.emplace_back(std::move(promise));
1434

1435
  auto P = td::PromiseCreator::lambda([id, force = true, SelfId = actor_id(this)](td::Result<BlockHandle> R) mutable {
1436
    BlockHandle handle;
1437
    if (R.is_error()) {
1438
      auto S = R.move_as_error();
1439
      if (S.code() == ErrorCode::notready && force) {
1440
        handle = create_empty_block_handle(id);
1441
      } else {
1442
        LOG(FATAL) << "db error: failed to get block " << id << ": " << S;
1443
        return;
1444
      }
1445
    } else {
1446
      handle = R.move_as_ok();
1447
    }
1448
    CHECK(handle);
1449
    CHECK(handle->id() == id);
1450
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::register_block_handle, std::move(handle));
1451
  });
1452

1453
  td::actor::send_closure(db_, &Db::get_block_handle, id, std::move(P));
1454
}
1455

1456
void ValidatorManagerImpl::register_block_handle(BlockHandle handle) {
1457
  CHECK(handles_.find(handle->id()) == handles_.end());
1458
  handles_.emplace(handle->id(), std::weak_ptr<BlockHandleInterface>(handle));
1459
  add_handle_to_lru(handle);
1460
  {
1461
    auto it = wait_block_handle_.find(handle->id());
1462
    CHECK(it != wait_block_handle_.end());
1463
    for (auto &p : it->second.waiting_) {
1464
      p.set_result(handle);
1465
    }
1466
    wait_block_handle_.erase(it);
1467
  }
1468
}
1469

1470
void ValidatorManagerImpl::get_top_masterchain_state(td::Promise<td::Ref<MasterchainState>> promise) {
1471
  if (last_masterchain_state_.is_null()) {
1472
    promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not started"));
1473
  } else {
1474
    promise.set_result(last_masterchain_state_);
1475
  }
1476
}
1477

1478
td::Ref<MasterchainState> ValidatorManagerImpl::do_get_last_liteserver_state() {
1479
  if (last_masterchain_state_.is_null()) {
1480
    return {};
1481
  }
1482
  if (last_liteserver_state_.is_null()) {
1483
    last_liteserver_state_ = last_masterchain_state_;
1484
    return last_liteserver_state_;
1485
  }
1486
  if (last_liteserver_state_->get_seqno() == last_masterchain_state_->get_seqno()) {
1487
    return last_liteserver_state_;
1488
  }
1489
  // If liteserver seqno (i.e. shard client) lags then use last masterchain state for liteserver
1490
  // Allowed lag depends on the block rate
1491
  double time_per_block = double(last_masterchain_state_->get_unix_time() - last_liteserver_state_->get_unix_time()) /
1492
                          double(last_masterchain_state_->get_seqno() - last_liteserver_state_->get_seqno());
1493
  if (td::Clocks::system() - double(last_liteserver_state_->get_unix_time()) > std::min(time_per_block * 8, 180.0)) {
1494
    last_liteserver_state_ = last_masterchain_state_;
1495
  }
1496
  return last_liteserver_state_;
1497
}
1498

1499
void ValidatorManagerImpl::get_top_masterchain_block(td::Promise<BlockIdExt> promise) {
1500
  if (!last_masterchain_block_id_.is_valid()) {
1501
    promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not started"));
1502
  } else {
1503
    promise.set_result(last_masterchain_block_id_);
1504
  }
1505
}
1506

1507
void ValidatorManagerImpl::get_top_masterchain_state_block(
1508
    td::Promise<std::pair<td::Ref<MasterchainState>, BlockIdExt>> promise) {
1509
  if (last_masterchain_state_.is_null()) {
1510
    promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not started"));
1511
  } else {
1512
    promise.set_result(
1513
        std::pair<td::Ref<MasterchainState>, BlockIdExt>{last_masterchain_state_, last_masterchain_block_id_});
1514
  }
1515
}
1516

1517
void ValidatorManagerImpl::get_last_liteserver_state_block(
1518
    td::Promise<std::pair<td::Ref<MasterchainState>, BlockIdExt>> promise) {
1519
  auto state = do_get_last_liteserver_state();
1520
  if (state.is_null()) {
1521
    promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not started"));
1522
  } else {
1523
    promise.set_result(std::pair<td::Ref<MasterchainState>, BlockIdExt>{state, state->get_block_id()});
1524
  }
1525
}
1526

1527
void ValidatorManagerImpl::send_get_block_request(BlockIdExt id, td::uint32 priority,
1528
                                                  td::Promise<ReceivedBlock> promise) {
1529
  {
1530
    auto it = cached_block_candidates_.find(id);
1531
    if (it != cached_block_candidates_.end()) {
1532
      LOG(DEBUG) << "send_get_block_request: got result from candidates cache for " << id.to_str();
1533
      return promise.set_value(it->second.clone());
1534
    }
1535
  }
1536
  callback_->download_block(id, priority, td::Timestamp::in(10.0), std::move(promise));
1537
}
1538

1539
void ValidatorManagerImpl::send_get_zero_state_request(BlockIdExt id, td::uint32 priority,
1540
                                                       td::Promise<td::BufferSlice> promise) {
1541
  callback_->download_zero_state(id, priority, td::Timestamp::in(10.0), std::move(promise));
1542
}
1543

1544
void ValidatorManagerImpl::send_get_persistent_state_request(BlockIdExt id, BlockIdExt masterchain_block_id,
1545
                                                             td::uint32 priority,
1546
                                                             td::Promise<td::BufferSlice> promise) {
1547
  callback_->download_persistent_state(id, masterchain_block_id, priority, td::Timestamp::in(3600 * 3),
1548
                                       std::move(promise));
1549
}
1550

1551
void ValidatorManagerImpl::send_get_block_proof_request(BlockIdExt block_id, td::uint32 priority,
1552
                                                        td::Promise<td::BufferSlice> promise) {
1553
  callback_->download_block_proof(block_id, priority, td::Timestamp::in(10.0), std::move(promise));
1554
}
1555

1556
void ValidatorManagerImpl::send_get_block_proof_link_request(BlockIdExt block_id, td::uint32 priority,
1557
                                                             td::Promise<td::BufferSlice> promise) {
1558
  if (!block_id.is_masterchain()) {
1559
    auto it = cached_block_candidates_.find(block_id);
1560
    if (it != cached_block_candidates_.end()) {
1561
      // Proof link can be created from the cached block candidate
1562
      LOG(DEBUG) << "send_get_block_proof_link_request: creating proof link from cached caniddate for "
1563
                 << block_id.to_str();
1564
      TRY_RESULT_PROMISE_PREFIX(promise, block_root, vm::std_boc_deserialize(it->second.data),
1565
                                "failed to create proof link: ");
1566
      TRY_RESULT_PROMISE_PREFIX(promise, proof_link, WaitBlockData::generate_proof_link(it->second.id, block_root),
1567
                                "failed to create proof link: ");
1568
      promise.set_result(std::move(proof_link));
1569
      return;
1570
    }
1571
  }
1572
  callback_->download_block_proof_link(block_id, priority, td::Timestamp::in(10.0), std::move(promise));
1573
}
1574

1575
void ValidatorManagerImpl::send_get_next_key_blocks_request(BlockIdExt block_id, td::uint32 priority,
1576
                                                            td::Promise<std::vector<BlockIdExt>> promise) {
1577
  callback_->get_next_key_blocks(block_id, td::Timestamp::in(10.0), std::move(promise));
1578
}
1579

1580
void ValidatorManagerImpl::send_external_message(td::Ref<ExtMessage> message) {
1581
  callback_->send_ext_message(message->shard(), message->serialize());
1582
  add_external_message(std::move(message), 0);
1583
}
1584

1585
void ValidatorManagerImpl::send_ihr_message(td::Ref<IhrMessage> message) {
1586
  callback_->send_ihr_message(message->shard(), message->serialize());
1587
}
1588

1589
void ValidatorManagerImpl::send_top_shard_block_description(td::Ref<ShardTopBlockDescription> desc) {
1590
  if (!resend_shard_blocks_at_) {
1591
    resend_shard_blocks_at_ = td::Timestamp::in(td::Random::fast(0, 100) * 0.01 + 2.0);
1592
    alarm_timestamp().relax(resend_shard_blocks_at_);
1593
  }
1594
  auto it = out_shard_blocks_.find(ShardTopBlockDescriptionId{desc->block_id().shard_full(), desc->catchain_seqno()});
1595
  if (it != out_shard_blocks_.end() && desc->block_id().id.seqno <= it->second->block_id().id.seqno) {
1596
    VLOG(VALIDATOR_DEBUG) << "dropping duplicate top block description";
1597
  } else {
1598
    out_shard_blocks_[ShardTopBlockDescriptionId{desc->block_id().shard_full(), desc->catchain_seqno()}] = desc;
1599
    callback_->send_shard_block_info(desc->block_id(), desc->catchain_seqno(), desc->serialize());
1600
  }
1601
}
1602

1603
void ValidatorManagerImpl::send_block_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) {
1604
  callback_->send_broadcast(std::move(broadcast), custom_overlays_only);
1605
}
1606

1607
void ValidatorManagerImpl::start_up() {
1608
  db_ = create_db_actor(actor_id(this), db_root_, opts_);
1609
  lite_server_cache_ = create_liteserver_cache_actor(actor_id(this), db_root_);
1610
  token_manager_ = td::actor::create_actor<TokenManager>("tokenmanager");
1611
  td::mkdir(db_root_ + "/tmp/").ensure();
1612
  td::mkdir(db_root_ + "/catchains/").ensure();
1613

1614
  auto Q =
1615
      td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::actor::ActorOwn<adnl::AdnlExtServer>> R) {
1616
        R.ensure();
1617
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::created_ext_server, R.move_as_ok());
1618
      });
1619
  td::actor::send_closure(adnl_, &adnl::Adnl::create_ext_server, std::vector<adnl::AdnlNodeIdShort>{},
1620
                          std::vector<td::uint16>{}, std::move(Q));
1621

1622
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<ValidatorManagerInitResult> R) {
1623
    R.ensure();
1624
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::started, R.move_as_ok());
1625
  });
1626

1627
  auto to_import_dir = db_root_ + "/import";
1628
  auto S = td::WalkPath::run(to_import_dir, [&](td::CSlice cfname, td::WalkPath::Type t) -> void {
1629
    auto fname = td::Slice(cfname);
1630
    if (t == td::WalkPath::Type::NotDir) {
1631
      auto d = fname.rfind(TD_DIR_SLASH);
1632
      if (d != td::Slice::npos) {
1633
        fname = fname.substr(d + 1);
1634
      }
1635
      if (fname.size() <= 13) {
1636
        return;
1637
      }
1638
      if (fname.substr(fname.size() - 5) != ".pack") {
1639
        return;
1640
      }
1641
      fname = fname.substr(0, fname.size() - 5);
1642
      if (fname.substr(0, 8) != "archive.") {
1643
        return;
1644
      }
1645
      fname = fname.substr(8);
1646

1647
      while (fname.size() > 1 && fname[0] == '0') {
1648
        fname.remove_prefix(1);
1649
      }
1650
      auto v = td::to_integer_safe<BlockSeqno>(fname);
1651
      if (v.is_error()) {
1652
        return;
1653
      }
1654
      auto pos = v.move_as_ok();
1655
      LOG(INFO) << "found archive slice '" << cfname << "' for position " << pos;
1656
      to_import_[pos] = std::make_pair(cfname.str(), true);
1657
    }
1658
  });
1659
  if (S.is_error()) {
1660
    LOG(INFO) << "failed to load blocks from import dir: " << S;
1661
  }
1662

1663
  validator_manager_init(opts_, actor_id(this), db_.get(), std::move(P));
1664

1665
  check_waiters_at_ = td::Timestamp::in(1.0);
1666
  alarm_timestamp().relax(check_waiters_at_);
1667
}
1668

1669
void ValidatorManagerImpl::started(ValidatorManagerInitResult R) {
1670
  CHECK(R.handle);
1671
  CHECK(R.state.not_null());
1672
  last_masterchain_block_handle_ = std::move(R.handle);
1673
  last_masterchain_block_id_ = last_masterchain_block_handle_->id();
1674
  last_masterchain_seqno_ = last_masterchain_block_id_.id.seqno;
1675
  last_masterchain_state_ = std::move(R.state);
1676

1677
  last_key_block_handle_ = std::move(R.last_key_block_handle_);
1678
  last_known_key_block_handle_ = last_key_block_handle_;
1679

1680
  CHECK(last_masterchain_block_handle_->is_applied());
1681
  if (last_known_key_block_handle_->inited_is_key_block()) {
1682
    callback_->new_key_block(last_key_block_handle_);
1683
  }
1684

1685
  gc_masterchain_handle_ = std::move(R.gc_handle);
1686
  gc_masterchain_state_ = std::move(R.gc_state);
1687

1688
  shard_client_ = std::move(R.clients);
1689

1690
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<ValidatorSessionId>> R) {
1691
    if (R.is_error()) {
1692
      if (R.error().code() == ErrorCode::notready) {
1693
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::read_gc_list, std::vector<ValidatorSessionId>{});
1694
      } else {
1695
        LOG(FATAL) << "db error: " << R.move_as_error();
1696
      }
1697
    } else {
1698
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::read_gc_list, R.move_as_ok());
1699
    }
1700
  });
1701
  td::actor::send_closure(db_, &Db::get_destroyed_validator_sessions, std::move(P));
1702

1703
  if (opts_->nonfinal_ls_queries_enabled()) {
1704
    candidates_buffer_ = td::actor::create_actor<CandidatesBuffer>("candidates-buffer", actor_id(this));
1705
  }
1706
}
1707

1708
void ValidatorManagerImpl::read_gc_list(std::vector<ValidatorSessionId> list) {
1709
  for (auto &v : list) {
1710
    check_gc_list_.insert(v);
1711
  }
1712

1713
  new_masterchain_block();
1714

1715
  serializer_ =
1716
      td::actor::create_actor<AsyncStateSerializer>("serializer", last_key_block_handle_->id(), opts_, actor_id(this));
1717

1718
  if (last_masterchain_block_handle_->inited_next_left()) {
1719
    auto b = last_masterchain_block_handle_->one_next(true);
1720
    if (opts_->is_hardfork(b) && !out_of_sync()) {
1721
      auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), b](td::Result<td::BufferSlice> R) {
1722
        if (R.is_error()) {
1723
          LOG(INFO) << "NO HARDFORK BLOCK IN STATIC FILES";
1724
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::applied_hardfork);
1725
          return;
1726
        }
1727

1728
        auto dataR = create_block(b, R.move_as_ok());
1729
        dataR.ensure();
1730

1731
        auto P = td::PromiseCreator::lambda([SelfId](td::Result<td::Unit> R) {
1732
          R.ensure();
1733
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::applied_hardfork);
1734
        });
1735
        run_hardfork_accept_block_query(b, dataR.move_as_ok(), SelfId, std::move(P));
1736
      });
1737
      td::actor::send_closure(db_, &Db::try_get_static_file, b.file_hash, std::move(P));
1738
      return;
1739
    }
1740
  }
1741

1742
  if (!out_of_sync()) {
1743
    completed_prestart_sync();
1744
  } else {
1745
    prestart_sync();
1746
  }
1747
}
1748

1749
void ValidatorManagerImpl::applied_hardfork() {
1750
  if (!out_of_sync()) {
1751
    completed_prestart_sync();
1752
  } else {
1753
    prestart_sync();
1754
  }
1755
}
1756

1757
bool ValidatorManagerImpl::out_of_sync() {
1758
  auto seqno = std::min(last_masterchain_seqno_, shard_client_handle_->id().seqno());
1759
  if (seqno < opts_->sync_upto()) {
1760
    return true;
1761
  }
1762
  if (shard_client_handle_->id().seqno() + 16 < last_masterchain_seqno_) {
1763
    return true;
1764
  }
1765
  if (last_masterchain_block_handle_->unix_time() + 600 > td::Clocks::system()) {
1766
    return false;
1767
  }
1768

1769
  if (last_masterchain_seqno_ < last_known_key_block_handle_->id().seqno()) {
1770
    return true;
1771
  }
1772

1773
  bool masterchain_validator = false;
1774
  if (!validator_groups_.size()) {
1775
    auto val_set = last_masterchain_state_->get_validator_set(ShardIdFull{masterchainId});
1776
    if (!get_validator(ShardIdFull{masterchainId}, val_set).is_zero()) {
1777
      masterchain_validator = true;
1778
    }
1779
  }
1780

1781
  if ((masterchain_validator || validator_groups_.size() > 0) &&
1782
      last_known_key_block_handle_->id().seqno() <= last_masterchain_seqno_) {
1783
    return false;
1784
  }
1785
  LOG(INFO) << "groups=" << validator_groups_.size() << " seqno=" << last_known_key_block_handle_->id().seqno()
1786
            << " our_seqno=" << last_masterchain_seqno_;
1787

1788
  return true;
1789
}
1790

1791
void ValidatorManagerImpl::prestart_sync() {
1792
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
1793
    R.ensure();
1794
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
1795
  });
1796
  td::actor::send_closure(db_, &Db::set_async_mode, false, std::move(P));
1797
}
1798

1799
void ValidatorManagerImpl::download_next_archive() {
1800
  if (!out_of_sync()) {
1801
    finish_prestart_sync();
1802
    return;
1803
  }
1804

1805
  auto seqno = std::min(last_masterchain_seqno_, shard_client_handle_->id().seqno());
1806
  auto it = to_import_.upper_bound(seqno + 1);
1807
  if (it != to_import_.begin()) {
1808
    it--;
1809
    if (it->second.second) {
1810
      it->second.second = false;
1811
      downloaded_archive_slice(it->second.first, false);
1812
      return;
1813
    }
1814
  }
1815
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::string> R) {
1816
    if (R.is_error()) {
1817
      LOG(INFO) << "failed to download archive slice: " << R.error();
1818
      delay_action([SelfId]() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive); },
1819
                   td::Timestamp::in(2.0));
1820
    } else {
1821
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::downloaded_archive_slice, R.move_as_ok(), true);
1822
    }
1823
  });
1824
  callback_->download_archive(seqno + 1, db_root_ + "/tmp/", td::Timestamp::in(36000.0), std::move(P));
1825
}
1826

1827
void ValidatorManagerImpl::downloaded_archive_slice(std::string name, bool is_tmp) {
1828
  LOG(INFO) << "downloaded archive slice: " << name;
1829
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), name, is_tmp](td::Result<std::vector<BlockSeqno>> R) {
1830
    if (is_tmp) {
1831
      td::unlink(name).ensure();
1832
    }
1833
    if (R.is_error()) {
1834
      LOG(INFO) << "failed to check downloaded archive slice: " << R.error();
1835
      delay_action([SelfId]() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive); },
1836
                   td::Timestamp::in(2.0));
1837
    } else {
1838
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::checked_archive_slice, R.move_as_ok());
1839
    }
1840
  });
1841

1842
  auto seqno = std::min(last_masterchain_seqno_, shard_client_handle_->id().seqno());
1843

1844
  td::actor::create_actor<ArchiveImporter>("archiveimport", name, last_masterchain_state_, seqno, opts_, actor_id(this),
1845
                                           std::move(P))
1846
      .release();
1847
}
1848

1849
void ValidatorManagerImpl::checked_archive_slice(std::vector<BlockSeqno> seqno) {
1850
  CHECK(seqno.size() == 2);
1851
  LOG(INFO) << "checked downloaded archive slice: mc_top_seqno=" << seqno[0] << " shard_top_seqno_=" << seqno[1];
1852
  CHECK(seqno[0] <= last_masterchain_seqno_);
1853
  CHECK(seqno[1] <= last_masterchain_seqno_);
1854

1855
  BlockIdExt b;
1856
  if (seqno[1] < last_masterchain_seqno_) {
1857
    CHECK(last_masterchain_state_->get_old_mc_block_id(seqno[1], b));
1858
  } else {
1859
    b = last_masterchain_block_id_;
1860
  }
1861

1862
  auto P = td::PromiseCreator::lambda(
1863
      [SelfId = actor_id(this), db = db_.get(), client = shard_client_.get()](td::Result<BlockHandle> R) {
1864
        R.ensure();
1865
        auto handle = R.move_as_ok();
1866
        auto P = td::PromiseCreator::lambda([SelfId, client, handle](td::Result<td::Ref<ShardState>> R) mutable {
1867
          auto P = td::PromiseCreator::lambda([SelfId](td::Result<td::Unit> R) {
1868
            R.ensure();
1869
            td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
1870
          });
1871
          td::actor::send_closure(client, &ShardClient::force_update_shard_client_ex, std::move(handle),
1872
                                  td::Ref<MasterchainState>{R.move_as_ok()}, std::move(P));
1873
        });
1874
        td::actor::send_closure(db, &Db::get_block_state, std::move(handle), std::move(P));
1875
      });
1876
  get_block_handle(b, true, std::move(P));
1877
}
1878

1879
void ValidatorManagerImpl::finish_prestart_sync() {
1880
  to_import_.clear();
1881

1882
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
1883
    R.ensure();
1884
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::completed_prestart_sync);
1885
  });
1886
  td::actor::send_closure(db_, &Db::set_async_mode, false, std::move(P));
1887
}
1888

1889
void ValidatorManagerImpl::completed_prestart_sync() {
1890
  td::actor::send_closure(shard_client_, &ShardClient::start);
1891

1892
  send_peek_key_block_request();
1893

1894
  LOG(WARNING) << "initial read complete: " << last_masterchain_block_handle_->id() << " "
1895
               << last_masterchain_block_id_;
1896
  callback_->initial_read_complete(last_masterchain_block_handle_);
1897
}
1898

1899
void ValidatorManagerImpl::new_masterchain_block() {
1900
  if (last_masterchain_seqno_ > 0 && last_masterchain_block_handle_->is_key_block()) {
1901
    last_key_block_handle_ = last_masterchain_block_handle_;
1902
    if (last_key_block_handle_->id().seqno() > last_known_key_block_handle_->id().seqno()) {
1903
      last_known_key_block_handle_ = last_key_block_handle_;
1904
      callback_->new_key_block(last_key_block_handle_);
1905
    }
1906
  }
1907

1908
  update_shards();
1909
  update_shard_blocks();
1910

1911
  if (!shard_client_.empty()) {
1912
    td::actor::send_closure(shard_client_, &ShardClient::new_masterchain_block_notification,
1913
                            last_masterchain_block_handle_, last_masterchain_state_);
1914
  }
1915

1916
  if (last_masterchain_seqno_ % 1024 == 0) {
1917
    LOG(WARNING) << "applied masterchain block " << last_masterchain_block_id_;
1918
  }
1919
}
1920

1921
void ValidatorManagerImpl::update_shards() {
1922
  if ((last_masterchain_state_->rotated_all_shards() || last_masterchain_seqno_ == 0) &&
1923
      opts_->get_last_fork_masterchain_seqno() <= last_masterchain_seqno_) {
1924
    allow_validate_ = true;
1925
  }
1926
  auto exp_vec = last_masterchain_state_->get_shards();
1927
  auto config = last_masterchain_state_->get_consensus_config();
1928
  validatorsession::ValidatorSessionOptions opts{config};
1929
  td::uint32 threshold = 9407194;
1930
  bool force_group_id_upgrade = last_masterchain_seqno_ == threshold;
1931
  auto legacy_opts_hash = opts.get_hash();
1932
  if (last_masterchain_seqno_ >= threshold) { //TODO move to get_consensus_config()
1933
    opts.proto_version = std::max<td::uint32>(opts.proto_version, 1);
1934
  }
1935
  auto opts_hash = opts.get_hash();
1936

1937
  std::map<ShardIdFull, std::vector<BlockIdExt>> new_shards;
1938
  std::set<ShardIdFull> future_shards;
1939

1940
  auto cur_time = static_cast<UnixTime>(td::Clocks::system());
1941

1942
  for (auto &v : exp_vec) {
1943
    auto shard = v->shard();
1944
    if (v->before_split()) {
1945
      CHECK(!v->before_merge());
1946
      ShardIdFull l_shard{shard.workchain, shard_child(shard.shard, true)};
1947
      ShardIdFull r_shard{shard.workchain, shard_child(shard.shard, false)};
1948
      new_shards.emplace(l_shard, std::vector<BlockIdExt>{v->top_block_id()});
1949
      new_shards.emplace(r_shard, std::vector<BlockIdExt>{v->top_block_id()});
1950
    } else if (v->before_merge()) {
1951
      ShardIdFull p_shard{shard.workchain, shard_parent(shard.shard)};
1952
      auto it = new_shards.find(p_shard);
1953
      if (it == new_shards.end()) {
1954
        new_shards.emplace(p_shard, std::vector<BlockIdExt>(2));
1955
      }
1956

1957
      bool left = shard_child(p_shard.shard, true) == shard.shard;
1958
      new_shards[p_shard][left ? 0 : 1] = v->top_block_id();
1959
    } else {
1960
      new_shards.emplace(shard, std::vector<BlockIdExt>{v->top_block_id()});
1961
    }
1962
    switch (v->fsm_state()) {
1963
      case McShardHash::FsmState::fsm_none: {
1964
        future_shards.insert(shard);
1965
        break;
1966
      }
1967
      case McShardHash::FsmState::fsm_split: {
1968
        if (v->fsm_utime() < cur_time + 60) {
1969
          ShardIdFull l_shard{shard.workchain, shard_child(shard.shard, true)};
1970
          ShardIdFull r_shard{shard.workchain, shard_child(shard.shard, false)};
1971
          future_shards.insert(l_shard);
1972
          future_shards.insert(r_shard);
1973
        } else {
1974
          future_shards.insert(shard);
1975
        }
1976
        break;
1977
      }
1978
      case McShardHash::FsmState::fsm_merge: {
1979
        if (v->fsm_utime() < cur_time + 60) {
1980
          ShardIdFull p_shard{shard.workchain, shard_parent(shard.shard)};
1981
          future_shards.insert(p_shard);
1982
        } else {
1983
          future_shards.insert(shard);
1984
        }
1985
        break;
1986
      }
1987
      default:
1988
        LOG(FATAL) << "state=" << static_cast<td::uint32>(v->fsm_state());
1989
    }
1990
  }
1991

1992
  new_shards.emplace(ShardIdFull{masterchainId, shardIdAll}, std::vector<BlockIdExt>{last_masterchain_block_id_});
1993
  future_shards.insert(ShardIdFull{masterchainId, shardIdAll});
1994

1995
  VLOG(VALIDATOR_DEBUG) << "total shards=" << new_shards.size() << " config shards=" << exp_vec.size();
1996

1997
  std::map<ValidatorSessionId, ValidatorGroupEntry> new_validator_groups_;
1998
  std::map<ValidatorSessionId, ValidatorGroupEntry> new_next_validator_groups_;
1999

2000
  bool force_recover = false;
2001
  {
2002
    auto val_set = last_masterchain_state_->get_validator_set(ShardIdFull{masterchainId});
2003
    auto r = opts_->check_unsafe_catchain_rotate(last_masterchain_seqno_, val_set->get_catchain_seqno());
2004
    force_recover = r > 0;
2005
  }
2006

2007
  BlockSeqno key_seqno = last_key_block_handle_->id().seqno();
2008

2009
  if (force_group_id_upgrade) {
2010
    for (auto &desc : new_shards) {
2011
      auto shard = desc.first;
2012
      auto prev = desc.second;
2013
      for (auto &p : prev) {
2014
        CHECK(p.is_valid());
2015
      }
2016
      auto val_set = last_masterchain_state_->get_validator_set(shard);
2017
      auto validator_id = get_validator(shard, val_set);
2018

2019
      if (!validator_id.is_zero()) {
2020
        auto legacy_val_group_id = get_validator_set_id(shard, val_set, legacy_opts_hash, key_seqno, opts);
2021
        auto val_group_id = get_validator_set_id(shard, val_set, opts_hash, key_seqno, opts);
2022

2023

2024
        auto it = validator_groups_.find(legacy_val_group_id);
2025
        if (it != validator_groups_.end()) {
2026
          new_validator_groups_.emplace(val_group_id, std::move(it->second));
2027
        } else {
2028
          auto it2 = next_validator_groups_.find(legacy_val_group_id);
2029
          if (it2 != next_validator_groups_.end()) {
2030
            if (!it2->second.actor.empty()) {
2031
              td::actor::send_closure(it2->second.actor, &ValidatorGroup::start, prev, last_masterchain_block_id_,
2032
                                      last_masterchain_state_->get_unix_time());
2033
            }
2034
            new_validator_groups_.emplace(val_group_id, std::move(it2->second));
2035
          } else {
2036
            auto G = create_validator_group(val_group_id, shard, val_set, opts, started_);
2037
            if (!G.empty()) {
2038
              td::actor::send_closure(G, &ValidatorGroup::start, prev, last_masterchain_block_id_,
2039
                                      last_masterchain_state_->get_unix_time());
2040
            }
2041
            new_validator_groups_.emplace(val_group_id, ValidatorGroupEntry{std::move(G), shard});
2042
          }
2043
        }
2044
      }
2045
    }
2046
  }
2047

2048
  if (allow_validate_) {
2049
    for (auto &desc : new_shards) {
2050
      auto shard = desc.first;
2051
      if (force_recover && !desc.first.is_masterchain()) {
2052
        continue;
2053
      }
2054
      auto prev = desc.second;
2055
      for (auto &p : prev) {
2056
        CHECK(p.is_valid());
2057
      }
2058
      auto val_set = last_masterchain_state_->get_validator_set(shard);
2059
      auto x = val_set->export_vector();
2060

2061
      auto validator_id = get_validator(shard, val_set);
2062

2063
      if (!validator_id.is_zero()) {
2064
        auto val_group_id = get_validator_set_id(shard, val_set, opts_hash, key_seqno, opts);
2065

2066
        if (force_recover) {
2067
          auto r = opts_->check_unsafe_catchain_rotate(last_masterchain_seqno_, val_set->get_catchain_seqno());
2068
          if (r) {
2069
            td::uint8 b[36];
2070
            td::MutableSlice x{b, 36};
2071
            x.copy_from(val_group_id.as_slice());
2072
            x.remove_prefix(32);
2073
            CHECK(x.size() == 4);
2074
            x.copy_from(td::Slice(reinterpret_cast<const td::uint8 *>(&r), 4));
2075
            val_group_id = sha256_bits256(td::Slice(b, 36));
2076
          }
2077
        }
2078

2079
        VLOG(VALIDATOR_DEBUG) << "validating group " << val_group_id;
2080
        auto it = validator_groups_.find(val_group_id);
2081
        if (it != validator_groups_.end()) {
2082
          new_validator_groups_.emplace(val_group_id, std::move(it->second));
2083
        } else {
2084
          auto it2 = next_validator_groups_.find(val_group_id);
2085
          if (it2 != next_validator_groups_.end()) {
2086
            if (!it2->second.actor.empty()) {
2087
              td::actor::send_closure(it2->second.actor, &ValidatorGroup::start, prev, last_masterchain_block_id_,
2088
                                      last_masterchain_state_->get_unix_time());
2089
            }
2090
            new_validator_groups_.emplace(val_group_id, std::move(it2->second));
2091
          } else {
2092
            auto G = create_validator_group(val_group_id, shard, val_set, opts, started_);
2093
            if (!G.empty()) {
2094
              td::actor::send_closure(G, &ValidatorGroup::start, prev, last_masterchain_block_id_,
2095
                                      last_masterchain_state_->get_unix_time());
2096
            }
2097
            new_validator_groups_.emplace(val_group_id, ValidatorGroupEntry{std::move(G), shard});
2098
          }
2099
        }
2100
      }
2101
    }
2102
  }
2103
  for (auto &shard : future_shards) {
2104
    auto val_set = last_masterchain_state_->get_next_validator_set(shard);
2105
    if (val_set.is_null()) {
2106
      continue;
2107
    }
2108

2109
    auto validator_id = get_validator(shard, val_set);
2110
    if (!validator_id.is_zero()) {
2111
      auto val_group_id = get_validator_set_id(shard, val_set, opts_hash, key_seqno, opts);
2112
      auto it = next_validator_groups_.find(val_group_id);
2113
      if (it != next_validator_groups_.end()) {
2114
        //CHECK(!it->second.empty());
2115
        new_next_validator_groups_.emplace(val_group_id, std::move(it->second));
2116
      } else {
2117
        new_next_validator_groups_.emplace(
2118
            val_group_id,
2119
            ValidatorGroupEntry{create_validator_group(val_group_id, shard, val_set, opts, started_), shard});
2120
      }
2121
    }
2122
  }
2123

2124
  std::vector<td::actor::ActorId<ValidatorGroup>> gc;
2125
  for (auto &v : validator_groups_) {
2126
    if (!v.second.actor.empty()) {
2127
      gc_list_.push_back(v.first);
2128
      gc.push_back(v.second.actor.release());
2129
    }
2130
  }
2131
  for (auto &v : next_validator_groups_) {
2132
    if (!v.second.actor.empty()) {
2133
      gc_list_.push_back(v.first);
2134
      gc.push_back(v.second.actor.release());
2135
    }
2136
  }
2137

2138
  validator_groups_ = std::move(new_validator_groups_);
2139
  next_validator_groups_ = std::move(new_next_validator_groups_);
2140

2141
  if (last_masterchain_state_->rotated_all_shards()) {
2142
    gc_list_.clear();
2143
    check_gc_list_.clear();
2144
    CHECK(last_masterchain_block_handle_->received_state());
2145
    auto P = td::PromiseCreator::lambda(
2146
        [SelfId = actor_id(this), gc = std::move(gc), block_id = last_masterchain_block_id_](td::Result<td::Unit> R) {
2147
          R.ensure();
2148
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_destroyed_validator_sessions, std::move(gc));
2149
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::updated_init_block, block_id);
2150
        });
2151
    td::actor::send_closure(db_, &Db::update_init_masterchain_block, last_masterchain_block_id_, std::move(P));
2152
  } else {
2153
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), gc = std::move(gc)](td::Result<td::Unit> R) {
2154
      R.ensure();
2155
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_destroyed_validator_sessions, std::move(gc));
2156
    });
2157
    td::actor::send_closure(db_, &Db::update_destroyed_validator_sessions, gc_list_, std::move(P));
2158
  }
2159
}  // namespace validator
2160

2161
void ValidatorManagerImpl::written_destroyed_validator_sessions(std::vector<td::actor::ActorId<ValidatorGroup>> list) {
2162
  for (auto &v : list) {
2163
    td::actor::send_closure(v, &ValidatorGroup::destroy);
2164
  }
2165
}
2166

2167
void ValidatorManagerImpl::update_shard_blocks() {
2168
  {
2169
    auto it = shard_blocks_.begin();
2170
    while (it != shard_blocks_.end()) {
2171
      auto &B = it->second;
2172
      if (!B->may_be_valid(last_masterchain_block_handle_, last_masterchain_state_)) {
2173
        auto it2 = it++;
2174
        shard_blocks_.erase(it2);
2175
      } else {
2176
        ++it;
2177
      }
2178
    }
2179
  }
2180

2181
  {
2182
    auto it = out_shard_blocks_.begin();
2183
    while (it != out_shard_blocks_.end()) {
2184
      auto &B = it->second;
2185
      if (!B->may_be_valid(last_masterchain_block_handle_, last_masterchain_state_)) {
2186
        auto it2 = it++;
2187
        out_shard_blocks_.erase(it2);
2188
      } else {
2189
        ++it;
2190
      }
2191
    }
2192
  }
2193
}
2194

2195
ValidatorSessionId ValidatorManagerImpl::get_validator_set_id(ShardIdFull shard, td::Ref<ValidatorSet> val_set,
2196
                                                              td::Bits256 opts_hash, BlockSeqno last_key_block_seqno,
2197
                                                              const validatorsession::ValidatorSessionOptions &opts) {
2198
  std::vector<tl_object_ptr<ton_api::validator_groupMember>> vec;
2199
  auto v = val_set->export_vector();
2200
  auto vert_seqno = opts_->get_maximal_vertical_seqno();
2201
  for (auto &n : v) {
2202
    auto pub_key = PublicKey{pubkeys::Ed25519{n.key}};
2203
    vec.push_back(
2204
        create_tl_object<ton_api::validator_groupMember>(pub_key.compute_short_id().bits256_value(), n.addr, n.weight));
2205
  }
2206
  if (!opts.new_catchain_ids) {
2207
    if (vert_seqno == 0) {
2208
      return create_hash_tl_object<ton_api::validator_group>(shard.workchain, shard.shard,
2209
                                                             val_set->get_catchain_seqno(), opts_hash, std::move(vec));
2210
    } else {
2211
      return create_hash_tl_object<ton_api::validator_groupEx>(
2212
          shard.workchain, shard.shard, vert_seqno, val_set->get_catchain_seqno(), opts_hash, std::move(vec));
2213
    }
2214
  } else {
2215
    return create_hash_tl_object<ton_api::validator_groupNew>(shard.workchain, shard.shard, vert_seqno,
2216
                                                              last_key_block_seqno, val_set->get_catchain_seqno(),
2217
                                                              opts_hash, std::move(vec));
2218
  }
2219
}
2220

2221
td::actor::ActorOwn<ValidatorGroup> ValidatorManagerImpl::create_validator_group(
2222
    ValidatorSessionId session_id, ShardIdFull shard, td::Ref<ValidatorSet> validator_set,
2223
    validatorsession::ValidatorSessionOptions opts, bool init_session) {
2224
  if (check_gc_list_.count(session_id) == 1) {
2225
    return td::actor::ActorOwn<ValidatorGroup>{};
2226
  } else {
2227
    // Call get_external_messages to cleanup mempool for the shard
2228
    get_external_messages(shard, [](td::Result<std::vector<std::pair<td::Ref<ExtMessage>, int>>>) {});
2229

2230
    auto validator_id = get_validator(shard, validator_set);
2231
    CHECK(!validator_id.is_zero());
2232
    auto G = td::actor::create_actor<ValidatorGroup>(
2233
        "validatorgroup", shard, validator_id, session_id, validator_set, opts, keyring_, adnl_, rldp_, overlays_,
2234
        db_root_, actor_id(this), init_session,
2235
        opts_->check_unsafe_resync_allowed(validator_set->get_catchain_seqno()), opts_);
2236
    return G;
2237
  }
2238
}
2239

2240
void ValidatorManagerImpl::add_handle_to_lru(BlockHandle handle) {
2241
  auto it = handle_lru_map_.find(handle->id());
2242
  if (it != handle_lru_map_.end()) {
2243
    CHECK(it->second->handle() == handle);
2244
    it->second->remove();
2245
    handle_lru_.put(it->second.get());
2246
  } else {
2247
    auto id = handle->id();
2248
    auto x = std::make_unique<BlockHandleLru>(std::move(handle));
2249
    handle_lru_.put(x.get());
2250
    handle_lru_map_.emplace(id, std::move(x));
2251
    handle_lru_size_++;
2252
    if (handle_lru_size_ > handle_lru_max_size_) {
2253
      auto to_remove = BlockHandleLru::from_list_node(handle_lru_.get());
2254
      CHECK(to_remove);
2255
      CHECK(handle_lru_map_.count(to_remove->handle()->id()) == 1);
2256
      handle_lru_map_.erase(to_remove->handle()->id());
2257
      handle_lru_size_--;
2258
    }
2259
  }
2260
}
2261

2262
BlockHandle ValidatorManagerImpl::get_handle_from_lru(BlockIdExt id) {
2263
  auto it = handle_lru_map_.find(id);
2264
  if (it != handle_lru_map_.end()) {
2265
    it->second->remove();
2266
    handle_lru_.put(it->second.get());
2267
    auto handle = it->second->handle();
2268
    CHECK(handle->id() == id);
2269
    return handle;
2270
  } else {
2271
    return nullptr;
2272
  }
2273
}
2274

2275
void ValidatorManagerImpl::try_advance_gc_masterchain_block() {
2276
  if (gc_masterchain_handle_ && last_masterchain_seqno_ > 0 && !gc_advancing_ &&
2277
      gc_masterchain_handle_->inited_next_left() &&
2278
      gc_masterchain_handle_->id().id.seqno < last_rotate_block_id_.id.seqno &&
2279
      gc_masterchain_handle_->id().id.seqno < last_masterchain_state_->min_ref_masterchain_seqno() &&
2280
      gc_masterchain_handle_->id().id.seqno + 1024 < last_masterchain_seqno_ &&
2281
      gc_masterchain_handle_->id().id.seqno < last_masterchain_state_->last_key_block_id().seqno() &&
2282
      gc_masterchain_handle_->id().id.seqno < min_confirmed_masterchain_seqno_ &&
2283
      gc_masterchain_handle_->id().id.seqno < state_serializer_masterchain_seqno_ &&
2284
      gc_masterchain_state_->get_unix_time() < td::Clocks::system() - state_ttl()) {
2285
    gc_advancing_ = true;
2286
    auto block_id = gc_masterchain_handle_->one_next(true);
2287

2288
    auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
2289
      R.ensure();
2290
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::got_next_gc_masterchain_handle, R.move_as_ok());
2291
    });
2292
    get_block_handle(block_id, true, std::move(P));
2293
  }
2294
}
2295

2296
void ValidatorManagerImpl::allow_persistent_state_file_gc(BlockIdExt block_id, BlockIdExt masterchain_block_id,
2297
                                                          td::Promise<bool> promise) {
2298
  if (!gc_masterchain_handle_) {
2299
    promise.set_result(false);
2300
    return;
2301
  }
2302
  if (masterchain_block_id.seqno() == 0) {
2303
    promise.set_result(false);
2304
    return;
2305
  }
2306
  if (masterchain_block_id.seqno() >= gc_masterchain_handle_->id().seqno()) {
2307
    promise.set_result(false);
2308
    return;
2309
  }
2310
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
2311
    R.ensure();
2312
    auto handle = R.move_as_ok();
2313
    CHECK(handle->is_key_block());
2314
    promise.set_result(ValidatorManager::persistent_state_ttl(handle->unix_time()) < td::Clocks::system());
2315
  });
2316
  get_block_handle(masterchain_block_id, false, std::move(P));
2317
}
2318

2319
void ValidatorManagerImpl::allow_archive(BlockIdExt block_id, td::Promise<bool> promise) {
2320
  /*if (!gc_masterchain_handle_) {
2321
    promise.set_result(false);
2322
    return;
2323
  }
2324
  if (!block_id.is_masterchain()) {
2325
    if (!gc_masterchain_state_->workchain_is_active(block_id.id.workchain)) {
2326
      promise.set_result(false);
2327
      return;
2328
    }
2329
    bool found = false;
2330
    auto S = gc_masterchain_state_->get_shard_from_config(block_id.shard_full());
2331
    if (S.not_null()) {
2332
      if (block_id.id.seqno >= S->top_block_id().id.seqno) {
2333
        promise.set_result(false);
2334
        return;
2335
      }
2336
      found = true;
2337
    } else {
2338
      auto shards = gc_masterchain_state_->get_shards();
2339
      for (auto shard : shards) {
2340
        if (shard_intersects(shard->shard(), block_id.shard_full())) {
2341
          if (block_id.id.seqno >= shard->top_block_id().id.seqno) {
2342
            promise.set_result(false);
2343
            return;
2344
          }
2345
          found = true;
2346
        }
2347
      }
2348
    }
2349
    CHECK(found);
2350
  } else {
2351
    if (block_id.id.seqno >= gc_masterchain_handle_->id().id.seqno) {
2352
      promise.set_result(false);
2353
      return;
2354
    }
2355
  }
2356
  auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Unit> R) mutable {
2357
    if (R.is_error()) {
2358
      promise.set_error(R.move_as_error());
2359
    } else {
2360
      promise.set_result(true);
2361
    }
2362
  });
2363
  td::actor::send_closure(db_, &Db::archive, block_id, std::move(P));*/
2364
  promise.set_result(false);
2365
}
2366

2367
void ValidatorManagerImpl::allow_delete(BlockIdExt block_id, td::Promise<bool> promise) {
2368
  auto key_ttl = td::Clocks::system() - opts_->key_proof_ttl();
2369
  auto ttl = td::Clocks::system() - opts_->archive_ttl();
2370
  auto P = td::PromiseCreator::lambda(
2371
      [SelfId = actor_id(this), promise = std::move(promise), ttl, key_ttl](td::Result<BlockHandle> R) mutable {
2372
        if (R.is_error()) {
2373
          promise.set_result(true);
2374
          return;
2375
        }
2376
        auto handle = R.move_as_ok();
2377
        if (!handle->inited_unix_time()) {
2378
          promise.set_result(true);
2379
          return;
2380
        }
2381
        if (!handle->inited_is_key_block() || !handle->is_key_block()) {
2382
          promise.set_result(handle->unix_time() <= ttl);
2383
        } else {
2384
          promise.set_result(handle->unix_time() <= key_ttl);
2385
        }
2386
      });
2387
  get_block_handle(block_id, false, std::move(P));
2388
}
2389

2390
void ValidatorManagerImpl::allow_block_state_gc(BlockIdExt block_id, td::Promise<bool> promise) {
2391
  if (!gc_masterchain_handle_) {
2392
    promise.set_result(false);
2393
    return;
2394
  }
2395
  if (block_id.is_masterchain()) {
2396
    promise.set_result(block_id.id.seqno < gc_masterchain_handle_->id().id.seqno);
2397
    return;
2398
  }
2399
  if (!gc_masterchain_state_->workchain_is_active(block_id.id.workchain)) {
2400
    promise.set_result(false);
2401
    return;
2402
  }
2403
  auto S = gc_masterchain_state_->get_shard_from_config(block_id.shard_full());
2404
  if (S.not_null()) {
2405
    promise.set_result(block_id.id.seqno < S->top_block_id().id.seqno);
2406
    return;
2407
  }
2408
  auto shards = gc_masterchain_state_->get_shards();
2409
  for (auto shard : shards) {
2410
    if (shard_intersects(shard->shard(), block_id.shard_full())) {
2411
      promise.set_result(block_id.id.seqno < shard->top_block_id().id.seqno);
2412
      return;
2413
    }
2414
  }
2415
  UNREACHABLE();
2416
}
2417

2418
void ValidatorManagerImpl::allow_block_info_gc(BlockIdExt block_id, td::Promise<bool> promise) {
2419
  auto P =
2420
      td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
2421
        if (R.is_error()) {
2422
          promise.set_result(false);
2423
        } else {
2424
          auto handle = R.move_as_ok();
2425
          if (!handle->moved_to_archive() || !handle->is_applied()) {
2426
            promise.set_result(false);
2427
          } else {
2428
            auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Unit> R) mutable {
2429
              R.ensure();
2430
              promise.set_result(true);
2431
            });
2432
            td::actor::send_closure(db, &Db::store_block_handle, handle, std::move(P));
2433
          }
2434
        }
2435
      });
2436
  get_block_handle(block_id, false, std::move(P));
2437
}
2438

2439
void ValidatorManagerImpl::got_next_gc_masterchain_handle(BlockHandle handle) {
2440
  CHECK(gc_advancing_);
2441
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
2442
    if (R.is_error()) {
2443
      if (R.error().code() == ErrorCode::timeout) {
2444
        LOG(ERROR) << "Failed to get gc masterchain state, retrying: " << R.move_as_error();
2445
        td::actor::send_closure(SelfId, &ValidatorManagerImpl::got_next_gc_masterchain_handle, std::move(handle));
2446
      } else {
2447
        LOG(FATAL) << "Failed to get gc masterchain state: " << R.move_as_error();
2448
      }
2449
      return;
2450
    }
2451
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::got_next_gc_masterchain_state, std::move(handle),
2452
                            td::Ref<MasterchainState>{R.move_as_ok()});
2453
  });
2454
  wait_block_state(handle, 0, td::Timestamp::in(60.0), std::move(P));
2455
}
2456

2457
void ValidatorManagerImpl::got_next_gc_masterchain_state(BlockHandle handle, td::Ref<MasterchainState> state) {
2458
  auto P = td::PromiseCreator::lambda([handle, state, SelfId = actor_id(this)](td::Result<td::Unit> R) {
2459
    R.ensure();
2460
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::advance_gc, handle, state);
2461
  });
2462
  update_gc_block_handle(std::move(handle), std::move(P));
2463
}
2464

2465
void ValidatorManagerImpl::update_gc_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
2466
  td::actor::send_closure(db_, &Db::update_gc_masterchain_block, handle->id(), std::move(promise));
2467
}
2468

2469
void ValidatorManagerImpl::advance_gc(BlockHandle handle, td::Ref<MasterchainState> state) {
2470
  CHECK(gc_advancing_);
2471
  gc_advancing_ = false;
2472
  gc_masterchain_handle_ = std::move(handle);
2473
  gc_masterchain_state_ = std::move(state);
2474
  try_advance_gc_masterchain_block();
2475
}
2476

2477
void ValidatorManagerImpl::update_shard_client_block_handle(BlockHandle handle, td::Ref<MasterchainState> state,
2478
                                                            td::Promise<td::Unit> promise) {
2479
  shard_client_handle_ = std::move(handle);
2480
  auto seqno = shard_client_handle_->id().seqno();
2481
  if (state.not_null()) {
2482
    shard_client_shards_ = state->get_shards();
2483
    if (last_liteserver_state_.is_null() || last_liteserver_state_->get_block_id().seqno() < seqno) {
2484
      last_liteserver_state_ = std::move(state);
2485
    }
2486
  }
2487
  shard_client_update(seqno);
2488
  promise.set_value(td::Unit());
2489
}
2490

2491
void ValidatorManagerImpl::shard_client_update(BlockSeqno seqno) {
2492
  if (min_confirmed_masterchain_seqno_ < seqno) {
2493
    min_confirmed_masterchain_seqno_ = seqno;
2494
  } else {
2495
    return;
2496
  }
2497
  while (shard_client_waiters_.size() > 0) {
2498
    auto it = shard_client_waiters_.begin();
2499
    if (it->first > min_confirmed_masterchain_seqno_) {
2500
      break;
2501
    }
2502
    for (auto &y : it->second.waiting_) {
2503
      y.promise.set_value(td::Unit());
2504
    }
2505
    shard_client_waiters_.erase(it);
2506
  }
2507
}
2508

2509
void ValidatorManagerImpl::state_serializer_update(BlockSeqno seqno) {
2510
  if (state_serializer_masterchain_seqno_ < seqno) {
2511
    state_serializer_masterchain_seqno_ = seqno;
2512
  }
2513
}
2514

2515
void ValidatorManagerImpl::alarm() {
2516
  try_advance_gc_masterchain_block();
2517
  alarm_timestamp() = td::Timestamp::in(1.0);
2518
  if (shard_client_handle_ && gc_masterchain_handle_) {
2519
    td::actor::send_closure(db_, &Db::run_gc, shard_client_handle_->unix_time(), gc_masterchain_handle_->unix_time(),
2520
                            static_cast<UnixTime>(opts_->archive_ttl()));
2521
  }
2522
  if (log_status_at_.is_in_past()) {
2523
    if (last_masterchain_block_handle_) {
2524
      LOG(ERROR) << "STATUS: last_masterchain_block_ago="
2525
                 << td::format::as_time(td::Clocks::system() - last_masterchain_block_handle_->unix_time())
2526
                 << " last_known_key_block_ago="
2527
                 << td::format::as_time(td::Clocks::system() - (last_known_key_block_handle_->inited_unix_time()
2528
                                                                    ? last_known_key_block_handle_->unix_time()
2529
                                                                    : 0))
2530
                 << " shard_client_ago="
2531
                 << td::format::as_time(td::Clocks::system() -
2532
                                        (shard_client_handle_ ? shard_client_handle_->unix_time() : 0));
2533
    }
2534
    log_status_at_ = td::Timestamp::in(60.0);
2535
  }
2536
  alarm_timestamp().relax(log_status_at_);
2537
  if (resend_shard_blocks_at_ && resend_shard_blocks_at_.is_in_past()) {
2538
    resend_shard_blocks_at_ = td::Timestamp::never();
2539
    for (auto &B : out_shard_blocks_) {
2540
      callback_->send_shard_block_info(B.second->block_id(), B.second->catchain_seqno(), B.second->serialize());
2541
    }
2542
    if (out_shard_blocks_.size() > 0) {
2543
      resend_shard_blocks_at_ = td::Timestamp::in(td::Random::fast(0, 100) * 0.01 + 2);
2544
    }
2545
  }
2546
  alarm_timestamp().relax(resend_shard_blocks_at_);
2547
  if (check_waiters_at_.is_in_past()) {
2548
    check_waiters_at_ = td::Timestamp::in(1.0);
2549
    for (auto &w : wait_block_data_) {
2550
      w.second.check_timers();
2551
    }
2552
    for (auto &w : wait_state_) {
2553
      w.second.check_timers();
2554
    }
2555
    for (auto &w : shard_client_waiters_) {
2556
      w.second.check_timers();
2557
    }
2558
    for (auto it = block_state_cache_.begin(); it != block_state_cache_.end();) {
2559
      bool del = it->second.ttl_.is_in_past();
2560
      if (del) {
2561
        auto block_id = it->first;
2562
        if (block_id.is_masterchain()) {
2563
          if (block_id.seqno() == last_masterchain_seqno_) {
2564
            it->second.ttl_ = td::Timestamp::in(30.0);
2565
            del = false;
2566
          }
2567
        } else if (last_masterchain_state_.not_null()) {
2568
          auto shard = last_masterchain_state_->get_shard_from_config(block_id.shard_full());
2569
          if (shard.not_null()) {
2570
            if (block_id.seqno() == shard->top_block_id().seqno()) {
2571
              it->second.ttl_ = td::Timestamp::in(30.0);
2572
              del = false;
2573
            }
2574
          }
2575
        }
2576
      }
2577
      if (del) {
2578
        it = block_state_cache_.erase(it);
2579
      } else {
2580
        ++it;
2581
      }
2582
    }
2583
  }
2584
  alarm_timestamp().relax(check_waiters_at_);
2585
  if (check_shard_clients_.is_in_past()) {
2586
    check_shard_clients_ = td::Timestamp::in(10.0);
2587

2588
    if (!serializer_.empty()) {
2589
      auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockSeqno> R) {
2590
        if (R.is_error()) {
2591
          VLOG(VALIDATOR_WARNING) << "failed to get shard client status: " << R.move_as_error();
2592
        } else {
2593
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::state_serializer_update, R.move_as_ok());
2594
        }
2595
      });
2596
      td::actor::send_closure(serializer_, &AsyncStateSerializer::get_masterchain_seqno, std::move(P));
2597
    }
2598
  }
2599
  alarm_timestamp().relax(check_shard_clients_);
2600

2601
  if (log_ls_stats_at_.is_in_past()) {
2602
    if (!ls_stats_.empty() || ls_stats_check_ext_messages_ != 0) {
2603
      td::StringBuilder sb;
2604
      sb << "Liteserver stats (1 minute):";
2605
      td::uint32 total = 0;
2606
      for (const auto &p : ls_stats_) {
2607
        sb << " " << lite_query_name_by_id(p.first) << ":" << p.second;
2608
        total += p.second;
2609
      }
2610
      if (total > 0) {
2611
        sb << " TOTAL:" << total;
2612
      }
2613
      if (ls_stats_check_ext_messages_ > 0) {
2614
        sb << " checkExtMessage:" << ls_stats_check_ext_messages_;
2615
      }
2616
      LOG(WARNING) << sb.as_cslice();
2617
    }
2618
    ls_stats_.clear();
2619
    ls_stats_check_ext_messages_ = 0;
2620
    log_ls_stats_at_ = td::Timestamp::in(60.0);
2621
  }
2622
  alarm_timestamp().relax(log_ls_stats_at_);
2623
  if (cleanup_mempool_at_.is_in_past()) {
2624
    if (is_validator()) {
2625
      get_external_messages(ShardIdFull{masterchainId, shardIdAll},
2626
                            [](td::Result<std::vector<std::pair<td::Ref<ExtMessage>, int>>>) {});
2627
      get_external_messages(ShardIdFull{basechainId, shardIdAll},
2628
                            [](td::Result<std::vector<std::pair<td::Ref<ExtMessage>, int>>>) {});
2629
    }
2630
    cleanup_mempool_at_ = td::Timestamp::in(250.0);
2631
  }
2632
  alarm_timestamp().relax(cleanup_mempool_at_);
2633
}
2634

2635
void ValidatorManagerImpl::update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) {
2636
  td::actor::send_closure(db_, &Db::update_shard_client_state, masterchain_block_id, std::move(promise));
2637
}
2638

2639
void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) {
2640
  if (shard_client_handle_ && !from_db) {
2641
    promise.set_result(shard_client_handle_->id());
2642
  } else {
2643
    td::actor::send_closure(db_, &Db::get_shard_client_state, std::move(promise));
2644
  }
2645
}
2646

2647
void ValidatorManagerImpl::subscribe_to_shard(ShardIdFull shard) {
2648
  callback_->add_shard(shard);
2649
}
2650

2651
void ValidatorManagerImpl::update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) {
2652
  td::actor::send_closure(db_, &Db::update_async_serializer_state, std::move(state), std::move(promise));
2653
}
2654

2655
void ValidatorManagerImpl::get_async_serializer_state(td::Promise<AsyncSerializerState> promise) {
2656
  td::actor::send_closure(db_, &Db::get_async_serializer_state, std::move(promise));
2657
}
2658

2659
void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) {
2660
  td::actor::send_closure(db_, &Db::try_get_static_file, file_hash, std::move(promise));
2661
}
2662

2663
void ValidatorManagerImpl::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise) {
2664
  if (masterchain_seqno > last_masterchain_seqno_) {
2665
    promise.set_error(td::Status::Error(ErrorCode::notready, "masterchain seqno too big"));
2666
    return;
2667
  }
2668
  td::actor::send_closure(db_, &Db::get_archive_id, masterchain_seqno, std::move(promise));
2669
}
2670

2671
void ValidatorManagerImpl::get_archive_slice(td::uint64 archive_id, td::uint64 offset, td::uint32 limit,
2672
                                             td::Promise<td::BufferSlice> promise) {
2673
  td::actor::send_closure(db_, &Db::get_archive_slice, archive_id, offset, limit, std::move(promise));
2674
}
2675

2676
bool ValidatorManagerImpl::is_validator() {
2677
  return temp_keys_.size() > 0 || permanent_keys_.size() > 0;
2678
}
2679

2680
PublicKeyHash ValidatorManagerImpl::get_validator(ShardIdFull shard, td::Ref<ValidatorSet> val_set) {
2681
  if (!opts_->need_validate(shard, val_set->get_catchain_seqno())) {
2682
    return PublicKeyHash::zero();
2683
  }
2684
  for (auto &key : temp_keys_) {
2685
    if (val_set->is_validator(key.bits256_value())) {
2686
      return key;
2687
    }
2688
  }
2689
  return PublicKeyHash::zero();
2690
}
2691

2692
void ValidatorManagerImpl::got_next_key_blocks(std::vector<BlockIdExt> r) {
2693
  if (r.size() == 0) {
2694
    delay_action([SelfId = actor_id(
2695
                      this)]() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::send_peek_key_block_request); },
2696
                 td::Timestamp::in(2.0 + td::Random::fast(0, 100) * 0.01));
2697
    return;
2698
  }
2699
  auto block_id = *r.rbegin();
2700
  if (block_id.seqno() <= last_known_key_block_handle_->id().seqno()) {
2701
    delay_action([SelfId = actor_id(
2702
                      this)]() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::send_peek_key_block_request); },
2703
                 td::Timestamp::in(2.0 + td::Random::fast(0, 100) * 0.01));
2704
    return;
2705
  }
2706

2707
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
2708
    R.ensure();
2709
    td::actor::send_closure(SelfId, &ValidatorManagerImpl::update_last_known_key_block, R.move_as_ok(), true);
2710
  });
2711
  get_block_handle(block_id, false, std::move(P));
2712
}
2713

2714
void ValidatorManagerImpl::update_last_known_key_block(BlockHandle handle, bool send_request) {
2715
  if (last_known_key_block_handle_ && handle->id().seqno() > last_known_key_block_handle_->id().seqno()) {
2716
    last_known_key_block_handle_ = std::move(handle);
2717
    callback_->new_key_block(last_known_key_block_handle_);
2718
  }
2719
  if (send_request) {
2720
    delay_action([SelfId = actor_id(
2721
                      this)]() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::send_peek_key_block_request); },
2722
                 td::Timestamp::in(0.1 + td::Random::fast(0, 100) * 0.001));
2723
  }
2724
}
2725

2726
void ValidatorManagerImpl::send_peek_key_block_request() {
2727
  auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<BlockIdExt>> R) {
2728
    if (R.is_error()) {
2729
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::got_next_key_blocks, std::vector<BlockIdExt>{});
2730
    } else {
2731
      td::actor::send_closure(SelfId, &ValidatorManagerImpl::got_next_key_blocks, R.move_as_ok());
2732
    }
2733
  });
2734

2735
  send_get_next_key_blocks_request(last_known_key_block_handle_->id(), 1, std::move(P));
2736
}
2737

2738
void ValidatorManagerImpl::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) {
2739
  auto merger = StatsMerger::create(std::move(promise));
2740

2741
  std::vector<std::pair<std::string, std::string>> vec;
2742
  vec.emplace_back("unixtime", td::to_string(static_cast<UnixTime>(td::Clocks::system())));
2743
  if (last_masterchain_block_handle_) {
2744
    vec.emplace_back("masterchainblock", last_masterchain_block_id_.to_str());
2745
    vec.emplace_back("masterchainblocktime", td::to_string(last_masterchain_block_handle_->unix_time()));
2746
    vec.emplace_back("gcmasterchainblock", gc_masterchain_handle_->id().to_str());
2747
    vec.emplace_back("keymasterchainblock", last_key_block_handle_->id().to_str());
2748
    vec.emplace_back("knownkeymasterchainblock", last_known_key_block_handle_->id().to_str());
2749
    vec.emplace_back("rotatemasterchainblock", last_rotate_block_id_.to_str());
2750
    //vec.emplace_back("shardclientmasterchainseqno", td::to_string(min_confirmed_masterchain_seqno_));
2751
    vec.emplace_back("stateserializermasterchainseqno", td::to_string(state_serializer_masterchain_seqno_));
2752
  }
2753

2754
  if (!shard_client_.empty()) {
2755
    auto P = td::PromiseCreator::lambda([promise = merger.make_promise("")](td::Result<BlockSeqno> R) mutable {
2756
      if (R.is_error()) {
2757
        promise.set_error(R.move_as_error());
2758
        return;
2759
      }
2760
      std::vector<std::pair<std::string, std::string>> vec;
2761
      vec.emplace_back("shardclientmasterchainseqno", td::to_string(R.move_as_ok()));
2762
      promise.set_value(std::move(vec));
2763
    });
2764
    td::actor::send_closure(shard_client_, &ShardClient::get_processed_masterchain_block, std::move(P));
2765
  }
2766

2767
  merger.make_promise("").set_value(std::move(vec));
2768

2769
  td::actor::send_closure(db_, &Db::prepare_stats, merger.make_promise("db."));
2770
}
2771

2772
void ValidatorManagerImpl::prepare_perf_timer_stats(td::Promise<std::vector<PerfTimerStats>> promise) {
2773
  promise.set_value(std::vector<PerfTimerStats>(perf_timer_stats));
2774
}
2775

2776
void ValidatorManagerImpl::add_perf_timer_stat(std::string name, double duration) {
2777
  for (auto &s : perf_timer_stats) {
2778
    if (s.name == name) {
2779
      double now = td::Time::now();
2780
      while (!s.stats.empty() && s.stats.front().first < now - 3600.0) {
2781
        s.stats.pop_front();
2782
      }
2783
      s.stats.push_back({td::Time::now(), duration});
2784
      return;
2785
    }
2786
  }
2787
  perf_timer_stats.push_back({name, {{td::Time::now(), duration}}});
2788
}
2789

2790
void ValidatorManagerImpl::truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
2791
  td::actor::send_closure(db_, &Db::truncate, seqno, std::move(handle), std::move(promise));
2792
}
2793

2794
void ValidatorManagerImpl::wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout,
2795
                                                   td::Promise<td::Unit> promise) {
2796
  if (seqno <= min_confirmed_masterchain_seqno_) {
2797
    promise.set_value(td::Unit());
2798
    return;
2799
  }
2800
  if (timeout.is_in_past()) {
2801
    promise.set_error(td::Status::Error(ErrorCode::timeout, "timeout"));
2802
    return;
2803
  }
2804
  if (seqno > min_confirmed_masterchain_seqno_ + 100) {
2805
    promise.set_error(td::Status::Error(ErrorCode::notready, "too big masterchain block seqno"));
2806
    return;
2807
  }
2808

2809
  shard_client_waiters_[seqno].waiting_.emplace_back(timeout, 0, std::move(promise));
2810
}
2811

2812
void ValidatorManagerImpl::log_validator_session_stats(BlockIdExt block_id,
2813
                                                       validatorsession::ValidatorSessionStats stats) {
2814
  std::string fname = opts_->get_session_logs_file();
2815
  if (fname.empty()) {
2816
    return;
2817
  }
2818

2819
  std::vector<tl_object_ptr<ton_api::validatorSession_statsRound>> rounds;
2820
  for (const auto &round : stats.rounds) {
2821
    std::vector<tl_object_ptr<ton_api::validatorSession_statsProducer>> producers;
2822
    for (const auto &producer : round.producers) {
2823
      producers.push_back(create_tl_object<ton_api::validatorSession_statsProducer>(
2824
          producer.id.bits256_value(), producer.candidate_id, producer.block_status, producer.comment,
2825
          producer.block_timestamp, producer.is_accepted, producer.is_ours, producer.got_submit_at,
2826
          producer.collation_time, producer.collated_at, producer.collation_cached, producer.validation_time,
2827
          producer.validated_at, producer.validation_cached, producer.gen_utime, producer.approved_weight,
2828
          producer.approved_33pct_at, producer.approved_66pct_at, producer.signed_weight, producer.signed_33pct_at,
2829
          producer.signed_66pct_at, producer.serialize_time, producer.deserialize_time, producer.serialized_size));
2830
    }
2831
    rounds.push_back(create_tl_object<ton_api::validatorSession_statsRound>(round.timestamp, std::move(producers)));
2832
  }
2833

2834
  auto obj = create_tl_object<ton_api::validatorSession_stats>(
2835
      stats.success, create_tl_block_id(block_id), stats.timestamp, stats.self.bits256_value(), stats.session_id,
2836
      stats.cc_seqno, stats.creator.bits256_value(), stats.total_validators, stats.total_weight, stats.signatures,
2837
      stats.signatures_weight, stats.approve_signatures, stats.approve_signatures_weight, stats.first_round,
2838
      std::move(rounds));
2839
  auto s = td::json_encode<std::string>(td::ToJson(*obj.get()), false);
2840
  s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return c == '\n' || c == '\r'; }), s.end());
2841

2842
  std::ofstream file;
2843
  file.open(fname, std::ios_base::app);
2844
  file << s << "\n";
2845
  file.close();
2846

2847
  LOG(INFO) << "Writing validator session stats for " << block_id.id.to_str();
2848
}
2849

2850
void ValidatorManagerImpl::log_new_validator_group_stats(validatorsession::NewValidatorGroupStats stats) {
2851
  std::string fname = opts_->get_session_logs_file();
2852
  if (fname.empty()) {
2853
    return;
2854
  }
2855
  std::vector<tl_object_ptr<ton_api::validatorSession_newValidatorGroupStats_node>> nodes;
2856
  for (const auto &node : stats.nodes) {
2857
    nodes.push_back(
2858
        create_tl_object<ton_api::validatorSession_newValidatorGroupStats_node>(node.id.bits256_value(), node.weight));
2859
  }
2860
  auto obj = create_tl_object<ton_api::validatorSession_newValidatorGroupStats>(
2861
      stats.session_id, stats.shard.workchain, stats.shard.shard, stats.cc_seqno, stats.timestamp, stats.self_idx,
2862
      std::move(nodes));
2863
  auto s = td::json_encode<std::string>(td::ToJson(*obj.get()), false);
2864
  s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return c == '\n' || c == '\r'; }), s.end());
2865

2866
  std::ofstream file;
2867
  file.open(fname, std::ios_base::app);
2868
  file << s << "\n";
2869
  file.close();
2870

2871
  LOG(INFO) << "Writing new validator group stats for " << stats.shard.to_str();
2872
}
2873

2874
void ValidatorManagerImpl::get_block_handle_for_litequery(BlockIdExt block_id, td::Promise<ConstBlockHandle> promise) {
2875
  get_block_handle(block_id, false,
2876
                   [SelfId = actor_id(this), block_id, promise = std::move(promise),
2877
                    allow_not_applied = opts_->nonfinal_ls_queries_enabled()](td::Result<BlockHandle> R) mutable {
2878
                     if (R.is_ok() && (allow_not_applied || R.ok()->is_applied())) {
2879
                       promise.set_value(R.move_as_ok());
2880
                     } else {
2881
                       td::actor::send_closure(SelfId, &ValidatorManagerImpl::process_block_handle_for_litequery_error,
2882
                                               block_id, std::move(R), std::move(promise));
2883
                     }
2884
                   });
2885
}
2886

2887
void ValidatorManagerImpl::get_block_data_for_litequery(BlockIdExt block_id, td::Promise<td::Ref<BlockData>> promise) {
2888
  if (candidates_buffer_.empty()) {
2889
    get_block_handle_for_litequery(
2890
        block_id, [manager = actor_id(this), promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2891
          TRY_RESULT_PROMISE(promise, handle, std::move(R));
2892
          td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, std::move(handle),
2893
                                        std::move(promise));
2894
        });
2895
  } else {
2896
    td::actor::send_closure(
2897
        candidates_buffer_, &CandidatesBuffer::get_block_data, block_id,
2898
        [manager = actor_id(this), promise = std::move(promise), block_id](td::Result<td::Ref<BlockData>> R) mutable {
2899
          if (R.is_ok()) {
2900
            promise.set_result(R.move_as_ok());
2901
            return;
2902
          }
2903
          td::actor::send_closure(manager, &ValidatorManagerImpl::get_block_handle_for_litequery, block_id,
2904
                                  [manager, promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2905
                                    TRY_RESULT_PROMISE(promise, handle, std::move(R));
2906
                                    td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db,
2907
                                                                  std::move(handle), std::move(promise));
2908
                                  });
2909
        });
2910
  }
2911
}
2912

2913
void ValidatorManagerImpl::get_block_state_for_litequery(BlockIdExt block_id,
2914
                                                         td::Promise<td::Ref<ShardState>> promise) {
2915
  if (candidates_buffer_.empty()) {
2916
    get_block_handle_for_litequery(
2917
        block_id, [manager = actor_id(this), promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2918
          TRY_RESULT_PROMISE(promise, handle, std::move(R));
2919
          td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, std::move(handle),
2920
                                        std::move(promise));
2921
        });
2922
  } else {
2923
    td::actor::send_closure(
2924
        candidates_buffer_, &CandidatesBuffer::get_block_state, block_id,
2925
        [manager = actor_id(this), promise = std::move(promise), block_id](td::Result<td::Ref<ShardState>> R) mutable {
2926
          if (R.is_ok()) {
2927
            promise.set_result(R.move_as_ok());
2928
            return;
2929
          }
2930
          td::actor::send_closure(manager, &ValidatorManagerImpl::get_block_handle_for_litequery,
2931
              block_id, [manager, promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2932
                TRY_RESULT_PROMISE(promise, handle, std::move(R));
2933
                td::actor::send_closure_later(manager, &ValidatorManager::get_shard_state_from_db, std::move(handle),
2934
                                              std::move(promise));
2935
              });
2936
        });
2937
  }
2938
}
2939

2940
void ValidatorManagerImpl::get_block_by_lt_for_litequery(AccountIdPrefixFull account, LogicalTime lt,
2941
                                                                 td::Promise<ConstBlockHandle> promise) {
2942
  get_block_by_lt_from_db(
2943
      account, lt, [=, SelfId = actor_id(this), promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2944
        if (R.is_ok() && R.ok()->is_applied()) {
2945
          promise.set_value(R.move_as_ok());
2946
        } else {
2947
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::process_lookup_block_for_litequery_error, account, 0,
2948
                                  lt, std::move(R), std::move(promise));
2949
        }
2950
      });
2951
}
2952

2953
void ValidatorManagerImpl::get_block_by_unix_time_for_litequery(AccountIdPrefixFull account, UnixTime ts,
2954
                                                                        td::Promise<ConstBlockHandle> promise) {
2955
  get_block_by_unix_time_from_db(
2956
      account, ts, [=, SelfId = actor_id(this), promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2957
        if (R.is_ok() && R.ok()->is_applied()) {
2958
          promise.set_value(R.move_as_ok());
2959
        } else {
2960
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::process_lookup_block_for_litequery_error, account, 1,
2961
                                  ts, std::move(R), std::move(promise));
2962
        }
2963
      });
2964
}
2965

2966
void ValidatorManagerImpl::get_block_by_seqno_for_litequery(AccountIdPrefixFull account, BlockSeqno seqno,
2967
                                                                    td::Promise<ConstBlockHandle> promise) {
2968
  get_block_by_seqno_from_db(
2969
      account, seqno,
2970
      [=, SelfId = actor_id(this), promise = std::move(promise)](td::Result<ConstBlockHandle> R) mutable {
2971
        if (R.is_ok() && R.ok()->is_applied()) {
2972
          promise.set_value(R.move_as_ok());
2973
        } else {
2974
          td::actor::send_closure(SelfId, &ValidatorManagerImpl::process_lookup_block_for_litequery_error, account, 2,
2975
                                  seqno, std::move(R), std::move(promise));
2976
        }
2977
      });
2978
}
2979

2980
void ValidatorManagerImpl::process_block_handle_for_litequery_error(BlockIdExt block_id,
2981
                                                                    td::Result<BlockHandle> r_handle,
2982
                                                                    td::Promise<ConstBlockHandle> promise) {
2983
  td::Status err;
2984
  if (r_handle.is_error()) {
2985
    err = r_handle.move_as_error();
2986
  } else {
2987
    auto handle = r_handle.move_as_ok();
2988
    if (handle->is_applied()) {
2989
      promise.set_value(std::move(handle));
2990
      return;
2991
    }
2992
    if (!handle->received() || !handle->received_state()) {
2993
      err = td::Status::Error(ErrorCode::notready, PSTRING() << "block " << block_id.id.to_str() << " is not in db");
2994
    } else {
2995
      err = td::Status::Error(ErrorCode::notready, PSTRING() << "block " << block_id.id.to_str() << " is not applied");
2996
    }
2997
  }
2998
  if (block_id.is_masterchain()) {
2999
    if (block_id.seqno() > last_masterchain_seqno_) {
3000
      err = err.move_as_error_suffix(PSTRING() << " (last known masterchain block: " << last_masterchain_seqno_ << ")");
3001
    }
3002
  } else {
3003
    for (auto &shard : shard_client_shards_) {
3004
      if (shard_intersects(shard->shard(), block_id.shard_full())) {
3005
        if (block_id.seqno() > shard->top_block_id().seqno()) {
3006
          err = err.move_as_error_suffix(
3007
              PSTRING() << " (possibly out of sync: shard_client_seqno="
3008
                        << (shard_client_handle_ ? shard_client_handle_->id().seqno() : 0) << " ls_seqno="
3009
                        << (last_liteserver_state_.not_null() ? last_liteserver_state_->get_seqno() : 0) << ")");
3010
        }
3011
        break;
3012
      }
3013
    }
3014
  }
3015
  promise.set_error(std::move(err));
3016
}
3017

3018
void ValidatorManagerImpl::process_lookup_block_for_litequery_error(AccountIdPrefixFull account, int type,
3019
                                                                    td::uint64 value,
3020
                                                                    td::Result<ConstBlockHandle> r_handle,
3021
                                                                    td::Promise<ConstBlockHandle> promise) {
3022
  td::Status err;
3023
  if (r_handle.is_error()) {
3024
    err = r_handle.move_as_error();
3025
  } else {
3026
    auto handle = r_handle.move_as_ok();
3027
    if (handle->is_applied()) {
3028
      promise.set_value(std::move(handle));
3029
      return;
3030
    }
3031
    if (!handle->received() || !handle->received_state()) {
3032
      err = td::Status::Error(ErrorCode::notready, PSTRING() << "block " << handle->id().to_str() << " is not in db");
3033
    } else {
3034
      err = td::Status::Error(ErrorCode::notready, PSTRING() << "block " << handle->id().to_str() << " is not applied");
3035
    }
3036
  }
3037
  if (account.is_masterchain()) {
3038
    if (value > (type == 0
3039
                     ? last_masterchain_state_->get_logical_time()
3040
                     : (type == 1 ? last_masterchain_state_->get_unix_time() : last_masterchain_state_->get_seqno()))) {
3041
      err = err.move_as_error_suffix(PSTRING() << " (last known masterchain block: " << last_masterchain_seqno_ << ")");
3042
    }
3043
  } else {
3044
    for (auto &shard : shard_client_shards_) {
3045
      if (shard_intersects(shard->shard(), account.as_leaf_shard())) {
3046
        if (value > (type == 0 ? shard->end_lt()
3047
                               : (type == 1 ? (shard_client_handle_ ? shard_client_handle_->unix_time() : 0)
3048
                                            : shard->top_block_id().seqno()))) {
3049
          err = err.move_as_error_suffix(
3050
              PSTRING() << " (possibly out of sync: shard_client_seqno="
3051
                        << (shard_client_handle_ ? shard_client_handle_->id().seqno() : 0) << " ls_seqno="
3052
                        << (last_liteserver_state_.not_null() ? last_liteserver_state_->get_seqno() : 0) << ")");
3053
        }
3054
        break;
3055
      }
3056
    }
3057
  }
3058
  static std::string names[3] = {"lt", "utime", "seqno"};
3059
  err = err.move_as_error_prefix(PSTRING() << "cannot find block " << account.to_str() << " " << names[type] << "="
3060
                                           << value << ": ");
3061
  promise.set_error(std::move(err));
3062
}
3063

3064
void ValidatorManagerImpl::get_block_candidate_for_litequery(PublicKey source, BlockIdExt block_id,
3065
                                                             FileHash collated_data_hash,
3066
                                                             td::Promise<BlockCandidate> promise) {
3067
  if (!opts_->nonfinal_ls_queries_enabled()) {
3068
    promise.set_error(td::Status::Error("query is not allowed"));
3069
    return;
3070
  }
3071
  get_block_candidate_from_db(source, block_id, collated_data_hash, std::move(promise));
3072
}
3073

3074
void ValidatorManagerImpl::get_validator_groups_info_for_litequery(
3075
    td::optional<ShardIdFull> shard,
3076
    td::Promise<tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroups>> promise) {
3077
  if (!opts_->nonfinal_ls_queries_enabled()) {
3078
    promise.set_error(td::Status::Error("query is not allowed"));
3079
    return;
3080
  }
3081
  class Actor : public td::actor::Actor {
3082
   public:
3083
    explicit Actor(std::vector<td::actor::ActorId<ValidatorGroup>> groups,
3084
                   td::Promise<tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroups>> promise)
3085
        : groups_(std::move(groups)), promise_(std::move(promise)) {
3086
    }
3087

3088
    void start_up() override {
3089
      pending_ = groups_.size();
3090
      if (pending_ == 0) {
3091
        promise_.set_result(std::move(result_));
3092
        stop();
3093
        return;
3094
      }
3095
      for (auto &x : groups_) {
3096
        td::actor::send_closure(
3097
            x, &ValidatorGroup::get_validator_group_info_for_litequery,
3098
            [SelfId = actor_id(this)](td::Result<tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroupInfo>> R) {
3099
              td::actor::send_closure(SelfId, &Actor::on_result, R.is_ok() ? R.move_as_ok() : nullptr);
3100
            });
3101
      }
3102
    }
3103

3104
    void on_result(tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroupInfo> r) {
3105
      if (r) {
3106
        result_->groups_.push_back(std::move(r));
3107
      }
3108
      --pending_;
3109
      if (pending_ == 0) {
3110
        promise_.set_result(std::move(result_));
3111
        stop();
3112
      }
3113
    }
3114

3115
   private:
3116
    std::vector<td::actor::ActorId<ValidatorGroup>> groups_;
3117
    size_t pending_;
3118
    td::Promise<tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroups>> promise_;
3119
    tl_object_ptr<lite_api::liteServer_nonfinal_validatorGroups> result_ =
3120
        create_tl_object<lite_api::liteServer_nonfinal_validatorGroups>();
3121
  };
3122
  std::vector<td::actor::ActorId<ValidatorGroup>> groups;
3123
  for (auto &x : validator_groups_) {
3124
    if (x.second.actor.empty()) {
3125
      continue;
3126
    }
3127
    if (shard && shard.value() != x.second.shard) {
3128
      continue;
3129
    }
3130
    groups.push_back(x.second.actor.get());
3131
  }
3132
  td::actor::create_actor<Actor>("get-validator-groups-info", std::move(groups), std::move(promise)).release();
3133
}
3134

3135
void ValidatorManagerImpl::update_options(td::Ref<ValidatorManagerOptions> opts) {
3136
  // Currently options can be updated only to change state_serializer_enabled flag
3137
  if (!serializer_.empty()) {
3138
    td::actor::send_closure(serializer_, &AsyncStateSerializer::update_options, opts);
3139
  }
3140
  opts_ = std::move(opts);
3141
}
3142

3143
td::actor::ActorOwn<ValidatorManagerInterface> ValidatorManagerFactory::create(
3144
    td::Ref<ValidatorManagerOptions> opts, std::string db_root, td::actor::ActorId<keyring::Keyring> keyring,
3145
    td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,
3146
    td::actor::ActorId<overlay::Overlays> overlays) {
3147
  return td::actor::create_actor<validator::ValidatorManagerImpl>("manager", std::move(opts), db_root, keyring, adnl,
3148
                                                                  rldp, overlays);
3149
}
3150

3151
size_t ValidatorManagerImpl::CheckedExtMsgCounter::get_msg_count(WorkchainId wc, StdSmcAddress addr) {
3152
  before_query();
3153
  auto it1 = counter_cur_.find({wc, addr});
3154
  auto it2 = counter_prev_.find({wc, addr});
3155
  return (it1 == counter_cur_.end() ? 0 : it1->second) + (it2 == counter_prev_.end() ? 0 : it2->second);
3156
}
3157
size_t ValidatorManagerImpl::CheckedExtMsgCounter::inc_msg_count(WorkchainId wc, StdSmcAddress addr) {
3158
  before_query();
3159
  auto it2 = counter_prev_.find({wc, addr});
3160
  return (it2 == counter_prev_.end() ? 0 : it2->second) + ++counter_cur_[{wc, addr}];
3161
}
3162
void ValidatorManagerImpl::CheckedExtMsgCounter::before_query() {
3163
  while (cleanup_at_.is_in_past()) {
3164
    counter_prev_ = std::move(counter_cur_);
3165
    counter_cur_.clear();
3166
    if (counter_prev_.empty()) {
3167
      cleanup_at_ = td::Timestamp::in(max_ext_msg_per_addr_time_window() / 2.0);
3168
      break;
3169
    }
3170
    cleanup_at_ += max_ext_msg_per_addr_time_window() / 2.0;
3171
  }
3172
}
3173

3174
}  // namespace validator
3175

3176
}  // namespace ton
3177

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

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

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

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