2
This file is part of TON Blockchain source code.
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.
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.
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/>.
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.
26
Copyright 2017-2020 Telegram Systems LLP
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"
35
#include "validator-session/validator-session-description.h"
36
#include "validator-session/validator-session-state.h"
37
#include "validator-session/validator-session-description.hpp"
43
class Description : public ton::validatorsession::ValidatorSessionDescription {
45
HashType compute_hash(td::Slice data) const override {
46
return td::crc32c(data);
48
HashType zero_hash() const {
51
void *alloc(size_t size, size_t align, bool temp) override {
52
return (temp ? mem_temp_ : mem_perm_).alloc(size, align);
54
bool is_persistent(const void *ptr) const override {
55
return mem_perm_.contains(ptr);
57
void clear_temp_memory() override {
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};
68
ton::PublicKey get_source_public_key(td::uint32 idx) const override {
71
ton::adnl::AdnlNodeIdShort get_source_adnl_id(td::uint32 idx) const override {
74
td::uint32 get_source_idx(ton::PublicKeyHash id) const override {
75
auto x = id.bits256_value();
76
auto y = x.as_array();
79
ton::ValidatorWeight get_node_weight(td::uint32 idx) const override {
82
td::uint32 get_total_nodes() const override {
85
ton::ValidatorWeight get_cutoff_weight() const override {
86
return 2 * total_nodes_ / 3 + 1;
88
ton::ValidatorWeight get_total_weight() const override {
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();
96
if (src_idx - round < opts_.round_candidates) {
97
return src_idx - round;
101
td::uint32 get_max_priority() const override {
102
return opts_.round_candidates - 1;
104
td::uint32 get_unixtime(td::uint64 ts) const override {
105
return static_cast<td::uint32>(ts >> 32);
107
td::uint32 get_attempt_seqno(td::uint64 ts) const override {
108
return get_unixtime(ts) / opts_.round_attempt_duration;
110
td::uint32 get_self_idx() const override {
113
td::uint64 get_ts() const override {
114
auto tm = td::Clocks::system();
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;
121
const RootObject *get_by_hash(HashType hash, bool allow_temp) const override {
122
auto x = hash % cache_size;
124
return cache_[x].load(std::memory_order_relaxed).ptr;
126
void update_hash(const RootObject *obj, HashType hash) override {
127
if (!is_persistent(obj)) {
130
auto x = hash % cache_size;
132
cache_[x].store(p, std::memory_order_relaxed);
134
void on_reuse() override {
136
td::Timestamp attempt_start_at(td::uint32 att) const override {
137
return td::Timestamp::at_unix(att * opts_.round_attempt_duration);
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);
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");
153
if (signature[0] == 126) {
154
return td::Status::OK();
156
return td::Status::Error("invalid");
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");
165
if (signature[0] == 127) {
166
return td::Status::OK();
168
return td::Status::Error("invalid");
171
double get_delay(td::uint32 priority) const override {
174
double get_empty_block_delay() const override {
177
std::vector<ton::catchain::CatChainNode> export_catchain_nodes() const override {
181
td::uint32 get_vote_for_author(td::uint32 attempt_seqno) const override {
182
return attempt_seqno % total_nodes_;
185
const ton::validatorsession::ValidatorSessionOptions &opts() const override {
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_) {
193
el.store(v, std::memory_order_relaxed);
196
CHECK(total_nodes_ > 0);
200
ton::validatorsession::ValidatorSessionOptions opts_;
202
td::uint32 total_nodes_;
204
static constexpr td::uint32 cache_size = (1 << 20);
207
const RootObject *ptr;
209
std::array<std::atomic<Cached>, cache_size> cache_;
211
ton::validatorsession::ValidatorSessionDescriptionImpl::MemPool mem_perm_, mem_temp_;
215
return td::Random::fast(0, 100) * 0.01;
219
SET_VERBOSITY_LEVEL(verbosity_INFO);
221
td::set_default_failure_signal_handler().ensure();
222
td::uint32 total_nodes = 100;
224
ton::validatorsession::ValidatorSessionOptions opts;
227
auto descptr = new Description(opts, total_nodes);
228
auto &desc = *descptr;
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());
234
auto s = ton::validatorsession::ValidatorSessionState::create(desc);
236
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
238
auto att = 1000000000;
240
for (td::uint32 i = 0; i < total_nodes; i++) {
241
auto act = s->create_action(desc, i, att);
243
CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID);
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());
251
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
255
for (td::uint32 i = 0; i < total_nodes; i++) {
256
auto act = s->create_action(desc, i, att);
258
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << act.get();
261
for (td::uint32 i = 0; i < total_nodes; i++) {
263
s->choose_block_to_sign(desc, i, found);
265
auto vec = s->choose_blocks_to_approve(desc, i);
266
LOG_CHECK(vec.size() == 2) << vec.size();
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());
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());
278
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
282
for (td::uint32 i = 0; i < total_nodes; i++) {
283
auto act = s->create_action(desc, i, att);
285
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << act.get();
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());
294
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
298
for (td::uint32 i = 0; i < total_nodes; i++) {
300
s->choose_block_to_sign(desc, i, 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());
308
for (td::uint32 i = 0; i < total_nodes; i++) {
309
auto act = s->create_action(desc, i, att);
311
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << act.get();
313
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
315
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
322
LOG_CHECK(act2->get_id() == ton::ton_api::validatorSession_message_precommit::ID)
323
<< "i=" << i << " " << act2.get();
326
for (td::uint32 j = 1; j < opts.max_round_attempts; j++) {
327
auto act = s->create_action(desc, 0, att + j);
329
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "j=" << j << " " << act.get();
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);
334
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "j=" << j << " " << act.get();
338
for (td::uint32 i = 0; i < total_nodes; i++) {
339
auto act = s->create_action(desc, i, att);
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();
346
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
349
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
351
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
359
for (td::uint32 i = 0; i < total_nodes; i++) {
360
auto act = s->create_action(desc, i, att);
362
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
365
for (td::uint32 i = 0; i < total_nodes; i++) {
367
auto block = s->choose_block_to_sign(desc, i, found);
369
CHECK(ton::validatorsession::SentBlock::get_block_id(block) == c2);
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());
378
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
382
CHECK(s->cur_round_seqno() == 0);
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());
390
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
394
CHECK(s->cur_round_seqno() == 1);
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);
405
for (td::uint32 i = 0; i < total_nodes / 3; i++) {
406
auto act = s->create_action(desc, i, att);
409
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID) << "i=" << i << " " << act.get();
411
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
413
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
420
att += opts.max_round_attempts - 1;
424
for (td::uint32 i = 0; i < total_nodes; i++) {
425
auto act = s->create_action(desc, i, att);
428
if (i < total_nodes / 3) {
429
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
431
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
434
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
436
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
442
desc.clear_temp_memory();
443
} while (desc.get_vote_for_author(att) < total_nodes / 3);
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());
450
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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);
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());
466
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
471
auto act = s->generate_vote_for(desc, idx, att);
473
act->candidate_ = c1;
474
s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
476
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
480
td::BufferSlice buf{10240};
481
td::StringBuilder sb{buf.as_slice()};
483
s->dump(desc, sb, att);
485
LOG(ERROR) << sb.as_cslice();
487
for (td::uint32 i = 0; i < total_nodes; i++) {
488
auto act = s->create_action(desc, i, att);
491
if (i < total_nodes / 3) {
492
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
494
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
497
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
499
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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);
509
for (td::uint32 i = 0; i < total_nodes; i++) {
510
auto act = s->create_action(desc, i, att);
513
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
515
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
517
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
522
auto act = s->generate_vote_for(desc, idx, att);
524
act->candidate_ = c1;
525
s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
527
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
531
for (td::uint32 i = 0; i < total_nodes; i++) {
532
auto act = s->create_action(desc, i, att);
535
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
537
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
539
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
543
for (td::uint32 i = 0; i < total_nodes / 3; i++) {
544
auto act = s->create_action(desc, i, att);
547
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_precommit::ID) << "i=" << i << " " << act.get();
549
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
551
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
559
idx = desc.get_vote_for_author(att);
561
auto act = s->generate_vote_for(desc, idx, att);
563
act->candidate_ = c1;
564
s = ton::validatorsession::ValidatorSessionState::action(desc, s, idx, att, act.get());
566
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
570
for (td::uint32 i = 0; i < total_nodes; i++) {
571
auto act = s->create_action(desc, i, att);
574
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_vote::ID) << "i=" << i << " " << act.get();
576
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
578
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
582
for (td::uint32 i = 0; i < total_nodes; i++) {
583
auto act = s->create_action(desc, i, att);
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();
590
LOG_CHECK(act->get_id() == ton::ton_api::validatorSession_message_empty::ID) << "i=" << i << " " << act.get();
593
s = ton::validatorsession::ValidatorSessionState::action(desc, s, i, att, act.get());
595
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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();
605
auto descptr = new Description(opts, total_nodes);
606
auto &desc = *descptr;
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"});
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");
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);
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);
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);
636
CHECK(m1->at(0)->as_slice() == "a");
637
CHECK(m1->at(1)->as_slice() == "b");
638
CHECK(m1->at(2)->as_slice() == "d");
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);
644
CHECK(m2->at(0)->as_slice() == "a");
645
CHECK(m2->at(1)->as_slice() == "b");
646
CHECK(m2->at(2)->as_slice() == "d");
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());
655
auto cand1 = ton::validatorsession::SessionBlockCandidate::create(desc, sentb, sig_vec1);
656
auto cand2 = ton::validatorsession::SessionBlockCandidate::create(desc, sentb, sig_vec2);
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));
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;
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;
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));
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));
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));
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);
714
vote2 = ton::validatorsession::SessionVoteCandidate::push(desc, vote2, i);
716
if (i < desc.get_cutoff_weight() - 1) {
717
vote1d = ton::validatorsession::SessionVoteCandidate::push(desc, vote1d, i);
719
vote2d = ton::validatorsession::SessionVoteCandidate::push(desc, vote2d, i);
723
auto v = ton::validatorsession::VoteVector::create(desc, {vote1, vote2});
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);
730
ton::validatorsession::ValidatorSessionRoundAttemptState::create(desc, 1, v, prec1_vec, nullptr, false);
732
CHECK(att0_0->get_voted_block(desc, f) == nullptr);
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);
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);
746
ton::validatorsession::ValidatorSessionRoundAttemptState::create(desc, 3, v, prec2_vec, nullptr, false);
747
CHECK(att2_0->get_voted_block(desc, f) == nullptr);
751
auto m = ton::validatorsession::ValidatorSessionRoundAttemptState::merge(desc, att1_0, att1_1);
752
CHECK(m->get_voted_block(desc, f) == sentb);
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);
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;
770
std::vector<td::uint32> last_precommit1;
771
last_precommit1.resize(desc.get_total_nodes());
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}));
785
auto m = ton::validatorsession::ValidatorSessionRoundState::merge(desc, r1, r2);
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]
793
for (td::uint32 i = 0; i < desc.get_total_nodes(); i++) {
795
CHECK(m->get_last_precommit(i) == 3);
797
CHECK(m->get_last_precommit(i) == 0);
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;
811
auto descptr = new Description(opts, total_nodes);
812
auto &desc = *descptr;
814
auto adj_total_nodes = total_nodes + (ver ? total_nodes / 3 : 0);
816
std::vector<std::vector<const ton::validatorsession::ValidatorSessionState *>> states;
817
states.resize(adj_total_nodes);
819
td::uint64 ts = desc.get_ts();
821
auto virt_state = ton::validatorsession::ValidatorSessionState::create(desc);
822
virt_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, virt_state);
824
for (td::uint32 ri = 0; ri < 100000; ri++) {
826
auto att = desc.get_attempt_seqno(ts_adj);
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;
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);
837
if (x + total_nodes < adj_total_nodes && td::Random::fast(0, 1) == 0) {
838
adj_x += total_nodes;
841
const ton::validatorsession::ValidatorSessionState *s;
842
if (states[adj_x].size() == 0) {
843
s = ton::validatorsession::ValidatorSessionState::create(desc);
845
s = *states[adj_x].rbegin();
848
for (td::uint32 z = 0; z < 3; z++) {
849
auto y = td::Random::fast(0, adj_total_nodes - 2);
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));
859
s = ton::validatorsession::ValidatorSessionState::merge(desc, s, states[y][k]);
861
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
865
auto round = s->cur_round_seqno();
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());
872
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
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};
882
sig.as_slice()[0] = 127;
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());
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};
896
sig.as_slice()[0] = 126;
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());
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());
910
auto act = s->create_action(desc, x, att);
912
if (act->get_id() == ton::ton_api::validatorSession_message_empty::ID) {
915
s = ton::validatorsession::ValidatorSessionState::action(desc, s, x, att, act.get());
923
s = ton::validatorsession::ValidatorSessionState::make_one(desc, s, x, att, made);
926
s = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, s);
929
states[adj_x].push_back(s);
931
if (myrand() <= 1.0 / blocks_per_sec_per_node / total_nodes) {
934
desc.clear_temp_memory();
936
virt_state = ton::validatorsession::ValidatorSessionState::merge(desc, virt_state, s);
937
virt_state = ton::validatorsession::ValidatorSessionState::move_to_persistent(desc, virt_state);
940
td::BufferSlice buf{10240};
941
td::StringBuilder sb{buf.as_slice()};
943
virt_state->dump(desc, sb, desc.get_attempt_seqno(ts));
945
LOG(ERROR) << sb.as_cslice();
947
for (auto &x : states) {
949
std::cout << "<EMPTY>"
952
auto s = *x.rbegin();
953
std::cout << "round=" << s->cur_round_seqno() << "\n";
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();
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);
976
CHECK(x_state->get_hash(desc) == virt_state->get_hash(desc));