19
#include "td/utils/bits.h"
20
#include "block/block-parse.h"
21
#include "block/block-auto.h"
22
#include "ton/ton-shard.h"
23
#include "common/util.h"
24
#include "td/utils/crypto.h"
27
using namespace std::literals::string_literals;
29
using CombineError = vm::CombineError;
32
bool debug(const char* str) TD_UNUSED;
33
bool debug(const char* str) {
38
bool debug(int x) TD_UNUSED;
41
std::cerr << '[' << (char)(64 + x) << ']';
43
std::cerr << '[' << (char)(64 + x / 100) << x % 100 << ']';
49
#define DBG_START int dbg = 0;
50
#define DBG debug(++dbg)&&
51
#define DEB_START DBG_START
58
int MsgAddressExt::get_size(const vm::CellSlice& cs) const {
59
switch (get_tag(cs)) {
64
int len = cs.prefetch_long(2 + 9) & 0x1ff;
71
const MsgAddressExt t_MsgAddressExt;
73
const Anycast t_Anycast;
75
bool Maybe_Anycast::skip_get_depth(vm::CellSlice& cs, int& depth) const {
78
return cs.fetch_bool_to(have) && (!have || t_Anycast.skip_get_depth(cs, depth));
81
const Maybe_Anycast t_Maybe_Anycast;
83
bool MsgAddressInt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
87
switch (get_tag(cs)) {
89
return cs.advance(2) && t_Maybe_Anycast.skip(cs) && cs.advance(8 + 256);
91
if (cs.advance(2) && t_Maybe_Anycast.skip(cs) && cs.have(9 + 32)) {
92
int addr_len = (int)cs.fetch_ulong(9);
93
int workchain_id = (int)cs.fetch_long(32);
94
return cs.advance(addr_len) && (workchain_id < -0x80 || workchain_id > 0x7f || addr_len != 256) &&
95
(workchain_id != 0 && workchain_id != -1);
101
bool MsgAddressInt::skip_get_depth(vm::CellSlice& cs, int& depth) const {
105
switch (get_tag(cs)) {
107
return cs.advance(2) && t_Maybe_Anycast.skip_get_depth(cs, depth) && cs.advance(8 + 256);
109
if (cs.advance(2) && t_Maybe_Anycast.skip_get_depth(cs, depth) && cs.have(9 + 32)) {
110
int addr_len = (int)cs.fetch_ulong(9);
111
return cs.advance(32 + addr_len);
117
ton::AccountIdPrefixFull MsgAddressInt::get_prefix(vm::CellSlice&& cs) {
118
if (!cs.have(3 + 8 + 64)) {
121
ton::WorkchainId workchain;
122
unsigned long long prefix;
123
int t = (int)cs.prefetch_ulong(2 + 1 + 5);
126
if (cs.advance(3) && cs.fetch_int_to(8, workchain) && cs.fetch_uint_to(64, prefix)) {
127
return {workchain, prefix};
133
unsigned long long rewrite;
134
if (cs.advance(8) && cs.fetch_uint_to(t, rewrite)
135
&& cs.fetch_int_to(8, workchain)
136
&& cs.fetch_uint_to(64, prefix)) {
138
return {workchain, (prefix & (std::numeric_limits<td::uint64>::max() >> t)) | rewrite};
144
if (cs.advance(3) && cs.fetch_uint_to(9, len)
146
&& cs.fetch_int_to(32, workchain)
147
&& cs.fetch_uint_to(64, prefix)) {
148
return {workchain, prefix};
155
unsigned long long rewrite;
156
if (cs.advance(8) && cs.fetch_uint_to(t, rewrite)
157
&& cs.fetch_uint_to(9, len)
159
&& cs.fetch_int_to(32, workchain)
160
&& cs.fetch_uint_to(64, prefix)) {
162
return {workchain, (prefix & (std::numeric_limits<td::uint64>::max() >> t)) | rewrite};
170
ton::AccountIdPrefixFull MsgAddressInt::get_prefix(const vm::CellSlice& cs) {
171
return get_prefix(vm::CellSlice{cs});
174
ton::AccountIdPrefixFull MsgAddressInt::get_prefix(Ref<vm::CellSlice> cs_ref) {
175
if (cs_ref->is_unique()) {
176
return get_prefix(std::move(cs_ref.unique_write()));
178
return get_prefix(vm::CellSlice{*cs_ref});
182
bool MsgAddressInt::extract_std_address(Ref<vm::CellSlice> cs_ref, ton::WorkchainId& workchain,
183
ton::StdSmcAddress& addr, bool rewrite) const {
184
if (cs_ref.is_null()) {
186
} else if (cs_ref->is_unique()) {
187
return extract_std_address(cs_ref.unique_write(), workchain, addr, rewrite);
189
vm::CellSlice cs{*cs_ref};
190
return extract_std_address(cs, workchain, addr, rewrite);
194
bool MsgAddressInt::extract_std_address(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::StdSmcAddress& addr,
195
bool do_rewrite) const {
196
if (!cs.have(3 + 8 + 64)) {
199
int t = (int)cs.prefetch_ulong(2 + 1 + 5);
202
return cs.advance(3) && cs.fetch_int_to(8, workchain) && cs.fetch_bits_to(addr);
206
unsigned long long rewrite;
207
if (cs.advance(8) && cs.fetch_uint_to(t, rewrite)
208
&& cs.fetch_int_to(8, workchain)
209
&& cs.fetch_bits_to(addr)) {
211
addr.bits().store_uint(rewrite, t);
219
return cs.advance(3) && cs.fetch_uint_to(9, len)
221
&& cs.fetch_int_to(32, workchain)
222
&& cs.fetch_bits_to(addr);
227
unsigned long long rewrite;
228
if (cs.advance(8) && cs.fetch_uint_to(t, rewrite)
229
&& cs.fetch_uint_to(9, len)
231
&& cs.fetch_int_to(32, workchain)
232
&& cs.fetch_bits_to(addr)) {
234
addr.bits().store_uint(rewrite, t);
244
bool MsgAddressInt::extract_std_address(Ref<vm::CellSlice> cs_ref, block::StdAddress& addr, bool rewrite) const {
245
return extract_std_address(std::move(cs_ref), addr.workchain, addr.addr, rewrite);
248
bool MsgAddressInt::extract_std_address(vm::CellSlice& cs, block::StdAddress& addr, bool rewrite) const {
249
return extract_std_address(cs, addr.workchain, addr.addr, rewrite);
252
bool MsgAddressInt::store_std_address(vm::CellBuilder& cb, ton::WorkchainId workchain,
253
const ton::StdSmcAddress& addr) const {
254
if (workchain >= -128 && workchain < 128) {
255
return cb.store_long_bool(4, 3)
256
&& cb.store_long_bool(workchain, 8)
257
&& cb.store_bits_bool(addr);
259
return cb.store_long_bool(0xd00, 12)
260
&& cb.store_long_bool(workchain, 32)
261
&& cb.store_bits_bool(addr);
265
Ref<vm::CellSlice> MsgAddressInt::pack_std_address(ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const {
267
if (store_std_address(cb, workchain, addr)) {
268
return vm::load_cell_slice_ref(cb.finalize());
274
bool MsgAddressInt::store_std_address(vm::CellBuilder& cb, const block::StdAddress& addr) const {
275
return store_std_address(cb, addr.workchain, addr.addr);
278
Ref<vm::CellSlice> MsgAddressInt::pack_std_address(const block::StdAddress& addr) const {
279
return pack_std_address(addr.workchain, addr.addr);
282
const MsgAddressInt t_MsgAddressInt;
284
bool MsgAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
285
switch (get_tag(cs)) {
288
return t_MsgAddressExt.validate_skip(ops, cs, weak);
291
return t_MsgAddressInt.validate_skip(ops, cs, weak);
296
const MsgAddress t_MsgAddress;
298
bool VarUInteger::skip(vm::CellSlice& cs) const {
299
int len = (int)cs.fetch_ulong(ln);
300
return len >= 0 && len < n && cs.advance(len * 8);
303
bool VarUInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
304
int len = (int)cs.fetch_ulong(ln);
305
return len >= 0 && len < n && (!len || cs.prefetch_ulong(8)) && cs.advance(len * 8);
308
td::RefInt256 VarUInteger::as_integer_skip(vm::CellSlice& cs) const {
309
int len = (int)cs.fetch_ulong(ln);
310
return (len >= 0 && len < n && (!len || cs.prefetch_ulong(8))) ? cs.fetch_int256(len * 8, false) : td::RefInt256{};
313
unsigned long long VarUInteger::as_uint(const vm::CellSlice& cs) const {
314
int len = (int)cs.prefetch_ulong(ln);
315
return len >= 0 && len <= 8 && cs.have(ln + len * 8) ? td::bitstring::bits_load_ulong(cs.data_bits() + ln, len * 8)
316
: std::numeric_limits<td::uint64>::max();
319
bool VarUInteger::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
320
int k = value.bit_size(false);
321
return k <= (n - 1) * 8 && cb.store_long_bool((k + 7) >> 3, ln) && cb.store_int256_bool(value, (k + 7) & -8, false);
324
unsigned VarUInteger::precompute_integer_size(const td::BigInt256& value) const {
325
int k = value.bit_size(false);
326
return k <= (n - 1) * 8 ? ln + ((k + 7) & -8) : 0xfff;
329
unsigned VarUInteger::precompute_integer_size(td::RefInt256 value) const {
330
if (value.is_null()) {
333
int k = value->bit_size(false);
334
return k <= (n - 1) * 8 ? ln + ((k + 7) & -8) : 0xfff;
337
const VarUInteger t_VarUInteger_3{3}, t_VarUInteger_7{7}, t_VarUInteger_16{16}, t_VarUInteger_32{32};
339
bool VarUIntegerPos::skip(vm::CellSlice& cs) const {
340
int len = (int)cs.fetch_ulong(ln);
341
return len > 0 && len < n && cs.advance(len * 8);
344
bool VarUIntegerPos::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
345
int len = (int)cs.fetch_ulong(ln);
346
return len > 0 && len < n && cs.prefetch_ulong(8) && cs.advance(len * 8);
349
td::RefInt256 VarUIntegerPos::as_integer_skip(vm::CellSlice& cs) const {
350
int len = (int)cs.fetch_ulong(ln);
351
return (len > 0 && len < n && cs.prefetch_ulong(8)) ? cs.fetch_int256(len * 8, false) : td::RefInt256{};
354
unsigned long long VarUIntegerPos::as_uint(const vm::CellSlice& cs) const {
355
int len = (int)cs.prefetch_ulong(ln);
356
return len > 0 && len <= 8 && cs.have(ln + len * 8) && cs.prefetch_ulong(8)
357
? td::bitstring::bits_load_ulong(cs.data_bits() + ln, len * 8)
358
: std::numeric_limits<td::uint64>::max();
361
bool VarUIntegerPos::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
362
int k = value.bit_size(false);
363
return k <= (n - 1) * 8 && value.sgn() >= (int)store_pos_only && cb.store_long_bool((k + 7) >> 3, ln) &&
364
cb.store_int256_bool(value, (k + 7) & -8, false);
367
const VarUIntegerPos t_VarUIntegerPos_16{16}, t_VarUIntegerPos_32{32}, t_VarUIntegerPosRelaxed_32{32, true};
369
static inline bool redundant_int(const vm::CellSlice& cs) {
370
int t = (int)cs.prefetch_long(9);
371
return t == 0 || t == -1;
374
bool VarInteger::skip(vm::CellSlice& cs) const {
375
int len = (int)cs.fetch_ulong(ln);
376
return len >= 0 && len < n && cs.advance(len * 8);
379
bool VarInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
380
int len = (int)cs.fetch_ulong(ln);
381
return len >= 0 && len < n && (!len || !redundant_int(cs)) && cs.advance(len * 8);
384
td::RefInt256 VarInteger::as_integer_skip(vm::CellSlice& cs) const {
385
int len = (int)cs.fetch_ulong(ln);
386
return (len >= 0 && len < n && (!len || !redundant_int(cs))) ? cs.fetch_int256(len * 8, true) : td::RefInt256{};
389
long long VarInteger::as_int(const vm::CellSlice& cs) const {
390
int len = (int)cs.prefetch_ulong(ln);
391
return len >= 0 && len <= 8 && cs.have(ln + len * 8) ? td::bitstring::bits_load_long(cs.data_bits() + ln, len * 8)
395
bool VarInteger::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
396
int k = value.bit_size(true);
397
return k <= (n - 1) * 8 && cb.store_long_bool((k + 7) >> 3, ln) && cb.store_int256_bool(value, (k + 7) & -8, true);
400
bool VarIntegerNz::skip(vm::CellSlice& cs) const {
401
int len = (int)cs.fetch_ulong(ln);
402
return len > 0 && len < n && cs.advance(len * 8);
405
bool VarIntegerNz::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
406
int len = (int)cs.fetch_ulong(ln);
407
return len > 0 && len < n && !redundant_int(cs) && cs.advance(len * 8);
410
td::RefInt256 VarIntegerNz::as_integer_skip(vm::CellSlice& cs) const {
411
int len = (int)cs.fetch_ulong(ln);
412
return (len > 0 && len < n && !redundant_int(cs)) ? cs.fetch_int256(len * 8, true) : td::RefInt256{};
415
long long VarIntegerNz::as_int(const vm::CellSlice& cs) const {
416
int len = (int)cs.prefetch_ulong(ln);
417
return len > 0 && len <= 8 && cs.have(ln + len * 8) && !redundant_int(cs)
418
? td::bitstring::bits_load_long(cs.data_bits() + ln, len * 8)
422
bool VarIntegerNz::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
423
int k = value.bit_size(true);
424
return k <= (n - 1) * 8 && value.sgn() != 0 && cb.store_long_bool((k + 7) >> 3, ln) &&
425
cb.store_int256_bool(value, (k + 7) & -8, true);
428
bool Grams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
429
return t_VarUInteger_16.validate_skip(ops, cs, weak);
432
td::RefInt256 Grams::as_integer_skip(vm::CellSlice& cs) const {
433
return t_VarUInteger_16.as_integer_skip(cs);
436
bool Grams::null_value(vm::CellBuilder& cb) const {
437
return t_VarUInteger_16.null_value(cb);
440
bool Grams::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
441
return t_VarUInteger_16.store_integer_value(cb, value);
444
unsigned Grams::precompute_size(const td::BigInt256& value) const {
445
return t_VarUInteger_16.precompute_integer_size(value);
448
unsigned Grams::precompute_size(td::RefInt256 value) const {
449
return t_VarUInteger_16.precompute_integer_size(std::move(value));
456
bool HmLabel::validate_skip(vm::CellSlice& cs, bool weak, int& n) const {
457
switch (get_tag(cs)) {
459
return cs.advance(1) && (n = cs.count_leading(1)) <= m && cs.advance(2 * n + 1);
461
return cs.advance(2) && cs.fetch_uint_leq(m, n) && cs.advance(n);
463
return cs.advance(3) && cs.fetch_uint_leq(m, n);
468
int HmLabel::get_tag(const vm::CellSlice& cs) const {
469
int tag = (int)cs.prefetch_ulong(2);
470
return tag != 1 ? tag : hml_short;
473
int HashmapNode::get_size(const vm::CellSlice& cs) const {
475
return n ? 0x20000 : value_type.get_size(cs);
478
bool HashmapNode::skip(vm::CellSlice& cs) const {
480
return n ? cs.advance_refs(2) : value_type.skip(cs);
483
bool HashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
487
return value_type.validate_skip(ops, cs, weak);
490
Hashmap branch_type{n - 1, value_type};
491
return branch_type.validate_ref(ops, cs.fetch_ref(), weak) && branch_type.validate_ref(ops, cs.fetch_ref(), weak);
495
bool Hashmap::skip(vm::CellSlice& cs) const {
497
return HmLabel{n}.skip(cs, l) && HashmapNode{n - l, value_type}.skip(cs);
500
bool Hashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
502
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(ops, cs, weak);
505
int HashmapE::get_size(const vm::CellSlice& cs) const {
506
int tag = get_tag(cs);
507
return (tag >= 0 ? (tag > 0 ? 0x10001 : 1) : -1);
510
bool HashmapE::validate(int* ops, const vm::CellSlice& cs, bool weak) const {
511
int tag = get_tag(cs);
512
return tag <= 0 ? !tag : root_type.validate_ref(ops, cs.prefetch_ref(), weak);
515
bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
517
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
518
const TLB& vt = root_type.value_type;
519
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
520
Ref<vm::CellSlice> cs2_ref) -> bool {
521
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
522
throw CombineError{};
526
return dict1.combine_with(dict2, combine) && std::move(dict1).append_dict_to_bool(cb);
529
bool HashmapE::add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
531
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
532
const TLB& vt = root_type.value_type;
533
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
534
Ref<vm::CellSlice> cs2_ref) -> bool {
535
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
536
throw CombineError{};
540
if (dict1.combine_with(dict2, combine)) {
542
res = std::move(dict1).extract_root_cell();
545
res = Ref<vm::Cell>{};
550
int HashmapE::sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
552
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
553
const TLB& vt = root_type.value_type;
554
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
555
Ref<vm::CellSlice> cs2_ref) -> bool {
556
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
558
throw CombineError{};
562
if (!dict1.combine_with(dict2, combine, 1)) {
566
bool not_empty = !dict1.is_empty();
567
return std::move(dict1).append_dict_to_bool(cb) ? not_empty : -1;
570
int HashmapE::sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
572
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
573
const TLB& vt = root_type.value_type;
574
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
575
Ref<vm::CellSlice> cs2_ref) -> bool {
576
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
578
throw CombineError{};
582
if (dict1.combine_with(dict2, combine, 1)) {
584
res = std::move(dict1).extract_root_cell();
585
return res.not_null();
587
res = Ref<vm::Cell>{};
592
bool HashmapE::store_ref(vm::CellBuilder& cb, Ref<vm::Cell> arg) const {
594
return cb.store_long_bool(0, 1);
596
return cb.store_long_bool(1, 1) && cb.store_ref_bool(std::move(arg));
600
const ExtraCurrencyCollection t_ExtraCurrencyCollection;
602
bool CurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
603
return t_Grams.validate_skip(ops, cs, weak) && t_ExtraCurrencyCollection.validate_skip(ops, cs, weak);
606
bool CurrencyCollection::skip(vm::CellSlice& cs) const {
607
return t_Grams.skip(cs) && t_ExtraCurrencyCollection.skip(cs);
610
td::RefInt256 CurrencyCollection::as_integer_skip(vm::CellSlice& cs) const {
611
auto res = t_Grams.as_integer_skip(cs);
612
if (res.not_null() && t_ExtraCurrencyCollection.skip(cs)) {
619
bool CurrencyCollection::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
620
return t_Grams.add_values(cb, cs1, cs2) && t_ExtraCurrencyCollection.add_values(cb, cs1, cs2);
623
bool CurrencyCollection::unpack_special(vm::CellSlice& cs, td::RefInt256& balance, Ref<vm::Cell>& extra,
624
bool inexact) const {
625
balance = t_Grams.as_integer_skip(cs);
626
if (cs.fetch_ulong(1) == 1) {
627
return balance.not_null() && cs.fetch_ref_to(extra) && (inexact || cs.empty_ext());
630
return balance.not_null() && (inexact || cs.empty_ext());
634
bool CurrencyCollection::unpack_special(vm::CellSlice& cs, block::CurrencyCollection& value, bool inexact) const {
635
return unpack_special(cs, value.grams, value.extra, inexact);
638
bool CurrencyCollection::pack_special(vm::CellBuilder& cb, td::RefInt256 balance, Ref<vm::Cell> extra) const {
639
return t_Grams.store_integer_ref(cb, std::move(balance)) && t_ExtraCurrencyCollection.store_ref(cb, std::move(extra));
642
bool CurrencyCollection::pack_special(vm::CellBuilder& cb, const block::CurrencyCollection& value) const {
643
return value.is_valid() && pack_special(cb, value.grams, value.extra);
646
bool CurrencyCollection::pack_special(vm::CellBuilder& cb, block::CurrencyCollection&& value) const {
647
return value.is_valid() && pack_special(cb, std::move(value.grams), std::move(value.extra));
650
bool CurrencyCollection::unpack(vm::CellSlice& cs, block::CurrencyCollection& res) const {
651
return unpack_special(cs, res.grams, res.extra);
654
bool CurrencyCollection::pack(vm::CellBuilder& cb, const block::CurrencyCollection& res) const {
655
return res.is_valid() && pack_special(cb, res.grams, res.extra);
658
const CurrencyCollection t_CurrencyCollection;
660
bool CommonMsgInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
661
int tag = get_tag(cs);
665
&& t_MsgAddressInt.validate_skip(ops, cs, weak)
666
&& t_MsgAddressInt.validate_skip(ops, cs, weak)
667
&& t_CurrencyCollection.validate_skip(ops, cs, weak)
668
&& t_Grams.validate_skip(ops, cs, weak)
669
&& t_Grams.validate_skip(ops, cs, weak)
670
&& cs.advance(64 + 32);
671
case ext_in_msg_info:
672
return cs.advance(2) && t_MsgAddressExt.validate_skip(ops, cs, weak)
673
&& t_MsgAddressInt.validate_skip(ops, cs, weak)
674
&& t_Grams.validate_skip(ops, cs, weak);
675
case ext_out_msg_info:
676
return cs.advance(2) && t_MsgAddressInt.validate_skip(ops, cs, weak)
677
&& t_MsgAddressExt.validate_skip(ops, cs, weak)
678
&& cs.advance(64 + 32);
683
bool CommonMsgInfo::unpack(vm::CellSlice& cs, CommonMsgInfo::Record_int_msg_info& data) const {
684
return get_tag(cs) == int_msg_info && cs.advance(1) && cs.fetch_bool_to(data.ihr_disabled) &&
685
cs.fetch_bool_to(data.bounce) && cs.fetch_bool_to(data.bounced) && t_MsgAddressInt.fetch_to(cs, data.src) &&
686
t_MsgAddressInt.fetch_to(cs, data.dest) && t_CurrencyCollection.fetch_to(cs, data.value) &&
687
t_Grams.fetch_to(cs, data.ihr_fee) && t_Grams.fetch_to(cs, data.fwd_fee) &&
688
cs.fetch_uint_to(64, data.created_lt) && cs.fetch_uint_to(32, data.created_at);
691
bool CommonMsgInfo::skip(vm::CellSlice& cs) const {
692
int tag = get_tag(cs);
696
&& t_MsgAddressInt.skip(cs)
697
&& t_MsgAddressInt.skip(cs)
698
&& t_CurrencyCollection.skip(cs)
701
&& cs.advance(64 + 32);
702
case ext_in_msg_info:
703
return cs.advance(2) && t_MsgAddressExt.skip(cs)
704
&& t_MsgAddressInt.skip(cs)
706
case ext_out_msg_info:
707
return cs.advance(2) && t_MsgAddressInt.skip(cs)
708
&& t_MsgAddressExt.skip(cs)
709
&& cs.advance(64 + 32);
714
bool CommonMsgInfo::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const {
715
switch (get_tag(cs)) {
718
&& t_MsgAddressInt.skip(cs)
719
&& t_MsgAddressInt.skip(cs)
720
&& t_CurrencyCollection.skip(cs)
723
&& cs.fetch_ulong_bool(64, created_lt)
725
case ext_in_msg_info:
727
case ext_out_msg_info:
728
return cs.advance(2) && t_MsgAddressInt.skip(cs)
729
&& t_MsgAddressExt.skip(cs)
730
&& cs.fetch_ulong_bool(64, created_lt)
736
const CommonMsgInfo t_CommonMsgInfo;
737
const TickTock t_TickTock;
738
const RefAnything t_RefCell;
740
bool StateInit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
741
return Maybe<UInt>{5}.validate_skip(ops, cs, weak)
742
&& Maybe<TickTock>{}.validate_skip(ops, cs, weak)
743
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak)
744
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak)
745
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak);
748
bool StateInit::get_ticktock(vm::CellSlice& cs, int& ticktock) const {
751
return Maybe<UInt>{5}.validate_skip_upto(1, cs) && cs.fetch_bool_to(have_tt) &&
752
(!have_tt || cs.fetch_uint_to(2, ticktock));
755
const StateInit t_StateInit;
757
bool Message::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
758
static const Maybe<Either<StateInit, RefTo<StateInit>>> init_type;
759
static const Either<Anything, RefAnything> body_type;
760
return t_CommonMsgInfo.validate_skip(ops, cs, weak)
761
&& init_type.validate_skip(ops, cs, weak)
762
&& body_type.validate_skip(ops, cs, weak);
765
bool Message::extract_info(vm::CellSlice& cs) const {
766
return t_CommonMsgInfo.extract(cs);
769
bool Message::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const {
770
return t_CommonMsgInfo.get_created_lt(cs, created_lt);
773
bool Message::is_internal(Ref<vm::Cell> ref) const {
774
return is_internal(load_cell_slice(std::move(ref)));
777
const Message t_Message;
778
const RefTo<Message> t_Ref_Message;
780
bool IntermediateAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
781
switch (get_tag(cs)) {
782
case interm_addr_regular:
783
return cs.advance(1) && cs.fetch_ulong(7) <= 96U;
784
case interm_addr_simple:
785
return cs.advance(2 + 8 + 64);
786
case interm_addr_ext:
787
if (cs.have(2 + 32 + 64)) {
789
int workchain_id = (int)cs.fetch_long(32);
790
return (workchain_id < -128 || workchain_id >= 128) && cs.advance(64);
797
bool IntermediateAddress::skip(vm::CellSlice& cs) const {
798
return cs.advance(get_size(cs));
801
int IntermediateAddress::get_size(const vm::CellSlice& cs) const {
802
switch (get_tag(cs)) {
803
case interm_addr_regular:
805
case interm_addr_simple:
807
case interm_addr_ext:
813
const IntermediateAddress t_IntermediateAddress;
815
bool MsgEnvelope::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
816
return cs.fetch_ulong(4) == 4
817
&& t_IntermediateAddress.validate_skip(ops, cs, weak)
818
&& t_IntermediateAddress.validate_skip(ops, cs, weak)
819
&& t_Grams.validate_skip(ops, cs, weak)
820
&& t_Ref_Message.validate_skip(ops, cs, weak);
823
bool MsgEnvelope::skip(vm::CellSlice& cs) const {
825
&& t_IntermediateAddress.skip(cs)
826
&& t_IntermediateAddress.skip(cs)
828
&& t_Ref_Message.skip(cs);
831
bool MsgEnvelope::extract_fwd_fees_remaining(vm::CellSlice& cs) const {
832
return t_IntermediateAddress.skip(cs) && t_IntermediateAddress.skip(cs) && t_Grams.extract(cs);
835
bool MsgEnvelope::unpack(vm::CellSlice& cs, MsgEnvelope::Record& data) const {
836
return cs.fetch_ulong(4) == 4
837
&& t_IntermediateAddress.fetch_to(cs, data.cur_addr)
838
&& t_IntermediateAddress.fetch_to(cs, data.next_addr)
839
&& t_Grams.fetch_to(cs, data.fwd_fee_remaining)
840
&& cs.fetch_ref_to(data.msg);
843
bool MsgEnvelope::unpack(vm::CellSlice& cs, MsgEnvelope::Record_std& data) const {
844
return cs.fetch_ulong(4) == 4
845
&& t_IntermediateAddress.fetch_regular(cs, data.cur_addr)
846
&& t_IntermediateAddress.fetch_regular(cs, data.next_addr)
847
&& t_Grams.as_integer_skip_to(cs, data.fwd_fee_remaining)
848
&& cs.fetch_ref_to(data.msg);
851
bool MsgEnvelope::unpack_std(vm::CellSlice& cs, int& cur_a, int& nhop_a, Ref<vm::Cell>& msg) const {
852
return cs.fetch_ulong(4) == 4
853
&& t_IntermediateAddress.fetch_regular(cs, cur_a)
854
&& t_IntermediateAddress.fetch_regular(cs, nhop_a)
855
&& cs.fetch_ref_to(msg);
858
bool MsgEnvelope::get_created_lt(const vm::CellSlice& cs, unsigned long long& created_lt) const {
859
if (!cs.size_refs()) {
862
auto msg_cs = load_cell_slice(cs.prefetch_ref());
863
return t_Message.get_created_lt(msg_cs, created_lt);
866
const MsgEnvelope t_MsgEnvelope;
867
const RefTo<MsgEnvelope> t_Ref_MsgEnvelope;
869
bool StorageUsed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
870
return t_VarUInteger_7.validate_skip(ops, cs, weak)
871
&& t_VarUInteger_7.validate_skip(ops, cs, weak)
872
&& t_VarUInteger_7.validate_skip(ops, cs, weak);
875
bool StorageUsed::skip(vm::CellSlice& cs) const {
876
return t_VarUInteger_7.skip(cs)
877
&& t_VarUInteger_7.skip(cs)
878
&& t_VarUInteger_7.skip(cs);
881
const StorageUsed t_StorageUsed;
883
bool StorageUsedShort::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
884
return t_VarUInteger_7.validate_skip(ops, cs, weak)
885
&& t_VarUInteger_7.validate_skip(ops, cs, weak);
888
bool StorageUsedShort::skip(vm::CellSlice& cs) const {
889
return t_VarUInteger_7.skip(cs)
890
&& t_VarUInteger_7.skip(cs);
893
const StorageUsedShort t_StorageUsedShort;
895
const Maybe<Grams> t_Maybe_Grams;
897
bool StorageInfo::skip(vm::CellSlice& cs) const {
898
return t_StorageUsed.skip(cs)
900
&& t_Maybe_Grams.skip(cs);
903
bool StorageInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
904
return t_StorageUsed.validate_skip(ops, cs, weak)
906
&& t_Maybe_Grams.validate_skip(ops, cs, weak);
909
const StorageInfo t_StorageInfo;
911
bool AccountState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
912
switch (get_tag(cs)) {
914
return cs.advance(2);
916
return cs.advance(2 + 256);
918
return cs.advance(1) && t_StateInit.validate_skip(ops, cs, weak);
923
bool AccountState::get_ticktock(vm::CellSlice& cs, int& ticktock) const {
924
if (get_tag(cs) != account_active) {
928
return cs.advance(1) && t_StateInit.get_ticktock(cs, ticktock);
931
const AccountState t_AccountState;
933
bool AccountStorage::skip(vm::CellSlice& cs) const {
934
return cs.advance(64) && t_CurrencyCollection.skip(cs) && t_AccountState.skip(cs);
937
bool AccountStorage::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const {
938
return cs.advance(64) && t_CurrencyCollection.skip_copy(cb, cs) && t_AccountState.skip(cs);
941
bool AccountStorage::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
942
return cs.advance(64) && t_CurrencyCollection.validate_skip(ops, cs, weak) &&
943
t_AccountState.validate_skip(ops, cs, weak);
946
const AccountStorage t_AccountStorage;
948
bool Account::skip(vm::CellSlice& cs) const {
949
switch (get_tag(cs)) {
951
return cs.advance(1);
954
&& t_MsgAddressInt.skip(cs)
955
&& t_StorageInfo.skip(cs)
956
&& t_AccountStorage.skip(cs);
961
bool Account::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
962
switch (get_tag(cs)) {
964
return allow_empty && cs.advance(1);
967
&& t_MsgAddressInt.validate_skip(ops, cs, weak)
968
&& t_StorageInfo.validate_skip(ops, cs, weak)
969
&& t_AccountStorage.validate_skip(ops, cs, weak);
974
bool Account::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const {
975
switch (get_tag(cs)) {
977
return allow_empty && cs.advance(1) && t_CurrencyCollection.null_value(cb);
980
&& t_MsgAddressInt.skip(cs)
981
&& t_StorageInfo.skip(cs)
982
&& t_AccountStorage.skip_copy_balance(cb, cs);
987
bool Account::skip_copy_depth_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const {
989
switch (get_tag(cs)) {
991
return allow_empty && cs.advance(1) && t_DepthBalanceInfo.null_value(cb);
994
&& t_MsgAddressInt.skip_get_depth(cs, depth)
995
&& cb.store_uint_leq(30, depth)
996
&& t_StorageInfo.skip(cs)
997
&& t_AccountStorage.skip_copy_balance(cb, cs);
1002
const Account t_Account, t_AccountE{true};
1003
const RefTo<Account> t_Ref_AccountE{true};
1005
bool ShardAccount::extract_account_state(Ref<vm::CellSlice> cs_ref, Ref<vm::Cell>& acc_state) {
1006
if (cs_ref.is_null()) {
1008
return cb.store_bool_bool(false) && cb.finalize_to(acc_state);
1010
return cs_ref->prefetch_ref_to(acc_state);
1014
bool ShardAccount::Record::reset() {
1015
last_trans_hash.set_zero();
1017
is_zero = valid = true;
1019
return (cb.store_bool_bool(false) && cb.finalize_to(account)) || invalidate();
1022
bool ShardAccount::Record::unpack(vm::CellSlice& cs) {
1025
return (cs.fetch_ref_to(account) && cs.fetch_bits_to(last_trans_hash) && cs.fetch_uint_to(64, last_trans_lt)) ||
1029
bool ShardAccount::Record::unpack(Ref<vm::CellSlice> cs_ref) {
1030
if (cs_ref.not_null()) {
1031
return unpack(cs_ref.write()) && (cs_ref->empty_ext() || invalidate());
1037
const ShardAccount t_ShardAccount;
1039
const AccountStatus t_AccountStatus;
1041
bool HashmapAugNode::skip(vm::CellSlice& cs) const {
1046
return aug.extra_type.skip(cs) && aug.value_type.skip(cs);
1049
return cs.advance_refs(2) && aug.extra_type.skip(cs);
1053
bool HashmapAugNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1059
vm::CellSlice cs_extra{cs};
1060
if (!aug.extra_type.validate_skip(ops, cs, weak)) {
1063
cs_extra.cut_tail(cs);
1064
vm::CellSlice cs_value{cs};
1065
if (!aug.value_type.validate_skip(ops, cs, weak)) {
1068
cs_value.cut_tail(cs);
1069
return aug.check_leaf(cs_extra, cs_value);
1072
if (!cs.have_refs(2)) {
1075
HashmapAug branch_type{n - 1, aug};
1076
if (!branch_type.validate_ref(ops, cs.prefetch_ref(0), weak) ||
1077
!branch_type.validate_ref(ops, cs.prefetch_ref(1), weak)) {
1080
auto cs_left = load_cell_slice(cs.fetch_ref());
1081
auto cs_right = load_cell_slice(cs.fetch_ref());
1082
vm::CellSlice cs_extra{cs};
1083
if (!aug.extra_type.validate_skip(ops, cs, weak)) {
1086
cs_extra.cut_tail(cs);
1087
return branch_type.extract_extra(cs_left) && branch_type.extract_extra(cs_right) &&
1088
aug.check_fork(cs_extra, cs_left, cs_right);
1091
bool HashmapAug::skip(vm::CellSlice& cs) const {
1093
return HmLabel{n}.skip(cs, l) && HashmapAugNode{n - l, aug}.skip(cs);
1096
bool HashmapAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1098
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(ops, cs, weak);
1101
bool HashmapAug::extract_extra(vm::CellSlice& cs) const {
1103
return HmLabel{n}.skip(cs, l) && (l == n || cs.advance_refs(2)) && aug.extra_type.extract(cs);
1106
bool HashmapAugE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1107
Ref<vm::CellSlice> extra;
1108
switch (get_tag(cs)) {
1110
return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
1111
root_type.aug.check_empty(extra.unique_write());
1113
if (cs.advance(1) && root_type.validate_ref(ops, cs.prefetch_ref(), weak)) {
1115
auto cs_root = load_cell_slice_special(cs.fetch_ref(), special);
1119
return (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
1120
root_type.extract_extra(cs_root) && extra->contents_equal(cs_root);
1127
bool HashmapAugE::skip(vm::CellSlice& cs) const {
1128
int tag = (int)cs.fetch_ulong(1);
1129
return tag >= 0 && cs.advance_refs(tag) && root_type.aug.extra_type.skip(cs);
1132
bool HashmapAugE::extract_extra(vm::CellSlice& cs) const {
1133
int tag = (int)cs.fetch_ulong(1);
1134
return tag >= 0 && cs.advance_refs(tag) && root_type.aug.extra_type.extract(cs);
1137
bool DepthBalanceInfo::skip(vm::CellSlice& cs) const {
1138
return cs.advance(5) &&
1139
t_CurrencyCollection.skip(
1143
bool DepthBalanceInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1144
return cs.fetch_ulong(5) <= 30 &&
1145
t_CurrencyCollection.validate_skip(ops, cs,
1149
bool DepthBalanceInfo::null_value(vm::CellBuilder& cb) const {
1150
return cb.store_zeroes_bool(5) && t_CurrencyCollection.null_value(cb);
1153
bool DepthBalanceInfo::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
1155
return cs1.fetch_uint_leq(30, d1) && cs2.fetch_uint_leq(30, d2) && cb.store_uint_leq(30, std::max(d1, d2)) &&
1156
t_CurrencyCollection.add_values(cb, cs1, cs2);
1159
const DepthBalanceInfo t_DepthBalanceInfo;
1161
bool Aug_ShardAccounts::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
1162
if (cs.have_refs()) {
1163
auto cs2 = load_cell_slice(cs.prefetch_ref());
1164
return t_Account.skip_copy_depth_balance(cb, cs2);
1170
const Aug_ShardAccounts aug_ShardAccounts;
1172
const ShardAccounts t_ShardAccounts;
1174
const AccStatusChange t_AccStatusChange;
1176
bool TrStoragePhase::skip(vm::CellSlice& cs) const {
1177
return t_Grams.skip(cs)
1178
&& t_Maybe_Grams.skip(cs)
1179
&& t_AccStatusChange.skip(cs);
1182
bool TrStoragePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1183
return t_Grams.validate_skip(ops, cs, weak)
1184
&& t_Maybe_Grams.validate_skip(ops, cs, weak)
1185
&& t_AccStatusChange.validate_skip(ops, cs, weak);
1188
bool TrStoragePhase::get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
1189
return t_Grams.as_integer_skip_to(cs, storage_fees);
1192
bool TrStoragePhase::maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
1193
auto z = cs.fetch_ulong(1);
1195
storage_fees = td::make_refint(0);
1198
return z == 1 && get_storage_fees(cs, storage_fees);
1202
const TrStoragePhase t_TrStoragePhase;
1204
bool TrCreditPhase::skip(vm::CellSlice& cs) const {
1205
return t_Maybe_Grams.skip(cs)
1206
&& t_CurrencyCollection.skip(cs);
1209
bool TrCreditPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1210
return t_Maybe_Grams.validate_skip(ops, cs, weak)
1211
&& t_CurrencyCollection.validate_skip(ops, cs, weak);
1214
const TrCreditPhase t_TrCreditPhase;
1216
bool TrComputeInternal1::skip(vm::CellSlice& cs) const {
1217
return t_VarUInteger_7.skip(cs)
1218
&& t_VarUInteger_7.skip(cs)
1219
&& Maybe<VarUInteger>{3}.skip(cs)
1220
&& cs.advance(8 + 32)
1221
&& Maybe<Int>{32}.skip(cs)
1222
&& cs.advance(32 + 256 + 256);
1227
bool TrComputeInternal1::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1228
return t_VarUInteger_7.validate_skip(ops, cs, weak)
1229
&& t_VarUInteger_7.validate_skip(ops, cs, weak)
1230
&& Maybe<VarUInteger>{3}.validate_skip(ops, cs, weak)
1231
&& cs.advance(8 + 32)
1232
&& Maybe<Int>{32}.validate_skip(ops, cs, weak)
1233
&& cs.advance(32 + 256 + 256);
1238
const TrComputeInternal1 t_TrComputeInternal1;
1239
const RefTo<TrComputeInternal1> t_Ref_TrComputeInternal1;
1240
const ComputeSkipReason t_ComputeSkipReason;
1242
bool TrComputePhase::skip(vm::CellSlice& cs) const {
1243
switch (get_tag(cs)) {
1244
case tr_phase_compute_skipped:
1245
return cs.advance(1) && t_ComputeSkipReason.skip(cs);
1246
case tr_phase_compute_vm:
1247
return cs.advance(1 + 3)
1249
&& t_Ref_TrComputeInternal1.skip(cs);
1254
bool TrComputePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1255
switch (get_tag(cs)) {
1256
case tr_phase_compute_skipped:
1257
return cs.advance(1) && t_ComputeSkipReason.validate_skip(ops, cs, weak);
1258
case tr_phase_compute_vm:
1259
return cs.advance(1 + 3)
1260
&& t_Grams.validate_skip(ops, cs, weak)
1261
&& t_Ref_TrComputeInternal1.validate_skip(ops, cs, weak);
1266
const TrComputePhase t_TrComputePhase;
1268
bool TrActionPhase::skip(vm::CellSlice& cs) const {
1269
return cs.advance(3)
1270
&& t_AccStatusChange.skip(cs)
1271
&& t_Maybe_Grams.skip(cs)
1272
&& t_Maybe_Grams.skip(cs)
1274
&& Maybe<Int>{32}.skip(cs)
1275
&& cs.advance(16 * 4 + 256)
1278
&& t_StorageUsedShort.skip(cs);
1281
bool TrActionPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1282
return cs.advance(3)
1283
&& t_AccStatusChange.validate_skip(ops, cs, weak)
1284
&& t_Maybe_Grams.validate_skip(ops, cs, weak)
1285
&& t_Maybe_Grams.validate_skip(ops, cs, weak)
1287
&& Maybe<Int>{32}.validate_skip(ops, cs, weak)
1288
&& cs.advance(16 * 4 + 256)
1291
&& t_StorageUsedShort.validate_skip(ops, cs, weak);
1294
const TrActionPhase t_TrActionPhase;
1296
bool TrBouncePhase::skip(vm::CellSlice& cs) const {
1297
switch (get_tag(cs)) {
1298
case tr_phase_bounce_negfunds:
1299
return cs.advance(2);
1300
case tr_phase_bounce_nofunds:
1301
return cs.advance(2)
1302
&& t_StorageUsedShort.skip(cs)
1303
&& t_Grams.skip(cs);
1304
case tr_phase_bounce_ok:
1305
return cs.advance(1)
1306
&& t_StorageUsedShort.skip(cs)
1308
&& t_Grams.skip(cs);
1313
bool TrBouncePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1314
switch (get_tag(cs)) {
1315
case tr_phase_bounce_negfunds:
1316
return cs.advance(2);
1317
case tr_phase_bounce_nofunds:
1318
return cs.advance(2)
1319
&& t_StorageUsedShort.validate_skip(ops, cs, weak)
1320
&& t_Grams.validate_skip(ops, cs, weak);
1321
case tr_phase_bounce_ok:
1322
return cs.advance(1)
1323
&& t_StorageUsedShort.validate_skip(ops, cs, weak)
1324
&& t_Grams.validate_skip(ops, cs, weak)
1325
&& t_Grams.validate_skip(ops, cs, weak);
1330
int TrBouncePhase::get_tag(const vm::CellSlice& cs) const {
1331
if (cs.size() == 1) {
1332
return (int)cs.prefetch_ulong(1) == 1 ? tr_phase_bounce_ok : -1;
1334
int v = (int)cs.prefetch_ulong(2);
1335
return v == 3 ? tr_phase_bounce_ok : v;
1338
const TrBouncePhase t_TrBouncePhase;
1340
bool SplitMergeInfo::skip(vm::CellSlice& cs) const {
1342
return cs.advance(6 + 6 + 256 + 256);
1345
bool SplitMergeInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1346
if (!cs.have(6 + 6 + 256 + 256)) {
1349
int cur_pfx_len = (int)cs.fetch_ulong(6);
1350
int split_depth = (int)cs.fetch_ulong(6);
1351
unsigned char this_addr[32], sibling_addr[32];
1352
if (!cs.fetch_bytes(this_addr, 32) || !cs.fetch_bytes(sibling_addr, 32)) {
1356
if (cur_pfx_len >= split_depth) {
1359
sibling_addr[cur_pfx_len >> 3] ^= (unsigned char)(0x80 >> (cur_pfx_len & 7));
1360
return !std::memcmp(this_addr, sibling_addr, 32);
1363
const SplitMergeInfo t_SplitMergeInfo;
1365
bool TransactionDescr::skip(vm::CellSlice& cs) const {
1366
switch (get_tag(cs)) {
1368
return cs.advance(4 + 1)
1369
&& Maybe<TrStoragePhase>{}.skip(cs)
1370
&& Maybe<TrCreditPhase>{}.skip(cs)
1371
&& t_TrComputePhase.skip(cs)
1372
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs)
1374
&& Maybe<TrBouncePhase>{}.skip(cs)
1377
return cs.advance(4)
1378
&& t_TrStoragePhase.skip(cs);
1379
case trans_tick_tock:
1380
return cs.advance(4)
1381
&& t_TrStoragePhase.skip(cs)
1382
&& t_TrComputePhase.skip(cs)
1383
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs)
1385
case trans_split_prepare:
1386
return cs.advance(4)
1387
&& t_SplitMergeInfo.skip(cs)
1388
&& Maybe<TrStoragePhase>{}.skip(cs)
1389
&& t_TrComputePhase.skip(cs)
1390
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs)
1392
case trans_split_install:
1393
return cs.advance(4)
1394
&& t_SplitMergeInfo.skip(cs)
1395
&& t_Ref_Transaction.skip(cs)
1397
case trans_merge_prepare:
1398
return cs.advance(4)
1399
&& t_SplitMergeInfo.skip(cs)
1400
&& t_TrStoragePhase.skip(cs)
1402
case trans_merge_install:
1403
return cs.advance(4)
1404
&& t_SplitMergeInfo.skip(cs)
1405
&& t_Ref_Transaction.skip(cs)
1406
&& Maybe<TrStoragePhase>{}.skip(cs)
1407
&& Maybe<TrCreditPhase>{}.skip(cs)
1408
&& Maybe<TrComputePhase>{}.skip(cs)
1409
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs)
1415
bool TransactionDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1416
switch (get_tag(cs)) {
1418
return cs.advance(4 + 1)
1419
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak)
1420
&& Maybe<TrCreditPhase>{}.validate_skip(ops, cs, weak)
1421
&& t_TrComputePhase.validate_skip(ops, cs, weak)
1422
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak)
1424
&& Maybe<TrBouncePhase>{}.validate_skip(ops, cs, weak)
1427
return cs.advance(4)
1428
&& t_TrStoragePhase.validate_skip(ops, cs, weak);
1429
case trans_tick_tock:
1430
return cs.advance(4)
1431
&& t_TrStoragePhase.validate_skip(ops, cs, weak)
1432
&& t_TrComputePhase.validate_skip(ops, cs, weak)
1433
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak)
1435
case trans_split_prepare:
1436
return cs.advance(4)
1437
&& t_SplitMergeInfo.validate_skip(ops, cs, weak)
1438
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak)
1439
&& t_TrComputePhase.validate_skip(ops, cs, weak)
1440
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak)
1442
case trans_split_install:
1443
return cs.advance(4)
1444
&& t_SplitMergeInfo.validate_skip(ops, cs, weak)
1445
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1447
case trans_merge_prepare:
1448
return cs.advance(4)
1449
&& t_SplitMergeInfo.validate_skip(ops, cs, weak)
1450
&& t_TrStoragePhase.validate_skip(ops, cs, weak)
1452
case trans_merge_install:
1453
return cs.advance(4)
1454
&& t_SplitMergeInfo.validate_skip(ops, cs, weak)
1455
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1456
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak)
1457
&& Maybe<TrCreditPhase>{}.validate_skip(ops, cs, weak)
1458
&& Maybe<TrComputePhase>{}.validate_skip(ops, cs, weak)
1459
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak)
1465
int TransactionDescr::get_tag(const vm::CellSlice& cs) const {
1466
int t = (int)cs.prefetch_ulong(4);
1467
return (t >= 0 && t <= 7) ? (t == 3 ? 2 : t) : -1;
1470
bool TransactionDescr::skip_to_storage_phase(vm::CellSlice& cs, bool& found) const {
1472
switch (get_tag(cs)) {
1474
return cs.advance(4 + 1)
1475
&& cs.fetch_bool_to(found);
1477
return cs.advance(4)
1479
case trans_tick_tock:
1480
return cs.advance(4)
1482
case trans_split_prepare:
1483
return cs.advance(4)
1484
&& t_SplitMergeInfo.skip(cs)
1485
&& cs.fetch_bool_to(found);
1486
case trans_split_install:
1488
case trans_merge_prepare:
1489
return cs.advance(4)
1490
&& t_SplitMergeInfo.skip(cs)
1492
case trans_merge_install:
1493
return cs.advance(4)
1494
&& t_SplitMergeInfo.skip(cs)
1495
&& t_Ref_Transaction.skip(cs)
1496
&& cs.fetch_bool_to(found);
1501
bool TransactionDescr::get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const {
1502
if (cell.is_null()) {
1505
auto cs = vm::load_cell_slice(std::move(cell));
1507
if (!skip_to_storage_phase(cs, found)) {
1510
return t_TrStoragePhase.get_storage_fees(cs, storage_fees);
1512
storage_fees = td::make_refint(0);
1517
const TransactionDescr t_TransactionDescr;
1519
bool Transaction_aux::skip(vm::CellSlice& cs) const {
1520
return Maybe<RefTo<Message>>{}.skip(cs)
1521
&& HashmapE{15, t_Ref_Message}.skip(cs);
1524
bool Transaction_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1525
return Maybe<RefTo<Message>>{}.validate_skip(ops, cs, weak)
1526
&& HashmapE{15, t_Ref_Message}.validate_skip(ops, cs, weak);
1529
const Transaction_aux t_Transaction_aux;
1531
bool Transaction::skip(vm::CellSlice& cs) const {
1533
4 + 256 + 64 + 256 + 64 + 32 +
1535
&& t_AccountStatus.skip(cs)
1536
&& t_AccountStatus.skip(cs)
1537
&& cs.advance_refs(1)
1538
&& t_CurrencyCollection.skip(cs)
1539
&& cs.advance_refs(1)
1540
&& RefTo<TransactionDescr>{}.skip(cs);
1543
bool Transaction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1544
return cs.fetch_ulong(4) == 7
1547
256 + 64 + 256 + 64 + 32 +
1549
&& t_AccountStatus.validate_skip(ops, cs, weak)
1550
&& t_AccountStatus.validate_skip(ops, cs, weak)
1551
&& RefTo<Transaction_aux>{}.validate_skip(ops, cs, weak)
1552
&& t_CurrencyCollection.validate_skip(ops, cs, weak)
1553
&& t_Ref_HashUpdate.validate_skip(ops, cs, weak)
1554
&& RefTo<TransactionDescr>{}.validate_skip(ops, cs, weak);
1557
bool Transaction::get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const {
1558
Ref<vm::Cell> tdescr;
1559
return get_descr(std::move(cell), tdescr) && t_TransactionDescr.get_storage_fees(std::move(tdescr), storage_fees);
1562
bool Transaction::get_descr(Ref<vm::Cell> cell, Ref<vm::Cell>& tdescr) const {
1563
if (cell.is_null()) {
1566
auto cs = vm::load_cell_slice(std::move(cell));
1567
return cs.is_valid() && get_descr(cs, tdescr) && cs.empty_ext();
1571
bool Transaction::get_descr(vm::CellSlice& cs, Ref<vm::Cell>& tdescr) const {
1573
4 + 256 + 64 + 256 + 64 + 32 +
1575
&& t_AccountStatus.skip(cs)
1576
&& t_AccountStatus.skip(cs)
1577
&& cs.advance_refs(1)
1578
&& t_CurrencyCollection.skip(cs)
1579
&& cs.advance_refs(1)
1580
&& cs.fetch_ref_to(tdescr);
1583
bool Transaction::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const {
1584
return cs.is_valid() && cs.fetch_ulong(4) == 7
1587
256 + 64 + 256 + 64 + 32 +
1589
&& t_AccountStatus.skip(cs)
1590
&& t_AccountStatus.skip(cs)
1591
&& cs.advance_refs(1)
1592
&& total_fees.fetch(cs);
1595
const Transaction t_Transaction;
1596
const RefTo<Transaction> t_Ref_Transaction;
1599
bool Aug_AccountTransactions::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
1600
auto cell_ref = cs.prefetch_ref();
1601
block::CurrencyCollection total_fees;
1602
return cell_ref.not_null() && t_Transaction.get_total_fees(vm::load_cell_slice(std::move(cell_ref)), total_fees) &&
1603
total_fees.store(cb);
1606
const Aug_AccountTransactions aug_AccountTransactions;
1607
const HashmapAug t_AccountTransactions{64, aug_AccountTransactions};
1609
const HashUpdate t_HashUpdate;
1610
const RefTo<HashUpdate> t_Ref_HashUpdate;
1612
bool AccountBlock::skip(vm::CellSlice& cs) const {
1613
return cs.advance(4 + 256)
1614
&& t_AccountTransactions.skip(cs)
1615
&& cs.advance_refs(1);
1618
bool AccountBlock::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1619
return cs.fetch_ulong(4) == 5
1621
&& t_AccountTransactions.validate_skip(ops, cs,
1623
&& t_Ref_HashUpdate.validate_skip(ops, cs, weak);
1626
bool AccountBlock::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const {
1627
return cs.advance(4 + 256)
1628
&& t_AccountTransactions.extract_extra(cs)
1629
&& total_fees.fetch(cs);
1632
const AccountBlock t_AccountBlock;
1634
bool Aug_ShardAccountBlocks::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
1635
block::CurrencyCollection total_fees;
1636
return t_AccountBlock.get_total_fees(std::move(cs), total_fees) && total_fees.store(cb);
1639
const Aug_ShardAccountBlocks aug_ShardAccountBlocks;
1640
const HashmapAugE t_ShardAccountBlocks{256,
1641
aug_ShardAccountBlocks};
1643
bool ImportFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1644
return t_Grams.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
1647
bool ImportFees::skip(vm::CellSlice& cs) const {
1648
return t_Grams.skip(cs) && t_CurrencyCollection.skip(cs);
1651
bool ImportFees::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
1652
return t_Grams.add_values(cb, cs1, cs2) && t_CurrencyCollection.add_values(cb, cs1, cs2);
1655
const ImportFees t_ImportFees;
1657
bool InMsg::skip(vm::CellSlice& cs) const {
1658
switch (get_tag(cs)) {
1659
case msg_import_ext:
1660
return cs.advance(3)
1661
&& t_Ref_Message.skip(cs)
1662
&& t_Ref_Transaction.skip(cs);
1663
case msg_import_ihr:
1664
return cs.advance(3)
1665
&& t_Ref_Message.skip(cs)
1666
&& t_Ref_Transaction.skip(cs)
1668
&& t_RefCell.skip(cs);
1669
case msg_import_imm:
1670
return cs.advance(3)
1671
&& t_Ref_MsgEnvelope.skip(cs)
1672
&& t_Ref_Transaction.skip(cs)
1673
&& t_Grams.skip(cs);
1674
case msg_import_fin:
1675
return cs.advance(3)
1676
&& t_Ref_MsgEnvelope.skip(cs)
1677
&& t_Ref_Transaction.skip(cs)
1678
&& t_Grams.skip(cs);
1680
return cs.advance(3)
1681
&& t_Ref_MsgEnvelope.skip(cs)
1682
&& t_Ref_MsgEnvelope.skip(cs)
1683
&& t_Grams.skip(cs);
1684
case msg_discard_fin:
1685
return cs.advance(3)
1686
&& t_Ref_MsgEnvelope.skip(cs)
1688
&& t_Grams.skip(cs);
1689
case msg_discard_tr:
1690
return cs.advance(3)
1691
&& t_Ref_MsgEnvelope.skip(cs)
1694
&& t_RefCell.skip(cs);
1699
bool InMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1700
switch (get_tag(cs)) {
1701
case msg_import_ext:
1702
return cs.advance(3)
1703
&& t_Ref_Message.validate_skip(ops, cs, weak)
1704
&& t_Ref_Transaction.validate_skip(ops, cs, weak);
1705
case msg_import_ihr:
1706
return cs.advance(3)
1707
&& t_Ref_Message.validate_skip(ops, cs, weak)
1708
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1709
&& t_Grams.validate_skip(ops, cs, weak)
1710
&& t_RefCell.validate_skip(ops, cs, weak);
1711
case msg_import_imm:
1712
return cs.advance(3)
1713
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1714
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1715
&& t_Grams.validate_skip(ops, cs, weak);
1716
case msg_import_fin:
1717
return cs.advance(3)
1718
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1719
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1720
&& t_Grams.validate_skip(ops, cs, weak);
1722
return cs.advance(3)
1723
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1724
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1725
&& t_Grams.validate_skip(ops, cs, weak);
1726
case msg_discard_fin:
1727
return cs.advance(3)
1728
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1730
&& t_Grams.validate_skip(ops, cs, weak);
1731
case msg_discard_tr:
1732
return cs.advance(3)
1733
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1735
&& t_Grams.validate_skip(ops, cs, weak)
1736
&& t_RefCell.validate_skip(ops, cs, weak);
1741
bool InMsg::get_import_fees(vm::CellBuilder& cb, vm::CellSlice& cs) const {
1742
switch (get_tag(cs)) {
1743
case msg_import_ext:
1744
return t_ImportFees.null_value(cb);
1745
case msg_import_ihr:
1746
if (cs.advance(3) && cs.size_refs() >= 3) {
1747
auto msg_cs = load_cell_slice(cs.fetch_ref());
1748
CommonMsgInfo::Record_int_msg_info msg_info;
1749
td::RefInt256 ihr_fee;
1750
vm::CellBuilder aux;
1752
return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) &&
1753
cs.fetch_ref().not_null() && (ihr_fee = t_Grams.as_integer_skip(cs)).not_null() &&
1754
cs.fetch_ref().not_null() && !cmp(ihr_fee, t_Grams.as_integer(*msg_info.ihr_fee)) &&
1755
cb.append_cellslice_bool(msg_info.ihr_fee)
1756
&& aux.append_cellslice_bool(msg_info.ihr_fee) && t_ExtraCurrencyCollection.null_value(aux) &&
1757
t_CurrencyCollection.add_values(cb, aux.as_cellslice_ref().write(),
1758
msg_info.value.write());
1761
case msg_import_imm:
1762
if (cs.advance(3) && cs.size_refs() >= 2) {
1763
return cs.fetch_ref().not_null() && cs.fetch_ref().not_null() &&
1764
cb.append_cellslice_bool(t_Grams.fetch(cs))
1765
&& t_CurrencyCollection.null_value(cb);
1768
case msg_import_fin:
1769
if (cs.advance(3) && cs.size_refs() >= 2) {
1770
auto msg_env_cs = load_cell_slice(cs.fetch_ref());
1771
MsgEnvelope::Record in_msg;
1772
td::RefInt256 fwd_fee, fwd_fee_remaining, value_grams, ihr_fee;
1773
if (!(t_MsgEnvelope.unpack(msg_env_cs, in_msg) && cs.fetch_ref().not_null() &&
1774
t_Grams.as_integer_skip_to(cs, fwd_fee) &&
1775
(fwd_fee_remaining = t_Grams.as_integer(in_msg.fwd_fee_remaining)).not_null() &&
1776
!(cmp(fwd_fee, fwd_fee_remaining)))) {
1779
auto msg_cs = load_cell_slice(std::move(in_msg.msg));
1780
CommonMsgInfo::Record_int_msg_info msg_info;
1781
return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) &&
1782
cb.append_cellslice_bool(in_msg.fwd_fee_remaining)
1783
&& t_Grams.as_integer_skip_to(msg_info.value.write(), value_grams) &&
1784
(ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() &&
1785
t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) &&
1786
cb.append_cellslice_bool(
1787
msg_info.value.write());
1791
if (cs.advance(3) && cs.size_refs() >= 2) {
1792
auto msg_env_cs = load_cell_slice(cs.fetch_ref());
1793
MsgEnvelope::Record in_msg;
1794
td::RefInt256 transit_fee, fwd_fee_remaining, value_grams, ihr_fee;
1795
if (!(t_MsgEnvelope.unpack(msg_env_cs, in_msg) && cs.fetch_ref().not_null() &&
1796
t_Grams.as_integer_skip_to(cs, transit_fee) &&
1797
(fwd_fee_remaining = t_Grams.as_integer(in_msg.fwd_fee_remaining)).not_null() &&
1798
cmp(transit_fee, fwd_fee_remaining) <= 0)) {
1801
auto msg_cs = load_cell_slice(in_msg.msg);
1802
CommonMsgInfo::Record_int_msg_info msg_info;
1803
return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) &&
1804
t_Grams.store_integer_ref(cb, std::move(transit_fee))
1805
&& t_Grams.as_integer_skip_to(msg_info.value.write(), value_grams) &&
1806
(ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() &&
1807
t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) &&
1808
cb.append_cellslice_bool(
1809
msg_info.value.write());
1812
case msg_discard_fin:
1813
if (cs.advance(3) && cs.size_refs() >= 1) {
1814
Ref<vm::CellSlice> fwd_fee;
1815
return cs.fetch_ref().not_null() && cs.advance(64) && (fwd_fee = t_Grams.fetch(cs)).not_null() &&
1816
cb.append_cellslice_bool(fwd_fee)
1817
&& cb.append_cellslice_bool(std::move(fwd_fee)) &&
1818
t_ExtraCurrencyCollection.null_value(cb);
1821
case msg_discard_tr:
1822
if (cs.advance(3) && cs.size_refs() >= 2) {
1823
Ref<vm::CellSlice> fwd_fee;
1824
return cs.fetch_ref().not_null() && cs.advance(64) && (fwd_fee = t_Grams.fetch(cs)).not_null() &&
1825
cs.fetch_ref().not_null() && cb.append_cellslice_bool(fwd_fee)
1826
&& cb.append_cellslice_bool(std::move(fwd_fee)) &&
1827
t_ExtraCurrencyCollection.null_value(cb);
1836
const Aug_InMsgDescr aug_InMsgDescr;
1837
const InMsgDescr t_InMsgDescr;
1839
bool OutMsg::skip(vm::CellSlice& cs) const {
1840
switch (get_tag(cs)) {
1841
case msg_export_ext:
1842
return cs.advance(3)
1843
&& t_Ref_Message.skip(cs)
1844
&& t_Ref_Transaction.skip(cs);
1845
case msg_export_imm:
1846
return cs.advance(3)
1847
&& t_Ref_MsgEnvelope.skip(cs)
1848
&& t_Ref_Transaction.skip(cs)
1849
&& RefTo<InMsg>{}.skip(cs);
1850
case msg_export_new:
1851
return cs.advance(3)
1852
&& t_Ref_MsgEnvelope.skip(cs)
1853
&& t_Ref_Transaction.skip(cs);
1855
return cs.advance(3)
1856
&& t_Ref_MsgEnvelope.skip(cs)
1857
&& RefTo<InMsg>{}.skip(cs);
1858
case msg_export_deq_imm:
1859
return cs.advance(3)
1860
&& t_Ref_MsgEnvelope.skip(cs)
1861
&& RefTo<InMsg>{}.skip(cs);
1862
case msg_export_deq:
1863
return cs.advance(4)
1864
&& t_Ref_MsgEnvelope.skip(cs)
1866
case msg_export_deq_short:
1870
case msg_export_tr_req:
1871
return cs.advance(3)
1872
&& t_Ref_MsgEnvelope.skip(cs)
1873
&& RefTo<InMsg>{}.skip(cs);
1878
bool OutMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1879
switch (get_tag(cs)) {
1880
case msg_export_ext:
1881
return cs.advance(3)
1882
&& t_Ref_Message.validate_skip(ops, cs, weak)
1883
&& t_Ref_Transaction.validate_skip(ops, cs, weak);
1884
case msg_export_imm:
1885
return cs.advance(3)
1886
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1887
&& t_Ref_Transaction.validate_skip(ops, cs, weak)
1888
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak);
1889
case msg_export_new:
1890
return cs.advance(3)
1891
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1892
&& t_Ref_Transaction.validate_skip(ops, cs, weak);
1894
return cs.advance(3)
1895
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1896
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak);
1897
case msg_export_deq_imm:
1898
return cs.advance(3)
1899
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1900
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak);
1901
case msg_export_deq:
1902
return cs.advance(4)
1903
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1905
case msg_export_deq_short:
1909
case msg_export_tr_req:
1910
return cs.advance(3)
1911
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak)
1912
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak);
1917
bool OutMsg::get_export_value(vm::CellBuilder& cb, vm::CellSlice& cs) const {
1918
switch (get_tag(cs)) {
1919
case msg_export_ext:
1920
if (cs.have(3, 2)) {
1921
return t_CurrencyCollection.null_value(cb);
1924
case msg_export_imm:
1925
return cs.have(3, 3) && t_CurrencyCollection.null_value(cb);
1926
case msg_export_deq_imm:
1927
return cs.have(3, 2) && t_CurrencyCollection.null_value(cb);
1928
case msg_export_deq:
1929
return cs.have(4 + 63, 1) && t_CurrencyCollection.null_value(cb);
1930
case msg_export_deq_short:
1931
return cs.have(4 + 256 + 32 + 64 + 64) && t_CurrencyCollection.null_value(cb);
1932
case msg_export_new:
1934
case msg_export_tr_req:
1935
if (cs.advance(3) && cs.size_refs() >= 2) {
1936
auto msg_env_cs = load_cell_slice(cs.fetch_ref());
1937
MsgEnvelope::Record out_msg;
1938
if (!(cs.fetch_ref().not_null() && t_MsgEnvelope.unpack(msg_env_cs, out_msg))) {
1941
auto msg_cs = load_cell_slice(std::move(out_msg.msg));
1942
CommonMsgInfo::Record_int_msg_info msg_info;
1943
td::RefInt256 value_grams, ihr_fee, fwd_fee_remaining;
1944
return t_Message.extract_info(msg_cs) && t_CommonMsgInfo.unpack(msg_cs, msg_info) &&
1945
(value_grams = t_Grams.as_integer_skip(msg_info.value.write())).not_null() &&
1946
(ihr_fee = t_Grams.as_integer(std::move(msg_info.ihr_fee))).not_null() &&
1947
(fwd_fee_remaining = t_Grams.as_integer(out_msg.fwd_fee_remaining)).not_null() &&
1948
t_Grams.store_integer_ref(cb, value_grams + ihr_fee + fwd_fee_remaining) &&
1949
cb.append_cellslice_bool(std::move(msg_info.value));
1957
bool OutMsg::get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const {
1958
switch (get_tag(cs)) {
1959
case msg_export_ext:
1960
if (cs.have(3, 1)) {
1961
auto msg_cs = load_cell_slice(cs.prefetch_ref());
1962
return t_Message.get_created_lt(msg_cs, created_lt);
1966
case msg_export_imm:
1967
case msg_export_new:
1969
case msg_export_deq:
1970
case msg_export_deq_short:
1971
case msg_export_deq_imm:
1972
case msg_export_tr_req:
1973
if (cs.have(3, 1)) {
1974
auto out_msg_cs = load_cell_slice(cs.prefetch_ref());
1975
return t_MsgEnvelope.get_created_lt(out_msg_cs, created_lt);
1983
const OutMsg t_OutMsg;
1985
const Aug_OutMsgDescr aug_OutMsgDescr;
1986
const OutMsgDescr t_OutMsgDescr;
1988
bool EnqueuedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
1989
return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak);
1992
const EnqueuedMsg t_EnqueuedMsg;
1994
bool Aug_OutMsgQueue::eval_fork(vm::CellBuilder& cb, vm::CellSlice& left_cs, vm::CellSlice& right_cs) const {
1995
unsigned long long x, y;
1996
return left_cs.fetch_ulong_bool(64, x) && right_cs.fetch_ulong_bool(64, y) &&
1997
cb.store_ulong_rchk_bool(std::min(x, y), 64);
2000
bool Aug_OutMsgQueue::eval_empty(vm::CellBuilder& cb) const {
2001
return cb.store_long_bool(0, 64);
2004
bool Aug_OutMsgQueue::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
2005
Ref<vm::Cell> msg_env;
2006
unsigned long long created_lt;
2007
return cs.fetch_ref_to(msg_env) && t_MsgEnvelope.get_created_lt(load_cell_slice(std::move(msg_env)), created_lt) &&
2008
cb.store_ulong_rchk_bool(created_lt, 64);
2011
const Aug_OutMsgQueue aug_OutMsgQueue;
2012
const OutMsgQueue t_OutMsgQueue;
2014
const ProcessedUpto t_ProcessedUpto;
2015
const HashmapE t_ProcessedInfo{96, t_ProcessedUpto};
2016
const HashmapE t_IhrPendingInfo{256, t_uint128};
2019
bool OutMsgQueueInfo::skip(vm::CellSlice& cs) const {
2020
return t_OutMsgQueue.skip(cs) && t_ProcessedInfo.skip(cs) && t_IhrPendingInfo.skip(cs);
2023
bool OutMsgQueueInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2024
return t_OutMsgQueue.validate_skip(ops, cs, weak) && t_ProcessedInfo.validate_skip(ops, cs, weak) &&
2025
t_IhrPendingInfo.validate_skip(ops, cs, weak);
2028
const OutMsgQueueInfo t_OutMsgQueueInfo;
2029
const RefTo<OutMsgQueueInfo> t_Ref_OutMsgQueueInfo;
2031
bool ExtBlkRef::unpack(vm::CellSlice& cs, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const {
2032
block::gen::ExtBlkRef::Record data;
2033
if (!tlb::unpack(cs, data)) {
2037
blkid.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, data.seq_no};
2038
blkid.root_hash = data.root_hash;
2039
blkid.file_hash = data.file_hash;
2041
*end_lt = data.end_lt;
2046
bool ExtBlkRef::unpack(Ref<vm::CellSlice> cs_ref, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt) const {
2047
block::gen::ExtBlkRef::Record data;
2048
if (!tlb::csr_unpack_safe(std::move(cs_ref), data)) {
2052
blkid.id = ton::BlockId{ton::masterchainId, ton::shardIdAll, data.seq_no};
2053
blkid.root_hash = data.root_hash;
2054
blkid.file_hash = data.file_hash;
2056
*end_lt = data.end_lt;
2061
bool ExtBlkRef::store(vm::CellBuilder& cb, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
2062
return cb.store_long_bool(end_lt, 64)
2063
&& cb.store_long_bool(blkid.seqno(), 32)
2064
&& cb.store_bits_bool(blkid.root_hash)
2065
&& cb.store_bits_bool(blkid.file_hash);
2068
Ref<vm::Cell> ExtBlkRef::pack_cell(const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
2070
return store(cb, blkid, end_lt) ? cb.finalize() : Ref<vm::Cell>{};
2073
bool ExtBlkRef::pack_to(Ref<vm::Cell>& cell, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
2075
return store(cb, blkid, end_lt) && cb.finalize_to(cell);
2078
const ExtBlkRef t_ExtBlkRef;
2079
const BlkMasterInfo t_BlkMasterInfo;
2081
bool ShardIdent::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2082
int shard_pfx_len, workchain_id;
2083
unsigned long long shard_pfx;
2084
if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, shard_pfx_len) && cs.fetch_int_to(32, workchain_id) &&
2085
workchain_id != ton::workchainInvalid && cs.fetch_uint_to(64, shard_pfx)) {
2086
auto pow2 = (1ULL << (63 - shard_pfx_len));
2087
if (!(shard_pfx & (pow2 - 1))) {
2094
bool ShardIdent::Record::check() const {
2095
return workchain_id != ton::workchainInvalid && !(shard_prefix & ((1ULL << (63 - shard_pfx_bits)) - 1));
2098
bool ShardIdent::unpack(vm::CellSlice& cs, ShardIdent::Record& data) const {
2099
if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, data.shard_pfx_bits) && cs.fetch_int_to(32, data.workchain_id) &&
2100
cs.fetch_uint_to(64, data.shard_prefix) && data.check()) {
2108
bool ShardIdent::pack(vm::CellBuilder& cb, const Record& data) const {
2109
return data.check() && cb.store_ulong_rchk_bool(0, 2) && cb.store_ulong_rchk_bool(data.shard_pfx_bits, 6) &&
2110
cb.store_long_rchk_bool(data.workchain_id, 32) && cb.store_ulong_rchk_bool(data.shard_prefix, 64);
2113
bool ShardIdent::unpack(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::ShardId& shard) const {
2115
unsigned long long pow2;
2116
auto assign = [](auto& a, auto b) { return a = b; };
2117
auto assign_or = [](auto& a, auto b) { return a |= b; };
2118
return cs.fetch_ulong(2) == 0
2119
&& cs.fetch_uint_leq(60, bits)
2120
&& assign(pow2, (1ULL << (63 - bits)))
2121
&& cs.fetch_int_to(32, workchain)
2122
&& cs.fetch_uint_to(64, shard)
2123
&& workchain != ton::workchainInvalid && !(shard & (2 * pow2 - 1)) && assign_or(shard, pow2);
2126
bool ShardIdent::unpack(vm::CellSlice& cs, ton::ShardIdFull& data) const {
2127
return unpack(cs, data.workchain, data.shard);
2130
bool ShardIdent::pack(vm::CellBuilder& cb, ton::WorkchainId workchain, ton::ShardId shard) const {
2131
int bits = ton::shard_prefix_length(shard);
2132
return workchain != ton::workchainInvalid
2134
&& cb.store_long_bool(0, 2)
2135
&& cb.store_uint_leq(60, bits)
2136
&& cb.store_long_bool(workchain, 32)
2137
&& cb.store_long_bool(shard & (shard - 1), 64);
2140
bool ShardIdent::pack(vm::CellBuilder& cb, ton::ShardIdFull data) const {
2141
return pack(cb, data.workchain, data.shard);
2144
const ShardIdent t_ShardIdent;
2146
bool BlockIdExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2147
return t_ShardIdent.validate_skip(ops, cs, weak) && cs.advance(32 + 256 * 2);
2150
bool BlockIdExt::unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const {
2151
return t_ShardIdent.unpack(cs, data.id.workchain, data.id.shard)
2152
&& cs.fetch_uint_to(32, data.id.seqno)
2153
&& cs.fetch_bits_to(data.root_hash)
2154
&& cs.fetch_bits_to(data.file_hash);
2157
bool BlockIdExt::pack(vm::CellBuilder& cb, const ton::BlockIdExt& data) const {
2158
return t_ShardIdent.pack(cb, data.id.workchain, data.id.shard)
2159
&& cb.store_long_bool(data.id.seqno, 32)
2160
&& cb.store_bits_bool(data.root_hash)
2161
&& cb.store_bits_bool(data.file_hash);
2164
const BlockIdExt t_BlockIdExt;
2166
bool ShardState::skip(vm::CellSlice& cs) const {
2167
return get_tag(cs) == shard_state && cs.advance(64)
2168
&& t_ShardIdent.skip(cs)
2169
&& cs.advance(32 + 32 + 32 + 64 +
2171
&& t_Ref_OutMsgQueueInfo.skip(cs)
2173
&& cs.advance_refs(1)
2177
&& Maybe<RefTo<McStateExtra>>{}.skip(cs);
2180
bool ShardState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2182
return get_tag(cs) == shard_state && cs.advance(64)
2183
&& t_ShardIdent.validate_skip(ops, cs, weak)
2184
&& cs.fetch_int_to(32, seq_no)
2186
&& cs.advance(32 + 32 + 64 + 32)
2187
&& t_Ref_OutMsgQueueInfo.validate_skip(ops, cs, weak)
2189
&& t_ShardAccounts.validate_skip_ref(ops, cs, weak)
2191
t_ShardState_aux.validate_skip_ref(
2194
&& Maybe<RefTo<McStateExtra>>{}.validate_skip(ops, cs, weak);
2197
const ShardState t_ShardState;
2199
bool ShardState_aux::skip(vm::CellSlice& cs) const {
2200
return cs.advance(128)
2201
&& t_CurrencyCollection.skip(cs)
2202
&& t_CurrencyCollection.skip(cs)
2203
&& HashmapE{256, t_LibDescr}.skip(cs)
2204
&& Maybe<BlkMasterInfo>{}.skip(cs);
2207
bool ShardState_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2208
return cs.advance(128)
2209
&& t_CurrencyCollection.validate_skip(ops, cs, weak)
2210
&& t_CurrencyCollection.validate_skip(ops, cs, weak)
2211
&& HashmapE{256, t_LibDescr}.validate_skip(ops, cs, weak)
2212
&& Maybe<BlkMasterInfo>{}.validate_skip(ops, cs, weak);
2215
const ShardState_aux t_ShardState_aux;
2217
bool LibDescr::skip(vm::CellSlice& cs) const {
2218
return cs.advance(2)
2219
&& cs.fetch_ref().not_null()
2220
&& Hashmap{256, t_True}.skip(cs);
2223
bool LibDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2224
return get_tag(cs) == shared_lib_descr && cs.advance(2)
2225
&& cs.fetch_ref().not_null()
2226
&& Hashmap{256, t_True}.validate_skip(ops, cs, weak);
2229
const LibDescr t_LibDescr;
2231
bool BlkPrevInfo::skip(vm::CellSlice& cs) const {
2232
return t_ExtBlkRef.skip(cs)
2233
&& (!merged || t_ExtBlkRef.skip(cs));
2236
bool BlkPrevInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2237
return t_ExtBlkRef.validate_skip(ops, cs, weak)
2238
&& (!merged || t_ExtBlkRef.validate_skip(ops, cs, weak));
2241
const BlkPrevInfo t_BlkPrevInfo_0{0};
2243
bool McStateExtra::skip(vm::CellSlice& cs) const {
2244
return block::gen::t_McStateExtra.skip(cs);
2247
bool McStateExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2248
return block::gen::t_McStateExtra.validate_skip(ops, cs, weak);
2251
const McStateExtra t_McStateExtra;
2253
const KeyExtBlkRef t_KeyExtBlkRef;
2255
bool KeyMaxLt::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
2257
unsigned long long lt1, lt2;
2258
return cs1.fetch_bool_to(key1) && cs1.fetch_ulong_bool(64, lt1)
2259
&& cs2.fetch_bool_to(key2) && cs2.fetch_ulong_bool(64, lt2)
2260
&& cb.store_bool_bool(key1 | key2) && cb.store_long_bool(std::max(lt1, lt2), 64);
2263
const KeyMaxLt t_KeyMaxLt;
2265
bool Aug_OldMcBlocksInfo::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
2266
return cs.have(65) && cb.append_bitslice(cs.prefetch_bits(65));
2269
const Aug_OldMcBlocksInfo aug_OldMcBlocksInfo;
2271
bool ShardFeeCreated::skip(vm::CellSlice& cs) const {
2272
return t_CurrencyCollection.skip(cs) && t_CurrencyCollection.skip(cs);
2275
bool ShardFeeCreated::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
2276
return t_CurrencyCollection.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
2279
bool ShardFeeCreated::null_value(vm::CellBuilder& cb) const {
2280
return t_CurrencyCollection.null_value(cb) && t_CurrencyCollection.null_value(cb);
2283
bool ShardFeeCreated::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
2284
return t_CurrencyCollection.add_values(cb, cs1, cs2) && t_CurrencyCollection.add_values(cb, cs1, cs2);
2287
const ShardFeeCreated t_ShardFeeCreated;
2289
bool Aug_ShardFees::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
2290
return cb.append_cellslice_bool(cs) && t_ShardFeeCreated.skip(cs) && cs.empty_ext();
2293
const Aug_ShardFees aug_ShardFees;
2295
bool validate_message_libs(const td::Ref<vm::Cell> &cell) {
2296
gen::Message::Record rec;
2297
if (!type_unpack_cell(cell, gen::t_Message_Any, rec)) {
2300
vm::CellSlice& state_init = rec.init.write();
2301
if (!state_init.fetch_long(1)) {
2304
if (state_init.fetch_long(1)) {
2305
return gen::t_StateInitWithLibs.validate_ref(state_init.prefetch_ref());
2307
return gen::t_StateInitWithLibs.validate_csr(rec.init);
2311
bool validate_message_relaxed_libs(const td::Ref<vm::Cell> &cell) {
2312
gen::MessageRelaxed::Record rec;
2313
if (!type_unpack_cell(cell, gen::t_MessageRelaxed_Any, rec)) {
2316
vm::CellSlice& state_init = rec.init.write();
2317
if (!state_init.fetch_long(1)) {
2320
if (state_init.fetch_long(1)) {
2321
return gen::t_StateInitWithLibs.validate_ref(state_init.prefetch_ref());
2323
return gen::t_StateInitWithLibs.validate_csr(rec.init);