Ton

Форк
0
/
test-catchain.cpp 
326 строк · 11.1 Кб
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
#include "adnl/utils.hpp"
30
#include "adnl/adnl-test-loopback-implementation.h"
31
#include "dht/dht.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"
44

45
#if TD_DARWIN || TD_LINUX
46
#include <unistd.h>
47
#endif
48
#include <iostream>
49
#include <sstream>
50

51
#include <set>
52

53
struct Node {
54
  ton::PublicKeyHash id;
55
  ton::PublicKey id_full;
56
  ton::adnl::AdnlNodeIdShort adnl_id;
57
  ton::adnl::AdnlNodeIdFull adnl_id_full;
58
};
59

60
class CatChainInst : public td::actor::Actor {
61
 public:
62
  class PayloadExtra : public ton::catchain::CatChainBlock::Extra {
63
   public:
64
    PayloadExtra(td::uint64 sum) : sum(sum) {
65
    }
66
    td::uint64 sum;
67
  };
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());
72
      CHECK(E);
73
      sum = std::max(sum, E->sum);
74
    }
75
    td::uint64 value = td::Random::fast_uint64();
76
    sum = std::max(sum, value);
77
    td::uint64 x[2];
78
    x[0] = value;
79
    x[1] = sum;
80

81
    sum_ = sum;
82

83
    td::actor::send_closure(catchain_, &ton::catchain::CatChain::processed_block,
84
                            td::BufferSlice{td::Slice{reinterpret_cast<char *>(x), 16}});
85

86
    alarm_timestamp() = td::Timestamp::in(0.1);
87
    height_++;
88
    prev_values_.push_back(sum_);
89
  }
90
  void finished_processing() {
91
  }
92
  void preprocess_block(ton::catchain::CatChainBlock *block) {
93
    td::uint64 sum = 0;
94
    auto prev = block->prev();
95
    if (prev) {
96
      auto E = dynamic_cast<const PayloadExtra *>(prev->extra());
97
      CHECK(E);
98
      sum = std::max(E->sum, sum);
99
    }
100
    for (auto &B : block->deps()) {
101
      auto E = dynamic_cast<const PayloadExtra *>(B->extra());
102
      CHECK(E);
103
      sum = std::max(E->sum, sum);
104
    }
105

106
    auto &payload = block->payload();
107
    if (!payload.empty()) {
108
      CHECK(payload.size() == 16);
109
      td::uint64 x[2];
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];
113
    } else {
114
      CHECK(!block->deps().size());
115
    }
116
    block->set_extra(std::make_unique<PayloadExtra>(sum));
117
  }
118

119
  void alarm() override {
120
    td::actor::send_closure(catchain_, &ton::catchain::CatChain::need_new_block, td::Timestamp::in(0.1));
121
  }
122

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;
128

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});
132
    }
133
    catchain_ =
134
        ton::catchain::CatChain::create(make_callback(), opts, keyring_, adnl_, overlay_manager_, std::move(nodes),
135
                                        nodes_[idx_].id, unique_hash_, std::string(""), "", false);
136
  }
137

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)
141
      : keyring_(keyring)
142
      , adnl_(adnl)
143
      , overlay_manager_(overlay_manager)
144
      , nodes_(std::move(nodes))
145
      , idx_(idx)
146
      , unique_hash_(unique_hash) {
147
  }
148

149
  std::unique_ptr<ton::catchain::CatChain::Callback> make_callback() {
150
    class Callback : public ton::catchain::CatChain::Callback {
151
     public:
152
      void process_blocks(std::vector<ton::catchain::CatChainBlock *> blocks) override {
153
        td::actor::send_closure(id_, &CatChainInst::process_blocks, std::move(blocks));
154
      }
155
      void finished_processing() override {
156
        td::actor::send_closure(id_, &CatChainInst::finished_processing);
157
      }
158
      void preprocess_block(ton::catchain::CatChainBlock *block) override {
159
        td::actor::send_closure(id_, &CatChainInst::preprocess_block, std::move(block));
160
      }
161
      void process_broadcast(const ton::PublicKeyHash &src, td::BufferSlice data) override {
162
        UNREACHABLE();
163
      }
164
      void process_message(const ton::PublicKeyHash &src, td::BufferSlice data) override {
165
        UNREACHABLE();
166
      }
167
      void process_query(const ton::PublicKeyHash &src, td::BufferSlice data,
168
                         td::Promise<td::BufferSlice> promise) override {
169
        UNREACHABLE();
170
      }
171
      void started() override {
172
      }
173
      Callback(td::actor::ActorId<CatChainInst> id) : id_(std::move(id)) {
174
      }
175

176
     private:
177
      td::actor::ActorId<CatChainInst> id_;
178
    };
179

180
    return std::make_unique<Callback>(actor_id(this));
181
  }
182

183
  td::uint64 value() {
184
    return sum_;
185
  }
186

187
  void create_fork() {
188
    auto height = height_ - 1;  //td::Random::fast(0, height_ - 1);
189
    LOG(WARNING) << "Creating fork, source_id=" << idx_ << ", height=" << height;
190

191
    auto sum = prev_values_[height] + 1;
192
    td::uint64 x[2];
193
    x[0] = sum + 1;
194
    x[1] = sum + 1;
195

196
    td::actor::send_closure(catchain_, &ton::catchain::CatChain::debug_add_fork,
197
                            td::BufferSlice{td::Slice{reinterpret_cast<char *>(x), 16}}, height + 1);
198
  }
199

200
 private:
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_;
204

205
  std::vector<Node> nodes_;
206
  td::uint32 idx_;
207

208
  ton::catchain::CatChainSessionId unique_hash_;
209

210
  td::actor::ActorOwn<ton::catchain::CatChain> catchain_;
211
  td::uint64 sum_ = 0;
212
  td::uint32 height_ = 0;
213
  std::vector<td::uint64> prev_values_;
214
};
215

216
static std::vector<Node> nodes;
217
static td::uint32 total_nodes = 11;
218

219
int main(int argc, char *argv[]) {
220
  SET_VERBOSITY_LEVEL(verbosity_INFO);
221
  td::set_default_failure_signal_handler().ensure();
222

223
  std::string db_root_ = "tmp-dir-test-catchain";
224
  td::rmrf(db_root_).ignore();
225
  td::mkdir(db_root_).ensure();
226

227
  td::set_default_failure_signal_handler().ensure();
228

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;
233

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());
240
    overlay_manager =
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());
243
  });
244

245
  for (td::uint32 att = 0; att < 20; att++) {
246
    LOG(WARNING) << "Test #" << att;
247
    nodes.resize(total_nodes);
248

249
    scheduler.run_in_context([&] {
250
      auto addr = ton::adnl::TestLoopbackNetworkManager::generate_dummy_addr_list();
251

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,
261
                                true);
262

263
        auto pk2 = ton::PrivateKey{ton::privkeys::Ed25519::random()};
264
        auto pub2 = pk2.compute_public_key();
265
        n.id_full = pub2;
266
        n.id = pub2.compute_short_id();
267
        td::actor::send_closure(keyring, &ton::keyring::Keyring::add_key, std::move(pk2), true, [](td::Unit) {});
268

269
        LOG(DEBUG) << "created node " << n.adnl_id << " " << n.id;
270
      }
271

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);
275
        }
276
      }
277
    });
278

279
    ton::catchain::CatChainSessionId unique_id;
280
    td::Random::secure_bytes(unique_id.as_slice());
281

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));
287
      }
288
    });
289

290
    auto t = td::Timestamp::in(10.0);
291
    while (scheduler.run(1)) {
292
      if (t.is_in_past()) {
293
        break;
294
      }
295
    }
296

297
    for (auto &n : inst) {
298
      std::cout << "value=" << n.get_actor_unsafe().value() << std::endl;
299
    }
300

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); });
304
    }
305

306
    t = td::Timestamp::in(1.0);
307
    while (scheduler.run(1)) {
308
      if (t.is_in_past()) {
309
        break;
310
      }
311
    }
312

313
    for (auto &n : inst) {
314
      std::cout << "value=" << n.get_actor_unsafe().value() << std::endl;
315
    }
316

317
    scheduler.run_in_context([&] {
318
      nodes.clear();
319
      inst.clear();
320
    });
321
  }
322

323
  td::rmrf(db_root_).ensure();
324
  std::_Exit(0);
325
  return 0;
326
}
327

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

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

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

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