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
28
#include "block/block.h"
32
#include "block-auto.h"
33
#include "block-parse.h"
40
using namespace std::literals::string_literals;
46
IntError(std::string _msg) : err_msg(_msg) {
48
IntError(const char* _msg) : err_msg(_msg) {
52
void throw_err(td::Status err) {
54
throw IntError{err.to_string()};
58
td::Ref<vm::Cell> load_boc(std::string filename) {
59
std::cerr << "loading bag-of-cell file " << filename << std::endl;
60
auto bytes_res = block::load_binary_file(filename);
61
if (bytes_res.is_error()) {
62
throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()};
65
auto res = boc.deserialize(bytes_res.move_as_ok());
67
throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()};
69
if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) {
70
throw IntError{"cannot deserialize bag-of-cells "};
72
return boc.get_root_cell();
75
std::vector<Ref<vm::Cell>> loaded_boc;
78
block::ShardId id{ton::masterchainId}, id2{ton::basechainId, 0x11efULL << 48};
79
std::cout << '[' << id << "][" << id2 << ']' << std::endl;
82
std::cout << "ShardIdent.pack() = " << block::tlb::t_ShardIdent.pack(cb, {12, 3, 0x3aeULL << 52}) << std::endl;
83
std::cout << cb << std::endl;
84
auto cref = cb.finalize();
85
td::Ref<vm::CellSlice> cs{true, cref}, cs2;
86
block::ShardId id3{cs.write()}, id4, id5;
88
std::cout << '[' << id3 << "][" << id4 << "][" << id5 << ']' << std::endl;
89
vm::CellSlice csl{std::move(cref)};
90
std::cout << "ShardIdent.get_size() = " << block::tlb::t_ShardIdent.get_size(csl) << std::endl;
91
std::cout << "MsgAddress.get_size() = " << block::tlb::t_MsgAddress.get_size(csl) << std::endl;
92
std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl) << std::endl;
93
std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl) << std::endl;
94
(csl + 8).print_rec(std::cout);
95
std::cout << "Grams.get_size() = " << block::tlb::t_Grams.get_size(csl + 8) << std::endl;
96
std::cout << "Grams.as_integer() = " << block::tlb::t_Grams.as_integer(csl + 8) << std::endl;
98
vm::CellSlice csl2{csl};
99
block::gen::ShardIdent::Record sh_id;
100
for (int i = 0; i < 3; i++) {
101
std::cout << csl2 << std::endl;
102
bool ok = tlb::unpack(csl2, sh_id);
103
std::cout << "block::gen::ShardIdent.unpack() = " << ok << std::endl;
105
std::cout << " (shard_ident shard_pfx_bits:" << sh_id.shard_pfx_bits << " workchain_id:" << sh_id.workchain_id
106
<< " shard_prefix:" << std::hex << sh_id.shard_prefix << std::dec << ")" << std::endl;
110
block::tlb::ShardIdent::Record shard_id;
111
for (int i = 0; i < 3; i++) {
112
std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate_upto(1024, csl) << std::endl;
113
csl.print_rec(std::cerr);
114
csl.dump(std::cerr, 7);
115
std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl;
116
if (shard_id.is_valid()) {
117
std::cout << "shard_pfx_bits:" << shard_id.shard_pfx_bits << " workchain_id:" << shard_id.workchain_id
118
<< " shard_prefix:" << shard_id.shard_prefix << std::endl;
121
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
122
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
123
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
124
using namespace td::literals;
125
std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl;
126
std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl;
127
std::cout << "Grams.store_intval(-17) = " << block::tlb::t_Grams.store_integer_value(cb, "-17"_i256) << std::endl;
128
std::cout << "Grams.store_intval(0) = " << block::tlb::t_Grams.store_integer_value(cb, "0"_i256) << std::endl;
129
std::cout << cb << std::endl;
130
cs = td::Ref<vm::CellSlice>{true, cb.finalize()};
131
std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl;
132
std::cout << cb << std::endl;
133
cs2 = td::Ref<vm::CellSlice>{true, cb.finalize()};
134
std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate_upto(1024, *cs) << std::endl;
135
std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate_upto(1024, *cs2) << std::endl;
137
block::gen::SplitMergeInfo::Record data;
138
block::gen::Grams::Record data2;
139
std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate_upto(1024, *cs) << std::endl;
140
std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate_upto(1024, *cs2) << std::endl;
141
std::cout << "[cs = " << cs << "]" << std::endl;
142
bool ok = tlb::csr_unpack_inexact(cs, data);
143
std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl;
145
std::cout << " cur_shard_pfx_len = " << data.cur_shard_pfx_len << "; acc_split_depth = " << data.acc_split_depth
146
<< "; this_addr = " << data.this_addr << "; sibling_addr = " << data.sibling_addr << std::endl;
148
ok = tlb::csr_unpack_inexact(cs, data2);
149
std::cout << "block::gen::Grams.unpack(cs, data2) = " << ok << std::endl;
151
std::cout << " amount = " << data2.amount << std::endl;
152
block::gen::VarUInteger::Record data3;
153
ok = tlb::csr_type_unpack(data2.amount, block::gen::t_VarUInteger_16, data3);
154
std::cout << " block::gen::VarUInteger16.unpack(amount, data3) = " << ok << std::endl;
156
std::cout << " len = " << data3.len << "; value = " << data3.value << std::endl;
158
std::cout << " block::gen::VarUInteger16.pack(cb, data3) = "
159
<< tlb::type_pack(cb, block::gen::t_VarUInteger_16, data3) << std::endl;
160
std::cout << " cb = " << cb.finalize() << std::endl;
166
td::BitArray<256> hash;
167
std::memset(hash.data(), 0x69, 32);
169
cb, block::gen::Test::Record{1000000000000, {170239, -888, {239017, "1000000000000000000"_ri256}, hash}, 17});
170
std::cout << " block::gen::Test::pack(cb, {1000000000000, ...}) = " << ok << std::endl;
171
std::cout << " cb = " << cb << std::endl;
172
auto cell = cb.finalize();
173
vm::CellSlice cs{cell};
174
cs.print_rec(std::cout);
175
block::gen::Test::Record data;
176
std::cout << " block::gen::Test::validate_ref(cell) = " << block::gen::t_Test.validate_ref(cell) << std::endl;
177
ok = tlb::unpack(cs, data);
178
std::cout << " block::gen::Test::unpack(cs, data) = " << ok << std::endl;
180
std::cout << "a:" << data.a << " b:" << data.r1.b << " c:" << data.r1.c << " d:" << data.r1.r1.d
181
<< " e:" << data.r1.r1.e << " f:" << data.r1.f << " g:" << data.g << std::endl;
183
std::cout << " block::gen::Test::print_ref(cell) = ";
184
block::gen::t_Test.print_ref(std::cout, cell, 2);
185
block::gen::t_CurrencyCollection.print_ref(std::cout, cell, 2);
186
std::cout << std::endl;
189
std::cout << "Grams.add_values() = " << block::tlb::t_Grams.add_values(cb, cs.write(), cs2.write()) << std::endl;
190
std::cout << cb << std::endl;
191
std::cout << "block::gen::t_HashmapAug_64_...print_type() = "
192
<< block::gen::t_HashmapAug_64_Ref_Transaction_CurrencyCollection << std::endl;
195
void test2(vm::CellSlice& cs) {
196
std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate_upto(1024, cs) << std::endl;
197
std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate_upto(1024, cs) << std::endl;
198
std::cout << "HashmapE(32,UInt16).validate() = "
199
<< block::tlb::HashmapE(32, block::tlb::t_uint16).validate_upto(1024, cs) << std::endl;
200
std::cout << "block::gen::HashmapE(32,UInt16).validate() = "
201
<< block::gen::HashmapE{32, block::gen::t_uint16}.validate_upto(1024, cs) << std::endl;
204
td::Status test_vset() {
205
if (loaded_boc.size() != 2) {
206
return td::Status::Error(
207
"must have exactly two boc files (with a masterchain Block and with ConfigParams) for vset compute test");
209
std::cerr << "running test_vset()\n";
210
TRY_RESULT(config, block::Config::unpack_config(vm::load_cell_slice_ref(loaded_boc[1])));
211
std::cerr << "config unpacked\n";
212
auto cv_root = config->get_config_param(34);
213
if (cv_root.is_null()) {
214
return td::Status::Error("no config parameter 34");
216
std::cerr << "config param #34 obtained\n";
217
TRY_RESULT(cur_validators, block::Config::unpack_validator_set(std::move(cv_root)));
218
// auto vconf = config->get_catchain_validators_config();
219
std::cerr << "validator set unpacked\n";
220
std::cerr << "unpacking ShardHashes\n";
221
block::ShardConfig shards;
222
if (!shards.unpack(vm::load_cell_slice_ref(loaded_boc[0]))) {
223
return td::Status::Error("cannot unpack ShardConfig");
225
std::cerr << "ShardHashes initialized\n";
226
ton::ShardIdFull shard{0, 0x6e80000000000000};
227
ton::CatchainSeqno cc_seqno = std::max(48763, 48763) + 1 + 1;
228
ton::UnixTime now = 1586169666;
229
cc_seqno = shards.get_shard_cc_seqno(shard);
230
std::cerr << "shard=" << shard.to_str() << " cc_seqno=" << cc_seqno << " time=" << now << std::endl;
231
if (cc_seqno == ~0U) {
232
return td::Status::Error("cannot compute cc_seqno for shard "s + shard.to_str());
234
auto nodes = config->compute_validator_set(shard, *cur_validators, now, cc_seqno);
236
return td::Status::Error(PSTRING() << "compute_validator_set() for " << shard.to_str() << "," << now << ","
237
<< cc_seqno << " returned empty list");
239
for (auto& x : nodes) {
240
std::cout << "weight=" << x.weight << " key=" << x.key.as_bits256().to_hex() << " addr=" << x.addr.to_hex()
244
return td::Status::OK();
248
std::cout << "usage: dump-block [-t<typename>][-S][<boc-file>]\n\tor dump-block -h\n\tDumps specified blockchain "
250
"from <boc-file>, or runs some tests\n\t-S\tDump a blockchain state instead of a block\n"
251
"\t-V<version>\tShow fift build information\n";
255
int main(int argc, char* const argv[]) {
257
int new_verbosity_level = VERBOSITY_NAME(INFO);
258
const char* tname = nullptr;
259
const tlb::TLB* type = &block::gen::t_Block;
260
bool vset_compute_test = false;
261
bool store_loaded = false;
263
auto zerostate = std::make_unique<block::ZerostateInfo>();
264
while ((i = getopt(argc, argv, "CSt:hqv:V")) != -1) {
267
type = &block::gen::t_VmCont;
270
type = &block::gen::t_ShardStateUnsplit;
277
new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer<int>(td::Slice(optarg)));
280
type = &block::gen::t_ShardHashes;
281
vset_compute_test = true;
286
std::cout << "dump-block build information: [ Commit: " << GitMetadata::CommitSHA1() << ", Date: " << GitMetadata::CommitDate() << "]\n";
297
SET_VERBOSITY_LEVEL(new_verbosity_level);
300
while (optind < argc) {
301
auto boc = load_boc(argv[optind++]);
303
std::cerr << "(invalid boc in file" << argv[optind - 1] << ")" << std::endl;
307
loaded_boc.push_back(boc);
311
vm::CellSlice cs{vm::NoVm(), boc};
312
cs.print_rec(std::cout);
313
std::cout << std::endl;
316
tlb::TypenameLookup dict(block::gen::register_simple_types);
317
type = dict.lookup(tname);
319
std::cerr << "unknown TL-B type " << tname << std::endl;
324
type->print_ref(std::cout, boc);
325
std::cout << std::endl;
327
bool ok = type->validate_ref(1048576, boc);
328
std::cout << "(" << (ok ? "" : "in") << "valid " << *type << ")" << std::endl;
329
if (vset_compute_test) {
330
if (!ok || loaded > 2) {
331
std::cerr << "fatal: validity check failed\n";
334
type = &block::gen::t_ConfigParams;
338
if (vset_compute_test) {
339
throw_err(test_vset());
340
} else if (!loaded) {
343
} catch (IntError& err) {
344
std::cerr << "internal error: " << err.err_msg << std::endl;
346
} catch (vm::VmError& err) {
347
std::cerr << "vm error: " << err.get_msg() << std::endl;