Ton

Форк
0
/
test-validator-session-state.cpp 
982 строки · 38.2 Кб
1
/* 
2
    This file is part of TON Blockchain source code.
3

4
    TON Blockchain is free software; you can redistribute it and/or
5
    modify it under the terms of the GNU General Public License
6
    as published by the Free Software Foundation; either version 2
7
    of the License, or (at your option) any later version.
8

9
    TON Blockchain 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 General Public License for more details.
13

14
    You should have received a copy of the GNU General Public License
15
    along with TON Blockchain.  If not, see <http://www.gnu.org/licenses/>.
16

17
    In addition, as a special exception, the copyright holders give permission 
18
    to link the code of portions of this program with the OpenSSL library. 
19
    You must obey the GNU General Public License in all respects for all 
20
    of the code used other than OpenSSL. If you modify file(s) with this 
21
    exception, you may extend this exception to your version of the file(s), 
22
    but you are not obligated to do so. If you do not wish to do so, delete this 
23
    exception statement from your version. If you delete this exception statement 
24
    from all source files in the program, then also delete it here.
25

26
    Copyright 2017-2020 Telegram Systems LLP
27
*/
28
#include "adnl/adnl.h"
29

30
#include "td/utils/misc.h"
31
#include "td/utils/port/signals.h"
32
#include "td/utils/port/path.h"
33
#include "td/utils/Random.h"
34

35
#include "validator-session/validator-session-description.h"
36
#include "validator-session/validator-session-state.h"
37
#include "validator-session/validator-session-description.hpp"
38

39
#include <limits>
40
#include <memory>
41
#include <set>
42

43
class Description : public ton::validatorsession::ValidatorSessionDescription {
44
 public:
45
  HashType compute_hash(td::Slice data) const override {
46
    return td::crc32c(data);
47
  }
48
  HashType zero_hash() const {
49
    return 0;
50
  }
51
  void *alloc(size_t size, size_t align, bool temp) override {
52
    return (temp ? mem_temp_ : mem_perm_).alloc(size, align);
53
  }
54
  bool is_persistent(const void *ptr) const override {
55
    return mem_perm_.contains(ptr);
56
  }
57
  void clear_temp_memory() override {
58
    mem_temp_.clear();
59
  }
60

61
  ton::PublicKeyHash get_source_id(td::uint32 idx) const override {
62
    CHECK(idx < total_nodes_);
63
    td::Bits256 x = td::Bits256::zero();
64
    auto &d = x.as_array();
65
    d[0] = static_cast<td::uint8>(idx);
66
    return ton::PublicKeyHash{x};
67
  }
68
  ton::PublicKey get_source_public_key(td::uint32 idx) const override {
69
    UNREACHABLE();
70
  }
71
  ton::adnl::AdnlNodeIdShort get_source_adnl_id(td::uint32 idx) const override {
72
    UNREACHABLE();
73
  }
74
  td::uint32 get_source_idx(ton::PublicKeyHash id) const override {
75
    auto x = id.bits256_value();
76
    auto y = x.as_array();
77
    return y[0];
78
  }
79
  ton::ValidatorWeight get_node_weight(td::uint32 idx) const override {
80
    return 1;
81
  }
82
  td::uint32 get_total_nodes() const override {
83
    return total_nodes_;
84
  }
85
  ton::ValidatorWeight get_cutoff_weight() const override {
86
    return 2 * total_nodes_ / 3 + 1;
87
  }
88
  ton::ValidatorWeight get_total_weight() const override {
89
    return total_nodes_;
90
  }
91
  td::int32 get_node_priority(td::uint32 src_idx, td::uint32 round) const override {
92
    round %= get_total_nodes();
93
    if (src_idx < round) {
94
      src_idx += get_total_nodes();
95
    }
96
    if (src_idx - round < opts_.round_candidates) {
97
      return src_idx - round;
98
    }
99
    return -1;
100
  }
101
  td::uint32 get_max_priority() const override {
102
    return opts_.round_candidates - 1;
103
  }
104
  td::uint32 get_unixtime(td::uint64 ts) const override {
105
    return static_cast<td::uint32>(ts >> 32);
106
  }
107
  td::uint32 get_attempt_seqno(td::uint64 ts) const override {
108
    return get_unixtime(ts) / opts_.round_attempt_duration;
109
  }
110
  td::uint32 get_self_idx() const override {
111
    UNREACHABLE();
112
  }
113
  td::uint64 get_ts() const override {
114
    auto tm = td::Clocks::system();
115
    CHECK(tm >= 0);
116
    auto t = static_cast<td::uint32>(tm);
117
    auto t2 = static_cast<td::uint64>((1ll << 32) * (tm - t));
118
    CHECK(t2 < (1ull << 32));
119
    return ((t * 1ull) << 32) + t2;
120
  }
121
  const RootObject *get_by_hash(HashType hash, bool allow_temp) const override {
122
    auto x = hash % cache_size;
123

124
    return cache_[x].load(std::memory_order_relaxed).ptr;
125
  }
126
  void update_hash(const RootObject *obj, HashType hash) override {
127
    if (!is_persistent(obj)) {
128
      return;
129
    }
130
    auto x = hash % cache_size;
131
    Cached p{obj};
132
    cache_[x].store(p, std::memory_order_relaxed);
133
  }
134
  void on_reuse() override {
135
  }
136
  td::Timestamp attempt_start_at(td::uint32 att) const override {
137
    return td::Timestamp::at_unix(att * opts_.round_attempt_duration);
138
  }
139
  ton::validatorsession::ValidatorSessionCandidateId candidate_id(
140
      td::uint32 src_idx, ton::validatorsession::ValidatorSessionRootHash root_hash,
141
      ton::validatorsession::ValidatorSessionFileHash file_hash,
142
      ton::validatorsession::ValidatorSessionCollatedDataFileHash collated_data_file_hash) const override {
143
    auto obj = ton::create_tl_object<ton::ton_api::validatorSession_candidateId>(get_source_id(src_idx).tl(), root_hash,
144
                                                                                 file_hash, collated_data_file_hash);
145
    return get_tl_object_sha_bits256(obj);
146
  }
147
  td::Status check_signature(ton::validatorsession::ValidatorSessionRootHash root_hash,
148
                             ton::validatorsession::ValidatorSessionFileHash file_hash, td::uint32 src_idx,
149
                             td::Slice signature) const override {
150
    if (signature.size() == 0) {
151
      return td::Status::Error("wrong size");
152
    }
153
    if (signature[0] == 126) {
154
      return td::Status::OK();
155
    } else {
156
      return td::Status::Error("invalid");
157
    }
158
  }
159
  td::Status check_approve_signature(ton::validatorsession::ValidatorSessionRootHash root_hash,
160
                                     ton::validatorsession::ValidatorSessionFileHash file_hash, td::uint32 src_idx,
161
                                     td::Slice signature) const override {
162
    if (signature.size() == 0) {
163
      return td::Status::Error("wrong size");
164
    }
165
    if (signature[0] == 127) {
166
      return td::Status::OK();
167
    } else {
168
      return td::Status::Error("invalid");
169
    }
170
  }
171
  double get_delay(td::uint32 priority) const override {
172
    return 0;
173
  }
174
  double get_empty_block_delay() const override {
175
    return 0;
176
  }
177
  std::vector<ton::catchain::CatChainNode> export_catchain_nodes() const override {
178
    UNREACHABLE();
179
  }
180

181
  td::uint32 get_vote_for_author(td::uint32 attempt_seqno) const override {
182
    return attempt_seqno % total_nodes_;
183
  }
184

185
  const ton::validatorsession::ValidatorSessionOptions &opts() const override {
186
    return opts_;
187
  }
188

189
  Description(ton::validatorsession::ValidatorSessionOptions opts, td::uint32 total_nodes)
190
      : opts_(opts), total_nodes_(total_nodes), mem_perm_(1 << 30), mem_temp_(1 << 22) {
191
    for (auto &el : cache_) {
192
      Cached v{nullptr};
193
      el.store(v, std::memory_order_relaxed);
194
    }
195

196
    CHECK(total_nodes_ > 0);
197
  }
198

199
 private:
200
  ton::validatorsession::ValidatorSessionOptions opts_;
201

202
  td::uint32 total_nodes_;
203

204
  static constexpr td::uint32 cache_size = (1 << 20);
205

206
  struct Cached {
207
    const RootObject *ptr;
208
  };
209
  std::array<std::atomic<Cached>, cache_size> cache_;
210

211
  ton::validatorsession::ValidatorSessionDescriptionImpl::MemPool mem_perm_, mem_temp_;
212
};
213

214
double myrand() {
215
  return td::Random::fast(0, 100) * 0.01;
216
}
217

218
int main() {
219
  SET_VERBOSITY_LEVEL(verbosity_INFO);
220

221
  td::set_default_failure_signal_handler().ensure();
222
  td::uint32 total_nodes = 100;
223

224
  ton::validatorsession::ValidatorSessionOptions opts;
225

226
  {
227
    auto descptr = new Description(opts, total_nodes);
228
    auto &desc = *descptr;
229

230
    auto c1 = desc.candidate_id(0, td::Bits256::zero(), td::Bits256::zero(), td::Bits256::zero());
231
    auto c2 = desc.candidate_id(1, td::Bits256::zero(), td::Bits256::zero(), td::Bits256::zero());
232
    CHECK(c1 != c2);
233

234
    auto s = ton::validatorsession::ValidatorSessionState::create(desc);
235
    CHECK(s);
236
    s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
237
    CHECK(s);
238
    auto att = 1000000000;
239

240
    for (td::uint32 i = 0; i < total_nodes; i++) {
241
      auto act = s->create_action(desc, i, att);
242
      CHECK(act);
243
      CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID);
244
    }
245

246
    {
247
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_submittedBlock>(
248
          0, ton::Bits256::zero(), ton::Bits256::zero(), ton::Bits256::zero());
249
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, 1, att, act.get());
250
      CHECK(s);
251
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
252
      CHECK(s);
253
    }
254

255
    for (td::uint32 i = 0; i < total_nodes; i++) {
256
      auto act = s->create_action(desc, i, att);
257
      CHECK(act);
258
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << act.get();
259
    }
260

261
    for (td::uint32 i = 0; i < total_nodes; i++) {
262
      bool found;
263
      s->choose_block_to_sign(desc, i, found);
264
      CHECK(!found);
265
      auto vec = s->choose_blocks_to_approve(desc, i);
266
      LOG_CHECK(vec.size() == 2) << vec.size();
267
      CHECK(vec[0]);
268
      CHECK(ton::validatorsession::SentBlock::get_block_id(vec[0]) == c2);
269
      CHECK(vec[1] == nullptr);
270
      CHECK(ton::validatorsession::SentBlock::get_block_id(vec[1]) == ton::validatorsession::skip_round_candidate_id());
271
    }
272
    for (td::uint32 i = 0; i < 2 * total_nodes / 3; i++) {
273
      td::BufferSlice sig{1};
274
      sig.as_slice()[0] = 127;
275
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_approvedBlock>(0, c2, std::move(sig));
276
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
277
      CHECK(s);
278
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
279
      CHECK(s);
280
    }
281

282
    for (td::uint32 i = 0; i < total_nodes; i++) {
283
      auto act = s->create_action(desc, i, att);
284
      CHECK(act);
285
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << act.get();
286
    }
287

288
    for (td::uint32 i = 2 * total_nodes / 3; i < total_nodes; i++) {
289
      td::BufferSlice sig{1};
290
      sig.as_slice()[0] = 127;
291
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_approvedBlock>(0, c2, std::move(sig));
292
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
293
      CHECK(s);
294
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
295
      CHECK(s);
296
    }
297

298
    for (td::uint32 i = 0; i < total_nodes; i++) {
299
      bool found;
300
      s->choose_block_to_sign(desc, i, found);
301
      CHECK(!found);
302
      auto vec = s->choose_blocks_to_approve(desc, i);
303
      CHECK(vec.size() == 1);
304
      CHECK(vec[0] == nullptr);
305
      CHECK(ton::validatorsession::SentBlock::get_block_id(vec[0]) == ton::validatorsession::skip_round_candidate_id());
306
    }
307

308
    for (td::uint32 i = 0; i < total_nodes; i++) {
309
      auto act = s->create_action(desc, i, att);
310
      CHECK(act);
311
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << act.get();
312

313
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
314
      CHECK(s);
315
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
316
      CHECK(s);
317

318
      auto act2 = s->create_action(desc, i, att);
319
      if (i < 2 * total_nodes / 3) {
320
        LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
321
      } else {
322
        LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_precommit::ID)
323
            << "i=" << i << " " << act2.get();
324
      }
325
    }
326
    for (td::uint32 j = 1; j < opts.max_round_attempts; j++) {
327
      auto act = s->create_action(desc, 0, att + j);
328
      CHECK(act);
329
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "j=" << j << " " << act.get();
330
    }
331
    for (td::uint32 j = opts.max_round_attempts; j < opts.max_round_attempts + 10; j++) {
332
      auto act = s->create_action(desc, 0, att + j);
333
      CHECK(act);
334
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "j=" << j << " " << act.get();
335
    }
336
    auto s_copy = s;
337
    auto att_copy = att;
338
    for (td::uint32 i = 0; i < total_nodes; i++) {
339
      auto act = s->create_action(desc, i, att);
340
      CHECK(act);
341

342
      if (i <= 2 * total_nodes / 3) {
343
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID)
344
            << "i=" << i << " " << act.get();
345
      } else {
346
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
347
      }
348

349
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
350
      CHECK(s);
351
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
352
      CHECK(s);
353

354
      auto act2 = s->create_action(desc, i, att);
355
      LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
356
    }
357

358
    att += 10;
359
    for (td::uint32 i = 0; i < total_nodes; i++) {
360
      auto act = s->create_action(desc, i, att);
361
      CHECK(act);
362
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
363
    }
364

365
    for (td::uint32 i = 0; i < total_nodes; i++) {
366
      bool found;
367
      auto block = s->choose_block_to_sign(desc, i, found);
368
      CHECK(found);
369
      CHECK(ton::validatorsession::SentBlock::get_block_id(block) == c2);
370
    }
371

372
    for (td::uint32 i = 0; i < 2 * total_nodes / 3; i++) {
373
      td::BufferSlice sig{1};
374
      sig.as_slice()[0] = 126;
375
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_commit>(0, c2, std::move(sig));
376
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
377
      CHECK(s);
378
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
379
      CHECK(s);
380
    }
381

382
    CHECK(s->cur_round_seqno() == 0);
383

384
    for (td::uint32 i = 2 * total_nodes / 3; i < total_nodes; i++) {
385
      td::BufferSlice sig{1};
386
      sig.as_slice()[0] = 126;
387
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_commit>(0, c2, std::move(sig));
388
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
389
      CHECK(s);
390
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
391
      CHECK(s);
392
    }
393

394
    CHECK(s->cur_round_seqno() == 1);
395

396
    auto sigs = s->get_committed_block_signatures(desc, 0);
397
    for (td::uint32 i = 0; i < sigs->size(); i++) {
398
      auto S = sigs->at(i);
399
      CHECK(S);
400
    }
401

402
    s = s_copy;
403
    att = att_copy;
404

405
    for (td::uint32 i = 0; i < total_nodes / 3; i++) {
406
      auto act = s->create_action(desc, i, att);
407
      CHECK(act);
408

409
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID) << "i=" << i << " " << act.get();
410

411
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
412
      CHECK(s);
413
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
414
      CHECK(s);
415

416
      auto act2 = s->create_action(desc, i, att);
417
      LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
418
    }
419

420
    att += opts.max_round_attempts - 1;
421

422
    do {
423
      att++;
424
      for (td::uint32 i = 0; i < total_nodes; i++) {
425
        auto act = s->create_action(desc, i, att);
426
        CHECK(act);
427

428
        if (i < total_nodes / 3) {
429
          LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
430
        } else {
431
          LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
432
        }
433

434
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
435
        CHECK(s);
436
        s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
437
        CHECK(s);
438

439
        auto act2 = s->create_action(desc, i, att);
440
        LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
441
      }
442
      desc.clear_temp_memory();
443
    } while (desc.get_vote_for_author(att) < total_nodes / 3);
444

445
    {
446
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_submittedBlock>(
447
          0, ton::Bits256::zero(), ton::Bits256::zero(), ton::Bits256::zero());
448
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, 0, att, act.get());
449
      CHECK(s);
450
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
451
      CHECK(s);
452
    }
453

454
    auto idx = desc.get_vote_for_author(att);
455
    for (td::uint32 i = 0; i < total_nodes; i++) {
456
      LOG_CHECK(s->check_need_generate_vote_for(desc, i, att) == (i == idx))
457
          << i << " " << idx << " " << s->check_need_generate_vote_for(desc, i, att);
458
    }
459

460
    for (td::uint32 i = 0; i < total_nodes; i++) {
461
      td::BufferSlice sig{1};
462
      sig.as_slice()[0] = 127;
463
      auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_approvedBlock>(0, c1, std::move(sig));
464
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
465
      CHECK(s);
466
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
467
      CHECK(s);
468
    }
469

470
    {
471
      auto act = s->generate_vote_for(desc, idx, att);
472
      CHECK(act);
473
      act->candidate_ = c1;
474
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
475
      CHECK(s);
476
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
477
      CHECK(s);
478
    }
479

480
    td::BufferSlice buf{10240};
481
    td::StringBuilder sb{buf.as_slice()};
482

483
    s->dump(desc, sb, att);
484

485
    LOG(ERROR) << sb.as_cslice();
486

487
    for (td::uint32 i = 0; i < total_nodes; i++) {
488
      auto act = s->create_action(desc, i, att);
489
      CHECK(act);
490

491
      if (i < total_nodes / 3) {
492
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
493
      } else {
494
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
495
      }
496

497
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
498
      CHECK(s);
499
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
500
      CHECK(s);
501
    }
502

503
    att++;
504
    idx = desc.get_vote_for_author(att);
505
    for (td::uint32 i = 0; i < total_nodes; i++) {
506
      LOG_CHECK(s->check_need_generate_vote_for(desc, i, att) == (i == idx))
507
          << i << " " << idx << " " << s->check_need_generate_vote_for(desc, i, att);
508
    }
509
    for (td::uint32 i = 0; i < total_nodes; i++) {
510
      auto act = s->create_action(desc, i, att);
511
      CHECK(act);
512

513
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
514

515
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
516
      CHECK(s);
517
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
518
      CHECK(s);
519
    }
520

521
    {
522
      auto act = s->generate_vote_for(desc, idx, att);
523
      CHECK(act);
524
      act->candidate_ = c1;
525
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
526
      CHECK(s);
527
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
528
      CHECK(s);
529
    }
530

531
    for (td::uint32 i = 0; i < total_nodes; i++) {
532
      auto act = s->create_action(desc, i, att);
533
      CHECK(act);
534

535
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
536

537
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
538
      CHECK(s);
539
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
540
      CHECK(s);
541
    }
542

543
    for (td::uint32 i = 0; i < total_nodes / 3; i++) {
544
      auto act = s->create_action(desc, i, att);
545
      CHECK(act);
546

547
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID) << "i=" << i << " " << act.get();
548

549
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
550
      CHECK(s);
551
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
552
      CHECK(s);
553

554
      auto act2 = s->create_action(desc, i, att);
555
      LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
556
    }
557

558
    att++;
559
    idx = desc.get_vote_for_author(att);
560
    {
561
      auto act = s->generate_vote_for(desc, idx, att);
562
      CHECK(act);
563
      act->candidate_ = c1;
564
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
565
      CHECK(s);
566
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
567
      CHECK(s);
568
    }
569

570
    for (td::uint32 i = 0; i < total_nodes; i++) {
571
      auto act = s->create_action(desc, i, att);
572
      CHECK(act);
573

574
      LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
575

576
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
577
      CHECK(s);
578
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
579
      CHECK(s);
580
    }
581

582
    for (td::uint32 i = 0; i < total_nodes; i++) {
583
      auto act = s->create_action(desc, i, att);
584
      CHECK(act);
585

586
      if (i <= 2 * total_nodes / 3) {
587
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID)
588
            << "i=" << i << " " << act.get();
589
      } else {
590
        LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
591
      }
592

593
      s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
594
      CHECK(s);
595
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
596
      CHECK(s);
597

598
      auto act2 = s->create_action(desc, i, att);
599
      LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act2.get();
600
    }
601
    delete descptr;
602
  }
603

604
  {
605
    auto descptr = new Description(opts, total_nodes);
606
    auto &desc = *descptr;
607

608
    auto sig1 = ton::validatorsession::SessionBlockCandidateSignature::create(desc, td::BufferSlice{"a"});
609
    auto sig2 = ton::validatorsession::SessionBlockCandidateSignature::create(desc, td::BufferSlice{"b"});
610
    auto sig3 = ton::validatorsession::SessionBlockCandidateSignature::create(desc, td::BufferSlice{"c"});
611
    auto sig4 = ton::validatorsession::SessionBlockCandidateSignature::create(desc, td::BufferSlice{"d"});
612

613
    {
614
      auto m1 = ton::validatorsession::SessionBlockCandidateSignature::merge(desc, sig1, sig2);
615
      CHECK(m1->as_slice() == "a");
616
      auto m2 = ton::validatorsession::SessionBlockCandidateSignature::merge(desc, sig2, sig1);
617
      CHECK(m2->as_slice() == "a");
618
    }
619

620
    std::vector<const ton::validatorsession::SessionBlockCandidateSignature *> sig_vec_null;
621
    sig_vec_null.resize(desc.get_total_nodes(), nullptr);
622
    auto sig_vec1 = ton::validatorsession::SessionBlockCandidateSignatureVector::create(desc, sig_vec_null);
623
    auto sig_vec2 = ton::validatorsession::SessionBlockCandidateSignatureVector::create(desc, sig_vec_null);
624

625
    sig_vec1 = ton::validatorsession::SessionBlockCandidateSignatureVector::change(desc, sig_vec1, 0, sig1);
626
    sig_vec1 = ton::validatorsession::SessionBlockCandidateSignatureVector::change(desc, sig_vec1, 1, sig3);
627
    sig_vec2 = ton::validatorsession::SessionBlockCandidateSignatureVector::change(desc, sig_vec2, 0, sig4);
628
    sig_vec2 = ton::validatorsession::SessionBlockCandidateSignatureVector::change(desc, sig_vec2, 1, sig2);
629
    sig_vec2 = ton::validatorsession::SessionBlockCandidateSignatureVector::change(desc, sig_vec2, 2, sig4);
630

631
    {
632
      auto m1 = ton::validatorsession::SessionBlockCandidateSignatureVector::merge(
633
          desc, sig_vec1, sig_vec2, [&](const auto l, const auto r) {
634
            return ton::validatorsession::SessionBlockCandidateSignature::merge(desc, l, r);
635
          });
636
      CHECK(m1->at(0)->as_slice() == "a");
637
      CHECK(m1->at(1)->as_slice() == "b");
638
      CHECK(m1->at(2)->as_slice() == "d");
639
      CHECK(!m1->at(3));
640
      auto m2 = ton::validatorsession::SessionBlockCandidateSignatureVector::merge(
641
          desc, sig_vec2, sig_vec1, [&](const auto l, const auto r) {
642
            return ton::validatorsession::SessionBlockCandidateSignature::merge(desc, l, r);
643
          });
644
      CHECK(m2->at(0)->as_slice() == "a");
645
      CHECK(m2->at(1)->as_slice() == "b");
646
      CHECK(m2->at(2)->as_slice() == "d");
647
      CHECK(!m2->at(3));
648
    }
649

650
    auto sentb = ton::validatorsession::SentBlock::create(desc, 0, ton::Bits256::zero(), ton::Bits256::zero(),
651
                                                          ton::Bits256::zero());
652
    //auto sentb2 = ton::validatorsession::SentBlock::create(desc, 1, ton::Bits256::zero(), ton::Bits256::zero(),
653
    //                                                       ton::Bits256::zero());
654

655
    auto cand1 = ton::validatorsession::SessionBlockCandidate::create(desc, sentb, sig_vec1);
656
    auto cand2 = ton::validatorsession::SessionBlockCandidate::create(desc, sentb, sig_vec2);
657

658
    {
659
      auto m1 = ton::validatorsession::SessionBlockCandidate::merge(desc, cand1, cand2);
660
      CHECK(m1->get_block() == sentb);
661
      CHECK(m1->get_approvers_list()->at(0)->as_slice() == "a");
662
      CHECK(m1->get_approvers_list()->at(1)->as_slice() == "b");
663
      CHECK(m1->get_approvers_list()->at(2)->as_slice() == "d");
664
      CHECK(!m1->get_approvers_list()->at(3));
665
      auto m2 = ton::validatorsession::SessionBlockCandidate::merge(desc, cand2, cand1);
666
      CHECK(m2->get_block() == sentb);
667
      CHECK(m2->get_approvers_list()->at(0)->as_slice() == "a");
668
      CHECK(m2->get_approvers_list()->at(1)->as_slice() == "b");
669
      CHECK(m2->get_approvers_list()->at(2)->as_slice() == "d");
670
      CHECK(!m2->get_approvers_list()->at(3));
671
    }
672

673
    std::vector<bool> vote_vec_1;
674
    vote_vec_1.resize(desc.get_total_nodes());
675
    for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
676
      vote_vec_1[i] = td::Random::fast(0, 1) == 0;
677
    }
678
    std::vector<bool> vote_vec_2;
679
    vote_vec_2.resize(desc.get_total_nodes());
680
    for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
681
      vote_vec_2[i] = td::Random::fast(0, 1) == 0;
682
    }
683

684
    auto vote_t1 = ton::validatorsession::SessionVoteCandidate::create(
685
        desc, sentb, ton::validatorsession::CntVector<bool>::create(desc, vote_vec_1));
686
    auto vote_t2 = ton::validatorsession::SessionVoteCandidate::create(
687
        desc, sentb, ton::validatorsession::CntVector<bool>::create(desc, vote_vec_2));
688

689
    {
690
      auto m = ton::validatorsession::SessionVoteCandidate::merge(desc, vote_t1, vote_t2);
691
      for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
692
        CHECK(m->check_block_is_voted_by(i) == vote_t1->check_block_is_voted_by(i) ||
693
              vote_t2->check_block_is_voted_by(i));
694
      }
695
    }
696

697
    std::vector<bool> vote_vec;
698
    vote_vec.resize(desc.get_total_nodes(), false);
699
    auto vote1 = ton::validatorsession::SessionVoteCandidate::create(
700
        desc, nullptr, ton::validatorsession::CntVector<bool>::create(desc, vote_vec));
701
    auto vote1d = ton::validatorsession::SessionVoteCandidate::create(
702
        desc, sentb, ton::validatorsession::CntVector<bool>::create(desc, vote_vec));
703
    auto vote2 = ton::validatorsession::SessionVoteCandidate::create(
704
        desc, sentb, ton::validatorsession::CntVector<bool>::create(desc, vote_vec));
705
    auto vote2d = ton::validatorsession::SessionVoteCandidate::create(
706
        desc, sentb, ton::validatorsession::CntVector<bool>::create(desc, vote_vec));
707
    CHECK(ton::validatorsession::SessionVoteCandidate::Compare()(vote1, vote2));
708
    CHECK(!ton::validatorsession::SessionVoteCandidate::Compare()(vote2, vote1));
709

710
    for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
711
      if (i < desc.get_cutoff_weight()) {
712
        vote1 = ton::validatorsession::SessionVoteCandidate::push(desc, vote1, i);
713
      } else {
714
        vote2 = ton::validatorsession::SessionVoteCandidate::push(desc, vote2, i);
715
      }
716
      if (i < desc.get_cutoff_weight() - 1) {
717
        vote1d = ton::validatorsession::SessionVoteCandidate::push(desc, vote1d, i);
718
      } else {
719
        vote2d = ton::validatorsession::SessionVoteCandidate::push(desc, vote2d, i);
720
      }
721
    }
722

723
    auto v = ton::validatorsession::VoteVector::create(desc, {vote1, vote2});
724

725
    auto prec0_vec = ton::validatorsession::CntVector<bool>::create(desc, vote_vec);
726
    auto prec1_vec = ton::validatorsession::CntVector<bool>::change(desc, prec0_vec, 0, true);
727
    auto prec2_vec = ton::validatorsession::CntVector<bool>::change(desc, prec0_vec, 1, true);
728

729
    auto att0_0 =
730
        ton::validatorsession::ValidatorSessionRoundAttemptState::create(desc, 1, v, prec1_vec, nullptr, false);
731
    bool f;
732
    CHECK(att0_0->get_voted_block(desc, f) == nullptr);
733
    CHECK(f);
734

735
    auto att1_0 = ton::validatorsession::ValidatorSessionRoundAttemptState::create(
736
        desc, 2, ton::validatorsession::VoteVector::create(desc, {vote1d}), prec0_vec, nullptr, false);
737
    CHECK(att1_0->get_voted_block(desc, f) == nullptr);
738
    CHECK(!f);
739

740
    auto att1_1 = ton::validatorsession::ValidatorSessionRoundAttemptState::create(
741
        desc, 2, ton::validatorsession::VoteVector::create(desc, {vote2d}), prec0_vec, nullptr, false);
742
    CHECK(att1_1->get_voted_block(desc, f) == nullptr);
743
    CHECK(!f);
744

745
    auto att2_0 =
746
        ton::validatorsession::ValidatorSessionRoundAttemptState::create(desc, 3, v, prec2_vec, nullptr, false);
747
    CHECK(att2_0->get_voted_block(desc, f) == nullptr);
748
    CHECK(f);
749

750
    {
751
      auto m = ton::validatorsession::ValidatorSessionRoundAttemptState::merge(desc, att1_0, att1_1);
752
      CHECK(m->get_voted_block(desc, f) == sentb);
753
      CHECK(f);
754
    }
755

756
    std::vector<td::uint32> first_att_1;
757
    first_att_1.resize(desc.get_total_nodes());
758
    std::vector<td::uint32> first_att_2;
759
    first_att_2.resize(desc.get_total_nodes());
760
    for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
761
      first_att_1[i] = td::Random::fast(0, 1000000000);
762
      first_att_2[i] = td::Random::fast(0, 1000000000);
763
    }
764

765
    std::vector<td::uint32> last_precommit0;
766
    last_precommit0.resize(desc.get_total_nodes());
767
    last_precommit0[0] = 1;
768
    last_precommit0[1] = 3;
769

770
    std::vector<td::uint32> last_precommit1;
771
    last_precommit1.resize(desc.get_total_nodes());
772

773
    auto r1 = ton::validatorsession::ValidatorSessionRoundState::create(
774
        desc, nullptr, 0, false, ton::validatorsession::CntVector<td::uint32>::create(desc, first_att_1),
775
        ton::validatorsession::CntVector<td::uint32>::create(desc, last_precommit0), nullptr, sig_vec1,
776
        ton::validatorsession::AttemptVector::create(desc, {att0_0, att1_0, att2_0}));
777
    CHECK(r1->get_last_precommit(0) == 1);
778
    CHECK(r1->get_last_precommit(1) == 3);
779
    auto r2 = ton::validatorsession::ValidatorSessionRoundState::create(
780
        desc, nullptr, 0, false, ton::validatorsession::CntVector<td::uint32>::create(desc, first_att_2),
781
        ton::validatorsession::CntVector<td::uint32>::create(desc, last_precommit1), nullptr, sig_vec2,
782
        ton::validatorsession::AttemptVector::create(desc, {att1_1}));
783

784
    {
785
      auto m = ton::validatorsession::ValidatorSessionRoundState::merge(desc, r1, r2);
786
      CHECK(m);
787

788
      for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
789
        CHECK(m->get_first_attempt(i) == first_att_1[i]
790
                  ? first_att_2[i] ? std::min(first_att_1[i], first_att_2[i]) : first_att_1[i]
791
                  : first_att_2[i]);
792
      }
793
      for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
794
        if (i == 1) {
795
          CHECK(m->get_last_precommit(i) == 3);
796
        } else {
797
          CHECK(m->get_last_precommit(i) == 0);
798
        }
799
      }
800
    }
801

802
    delete descptr;
803
  }
804

805
  for (td::uint32 ver = 0; ver < 2; ver++) {
806
    double sign_prob = 1.0;
807
    double submit_prob = 0.8;
808
    double approve_prob = 0.5;
809
    double blocks_per_sec_per_node = 0.5;
810

811
    auto descptr = new Description(opts, total_nodes);
812
    auto &desc = *descptr;
813

814
    auto adj_total_nodes = total_nodes + (ver ? total_nodes / 3 : 0);
815

816
    std::vector<std::vector<const ton::validatorsession::ValidatorSessionState *>> states;
817
    states.resize(adj_total_nodes);
818

819
    td::uint64 ts = desc.get_ts();
820

821
    auto virt_state = ton::validatorsession::ValidatorSessionState::create(desc);
822
    virt_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, virt_state);
823

824
    for (td::uint32 ri = 0; ri < 100000; ri++) {
825
      auto ts_adj = ts;
826
      auto att = desc.get_attempt_seqno(ts_adj);
827

828
      //auto virt_round = virt_state->cur_round_seqno();
829
      auto virt_x = desc.get_vote_for_author(att);
830
      td::int32 x = virt_x;
831

832
      if (!virt_state->check_need_generate_vote_for(desc, virt_x, att) || myrand() < 0.5) {
833
        x = td::Random::fast(0, total_nodes - 1);
834
      }
835

836
      auto adj_x = x;
837
      if (x + total_nodes < adj_total_nodes && td::Random::fast(0, 1) == 0) {
838
        adj_x += total_nodes;
839
      }
840

841
      const ton::validatorsession::ValidatorSessionState *s;
842
      if (states[adj_x].size() == 0) {
843
        s = ton::validatorsession::ValidatorSessionState::create(desc);
844
      } else {
845
        s = *states[adj_x].rbegin();
846
      }
847

848
      for (td::uint32 z = 0; z < 3; z++) {
849
        auto y = td::Random::fast(0, adj_total_nodes - 2);
850
        if (adj_x <= y) {
851
          y++;
852
        }
853
        if (states[y].size() > 0) {
854
          auto k = td::Random::fast(static_cast<td::int32>(states[y].size() - 2),
855
                                    static_cast<td::int32>(states[y].size() - 1));
856
          if (k < 0) {
857
            k = 0;
858
          }
859
          s = ton::validatorsession::ValidatorSessionState::merge(desc, s, states[y][k]);
860
          CHECK(s);
861
          s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
862
          CHECK(s);
863
        }
864
      }
865
      auto round = s->cur_round_seqno();
866

867
      if (desc.get_node_priority(x, round) >= 0 && myrand() <= submit_prob && !s->check_block_is_sent_by(desc, x)) {
868
        auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_submittedBlock>(
869
            round, ton::Bits256::zero(), ton::Bits256::zero(), ton::Bits256::zero());
870
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
871
        CHECK(s);
872
        s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
873
        CHECK(s);
874
      }
875

876
      auto vec = s->choose_blocks_to_approve(desc, x);
877
      if (vec.size() > 0 && myrand() <= approve_prob) {
878
        auto B = vec[td::Random::fast(0, static_cast<td::uint32>(vec.size() - 1))];
879
        auto id = ton::validatorsession::SentBlock::get_block_id(B);
880
        td::BufferSlice sig{B ? 1u : 0u};
881
        if (B) {
882
          sig.as_slice()[0] = 127;
883
        }
884
        auto act =
885
            ton::create_tl_object<ton::ton_api::validatorSession_message_approvedBlock>(round, id, std::move(sig));
886
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
887
        CHECK(s);
888
      }
889

890
      bool found;
891
      auto to_sign = s->choose_block_to_sign(desc, x, found);
892
      if (found && myrand() <= sign_prob) {
893
        auto id = ton::validatorsession::SentBlock::get_block_id(to_sign);
894
        td::BufferSlice sig{to_sign ? 1u : 0u};
895
        if (to_sign) {
896
          sig.as_slice()[0] = 126;
897
        }
898
        auto act = ton::create_tl_object<ton::ton_api::validatorSession_message_commit>(round, id, std::move(sig));
899
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
900
        CHECK(s);
901
      }
902

903
      if (s->check_need_generate_vote_for(desc, x, att)) {
904
        auto act = s->generate_vote_for(desc, x, att);
905
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
906
        CHECK(s);
907
      }
908

909
      while (true) {
910
        auto act = s->create_action(desc, x, att);
911
        bool stop = false;
912
        if (act->get_id() == ton::ton_api::validatorSession_message_empty::ID) {
913
          stop = true;
914
        }
915
        s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
916
        CHECK(s);
917
        if (stop) {
918
          break;
919
        }
920
      }
921

922
      bool made = false;
923
      s = ton::validatorsession::ValidatorSessionState::make_one(desc, s, x, att, made);
924
      CHECK(!made);
925

926
      s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
927
      CHECK(s);
928

929
      states[adj_x].push_back(s);
930

931
      if (myrand() <= 1.0 / blocks_per_sec_per_node / total_nodes) {
932
        ts += 1ull << 32;
933
      }
934
      desc.clear_temp_memory();
935

936
      virt_state = ton::validatorsession::ValidatorSessionState::merge(desc, virt_state, s);
937
      virt_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, virt_state);
938
    }
939

940
    td::BufferSlice buf{10240};
941
    td::StringBuilder sb{buf.as_slice()};
942

943
    virt_state->dump(desc, sb, desc.get_attempt_seqno(ts));
944

945
    LOG(ERROR) << sb.as_cslice();
946

947
    for (auto &x : states) {
948
      if (x.size() == 0) {
949
        std::cout << "<EMPTY>"
950
                  << "\n";
951
      } else {
952
        auto s = *x.rbegin();
953
        std::cout << "round=" << s->cur_round_seqno() << "\n";
954
      }
955
    }
956

957
    for (td::uint32 i = 0; i < total_nodes; i++) {
958
      for (td::uint32 j = 0; j < total_nodes; j++) {
959
        td::uint32 x = td::Random::fast(0, static_cast<td::uint32>(states[i].size() - 1));
960
        td::uint32 y = td::Random::fast(0, static_cast<td::uint32>(states[j].size() - 1));
961
        auto s1 = states[i][x];
962
        auto s2 = states[j][y];
963
        auto m1 = ton::validatorsession::ValidatorSessionState::merge(desc, s1, s2);
964
        auto m2 = ton::validatorsession::ValidatorSessionState::merge(desc, s2, s1);
965
        CHECK(m1->get_hash(desc) == m2->get_hash(desc));
966
        desc.clear_temp_memory();
967
      }
968
    }
969

970
    auto x_state = ton::validatorsession::ValidatorSessionState::create(desc);
971
    x_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, x_state);
972
    for (td::uint32 i = 0; i < adj_total_nodes; i++) {
973
      x_state = ton::validatorsession::ValidatorSessionState::merge(desc, x_state, *states[i].rbegin());
974
      x_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, x_state);
975
    }
976
    CHECK(x_state->get_hash(desc) == virt_state->get_hash(desc));
977
    delete descptr;
978
  }
979

980
  std::_Exit(0);
981
  return 0;
982
}
983

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

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

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

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