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
29
#include "adnl/utils.hpp"
30
#include "adnl/adnl-test-loopback-implementation.h"
32
#include "overlay/overlays.h"
33
#include "td/utils/OptionParser.h"
34
#include "td/utils/Time.h"
35
#include "td/utils/filesystem.h"
36
#include "td/utils/format.h"
37
#include "td/utils/port/path.h"
38
#include "td/utils/Random.h"
39
#include "td/utils/port/signals.h"
40
#include "td/utils/port/FileFd.h"
41
#include "td/utils/overloaded.h"
42
#include "catchain/catchain.h"
43
#include "common/errorlog.h"
45
#if TD_DARWIN || TD_LINUX
54
ton::PublicKeyHash id;
55
ton::PublicKey id_full;
56
ton::adnl::AdnlNodeIdShort adnl_id;
57
ton::adnl::AdnlNodeIdFull adnl_id_full;
60
class CatChainInst : public td::actor::Actor {
62
class PayloadExtra : public ton::catchain::CatChainBlock::Extra {
64
PayloadExtra(td::uint64 sum) : sum(sum) {
68
void process_blocks(std::vector<ton::catchain::CatChainBlock *> blocks) {
69
td::uint64 sum = sum_;
70
for (auto &B : blocks) {
71
auto E = dynamic_cast<const PayloadExtra *>(B->extra());
73
sum = std::max(sum, E->sum);
75
td::uint64 value = td::Random::fast_uint64();
76
sum = std::max(sum, value);
83
td::actor::send_closure(catchain_, &ton::catchain::CatChain::processed_block,
84
td::BufferSlice{td::Slice{reinterpret_cast<char *>(x), 16}});
86
alarm_timestamp() = td::Timestamp::in(0.1);
88
prev_values_.push_back(sum_);
90
void finished_processing() {
92
void preprocess_block(ton::catchain::CatChainBlock *block) {
94
auto prev = block->prev();
96
auto E = dynamic_cast<const PayloadExtra *>(prev->extra());
98
sum = std::max(E->sum, sum);
100
for (auto &B : block->deps()) {
101
auto E = dynamic_cast<const PayloadExtra *>(B->extra());
103
sum = std::max(E->sum, sum);
106
auto &payload = block->payload();
107
if (!payload.empty()) {
108
CHECK(payload.size() == 16);
110
td::MutableSlice{reinterpret_cast<td::uint8 *>(x), 16}.copy_from(payload.as_slice());
111
sum = std::max(sum, x[0]);
112
LOG_CHECK(sum == x[1]) << sum << " " << x[0];
114
CHECK(!block->deps().size());
116
block->set_extra(std::make_unique<PayloadExtra>(sum));
119
void alarm() override {
120
td::actor::send_closure(catchain_, &ton::catchain::CatChain::need_new_block, td::Timestamp::in(0.1));
123
void start_up() override {
124
alarm_timestamp() = td::Timestamp::in(0.1);
125
ton::CatChainOptions opts;
126
opts.debug_disable_db = true;
127
//opts.block_hash_covers_data = true;
129
std::vector<ton::catchain::CatChainNode> nodes;
130
for (auto &n : nodes_) {
131
nodes.push_back(ton::catchain::CatChainNode{n.adnl_id, n.id_full});
134
ton::catchain::CatChain::create(make_callback(), opts, keyring_, adnl_, overlay_manager_, std::move(nodes),
135
nodes_[idx_].id, unique_hash_, std::string(""), "", false);
138
CatChainInst(td::actor::ActorId<ton::keyring::Keyring> keyring, td::actor::ActorId<ton::adnl::Adnl> adnl,
139
td::actor::ActorId<ton::overlay::Overlays> overlay_manager, std::vector<Node> nodes, td::uint32 idx,
140
ton::catchain::CatChainSessionId unique_hash)
143
, overlay_manager_(overlay_manager)
144
, nodes_(std::move(nodes))
146
, unique_hash_(unique_hash) {
149
std::unique_ptr<ton::catchain::CatChain::Callback> make_callback() {
150
class Callback : public ton::catchain::CatChain::Callback {
152
void process_blocks(std::vector<ton::catchain::CatChainBlock *> blocks) override {
153
td::actor::send_closure(id_, &CatChainInst::process_blocks, std::move(blocks));
155
void finished_processing() override {
156
td::actor::send_closure(id_, &CatChainInst::finished_processing);
158
void preprocess_block(ton::catchain::CatChainBlock *block) override {
159
td::actor::send_closure(id_, &CatChainInst::preprocess_block, std::move(block));
161
void process_broadcast(const ton::PublicKeyHash &src, td::BufferSlice data) override {
164
void process_message(const ton::PublicKeyHash &src, td::BufferSlice data) override {
167
void process_query(const ton::PublicKeyHash &src, td::BufferSlice data,
168
td::Promise<td::BufferSlice> promise) override {
171
void started() override {
173
Callback(td::actor::ActorId<CatChainInst> id) : id_(std::move(id)) {
177
td::actor::ActorId<CatChainInst> id_;
180
return std::make_unique<Callback>(actor_id(this));
188
auto height = height_ - 1; //td::Random::fast(0, height_ - 1);
189
LOG(WARNING) << "Creating fork, source_id=" << idx_ << ", height=" << height;
191
auto sum = prev_values_[height] + 1;
196
td::actor::send_closure(catchain_, &ton::catchain::CatChain::debug_add_fork,
197
td::BufferSlice{td::Slice{reinterpret_cast<char *>(x), 16}}, height + 1);
201
td::actor::ActorId<ton::keyring::Keyring> keyring_;
202
td::actor::ActorId<ton::adnl::Adnl> adnl_;
203
td::actor::ActorId<ton::overlay::Overlays> overlay_manager_;
205
std::vector<Node> nodes_;
208
ton::catchain::CatChainSessionId unique_hash_;
210
td::actor::ActorOwn<ton::catchain::CatChain> catchain_;
212
td::uint32 height_ = 0;
213
std::vector<td::uint64> prev_values_;
216
static std::vector<Node> nodes;
217
static td::uint32 total_nodes = 11;
219
int main(int argc, char *argv[]) {
220
SET_VERBOSITY_LEVEL(verbosity_INFO);
221
td::set_default_failure_signal_handler().ensure();
223
std::string db_root_ = "tmp-dir-test-catchain";
224
td::rmrf(db_root_).ignore();
225
td::mkdir(db_root_).ensure();
227
td::set_default_failure_signal_handler().ensure();
229
td::actor::ActorOwn<ton::keyring::Keyring> keyring;
230
td::actor::ActorOwn<ton::adnl::TestLoopbackNetworkManager> network_manager;
231
td::actor::ActorOwn<ton::adnl::Adnl> adnl;
232
td::actor::ActorOwn<ton::overlay::Overlays> overlay_manager;
234
td::actor::Scheduler scheduler({7});
235
scheduler.run_in_context([&] {
236
ton::errorlog::ErrorLog::create(db_root_);
237
keyring = ton::keyring::Keyring::create(db_root_);
238
network_manager = td::actor::create_actor<ton::adnl::TestLoopbackNetworkManager>("test net");
239
adnl = ton::adnl::Adnl::create(db_root_, keyring.get());
241
ton::overlay::Overlays::create(db_root_, keyring.get(), adnl.get(), td::actor::ActorId<ton::dht::Dht>{});
242
td::actor::send_closure(adnl, &ton::adnl::Adnl::register_network_manager, network_manager.get());
245
for (td::uint32 att = 0; att < 20; att++) {
246
LOG(WARNING) << "Test #" << att;
247
nodes.resize(total_nodes);
249
scheduler.run_in_context([&] {
250
auto addr = ton::adnl::TestLoopbackNetworkManager::generate_dummy_addr_list();
252
for (auto &n : nodes) {
253
auto pk1 = ton::PrivateKey{ton::privkeys::Ed25519::random()};
254
auto pub1 = pk1.compute_public_key();
255
n.adnl_id_full = ton::adnl::AdnlNodeIdFull{pub1};
256
n.adnl_id = ton::adnl::AdnlNodeIdShort{pub1.compute_short_id()};
257
td::actor::send_closure(keyring, &ton::keyring::Keyring::add_key, std::move(pk1), true, [](td::Unit) {});
258
td::actor::send_closure(adnl, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub1}, addr,
259
static_cast<td::uint8>(0));
260
td::actor::send_closure(network_manager, &ton::adnl::TestLoopbackNetworkManager::add_node_id, n.adnl_id, true,
263
auto pk2 = ton::PrivateKey{ton::privkeys::Ed25519::random()};
264
auto pub2 = pk2.compute_public_key();
266
n.id = pub2.compute_short_id();
267
td::actor::send_closure(keyring, &ton::keyring::Keyring::add_key, std::move(pk2), true, [](td::Unit) {});
269
LOG(DEBUG) << "created node " << n.adnl_id << " " << n.id;
272
for (auto &n1 : nodes) {
273
for (auto &n2 : nodes) {
274
td::actor::send_closure(adnl, &ton::adnl::Adnl::add_peer, n1.adnl_id, n2.adnl_id_full, addr);
279
ton::catchain::CatChainSessionId unique_id;
280
td::Random::secure_bytes(unique_id.as_slice());
282
std::vector<td::actor::ActorOwn<CatChainInst>> inst;
283
scheduler.run_in_context([&] {
284
for (td::uint32 idx = 0; idx < total_nodes; idx++) {
285
inst.push_back(td::actor::create_actor<CatChainInst>("inst", keyring.get(), adnl.get(), overlay_manager.get(),
286
nodes, idx, unique_id));
290
auto t = td::Timestamp::in(10.0);
291
while (scheduler.run(1)) {
292
if (t.is_in_past()) {
297
for (auto &n : inst) {
298
std::cout << "value=" << n.get_actor_unsafe().value() << std::endl;
301
td::uint32 fork_cnt = att < 10 ? 1 : (att - 10) / 5 + 2;
302
for (td::uint32 idx = 0; idx < fork_cnt; ++idx) {
303
scheduler.run_in_context([&] { td::actor::send_closure(inst[idx], &CatChainInst::create_fork); });
306
t = td::Timestamp::in(1.0);
307
while (scheduler.run(1)) {
308
if (t.is_in_past()) {
313
for (auto &n : inst) {
314
std::cout << "value=" << n.get_actor_unsafe().value() << std::endl;
317
scheduler.run_in_context([&] {
323
td::rmrf(db_root_).ensure();