diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbb858e1..a005e915 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -519,7 +519,7 @@ if (NOT TON_ONLY_TONLIB)
add_test(test-adnl test-adnl)
add_test(test-dht test-dht)
add_test(test-rldp test-rldp)
-add_test(test-validator-session-state test-validator-session-state)
+#add_test(test-validator-session-state test-validator-session-state)
add_test(test-catchain test-catchain)
add_test(test-fec test-fec)
diff --git a/common/int-to-string.hpp b/common/int-to-string.hpp
index 414342cd..88aecc65 100644
--- a/common/int-to-string.hpp
+++ b/common/int-to-string.hpp
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2017-2020 Telegram Systems LLP
+*/
#pragma once
#include "td/utils/int_types.h"
diff --git a/crypto/block/block-parse.cpp b/crypto/block/block-parse.cpp
index ae1df343..a0322366 100644
--- a/crypto/block/block-parse.cpp
+++ b/crypto/block/block-parse.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/bits.h"
#include "block/block-parse.h"
@@ -80,7 +80,7 @@ bool Maybe_Anycast::skip_get_depth(vm::CellSlice& cs, int& depth) const {
const Maybe_Anycast t_Maybe_Anycast;
-bool MsgAddressInt::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool MsgAddressInt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (!cs.have(3)) {
return false;
}
@@ -265,14 +265,14 @@ Ref MsgAddressInt::pack_std_address(ton::WorkchainId workchain, c
const MsgAddressInt t_MsgAddressInt;
-bool MsgAddress::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool MsgAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case addr_none:
case addr_ext:
- return t_MsgAddressExt.validate_skip(cs, weak);
+ return t_MsgAddressExt.validate_skip(ops, cs, weak);
case addr_std:
case addr_var:
- return t_MsgAddressInt.validate_skip(cs, weak);
+ return t_MsgAddressInt.validate_skip(ops, cs, weak);
}
return false;
}
@@ -284,7 +284,7 @@ bool VarUInteger::skip(vm::CellSlice& cs) const {
return len >= 0 && len < n && cs.advance(len * 8);
}
-bool VarUInteger::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool VarUInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len >= 0 && len < n && (!len || cs.prefetch_ulong(8)) && cs.advance(len * 8);
}
@@ -325,7 +325,7 @@ bool VarUIntegerPos::skip(vm::CellSlice& cs) const {
return len > 0 && len < n && cs.advance(len * 8);
}
-bool VarUIntegerPos::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool VarUIntegerPos::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len > 0 && len < n && cs.prefetch_ulong(8) && cs.advance(len * 8);
}
@@ -360,7 +360,7 @@ bool VarInteger::skip(vm::CellSlice& cs) const {
return len >= 0 && len < n && cs.advance(len * 8);
}
-bool VarInteger::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool VarInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len >= 0 && len < n && (!len || !redundant_int(cs)) && cs.advance(len * 8);
}
@@ -386,7 +386,7 @@ bool VarIntegerNz::skip(vm::CellSlice& cs) const {
return len > 0 && len < n && cs.advance(len * 8);
}
-bool VarIntegerNz::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool VarIntegerNz::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len > 0 && len < n && !redundant_int(cs) && cs.advance(len * 8);
}
@@ -409,8 +409,8 @@ bool VarIntegerNz::store_integer_value(vm::CellBuilder& cb, const td::BigInt256&
cb.store_int256_bool(value, (k + 7) & -8, true);
}
-bool Grams::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_VarUInteger_16.validate_skip(cs, weak);
+bool Grams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_VarUInteger_16.validate_skip(ops, cs, weak);
}
td::RefInt256 Grams::as_integer_skip(vm::CellSlice& cs) const {
@@ -464,15 +464,15 @@ bool HashmapNode::skip(vm::CellSlice& cs) const {
return n ? cs.advance_refs(2) : value_type.skip(cs);
}
-bool HashmapNode::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool HashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
assert(n >= 0);
if (!n) {
// hmn_leaf
- return value_type.validate_skip(cs, weak);
+ return value_type.validate_skip(ops, cs, weak);
} else {
// hmn_fork
Hashmap branch_type{n - 1, value_type};
- return branch_type.validate_ref(cs.fetch_ref(), weak) && branch_type.validate_ref(cs.fetch_ref(), weak);
+ return branch_type.validate_ref(ops, cs.fetch_ref(), weak) && branch_type.validate_ref(ops, cs.fetch_ref(), weak);
}
}
@@ -481,9 +481,9 @@ bool Hashmap::skip(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && HashmapNode{n - l, value_type}.skip(cs);
}
-bool Hashmap::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool Hashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int l;
- return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(cs, weak);
+ return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(ops, cs, weak);
}
int HashmapE::get_size(const vm::CellSlice& cs) const {
@@ -491,9 +491,9 @@ int HashmapE::get_size(const vm::CellSlice& cs) const {
return (tag >= 0 ? (tag > 0 ? 0x10001 : 1) : -1);
}
-bool HashmapE::validate(const vm::CellSlice& cs, bool weak) const {
+bool HashmapE::validate(int* ops, const vm::CellSlice& cs, bool weak) const {
int tag = get_tag(cs);
- return tag <= 0 ? !tag : root_type.validate_ref(cs.prefetch_ref(), weak);
+ return tag <= 0 ? !tag : root_type.validate_ref(ops, cs.prefetch_ref(), weak);
}
bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
@@ -583,8 +583,8 @@ bool HashmapE::store_ref(vm::CellBuilder& cb, Ref arg) const {
const ExtraCurrencyCollection t_ExtraCurrencyCollection;
-bool CurrencyCollection::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_Grams.validate_skip(cs, weak) && t_ExtraCurrencyCollection.validate_skip(cs, weak);
+bool CurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_Grams.validate_skip(ops, cs, weak) && t_ExtraCurrencyCollection.validate_skip(ops, cs, weak);
}
bool CurrencyCollection::skip(vm::CellSlice& cs) const {
@@ -641,25 +641,25 @@ bool CurrencyCollection::pack(vm::CellBuilder& cb, const block::CurrencyCollecti
const CurrencyCollection t_CurrencyCollection;
-bool CommonMsgInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool CommonMsgInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int tag = get_tag(cs);
switch (tag) {
case int_msg_info:
- return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
- && t_MsgAddressInt.validate_skip(cs, weak) // src
- && t_MsgAddressInt.validate_skip(cs, weak) // dest
- && t_CurrencyCollection.validate_skip(cs, weak) // value
- && t_Grams.validate_skip(cs, weak) // ihr_fee
- && t_Grams.validate_skip(cs, weak) // fwd_fee
- && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
+ return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
+ && t_MsgAddressInt.validate_skip(ops, cs, weak) // src
+ && t_MsgAddressInt.validate_skip(ops, cs, weak) // dest
+ && t_CurrencyCollection.validate_skip(ops, cs, weak) // value
+ && t_Grams.validate_skip(ops, cs, weak) // ihr_fee
+ && t_Grams.validate_skip(ops, cs, weak) // fwd_fee
+ && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
case ext_in_msg_info:
- return cs.advance(2) && t_MsgAddressExt.validate_skip(cs, weak) // src
- && t_MsgAddressInt.validate_skip(cs, weak) // dest
- && t_Grams.validate_skip(cs, weak); // import_fee
+ return cs.advance(2) && t_MsgAddressExt.validate_skip(ops, cs, weak) // src
+ && t_MsgAddressInt.validate_skip(ops, cs, weak) // dest
+ && t_Grams.validate_skip(ops, cs, weak); // import_fee
case ext_out_msg_info:
- return cs.advance(2) && t_MsgAddressInt.validate_skip(cs, weak) // src
- && t_MsgAddressExt.validate_skip(cs, weak) // dest
- && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
+ return cs.advance(2) && t_MsgAddressInt.validate_skip(ops, cs, weak) // src
+ && t_MsgAddressExt.validate_skip(ops, cs, weak) // dest
+ && cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
}
return false;
}
@@ -721,28 +721,29 @@ const CommonMsgInfo t_CommonMsgInfo;
const TickTock t_TickTock;
const RefAnything t_RefCell;
-bool StateInit::validate_skip(vm::CellSlice& cs, bool weak) const {
- return Maybe{5}.validate_skip(cs, weak) // split_depth:(Maybe (## 5))
- && Maybe{}.validate_skip(cs, weak) // special:(Maybe TickTock)
- && Maybe{}.validate_skip(cs, weak) // code:(Maybe ^Cell)
- && Maybe{}.validate_skip(cs, weak) // data:(Maybe ^Cell)
- && Maybe{}.validate_skip(cs, weak); // library:(Maybe ^Cell)
+bool StateInit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return Maybe{5}.validate_skip(ops, cs, weak) // split_depth:(Maybe (## 5))
+ && Maybe{}.validate_skip(ops, cs, weak) // special:(Maybe TickTock)
+ && Maybe{}.validate_skip(ops, cs, weak) // code:(Maybe ^Cell)
+ && Maybe{}.validate_skip(ops, cs, weak) // data:(Maybe ^Cell)
+ && Maybe{}.validate_skip(ops, cs, weak); // library:(Maybe ^Cell)
}
bool StateInit::get_ticktock(vm::CellSlice& cs, int& ticktock) const {
bool have_tt;
ticktock = 0;
- return Maybe{5}.validate_skip(cs) && cs.fetch_bool_to(have_tt) && (!have_tt || cs.fetch_uint_to(2, ticktock));
+ return Maybe{5}.validate_skip_upto(1, cs) && cs.fetch_bool_to(have_tt) &&
+ (!have_tt || cs.fetch_uint_to(2, ticktock));
}
const StateInit t_StateInit;
-bool Message::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool Message::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
static const Maybe>> init_type;
static const Either body_type;
- return t_CommonMsgInfo.validate_skip(cs, weak) // info:CommonMsgInfo
- && init_type.validate_skip(cs, weak) // init:(Maybe (Either StateInit ^StateInit))
- && body_type.validate_skip(cs, weak); // body:(Either X ^X)
+ return t_CommonMsgInfo.validate_skip(ops, cs, weak) // info:CommonMsgInfo
+ && init_type.validate_skip(ops, cs, weak) // init:(Maybe (Either StateInit ^StateInit))
+ && body_type.validate_skip(ops, cs, weak); // body:(Either X ^X)
}
bool Message::extract_info(vm::CellSlice& cs) const {
@@ -760,7 +761,7 @@ bool Message::is_internal(Ref ref) const {
const Message t_Message;
const RefTo t_Ref_Message;
-bool IntermediateAddress::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool IntermediateAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case interm_addr_regular:
return cs.advance(1) && cs.fetch_ulong(7) <= 96U;
@@ -795,12 +796,12 @@ int IntermediateAddress::get_size(const vm::CellSlice& cs) const {
const IntermediateAddress t_IntermediateAddress;
-bool MsgEnvelope::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.fetch_ulong(4) == 4 // msg_envelope#4
- && t_IntermediateAddress.validate_skip(cs, weak) // cur_addr:IntermediateAddress
- && t_IntermediateAddress.validate_skip(cs, weak) // next_addr:IntermediateAddress
- && t_Grams.validate_skip(cs, weak) // fwd_fee_remaining:Grams
- && t_Ref_Message.validate_skip(cs, weak); // msg:^Message
+bool MsgEnvelope::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.fetch_ulong(4) == 4 // msg_envelope#4
+ && t_IntermediateAddress.validate_skip(ops, cs, weak) // cur_addr:IntermediateAddress
+ && t_IntermediateAddress.validate_skip(ops, cs, weak) // next_addr:IntermediateAddress
+ && t_Grams.validate_skip(ops, cs, weak) // fwd_fee_remaining:Grams
+ && t_Ref_Message.validate_skip(ops, cs, weak); // msg:^Message
}
bool MsgEnvelope::skip(vm::CellSlice& cs) const {
@@ -849,10 +850,10 @@ bool MsgEnvelope::get_created_lt(const vm::CellSlice& cs, unsigned long long& cr
const MsgEnvelope t_MsgEnvelope;
const RefTo t_Ref_MsgEnvelope;
-bool StorageUsed::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_VarUInteger_7.validate_skip(cs, weak) // cells:(VarUInteger 7)
- && t_VarUInteger_7.validate_skip(cs, weak) // bits:(VarUInteger 7)
- && t_VarUInteger_7.validate_skip(cs, weak); // public_cells:(VarUInteger 7)
+bool StorageUsed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7)
+ && t_VarUInteger_7.validate_skip(ops, cs, weak) // bits:(VarUInteger 7)
+ && t_VarUInteger_7.validate_skip(ops, cs, weak); // public_cells:(VarUInteger 7)
}
bool StorageUsed::skip(vm::CellSlice& cs) const {
@@ -863,9 +864,9 @@ bool StorageUsed::skip(vm::CellSlice& cs) const {
const StorageUsed t_StorageUsed;
-bool StorageUsedShort::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_VarUInteger_7.validate_skip(cs, weak) // cells:(VarUInteger 7)
- && t_VarUInteger_7.validate_skip(cs, weak); // bits:(VarUInteger 7)
+bool StorageUsedShort::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7)
+ && t_VarUInteger_7.validate_skip(ops, cs, weak); // bits:(VarUInteger 7)
}
bool StorageUsedShort::skip(vm::CellSlice& cs) const {
@@ -883,22 +884,22 @@ bool StorageInfo::skip(vm::CellSlice& cs) const {
&& t_Maybe_Grams.skip(cs); // due_payment:(Maybe Grams)
}
-bool StorageInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_StorageUsed.validate_skip(cs, weak) // used:StorageUsed
- && cs.advance(32) // last_paid:uint32
- && t_Maybe_Grams.validate_skip(cs, weak); // due_payment:(Maybe Grams)
+bool StorageInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_StorageUsed.validate_skip(ops, cs, weak) // used:StorageUsed
+ && cs.advance(32) // last_paid:uint32
+ && t_Maybe_Grams.validate_skip(ops, cs, weak); // due_payment:(Maybe Grams)
}
const StorageInfo t_StorageInfo;
-bool AccountState::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool AccountState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case account_uninit:
return cs.advance(2);
case account_frozen:
return cs.advance(2 + 256);
case account_active:
- return cs.advance(1) && t_StateInit.validate_skip(cs, weak);
+ return cs.advance(1) && t_StateInit.validate_skip(ops, cs, weak);
}
return false;
}
@@ -921,8 +922,9 @@ bool AccountStorage::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) c
return cs.advance(64) && t_CurrencyCollection.skip_copy(cb, cs) && t_AccountState.skip(cs);
}
-bool AccountStorage::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.advance(64) && t_CurrencyCollection.validate_skip(cs, weak) && t_AccountState.validate_skip(cs, weak);
+bool AccountStorage::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.advance(64) && t_CurrencyCollection.validate_skip(ops, cs, weak) &&
+ t_AccountState.validate_skip(ops, cs, weak);
}
const AccountStorage t_AccountStorage;
@@ -940,15 +942,15 @@ bool Account::skip(vm::CellSlice& cs) const {
return false;
}
-bool Account::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool Account::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case account_none:
return allow_empty && cs.advance(1);
case account:
- return cs.advance(1) // account$1
- && t_MsgAddressInt.validate_skip(cs, weak) // addr:MsgAddressInt
- && t_StorageInfo.validate_skip(cs, weak) // storage_stat:StorageInfo
- && t_AccountStorage.validate_skip(cs, weak); // storage:AccountStorage
+ return cs.advance(1) // account$1
+ && t_MsgAddressInt.validate_skip(ops, cs, weak) // addr:MsgAddressInt
+ && t_StorageInfo.validate_skip(ops, cs, weak) // storage_stat:StorageInfo
+ && t_AccountStorage.validate_skip(ops, cs, weak); // storage:AccountStorage
}
return false;
}
@@ -1032,19 +1034,19 @@ bool HashmapAugNode::skip(vm::CellSlice& cs) const {
}
}
-bool HashmapAugNode::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool HashmapAugNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (n < 0) {
return false;
}
if (!n) {
// ahmn_leaf
vm::CellSlice cs_extra{cs};
- if (!aug.extra_type.validate_skip(cs, weak)) {
+ if (!aug.extra_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_extra.cut_tail(cs);
vm::CellSlice cs_value{cs};
- if (!aug.value_type.validate_skip(cs, weak)) {
+ if (!aug.value_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_value.cut_tail(cs);
@@ -1055,13 +1057,14 @@ bool HashmapAugNode::validate_skip(vm::CellSlice& cs, bool weak) const {
return false;
}
HashmapAug branch_type{n - 1, aug};
- if (!branch_type.validate_ref(cs.prefetch_ref(0), weak) || !branch_type.validate_ref(cs.prefetch_ref(1), weak)) {
+ if (!branch_type.validate_ref(ops, cs.prefetch_ref(0), weak) ||
+ !branch_type.validate_ref(ops, cs.prefetch_ref(1), weak)) {
return false;
}
auto cs_left = load_cell_slice(cs.fetch_ref());
auto cs_right = load_cell_slice(cs.fetch_ref());
vm::CellSlice cs_extra{cs};
- if (!aug.extra_type.validate_skip(cs, weak)) {
+ if (!aug.extra_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_extra.cut_tail(cs);
@@ -1074,9 +1077,9 @@ bool HashmapAug::skip(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && HashmapAugNode{n - l, aug}.skip(cs);
}
-bool HashmapAug::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool HashmapAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int l;
- return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(cs, weak);
+ return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(ops, cs, weak);
}
bool HashmapAug::extract_extra(vm::CellSlice& cs) const {
@@ -1084,20 +1087,20 @@ bool HashmapAug::extract_extra(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && (l == n || cs.advance_refs(2)) && aug.extra_type.extract(cs);
}
-bool HashmapAugE::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool HashmapAugE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
Ref extra;
switch (get_tag(cs)) {
case ahme_empty:
- return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(cs, weak)).not_null() &&
+ return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
root_type.aug.check_empty(extra.unique_write());
case ahme_root:
- if (cs.advance(1) && root_type.validate_ref(cs.prefetch_ref(), weak)) {
+ if (cs.advance(1) && root_type.validate_ref(ops, cs.prefetch_ref(), weak)) {
bool special;
auto cs_root = load_cell_slice_special(cs.fetch_ref(), special);
if (special) {
return weak;
}
- return (extra = root_type.aug.extra_type.validate_fetch(cs, weak)).not_null() &&
+ return (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
root_type.extract_extra(cs_root) && extra->contents_equal(cs_root);
}
break;
@@ -1121,9 +1124,10 @@ bool DepthBalanceInfo::skip(vm::CellSlice& cs) const {
cs); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection = DepthBalanceInfo;
}
-bool DepthBalanceInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.fetch_ulong(5) <= 30 && t_CurrencyCollection.validate_skip(
- cs, weak); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection
+bool DepthBalanceInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.fetch_ulong(5) <= 30 &&
+ t_CurrencyCollection.validate_skip(ops, cs,
+ weak); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection
}
bool DepthBalanceInfo::null_value(vm::CellBuilder& cb) const {
@@ -1159,10 +1163,10 @@ bool TrStoragePhase::skip(vm::CellSlice& cs) const {
&& t_AccStatusChange.skip(cs); // status_change:AccStatusChange
}
-bool TrStoragePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_Grams.validate_skip(cs, weak) // storage_fees_collected:Grams
- && t_Maybe_Grams.validate_skip(cs, weak) // storage_fees_due:Grams
- && t_AccStatusChange.validate_skip(cs, weak); // status_change:AccStatusChange
+bool TrStoragePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_Grams.validate_skip(ops, cs, weak) // storage_fees_collected:Grams
+ && t_Maybe_Grams.validate_skip(ops, cs, weak) // storage_fees_due:Grams
+ && t_AccStatusChange.validate_skip(ops, cs, weak); // status_change:AccStatusChange
}
bool TrStoragePhase::get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
@@ -1186,9 +1190,9 @@ bool TrCreditPhase::skip(vm::CellSlice& cs) const {
&& t_CurrencyCollection.skip(cs); // credit:CurrencyCollection
}
-bool TrCreditPhase::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_Maybe_Grams.validate_skip(cs, weak) // due_fees_collected:(Maybe Grams)
- && t_CurrencyCollection.validate_skip(cs, weak); // credit:CurrencyCollection
+bool TrCreditPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_Maybe_Grams.validate_skip(ops, cs, weak) // due_fees_collected:(Maybe Grams)
+ && t_CurrencyCollection.validate_skip(ops, cs, weak); // credit:CurrencyCollection
}
const TrCreditPhase t_TrCreditPhase;
@@ -1204,15 +1208,15 @@ bool TrComputeInternal1::skip(vm::CellSlice& cs) const {
// vm_final_state_hash:uint256
}
-bool TrComputeInternal1::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_VarUInteger_7.validate_skip(cs, weak) // gas_used:(VarUInteger 7)
- && t_VarUInteger_7.validate_skip(cs, weak) // gas_limit:(VarUInteger 7)
- && Maybe{3}.validate_skip(cs, weak) // gas_credit:(Maybe (VarUInteger 3))
- && cs.advance(8 + 32) // mode:int8 exit_code:int32
- && Maybe{32}.validate_skip(cs, weak) // exit_arg:(Maybe int32)
- && cs.advance(32 + 256 + 256); // vm_steps:uint32
- // vm_init_state_hash:uint256
- // vm_final_state_hash:uint256
+bool TrComputeInternal1::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_used:(VarUInteger 7)
+ && t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_limit:(VarUInteger 7)
+ && Maybe{3}.validate_skip(ops, cs, weak) // gas_credit:(Maybe (VarUInteger 3))
+ && cs.advance(8 + 32) // mode:int8 exit_code:int32
+ && Maybe{32}.validate_skip(ops, cs, weak) // exit_arg:(Maybe int32)
+ && cs.advance(32 + 256 + 256); // vm_steps:uint32
+ // vm_init_state_hash:uint256
+ // vm_final_state_hash:uint256
}
const TrComputeInternal1 t_TrComputeInternal1;
@@ -1231,14 +1235,14 @@ bool TrComputePhase::skip(vm::CellSlice& cs) const {
return false;
}
-bool TrComputePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool TrComputePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case tr_phase_compute_skipped:
- return cs.advance(1) && t_ComputeSkipReason.validate_skip(cs, weak);
+ return cs.advance(1) && t_ComputeSkipReason.validate_skip(ops, cs, weak);
case tr_phase_compute_vm:
return cs.advance(1 + 3) // tr_phase_compute_vm$1 success:Bool msg_state_used:Bool account_activated:Bool
- && t_Grams.validate_skip(cs, weak) // gas_fees:Grams
- && t_Ref_TrComputeInternal1.validate_skip(cs, weak); // ^[ gas_used:(..) .. ]
+ && t_Grams.validate_skip(ops, cs, weak) // gas_fees:Grams
+ && t_Ref_TrComputeInternal1.validate_skip(ops, cs, weak); // ^[ gas_used:(..) .. ]
}
return false;
}
@@ -1258,17 +1262,17 @@ bool TrActionPhase::skip(vm::CellSlice& cs) const {
&& t_StorageUsedShort.skip(cs); // tot_msg_size:StorageUsedShort
}
-bool TrActionPhase::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.advance(3) // success:Bool valid:Bool no_funds:Bool
- && t_AccStatusChange.validate_skip(cs, weak) // status_change:AccStatusChange
- && t_Maybe_Grams.validate_skip(cs, weak) // total_fwd_fees:(Maybe Grams)
- && t_Maybe_Grams.validate_skip(cs, weak) // total_action_fees:(Maybe Grams)
- && cs.advance(32) // result_code:int32
- && Maybe{32}.validate_skip(cs, weak) // result_arg:(Maybe int32)
- && cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16
- // skipped_actions:uint16 msgs_created:uint16
- // action_list_hash:uint256
- && t_StorageUsedShort.validate_skip(cs, weak); // tot_msg_size:StorageUsed
+bool TrActionPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.advance(3) // success:Bool valid:Bool no_funds:Bool
+ && t_AccStatusChange.validate_skip(ops, cs, weak) // status_change:AccStatusChange
+ && t_Maybe_Grams.validate_skip(ops, cs, weak) // total_fwd_fees:(Maybe Grams)
+ && t_Maybe_Grams.validate_skip(ops, cs, weak) // total_action_fees:(Maybe Grams)
+ && cs.advance(32) // result_code:int32
+ && Maybe{32}.validate_skip(ops, cs, weak) // result_arg:(Maybe int32)
+ && cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16
+ // skipped_actions:uint16 msgs_created:uint16
+ // action_list_hash:uint256
+ && t_StorageUsedShort.validate_skip(ops, cs, weak); // tot_msg_size:StorageUsed
}
const TrActionPhase t_TrActionPhase;
@@ -1290,19 +1294,19 @@ bool TrBouncePhase::skip(vm::CellSlice& cs) const {
return false;
}
-bool TrBouncePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool TrBouncePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case tr_phase_bounce_negfunds:
return cs.advance(2); // tr_phase_bounce_negfunds$00
case tr_phase_bounce_nofunds:
- return cs.advance(2) // tr_phase_bounce_nofunds$01
- && t_StorageUsedShort.validate_skip(cs, weak) // msg_size:StorageUsedShort
- && t_Grams.validate_skip(cs, weak); // req_fwd_fees:Grams
+ return cs.advance(2) // tr_phase_bounce_nofunds$01
+ && t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort
+ && t_Grams.validate_skip(ops, cs, weak); // req_fwd_fees:Grams
case tr_phase_bounce_ok:
- return cs.advance(1) // tr_phase_bounce_ok$1
- && t_StorageUsedShort.validate_skip(cs, weak) // msg_size:StorageUsedShort
- && t_Grams.validate_skip(cs, weak) // msg_fees:Grams
- && t_Grams.validate_skip(cs, weak); // fwd_fees:Grams
+ return cs.advance(1) // tr_phase_bounce_ok$1
+ && t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort
+ && t_Grams.validate_skip(ops, cs, weak) // msg_fees:Grams
+ && t_Grams.validate_skip(ops, cs, weak); // fwd_fees:Grams
}
return false;
}
@@ -1322,7 +1326,7 @@ bool SplitMergeInfo::skip(vm::CellSlice& cs) const {
return cs.advance(6 + 6 + 256 + 256);
}
-bool SplitMergeInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool SplitMergeInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (!cs.have(6 + 6 + 256 + 256)) {
return false;
}
@@ -1392,52 +1396,52 @@ bool TransactionDescr::skip(vm::CellSlice& cs) const {
return false;
}
-bool TransactionDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool TransactionDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case trans_ord:
- return cs.advance(4 + 1) // trans_ord$0000 credit_first:Bool
- && Maybe{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
- && Maybe{}.validate_skip(cs, weak) // credit_ph:(Maybe TrCreditPhase)
- && t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
- && Maybe>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
- && cs.advance(1) // aborted:Bool
- && Maybe{}.validate_skip(cs, weak) // bounce:(Maybe TrBouncePhase)
- && cs.advance(1); // destroyed:Bool
+ return cs.advance(4 + 1) // trans_ord$0000 credit_first:Bool
+ && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
+ && Maybe{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase)
+ && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
+ && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
+ && cs.advance(1) // aborted:Bool
+ && Maybe{}.validate_skip(ops, cs, weak) // bounce:(Maybe TrBouncePhase)
+ && cs.advance(1); // destroyed:Bool
case trans_storage:
- return cs.advance(4) // trans_storage$0001
- && t_TrStoragePhase.validate_skip(cs, weak); // storage_ph:TrStoragePhase
+ return cs.advance(4) // trans_storage$0001
+ && t_TrStoragePhase.validate_skip(ops, cs, weak); // storage_ph:TrStoragePhase
case trans_tick_tock:
- return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
- && t_TrStoragePhase.validate_skip(cs, weak) // storage_ph:TrStoragePhase
- && t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
- && Maybe>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
- && cs.advance(2); // aborted:Bool destroyed:Bool
+ return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
+ && t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase
+ && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
+ && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
+ && cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_prepare:
- return cs.advance(4) // trans_split_prepare$0100
- && t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
- && Maybe{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
- && t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
- && Maybe>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
- && cs.advance(2); // aborted:Bool destroyed:Bool
+ return cs.advance(4) // trans_split_prepare$0100
+ && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
+ && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
+ && t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
+ && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
+ && cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_install:
- return cs.advance(4) // trans_split_install$0101
- && t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
- && t_Ref_Transaction.validate_skip(cs, weak) // prepare_transaction:^Transaction
- && cs.advance(1); // installed:Bool
+ return cs.advance(4) // trans_split_install$0101
+ && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction
+ && cs.advance(1); // installed:Bool
case trans_merge_prepare:
- return cs.advance(4) // trans_merge_prepare$0110
- && t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
- && t_TrStoragePhase.validate_skip(cs, weak) // storage_ph:TrStoragePhase
- && cs.advance(1); // aborted:Bool
+ return cs.advance(4) // trans_merge_prepare$0110
+ && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
+ && t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase
+ && cs.advance(1); // aborted:Bool
case trans_merge_install:
- return cs.advance(4) // trans_merge_install$0111
- && t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
- && t_Ref_Transaction.validate_skip(cs, weak) // prepare_transaction:^Transaction
- && Maybe{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
- && Maybe{}.validate_skip(cs, weak) // credit_ph:(Maybe TrCreditPhase)
- && Maybe{}.validate_skip(cs, weak) // compute_ph:TrComputePhase
- && Maybe>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
- && cs.advance(2); // aborted:Bool destroyed:Bool
+ return cs.advance(4) // trans_merge_install$0111
+ && t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction
+ && Maybe{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
+ && Maybe{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase)
+ && Maybe{}.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
+ && Maybe>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
+ && cs.advance(2); // aborted:Bool destroyed:Bool
}
return false;
}
@@ -1501,9 +1505,9 @@ bool Transaction_aux::skip(vm::CellSlice& cs) const {
&& HashmapE{15, t_Ref_Message}.skip(cs); // out_msgs:(HashmapE 15 ^Message)
}
-bool Transaction_aux::validate_skip(vm::CellSlice& cs, bool weak) const {
- return Maybe>{}.validate_skip(cs, weak) // in_msg:(Maybe ^Message)
- && HashmapE{15, t_Ref_Message}.validate_skip(cs, weak); // out_msgs:(HashmapE 15 ^Message)
+bool Transaction_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return Maybe>{}.validate_skip(ops, cs, weak) // in_msg:(Maybe ^Message)
+ && HashmapE{15, t_Ref_Message}.validate_skip(ops, cs, weak); // out_msgs:(HashmapE 15 ^Message)
}
const Transaction_aux t_Transaction_aux;
@@ -1520,18 +1524,18 @@ bool Transaction::skip(vm::CellSlice& cs) const {
&& RefTo{}.skip(cs); // description:^TransactionDescr
}
-bool Transaction::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool Transaction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 7 // transaction$0111
&&
cs.advance(
256 + 64 + 256 + 64 + 32 +
15) // account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15
- && t_AccountStatus.validate_skip(cs, weak) // orig_status:AccountStatus
- && t_AccountStatus.validate_skip(cs, weak) // end_status:AccountStatus
- && RefTo{}.validate_skip(cs, weak) // ^[ in_msg:... out_msgs:... ]
- && t_CurrencyCollection.validate_skip(cs, weak) // total_fees:CurrencyCollection
- && t_Ref_HashUpdate.validate_skip(cs, weak) // state_update:^(HASH_UPDATE Account)
- && RefTo{}.validate_skip(cs, weak); // description:^TransactionDescr
+ && t_AccountStatus.validate_skip(ops, cs, weak) // orig_status:AccountStatus
+ && t_AccountStatus.validate_skip(ops, cs, weak) // end_status:AccountStatus
+ && RefTo{}.validate_skip(ops, cs, weak) // ^[ in_msg:... out_msgs:... ]
+ && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_fees:CurrencyCollection
+ && t_Ref_HashUpdate.validate_skip(ops, cs, weak) // state_update:^(HASH_UPDATE Account)
+ && RefTo{}.validate_skip(ops, cs, weak); // description:^TransactionDescr
}
bool Transaction::get_storage_fees(Ref cell, td::RefInt256& storage_fees) const {
@@ -1595,12 +1599,12 @@ bool AccountBlock::skip(vm::CellSlice& cs) const {
&& cs.advance_refs(1); // state_update:^(HASH_UPDATE Account)
}
-bool AccountBlock::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool AccountBlock::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 5 // acc_trans#5
&& cs.advance(256) // account_addr:bits256
- &&
- t_AccountTransactions.validate_skip(cs, weak) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection)
- && t_Ref_HashUpdate.validate_skip(cs, weak); // state_update:^(HASH_UPDATE Account)
+ && t_AccountTransactions.validate_skip(ops, cs,
+ weak) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection)
+ && t_Ref_HashUpdate.validate_skip(ops, cs, weak); // state_update:^(HASH_UPDATE Account)
}
bool AccountBlock::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const {
@@ -1620,8 +1624,8 @@ const Aug_ShardAccountBlocks aug_ShardAccountBlocks;
const HashmapAugE t_ShardAccountBlocks{256,
aug_ShardAccountBlocks}; // (HashmapAugE 256 AccountBlock CurrencyCollection)
-bool ImportFees::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_Grams.validate_skip(cs, weak) && t_CurrencyCollection.validate_skip(cs, weak);
+bool ImportFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_Grams.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
}
bool ImportFees::skip(vm::CellSlice& cs) const {
@@ -1676,44 +1680,44 @@ bool InMsg::skip(vm::CellSlice& cs) const {
return false;
}
-bool InMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool InMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case msg_import_ext:
- return cs.advance(3) // msg_import_ext$000
- && t_Ref_Message.validate_skip(cs, weak) // msg:^Message
- && t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
+ return cs.advance(3) // msg_import_ext$000
+ && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
+ && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_import_ihr:
- return cs.advance(3) // msg_import_ihr$010
- && t_Ref_Message.validate_skip(cs, weak) // msg:^Message
- && t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
- && t_Grams.validate_skip(cs, weak) // ihr_fee:Grams
- && t_RefCell.validate_skip(cs, weak); // proof_created:^Cell
+ return cs.advance(3) // msg_import_ihr$010
+ && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
+ && t_Grams.validate_skip(ops, cs, weak) // ihr_fee:Grams
+ && t_RefCell.validate_skip(ops, cs, weak); // proof_created:^Cell
case msg_import_imm:
- return cs.advance(3) // msg_import_imm$011
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
- && t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
- && t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
+ return cs.advance(3) // msg_import_imm$011
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
+ && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_import_fin:
- return cs.advance(3) // msg_import_fin$100
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
- && t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
- && t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
+ return cs.advance(3) // msg_import_fin$100
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
+ && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_import_tr:
- return cs.advance(3) // msg_import_tr$101
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && t_Grams.validate_skip(cs, weak); // transit_fee:Grams
+ return cs.advance(3) // msg_import_tr$101
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && t_Grams.validate_skip(ops, cs, weak); // transit_fee:Grams
case msg_discard_fin:
- return cs.advance(3) // msg_discard_fin$110
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
- && cs.advance(64) // transaction_id:uint64
- && t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
+ return cs.advance(3) // msg_discard_fin$110
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
+ && cs.advance(64) // transaction_id:uint64
+ && t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_discard_tr:
- return cs.advance(3) // msg_discard_tr$111
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
- && cs.advance(64) // transaction_id:uint64
- && t_Grams.validate_skip(cs, weak) // fwd_fee:Grams
- && t_RefCell.validate_skip(cs, weak); // proof_delivered:^Cell
+ return cs.advance(3) // msg_discard_tr$111
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
+ && cs.advance(64) // transaction_id:uint64
+ && t_Grams.validate_skip(ops, cs, weak) // fwd_fee:Grams
+ && t_RefCell.validate_skip(ops, cs, weak); // proof_delivered:^Cell
}
return false;
}
@@ -1851,37 +1855,37 @@ bool OutMsg::skip(vm::CellSlice& cs) const {
return false;
}
-bool OutMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool OutMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case msg_export_ext:
- return cs.advance(3) // msg_export_ext$000
- && t_Ref_Message.validate_skip(cs, weak) // msg:^Message
- && t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
+ return cs.advance(3) // msg_export_ext$000
+ && t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
+ && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_export_imm:
- return cs.advance(3) // msg_export_imm$010
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
- && RefTo{}.validate_skip(cs, weak); // reimport:^InMsg
+ return cs.advance(3) // msg_export_imm$010
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
+ && RefTo{}.validate_skip(ops, cs, weak); // reimport:^InMsg
case msg_export_new:
- return cs.advance(3) // msg_export_new$001
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
+ return cs.advance(3) // msg_export_new$001
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_export_tr:
- return cs.advance(3) // msg_export_tr$011
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && RefTo{}.validate_skip(cs, weak); // imported:^InMsg
+ return cs.advance(3) // msg_export_tr$011
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && RefTo{}.validate_skip(ops, cs, weak); // imported:^InMsg
case msg_export_deq_imm:
- return cs.advance(3) // msg_export_deq_imm$100
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && RefTo{}.validate_skip(cs, weak); // reimport:^InMsg
+ return cs.advance(3) // msg_export_deq_imm$100
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && RefTo{}.validate_skip(ops, cs, weak); // reimport:^InMsg
case msg_export_deq:
- return cs.advance(3) // msg_export_deq$110
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && cs.advance(64); // import_block_lt:uint64
+ return cs.advance(3) // msg_export_deq$110
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && cs.advance(64); // import_block_lt:uint64
case msg_export_tr_req:
- return cs.advance(3) // msg_export_tr_req$111
- && t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
- && RefTo{}.validate_skip(cs, weak); // imported:^InMsg
+ return cs.advance(3) // msg_export_tr_req$111
+ && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
+ && RefTo{}.validate_skip(ops, cs, weak); // imported:^InMsg
}
return false;
}
@@ -1954,8 +1958,8 @@ const OutMsg t_OutMsg;
const Aug_OutMsgDescr aug_OutMsgDescr;
const OutMsgDescr t_OutMsgDescr;
-bool EnqueuedMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(cs, weak);
+bool EnqueuedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak);
}
const EnqueuedMsg t_EnqueuedMsg;
@@ -1989,9 +1993,9 @@ bool OutMsgQueueInfo::skip(vm::CellSlice& cs) const {
return t_OutMsgQueue.skip(cs) && t_ProcessedInfo.skip(cs) && t_IhrPendingInfo.skip(cs);
}
-bool OutMsgQueueInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_OutMsgQueue.validate_skip(cs, weak) && t_ProcessedInfo.validate_skip(cs, weak) &&
- t_IhrPendingInfo.validate_skip(cs, weak);
+bool OutMsgQueueInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_OutMsgQueue.validate_skip(ops, cs, weak) && t_ProcessedInfo.validate_skip(ops, cs, weak) &&
+ t_IhrPendingInfo.validate_skip(ops, cs, weak);
}
const OutMsgQueueInfo t_OutMsgQueueInfo;
@@ -2047,7 +2051,7 @@ bool ExtBlkRef::pack_to(Ref& cell, const ton::BlockIdExt& blkid, ton::
const ExtBlkRef t_ExtBlkRef;
const BlkMasterInfo t_BlkMasterInfo;
-bool ShardIdent::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool ShardIdent::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int shard_pfx_len, workchain_id;
unsigned long long shard_pfx;
if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, shard_pfx_len) && cs.fetch_int_to(32, workchain_id) &&
@@ -2112,8 +2116,8 @@ bool ShardIdent::pack(vm::CellBuilder& cb, ton::ShardIdFull data) const {
const ShardIdent t_ShardIdent;
-bool BlockIdExt::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_ShardIdent.validate_skip(cs, weak) && cs.advance(32 + 256 * 2);
+bool BlockIdExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_ShardIdent.validate_skip(ops, cs, weak) && cs.advance(32 + 256 * 2);
}
bool BlockIdExt::unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const {
@@ -2146,21 +2150,21 @@ bool ShardState::skip(vm::CellSlice& cs) const {
&& Maybe>{}.skip(cs); // custom:(Maybe ^McStateExtra)
}
-bool ShardState::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool ShardState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int seq_no;
return get_tag(cs) == shard_state && cs.advance(64) // shard_state#9023afe2 blockchain_id:int32
- && t_ShardIdent.validate_skip(cs, weak) // shard_id:ShardIdent
+ && t_ShardIdent.validate_skip(ops, cs, weak) // shard_id:ShardIdent
&& cs.fetch_int_to(32, seq_no) // seq_no:int32
&& seq_no >= -1 // { seq_no >= -1 }
&& cs.advance(32 + 32 + 64 + 32) // vert_seq_no:# gen_utime:uint32 gen_lt:uint64 min_ref_mc_seqno:uint32
- && t_Ref_OutMsgQueueInfo.validate_skip(cs, weak) // out_msg_queue_info:^OutMsgQueueInfo
- && cs.advance(1) // before_split:Bool
- && t_ShardAccounts.validate_skip_ref(cs, weak) // accounts:^ShardAccounts
+ && t_Ref_OutMsgQueueInfo.validate_skip(ops, cs, weak) // out_msg_queue_info:^OutMsgQueueInfo
+ && cs.advance(1) // before_split:Bool
+ && t_ShardAccounts.validate_skip_ref(ops, cs, weak) // accounts:^ShardAccounts
&&
t_ShardState_aux.validate_skip_ref(
- cs,
+ ops, cs,
weak) // ^[ total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ]
- && Maybe>{}.validate_skip(cs, weak); // custom:(Maybe ^McStateExtra)
+ && Maybe>{}.validate_skip(ops, cs, weak); // custom:(Maybe ^McStateExtra)
}
const ShardState t_ShardState;
@@ -2173,12 +2177,12 @@ bool ShardState_aux::skip(vm::CellSlice& cs) const {
&& Maybe{}.skip(cs); // master_ref:(Maybe BlkMasterInfo)
}
-bool ShardState_aux::validate_skip(vm::CellSlice& cs, bool weak) const {
- return cs.advance(128) // overload_history:uint64 underload_history:uint64
- && t_CurrencyCollection.validate_skip(cs, weak) // total_balance:CurrencyCollection
- && t_CurrencyCollection.validate_skip(cs, weak) // total_validator_fees:CurrencyCollection
- && HashmapE{256, t_LibDescr}.validate_skip(cs, weak) // libraries:(HashmapE 256 LibDescr)
- && Maybe{}.validate_skip(cs, weak); // master_ref:(Maybe BlkMasterInfo)
+bool ShardState_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return cs.advance(128) // overload_history:uint64 underload_history:uint64
+ && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_balance:CurrencyCollection
+ && t_CurrencyCollection.validate_skip(ops, cs, weak) // total_validator_fees:CurrencyCollection
+ && HashmapE{256, t_LibDescr}.validate_skip(ops, cs, weak) // libraries:(HashmapE 256 LibDescr)
+ && Maybe{}.validate_skip(ops, cs, weak); // master_ref:(Maybe BlkMasterInfo)
}
const ShardState_aux t_ShardState_aux;
@@ -2189,10 +2193,10 @@ bool LibDescr::skip(vm::CellSlice& cs) const {
&& Hashmap{256, t_True}.skip(cs); // publishers:(Hashmap 256 False)
}
-bool LibDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
- return get_tag(cs) == shared_lib_descr && cs.advance(2) // shared_lib_descr$00
- && cs.fetch_ref().not_null() // lib:^Cell
- && Hashmap{256, t_True}.validate_skip(cs, weak); // publishers:(Hashmap 256 False)
+bool LibDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return get_tag(cs) == shared_lib_descr && cs.advance(2) // shared_lib_descr$00
+ && cs.fetch_ref().not_null() // lib:^Cell
+ && Hashmap{256, t_True}.validate_skip(ops, cs, weak); // publishers:(Hashmap 256 False)
}
const LibDescr t_LibDescr;
@@ -2202,9 +2206,9 @@ bool BlkPrevInfo::skip(vm::CellSlice& cs) const {
&& (!merged || t_ExtBlkRef.skip(cs)); // prev_alt:merged?ExtBlkRef
}
-bool BlkPrevInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_ExtBlkRef.validate_skip(cs, weak) // prev_blk_info$_ {merged:#} prev:ExtBlkRef
- && (!merged || t_ExtBlkRef.validate_skip(cs, weak)); // prev_alt:merged?ExtBlkRef
+bool BlkPrevInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_ExtBlkRef.validate_skip(ops, cs, weak) // prev_blk_info$_ {merged:#} prev:ExtBlkRef
+ && (!merged || t_ExtBlkRef.validate_skip(ops, cs, weak)); // prev_alt:merged?ExtBlkRef
}
const BlkPrevInfo t_BlkPrevInfo_0{0};
@@ -2213,8 +2217,8 @@ bool McStateExtra::skip(vm::CellSlice& cs) const {
return block::gen::t_McStateExtra.skip(cs);
}
-bool McStateExtra::validate_skip(vm::CellSlice& cs, bool weak) const {
- return block::gen::t_McStateExtra.validate_skip(cs, weak); // ??
+bool McStateExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return block::gen::t_McStateExtra.validate_skip(ops, cs, weak); // ??
}
const McStateExtra t_McStateExtra;
@@ -2241,8 +2245,8 @@ bool ShardFeeCreated::skip(vm::CellSlice& cs) const {
return t_CurrencyCollection.skip(cs) && t_CurrencyCollection.skip(cs);
}
-bool ShardFeeCreated::validate_skip(vm::CellSlice& cs, bool weak) const {
- return t_CurrencyCollection.validate_skip(cs, weak) && t_CurrencyCollection.validate_skip(cs, weak);
+bool ShardFeeCreated::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
+ return t_CurrencyCollection.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
}
bool ShardFeeCreated::null_value(vm::CellBuilder& cb) const {
diff --git a/crypto/block/block-parse.h b/crypto/block/block-parse.h
index 8ea3325e..95906311 100644
--- a/crypto/block/block-parse.h
+++ b/crypto/block/block-parse.h
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
@@ -59,7 +59,7 @@ struct VarUInteger final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
unsigned long long as_uint(const vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
@@ -78,7 +78,7 @@ struct VarUIntegerPos final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
unsigned long long as_uint(const vm::CellSlice& cs) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
@@ -92,7 +92,7 @@ struct VarInteger final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
long long as_int(const vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
@@ -107,7 +107,7 @@ struct VarIntegerNz final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
long long as_int(const vm::CellSlice& cs) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
@@ -123,13 +123,13 @@ struct Unary final : TLB {
bool skip(vm::CellSlice& cs, int& n) const {
return validate_skip(cs, false, n);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return cs.advance(get_size(cs));
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return skip(cs);
}
bool skip(vm::CellSlice& cs) const override {
- return validate_skip(cs);
+ return cs.advance(get_size(cs));
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
return cs.have(get_size(cs));
}
};
@@ -149,7 +149,7 @@ struct HmLabel final : TLB_Complex {
int n;
return skip(cs, n);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
int n;
return validate_skip(cs, weak, n);
}
@@ -162,7 +162,7 @@ struct Hashmap final : TLB_Complex {
Hashmap(int _n, const TLB& _val_type) : value_type(_val_type), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
struct HashmapNode final : TLB_Complex {
@@ -173,7 +173,7 @@ struct HashmapNode final : TLB_Complex {
}
int get_size(const vm::CellSlice& cs) const override;
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return n > 0 ? hmn_fork : n;
}
@@ -185,7 +185,7 @@ struct HashmapE final : TLB {
HashmapE(int _n, const TLB& _val_type) : root_type(_n, _val_type) {
}
int get_size(const vm::CellSlice& cs) const override;
- bool validate(const vm::CellSlice& cs, bool weak = false) const override;
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
}
@@ -221,7 +221,7 @@ struct HashmapAug final : TLB_Complex {
HashmapAug(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_extra(vm::CellSlice& cs) const;
};
@@ -232,7 +232,7 @@ struct HashmapAugNode final : TLB_Complex {
HashmapAugNode(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return n > 0 ? ahmn_fork : n;
}
@@ -244,7 +244,7 @@ struct HashmapAugE final : TLB_Complex {
HashmapAugE(int _n, const AugmentationCheckData& _aug) : root_type(_n, std::move(_aug)) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_extra(vm::CellSlice& cs) const;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
@@ -252,7 +252,7 @@ struct HashmapAugE final : TLB_Complex {
};
struct Grams final : TLB_Complex {
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
@@ -264,7 +264,7 @@ extern const Grams t_Grams;
struct MsgAddressInt final : TLB_Complex {
enum { addr_std = 2, addr_var = 3 };
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@@ -303,7 +303,7 @@ extern const MsgAddressExt t_MsgAddressExt;
struct MsgAddress final : TLB_Complex {
enum { addr_none = 0, addr_ext = 1, addr_std = 2, addr_var = 3 };
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@@ -318,8 +318,8 @@ struct ExtraCurrencyCollection final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return dict_type.get_size(cs);
}
- bool validate(const vm::CellSlice& cs, bool weak) const override {
- return dict_type.validate(cs, weak);
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak) const override {
+ return dict_type.validate(ops, cs, weak);
}
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_zeroes_bool(1);
@@ -348,7 +348,7 @@ extern const ExtraCurrencyCollection t_ExtraCurrencyCollection;
struct CurrencyCollection final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_bits_same_bool(1 + 4, false);
@@ -371,7 +371,7 @@ extern const CurrencyCollection t_CurrencyCollection;
struct CommonMsgInfo final : TLB_Complex {
enum { int_msg_info = 0, ext_in_msg_info = 2, ext_out_msg_info = 3 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
int v = (int)cs.prefetch_ulong(2);
return v == 1 ? int_msg_info : v;
@@ -402,14 +402,14 @@ struct TickTock final : TLB {
extern const TickTock t_TickTock;
struct StateInit final : TLB_Complex {
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_ticktock(vm::CellSlice& cs, int& ticktock) const;
};
extern const StateInit t_StateInit;
struct Message final : TLB_Complex {
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_info(vm::CellSlice& cs) const;
bool get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const;
bool is_internal(const vm::CellSlice& cs) const {
@@ -425,7 +425,7 @@ struct IntermediateAddress final : TLB_Complex {
enum { interm_addr_regular = 0, interm_addr_simple = 2, interm_addr_ext = 3 };
int get_size(const vm::CellSlice& cs) const override;
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool fetch_regular(vm::CellSlice& cs, int& use_dst_bits) const {
return cs.fetch_uint_to(8, use_dst_bits) && use_dst_bits <= 96;
}
@@ -439,7 +439,7 @@ extern const IntermediateAddress t_IntermediateAddress;
struct MsgEnvelope final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_fwd_fees_remaining(vm::CellSlice& cs) const;
struct Record {
typedef MsgEnvelope type_class;
@@ -463,28 +463,28 @@ extern const RefTo t_Ref_MsgEnvelope;
struct StorageUsed final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageUsed t_StorageUsed;
struct StorageUsedShort final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageUsedShort t_StorageUsedShort;
struct StorageInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageInfo t_StorageInfo;
struct AccountState final : TLB_Complex {
enum { account_uninit = 0, account_frozen = 1, account_active = 2 };
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
int t = (int)cs.prefetch_ulong(2);
return t == 3 ? account_active : t;
@@ -496,7 +496,7 @@ extern const AccountState t_AccountState;
struct AccountStorage final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
};
@@ -508,7 +508,7 @@ struct Account final : TLB_Complex {
Account(bool _allow_empty = false) : allow_empty(_allow_empty) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
// Ref get_balance(const vm::CellSlice& cs) const;
bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
bool skip_copy_depth_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
@@ -553,8 +553,8 @@ struct ShardAccount final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance_ext(0x140, 1);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return cs.advance(0x140) && t_Ref_Account.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return cs.advance(0x140) && t_Ref_Account.validate_skip(ops, cs, weak);
}
static bool unpack(vm::CellSlice& cs, Record& info) {
return info.unpack(cs);
@@ -569,7 +569,7 @@ extern const ShardAccount t_ShardAccount;
struct DepthBalanceInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override;
};
@@ -590,8 +590,8 @@ struct ShardAccounts final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return dict_type.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return dict_type.validate_skip(ops, cs, weak);
}
};
@@ -615,7 +615,7 @@ extern const AccStatusChange t_AccStatusChange;
struct TrStoragePhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
bool maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
};
@@ -624,14 +624,14 @@ extern const TrStoragePhase t_TrStoragePhase;
struct TrCreditPhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const TrCreditPhase t_TrCreditPhase;
struct TrComputeInternal1 final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
struct ComputeSkipReason final : TLB {
@@ -639,7 +639,7 @@ struct ComputeSkipReason final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return 2;
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return get_tag(cs) >= 0 && cs.advance(2);
}
int get_tag(const vm::CellSlice& cs) const override {
@@ -653,7 +653,7 @@ extern const ComputeSkipReason t_ComputeSkipReason;
struct TrComputePhase final : TLB_Complex {
enum { tr_phase_compute_skipped = 0, tr_phase_compute_vm = 1 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
}
@@ -663,7 +663,7 @@ extern const TrComputePhase t_TrComputePhase;
struct TrActionPhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const TrActionPhase t_TrActionPhase;
@@ -671,7 +671,7 @@ extern const TrActionPhase t_TrActionPhase;
struct TrBouncePhase final : TLB_Complex {
enum { tr_phase_bounce_negfunds = 0, tr_phase_bounce_nofunds = 1, tr_phase_bounce_ok = 2 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override;
};
@@ -679,7 +679,7 @@ extern const TrBouncePhase t_TrBouncePhase;
struct SplitMergeInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const SplitMergeInfo t_SplitMergeInfo;
@@ -695,7 +695,7 @@ struct TransactionDescr final : TLB_Complex {
trans_merge_install = 7
};
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override;
bool skip_to_storage_phase(vm::CellSlice& cs, bool& found) const;
bool get_storage_fees(Ref cell, td::RefInt256& storage_fees) const;
@@ -705,14 +705,14 @@ extern const TransactionDescr t_TransactionDescr;
struct Transaction_aux final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const Transaction_aux t_Transaction_aux;
struct Transaction final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const;
bool get_descr(Ref cell, Ref& tdescr) const;
bool get_descr(vm::CellSlice& cs, Ref& tdescr) const;
@@ -735,7 +735,7 @@ struct HashUpdate final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(8 + 256 * 2);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return cs.fetch_ulong(8) == 0x72 && cs.advance(256 * 2);
}
};
@@ -745,7 +745,7 @@ extern const RefTo t_Ref_HashUpdate;
struct AccountBlock final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const;
};
@@ -762,7 +762,7 @@ extern const HashmapAugE t_ShardAccountBlocks; // (HashmapAugE 256 AccountBlock
struct ImportFees final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_bits_same_bool(4 + 4 + 1, false);
}
@@ -782,7 +782,7 @@ struct InMsg final : TLB_Complex {
msg_discard_tr = 7
};
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(3);
}
@@ -802,7 +802,7 @@ struct OutMsg final : TLB_Complex {
msg_export_tr_req = 7
};
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(3);
}
@@ -830,8 +830,8 @@ struct InMsgDescr final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return dict_type.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return dict_type.validate_skip(ops, cs, weak);
}
};
@@ -853,8 +853,8 @@ struct OutMsgDescr final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return dict_type.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return dict_type.validate_skip(ops, cs, weak);
}
};
@@ -867,7 +867,7 @@ struct EnqueuedMsg final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance_ext(0x10040);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, EnqueuedMsgDescr& descr) const {
return descr.unpack(cs);
}
@@ -891,8 +891,8 @@ struct OutMsgQueue final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return dict_type.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return dict_type.validate_skip(ops, cs, weak);
}
};
@@ -910,7 +910,7 @@ extern const HashmapE t_IhrPendingInfo;
struct OutMsgQueueInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const OutMsgQueueInfo t_OutMsgQueueInfo;
@@ -946,7 +946,7 @@ struct ShardIdent final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(get_size(cs));
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
@@ -985,7 +985,7 @@ struct BlockIdExt final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(get_size(cs));
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const;
bool pack(vm::CellBuilder& cb, const ton::BlockIdExt& data) const;
};
@@ -995,7 +995,7 @@ extern const BlockIdExt t_BlockIdExt;
struct ShardState final : TLB_Complex {
enum { shard_state = (int)0x9023afe2, split_state = 0x5f327da5 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(32) == shard_state ? shard_state : -1;
}
@@ -1005,7 +1005,7 @@ extern const ShardState t_ShardState;
struct ShardState_aux final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
@@ -1016,7 +1016,7 @@ extern const ShardState_aux t_ShardState_aux;
struct LibDescr final : TLB_Complex {
enum { shared_lib_descr = 0 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@@ -1029,7 +1029,7 @@ struct BlkPrevInfo final : TLB_Complex {
BlkPrevInfo(bool _merged) : merged(_merged) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const BlkPrevInfo t_BlkPrevInfo_0;
@@ -1037,7 +1037,7 @@ extern const BlkPrevInfo t_BlkPrevInfo_0;
struct McStateExtra final : TLB_Complex {
enum { masterchain_state_extra = 0xcc26 };
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const McStateExtra t_McStateExtra;
@@ -1074,7 +1074,7 @@ extern const Aug_OldMcBlocksInfo aug_OldMcBlocksInfo;
struct ShardFeeCreated final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override;
};
diff --git a/crypto/block/block.cpp b/crypto/block/block.cpp
index b2cad142..d9d3c267 100644
--- a/crypto/block/block.cpp
+++ b/crypto/block/block.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/bits.h"
#include "block/block.h"
@@ -813,11 +813,11 @@ td::Status ShardState::unpack_out_msg_queue_info(Ref out_msg_queue_inf
LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str();
block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info);
}
- if (!block::gen::t_ProcessedInfo.validate_csr(qinfo.proc_info)) {
+ if (!block::gen::t_ProcessedInfo.validate_csr(1024, qinfo.proc_info)) {
return td::Status::Error(
-666, "ProcessedInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks");
}
- if (!block::gen::t_IhrPendingInfo.validate_csr(qinfo.ihr_pending)) {
+ if (!block::gen::t_IhrPendingInfo.validate_csr(1024, qinfo.ihr_pending)) {
return td::Status::Error(
-666, "IhrPendingInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks");
}
@@ -1036,7 +1036,7 @@ td::Status ShardState::split(ton::ShardIdFull subshard) {
LOG(DEBUG) << "splitting total_balance";
auto old_total_balance = total_balance_;
auto accounts_extra = account_dict_->get_root_extra();
- if (!(accounts_extra.write().advance(5) && total_balance_.validate_unpack(accounts_extra))) {
+ if (!(accounts_extra.write().advance(5) && total_balance_.validate_unpack(accounts_extra, 1024))) {
LOG(ERROR) << "cannot unpack CurrencyCollection from the root of newly-split accounts dictionary";
return td::Status::Error(
-666, "error splitting total balance in account dictionary of shardchain state "s + id_.to_str());
@@ -1085,16 +1085,16 @@ int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull ol
});
}
-bool CurrencyCollection::validate() const {
- return is_valid() && td::sgn(grams) >= 0 && validate_extra();
+bool CurrencyCollection::validate(int max_cells) const {
+ return is_valid() && td::sgn(grams) >= 0 && validate_extra(max_cells);
}
-bool CurrencyCollection::validate_extra() const {
+bool CurrencyCollection::validate_extra(int max_cells) const {
if (extra.is_null()) {
return true;
}
vm::CellBuilder cb;
- return cb.store_maybe_ref(extra) && block::tlb::t_ExtraCurrencyCollection.validate_ref(cb.finalize());
+ return cb.store_maybe_ref(extra) && block::tlb::t_ExtraCurrencyCollection.validate_ref(max_cells, cb.finalize());
}
bool CurrencyCollection::add(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c) {
@@ -1265,8 +1265,8 @@ bool CurrencyCollection::unpack(Ref csr) {
return unpack_CurrencyCollection(std::move(csr), grams, extra) || invalidate();
}
-bool CurrencyCollection::validate_unpack(Ref csr) {
- return (csr.not_null() && block::tlb::t_CurrencyCollection.validate(*csr) &&
+bool CurrencyCollection::validate_unpack(Ref csr, int max_cells) {
+ return (csr.not_null() && block::tlb::t_CurrencyCollection.validate_upto(max_cells, *csr) &&
unpack_CurrencyCollection(std::move(csr), grams, extra)) ||
invalidate();
}
@@ -1593,7 +1593,7 @@ bool check_one_config_param(Ref cs_ref, td::ConstBitPtr key, td::
} else if (idx < 0) {
return true;
}
- bool ok = block::gen::ConfigParam{idx}.validate_ref(std::move(cell));
+ bool ok = block::gen::ConfigParam{idx}.validate_ref(1024, std::move(cell));
if (!ok) {
LOG(ERROR) << "configuration parameter #" << idx << " is invalid";
}
diff --git a/crypto/block/block.h b/crypto/block/block.h
index 0cfbe24a..0d961320 100644
--- a/crypto/block/block.h
+++ b/crypto/block/block.h
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
@@ -323,8 +323,8 @@ struct CurrencyCollection {
grams.clear();
return false;
}
- bool validate() const;
- bool validate_extra() const;
+ bool validate(int max_cells = 1024) const;
+ bool validate_extra(int max_cells = 1024) const;
bool operator==(const CurrencyCollection& other) const;
bool operator!=(const CurrencyCollection& other) const {
return !operator==(other);
@@ -360,7 +360,7 @@ struct CurrencyCollection {
bool fetch(vm::CellSlice& cs);
bool fetch_exact(vm::CellSlice& cs);
bool unpack(Ref csr);
- bool validate_unpack(Ref csr);
+ bool validate_unpack(Ref csr, int max_cells = 1024);
Ref pack() const;
bool pack_to(Ref& csr) const {
return (csr = pack()).not_null();
diff --git a/crypto/block/create-state.cpp b/crypto/block/create-state.cpp
index 02896e7b..5eb14528 100644
--- a/crypto/block/create-state.cpp
+++ b/crypto/block/create-state.cpp
@@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include
#include
@@ -697,7 +697,7 @@ void interpret_tlb_skip(vm::Stack& stack) {
void interpret_tlb_validate_skip(vm::Stack& stack) {
auto tp = pop_tlb_type(stack);
auto cs = stack.pop_cellslice();
- bool ok = (*tp)->validate_skip(cs.write());
+ bool ok = (*tp)->validate_skip_upto(1048576, cs.write());
if (ok) {
stack.push(std::move(cs));
}
diff --git a/crypto/block/dump-block.cpp b/crypto/block/dump-block.cpp
index 25eb0eed..716aa3bc 100644
--- a/crypto/block/dump-block.cpp
+++ b/crypto/block/dump-block.cpp
@@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "block/block.h"
#include "vm/boc.h"
@@ -98,7 +98,7 @@ void test1() {
block::tlb::ShardIdent::Record shard_id;
for (int i = 0; i < 3; i++) {
- std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate(csl) << std::endl;
+ std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate_upto(1024, csl) << std::endl;
csl.print_rec(std::cerr);
csl.dump(std::cerr, 7);
std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl;
@@ -107,9 +107,9 @@ void test1() {
<< " shard_prefix:" << shard_id.shard_prefix << std::endl;
}
}
- std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
- std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
- std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
+ std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
+ std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
+ std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
using namespace td::literals;
std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl;
std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl;
@@ -120,13 +120,13 @@ void test1() {
std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl;
std::cout << cb << std::endl;
cs2 = td::Ref{true, cb.finalize()};
- std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate(*cs) << std::endl;
- std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate(*cs2) << std::endl;
+ std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate_upto(1024, *cs) << std::endl;
+ std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate_upto(1024, *cs2) << std::endl;
//
block::gen::SplitMergeInfo::Record data;
block::gen::Grams::Record data2;
- std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate(*cs) << std::endl;
- std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate(*cs2) << std::endl;
+ std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate_upto(1024, *cs) << std::endl;
+ std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate_upto(1024, *cs2) << std::endl;
std::cout << "[cs = " << cs << "]" << std::endl;
bool ok = tlb::csr_unpack_inexact(cs, data);
std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl;
@@ -182,12 +182,12 @@ void test1() {
}
void test2(vm::CellSlice& cs) {
- std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate(cs) << std::endl;
- std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate(cs) << std::endl;
- std::cout << "HashmapE(32,UInt16).validate() = " << block::tlb::HashmapE(32, block::tlb::t_uint16).validate(cs)
- << std::endl;
+ std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate_upto(1024, cs) << std::endl;
+ std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate_upto(1024, cs) << std::endl;
+ std::cout << "HashmapE(32,UInt16).validate() = "
+ << block::tlb::HashmapE(32, block::tlb::t_uint16).validate_upto(1024, cs) << std::endl;
std::cout << "block::gen::HashmapE(32,UInt16).validate() = "
- << block::gen::HashmapE{32, block::gen::t_uint16}.validate(cs) << std::endl;
+ << block::gen::HashmapE{32, block::gen::t_uint16}.validate_upto(1024, cs) << std::endl;
}
void usage() {
@@ -249,7 +249,7 @@ int main(int argc, char* const argv[]) {
}
type->print_ref(std::cout, boc);
std::cout << std::endl;
- bool ok = type->validate_ref(boc);
+ bool ok = type->validate_ref(1048576, boc);
std::cout << "(" << (ok ? "" : "in") << "valid " << *type << ")" << std::endl;
}
}
diff --git a/crypto/block/mc-config.cpp b/crypto/block/mc-config.cpp
index 719d76b0..555b2603 100644
--- a/crypto/block/mc-config.cpp
+++ b/crypto/block/mc-config.cpp
@@ -1239,7 +1239,7 @@ bool ShardConfig::new_workchain(ton::WorkchainId workchain, ton::BlockSeqno reg_
cb.store_zeroes_bool(
1 + 5 +
5) // split_merge_at:FutureSplitMerge fees_collected:CurrencyCollection funds_created:CurrencyCollection
- && cb.finalize_to(cell) && block::gen::t_BinTree_ShardDescr.validate_ref(cell) &&
+ && cb.finalize_to(cell) && block::gen::t_BinTree_ShardDescr.validate_ref(1024, cell) &&
shard_hashes_dict_->set_ref(td::BitArray<32>{workchain}, std::move(cell), vm::Dictionary::SetMode::Add);
}
@@ -1469,7 +1469,7 @@ static bool btree_set(Ref& root, ton::ShardId shard, Ref val
}
bool ShardConfig::set_shard_info(ton::ShardIdFull shard, Ref value) {
- if (!gen::t_BinTree_ShardDescr.validate_ref(value)) {
+ if (!gen::t_BinTree_ShardDescr.validate_ref(1024, value)) {
LOG(ERROR) << "attempting to store an invalid (BinTree ShardDescr) at shard configuration position "
<< shard.to_str();
gen::t_BinTree_ShardDescr.print_ref(std::cerr, value);
diff --git a/crypto/block/transaction.cpp b/crypto/block/transaction.cpp
index 1387e1f9..34abfff1 100644
--- a/crypto/block/transaction.cpp
+++ b/crypto/block/transaction.cpp
@@ -150,7 +150,7 @@ bool Account::unpack_storage_info(vm::CellSlice& cs) {
return false;
}
} else {
- due_payment = td::RefInt256{true, 0};
+ due_payment = td::zero_refint();
}
unsigned long long u = 0;
u |= storage_stat.cells = block::tlb::t_VarUInteger_7.as_uint(*used.cells);
@@ -369,7 +369,7 @@ bool Account::init_new(ton::UnixTime now) {
now_ = now;
last_paid = 0;
storage_stat.clear();
- due_payment = td::RefInt256{true, 0};
+ due_payment = td::zero_refint();
balance.set_zero();
if (my_addr_exact.is_null()) {
vm::CellBuilder cb;
@@ -473,6 +473,9 @@ Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime re
start_lt = std::max(req_start_lt, account.last_trans_end_lt_);
end_lt = start_lt + 1;
acc_status = (account.status == Account::acc_nonexist ? Account::acc_uninit : account.status);
+ if (acc_status == Account::acc_frozen) {
+ frozen_hash = account.state_hash;
+ }
}
bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* cfg) {
@@ -504,7 +507,7 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
if (ihr_delivered) {
in_fwd_fee = std::move(ihr_fee);
} else {
- in_fwd_fee = td::RefInt256{true, 0};
+ in_fwd_fee = td::zero_refint();
msg_balance_remaining += std::move(ihr_fee);
}
if (info.created_lt >= start_lt) {
@@ -544,7 +547,7 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
LOG(DEBUG) << "computed fwd fees set to zero for special account";
fees_c.first = fees_c.second = 0;
}
- in_fwd_fee = td::RefInt256{true, fees_c.first};
+ in_fwd_fee = td::make_refint(fees_c.first);
if (balance.grams < in_fwd_fee) {
LOG(DEBUG) << "cannot pay for importing this external message";
return false;
@@ -616,19 +619,19 @@ bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool forc
res->is_special = account.is_special;
last_paid = res->last_paid_updated = (res->is_special ? 0 : now);
if (to_pay.is_null() || sgn(to_pay) == 0) {
- res->fees_collected = res->fees_due = td::RefInt256{true, 0};
+ res->fees_collected = res->fees_due = td::zero_refint();
} else if (to_pay <= balance.grams) {
res->fees_collected = to_pay;
- res->fees_due = td::RefInt256{true, 0};
+ res->fees_due = td::zero_refint();
balance -= std::move(to_pay);
} else if (acc_status == Account::acc_frozen && !force_collect && to_pay + due_payment < cfg.delete_due_limit) {
// do not collect fee
res->last_paid_updated = (res->is_special ? 0 : account.last_paid);
- res->fees_collected = res->fees_due = td::RefInt256{true, 0};
+ res->fees_collected = res->fees_due = td::zero_refint();
} else {
res->fees_collected = balance.grams;
res->fees_due = std::move(to_pay) - std::move(balance.grams);
- balance.grams = td::RefInt256{true, 0};
+ balance.grams = td::zero_refint();
if (!res->is_special) {
auto total_due = res->fees_due + due_payment;
switch (acc_status) {
@@ -707,8 +710,8 @@ bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref cs, t
special_gas_limit = spec_limit;
gas_credit = r.gas_credit;
gas_price = r.gas_price;
- freeze_due_limit = td::RefInt256{true, r.freeze_due_limit};
- delete_due_limit = td::RefInt256{true, r.delete_due_limit};
+ freeze_due_limit = td::make_refint(r.freeze_due_limit);
+ delete_due_limit = td::make_refint(r.delete_due_limit);
};
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
if (tlb::csr_unpack(cs, rec)) {
@@ -728,10 +731,10 @@ bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref cs, t
}
void ComputePhaseConfig::compute_threshold() {
- gas_price256 = td::RefInt256{true, gas_price};
+ gas_price256 = td::make_refint(gas_price);
if (gas_limit > flat_gas_limit) {
max_gas_threshold =
- td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_refint(flat_gas_price);
+ td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_bigint(flat_gas_price);
} else {
max_gas_threshold = td::make_refint(flat_gas_price);
}
@@ -828,8 +831,8 @@ Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
}
auto tuple = vm::make_tuple_ref(
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
- td::make_refint(0), // actions:Integer
- td::make_refint(0), // msgs_sent:Integer
+ td::zero_refint(), // actions:Integer
+ td::zero_refint(), // msgs_sent:Integer
td::make_refint(now), // unixtime:Integer
td::make_refint(account.block_lt), // block_lt:Integer
td::make_refint(start_lt), // trans_lt:Integer
@@ -1012,7 +1015,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
}
if (cp.accepted) {
if (account.is_special) {
- cp.gas_fees = td::RefInt256{true, 0};
+ cp.gas_fees = td::zero_refint();
} else {
cp.gas_fees = cfg.compute_gas_price(cp.gas_used);
total_fees += cp.gas_fees;
@@ -1040,8 +1043,8 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
ap.action_list_hash = list->get_hash().bits();
ap.remaining_balance = balance;
ap.end_lt = end_lt;
- ap.total_fwd_fees = td::RefInt256{true, 0};
- ap.total_action_fees = td::RefInt256{true, 0};
+ ap.total_fwd_fees = td::zero_refint();
+ ap.total_action_fees = td::zero_refint();
ap.reserved_balance.set_zero();
int n = 0;
@@ -1429,7 +1432,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
info.ihr_disabled = true;
info.bounce = false;
info.bounced = false;
- fwd_fee = ihr_fee = td::RefInt256{true, 0};
+ fwd_fee = ihr_fee = td::zero_refint();
} else {
// int_msg_info$0 constructor
if (!tlb::csr_unpack(msg.info, info) || !block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
@@ -1482,10 +1485,10 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
// set fees to computed values
if (fwd_fee->unsigned_fits_bits(63) && fwd_fee->to_long() < (long long)fees_c.first) {
- fwd_fee = td::RefInt256{true, fees_c.first};
+ fwd_fee = td::make_refint(fees_c.first);
}
if (fees_c.second && ihr_fee->unsigned_fits_bits(63) && ihr_fee->to_long() < (long long)fees_c.second) {
- ihr_fee = td::RefInt256{true, fees_c.second};
+ ihr_fee = td::make_refint(fees_c.second);
}
Ref new_msg;
@@ -1502,7 +1505,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
}
if (info.ihr_disabled) {
// if IHR is disabled, IHR fees will be always zero
- ihr_fee = td::RefInt256{true, 0};
+ ihr_fee = td::zero_refint();
}
// extract value to be carried by the message
block::CurrencyCollection req;
@@ -1757,10 +1760,10 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
balance -= msg_balance;
CHECK(balance.is_valid());
// debit total forwarding fees from the message's balance, then split forwarding fees into our part and remaining part
- msg_balance -= td::RefInt256{true, bp.fwd_fees};
+ msg_balance -= td::make_refint(bp.fwd_fees);
bp.fwd_fees_collected = msg_prices.get_first_part(bp.fwd_fees);
bp.fwd_fees -= bp.fwd_fees_collected;
- total_fees += td::RefInt256{true, bp.fwd_fees_collected};
+ total_fees += td::make_refint(bp.fwd_fees_collected);
// serialize outbound message
info.created_lt = end_lt++;
info.created_at = now;
diff --git a/crypto/common/bigint.hpp b/crypto/common/bigint.hpp
index 6734f07e..7f6cf971 100644
--- a/crypto/common/bigint.hpp
+++ b/crypto/common/bigint.hpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include
@@ -169,6 +169,8 @@ class PropagateConstSpan {
size_t size_{0};
};
+struct Normalize {};
+
template
class AnyIntView {
public:
@@ -308,6 +310,10 @@ class BigIntG {
explicit BigIntG(word_t x) : n(1) {
digits[0] = x;
}
+ BigIntG(Normalize, word_t x) : n(1) {
+ digits[0] = x;
+ normalize_bool();
+ }
BigIntG(const BigIntG& x) : n(x.n) {
std::memcpy(digits, x.digits, n * sizeof(word_t));
///std::cout << "(BiCC " << (const void*)&x << "->" << (void*)this << ")";
@@ -2515,6 +2521,11 @@ extern template class AnyIntView;
extern template class BigIntG<257, BigIntInfo>;
typedef BigIntG<257, BigIntInfo> BigInt256;
+template
+BigIntG make_bigint(long long x) {
+ return BigIntG{Normalize(), x};
+}
+
namespace literals {
extern BigInt256 operator""_i256(const char* str, std::size_t str_len);
diff --git a/crypto/common/refint.cpp b/crypto/common/refint.cpp
index f252aba6..3a031a5a 100644
--- a/crypto/common/refint.cpp
+++ b/crypto/common/refint.cpp
@@ -38,6 +38,11 @@ RefInt256 operator+(RefInt256 x, long long y) {
return x;
}
+RefInt256 operator+(RefInt256 x, const BigInt256& y) {
+ (x.write() += y).normalize();
+ return x;
+}
+
RefInt256 operator-(RefInt256 x, RefInt256 y) {
(x.write() -= *y).normalize();
return x;
@@ -48,6 +53,11 @@ RefInt256 operator-(RefInt256 x, long long y) {
return x;
}
+RefInt256 operator-(RefInt256 x, const BigInt256& y) {
+ (x.write() -= y).normalize();
+ return x;
+}
+
RefInt256 operator-(RefInt256 x) {
x.write().negate().normalize();
return x;
@@ -69,6 +79,12 @@ RefInt256 operator*(RefInt256 x, long long y) {
return x;
}
+RefInt256 operator*(RefInt256 x, const BigInt256& y) {
+ RefInt256 z{true, 0};
+ z.write().add_mul(*x, y).normalize();
+ return z;
+}
+
RefInt256 operator/(RefInt256 x, RefInt256 y) {
RefInt256 quot{true};
x.write().mod_div(*y, quot.write());
@@ -142,6 +158,11 @@ RefInt256& operator+=(RefInt256& x, long long y) {
return x;
}
+RefInt256& operator+=(RefInt256& x, const BigInt256& y) {
+ (x.write() += y).normalize();
+ return x;
+}
+
RefInt256& operator-=(RefInt256& x, RefInt256 y) {
(x.write() -= *y).normalize();
return x;
@@ -152,6 +173,11 @@ RefInt256& operator-=(RefInt256& x, long long y) {
return x;
}
+RefInt256& operator-=(RefInt256& x, const BigInt256& y) {
+ (x.write() -= y).normalize();
+ return x;
+}
+
RefInt256& operator*=(RefInt256& x, RefInt256 y) {
RefInt256 z{true, 0};
z.write().add_mul(*x, *y).normalize();
@@ -163,6 +189,12 @@ RefInt256& operator*=(RefInt256& x, long long y) {
return x;
}
+RefInt256& operator*=(RefInt256& x, const BigInt256& y) {
+ RefInt256 z{true, 0};
+ z.write().add_mul(*x, y).normalize();
+ return x = z;
+}
+
RefInt256& operator/=(RefInt256& x, RefInt256 y) {
RefInt256 quot{true};
x.write().mod_div(*y, quot.write());
@@ -214,9 +246,13 @@ int sgn(RefInt256 x) {
}
RefInt256 make_refint(long long x) {
- auto xx = td::RefInt256{true, x};
- xx.unique_write().normalize();
- return xx;
+ return td::RefInt256{true, td::Normalize(), x};
+}
+
+RefInt256 zero_refint() {
+ // static RefInt256 Zero = td::RefInt256{true, 0};
+ // return Zero;
+ return td::RefInt256{true, 0};
}
RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd) {
diff --git a/crypto/common/refint.h b/crypto/common/refint.h
index 4c21aab8..ea1ae81b 100644
--- a/crypto/common/refint.h
+++ b/crypto/common/refint.h
@@ -33,10 +33,13 @@ typedef Ref RefInt256;
extern RefInt256 operator+(RefInt256 x, RefInt256 y);
extern RefInt256 operator+(RefInt256 x, long long y);
+extern RefInt256 operator+(RefInt256 x, const BigInt256& y);
extern RefInt256 operator-(RefInt256 x, RefInt256 y);
extern RefInt256 operator-(RefInt256 x, long long y);
+extern RefInt256 operator-(RefInt256 x, const BigInt256& y);
extern RefInt256 operator*(RefInt256 x, RefInt256 y);
extern RefInt256 operator*(RefInt256 x, long long y);
+extern RefInt256 operator*(RefInt256 x, const BigInt256& y);
extern RefInt256 operator/(RefInt256 x, RefInt256 y);
extern RefInt256 operator%(RefInt256 x, RefInt256 y);
extern RefInt256 div(RefInt256 x, RefInt256 y, int round_mode = -1);
@@ -53,10 +56,13 @@ extern RefInt256 rshift(RefInt256 x, int y, int round_mode = -1);
extern RefInt256& operator+=(RefInt256& x, RefInt256 y);
extern RefInt256& operator+=(RefInt256& x, long long y);
+extern RefInt256& operator+=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator-=(RefInt256& x, RefInt256 y);
extern RefInt256& operator-=(RefInt256& x, long long y);
+extern RefInt256& operator-=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator*=(RefInt256& x, RefInt256 y);
extern RefInt256& operator*=(RefInt256& x, long long y);
+extern RefInt256& operator*=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator/=(RefInt256& x, RefInt256 y);
extern RefInt256& operator%=(RefInt256& x, RefInt256 y);
@@ -100,7 +106,14 @@ extern int cmp(RefInt256 x, RefInt256 y);
extern int cmp(RefInt256 x, long long y);
extern int sgn(RefInt256 x);
+template
+RefInt256 make_refint(Args&&... args) {
+ return td::RefInt256{true, std::forward(args)...};
+}
+
extern RefInt256 make_refint(long long x);
+
+extern RefInt256 zero_refint();
extern RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd = false);
extern std::string dec_string(RefInt256 x);
diff --git a/crypto/fift/words.cpp b/crypto/fift/words.cpp
index 38cb2944..3afd687e 100644
--- a/crypto/fift/words.cpp
+++ b/crypto/fift/words.cpp
@@ -180,9 +180,9 @@ void interpret_times_div(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
- td::BigIntG<257 * 2> tmp{0};
+ typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
@@ -192,26 +192,23 @@ void interpret_times_divmod(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
- td::BigIntG<257 * 2> tmp{0};
+ typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
- auto r = td::RefInt256{true, tmp};
stack.push_int(std::move(q));
- stack.push_int(std::move(r));
+ stack.push_int(td::make_refint(tmp));
}
void interpret_times_mod(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
- td::BigIntG<257 * 2> tmp{0};
+ typename td::BigInt256::DoubleInt tmp{0}, q;
tmp.add_mul(*x, *y);
- td::BigIntG<257 * 2> q;
tmp.mod_div(*z, q, round_mode);
- auto r = td::RefInt256{true, tmp};
- stack.push_int(std::move(r));
+ stack.push_int(td::make_refint(tmp));
}
void interpret_negate(vm::Stack& stack) {
@@ -253,21 +250,21 @@ void interpret_fits(vm::Stack& stack, bool sgnd) {
void interpret_pow2(vm::Stack& stack) {
int x = stack.pop_smallint_range(255);
- auto r = td::RefInt256{true};
+ auto r = td::make_refint();
r.unique_write().set_pow2(x);
stack.push_int(r);
}
void interpret_neg_pow2(vm::Stack& stack) {
int x = stack.pop_smallint_range(256);
- auto r = td::RefInt256{true};
+ auto r = td::make_refint();
r.unique_write().set_pow2(x).negate().normalize();
stack.push_int(r);
}
void interpret_pow2_minus1(vm::Stack& stack) {
int x = stack.pop_smallint_range(256);
- auto r = td::RefInt256{true};
+ auto r = td::make_refint();
r.unique_write().set_pow2(x).add_tiny(-1).normalize();
stack.push_int(r);
}
@@ -301,19 +298,18 @@ void interpret_times_rshift(vm::Stack& stack, int round_mode) {
int z = stack.pop_smallint_range(256);
auto y = stack.pop_int();
auto x = stack.pop_int();
- td::BigIntG<257 * 2> tmp{0};
+ typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y).rshift(z, round_mode).normalize();
- auto q = td::RefInt256{true, tmp};
- stack.push_int(std::move(q));
+ stack.push_int(td::make_refint(tmp));
}
void interpret_lshift_div(vm::Stack& stack, int round_mode) {
int z = stack.pop_smallint_range(256);
auto y = stack.pop_int();
auto x = stack.pop_int();
- td::BigIntG<257 * 2> tmp{*x};
+ typename td::BigInt256::DoubleInt tmp{*x};
tmp <<= z;
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*y, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
@@ -1932,7 +1928,7 @@ int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool a
const char* str = s.c_str();
int len = (int)s.size();
int frac = -1, base, *frac_ptr = allow_frac ? &frac : nullptr;
- num = td::RefInt256{true};
+ num = td::make_refint();
auto& x = num.unique_write();
if (len >= 4 && str[0] == '-' && str[1] == '0' && (str[2] == 'x' || str[2] == 'b')) {
if (str[2] == 'x') {
@@ -1974,7 +1970,7 @@ int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool a
if (frac < 0) {
return 1;
} else {
- denom = td::RefInt256{true, 1};
+ denom = td::make_refint(1);
while (frac-- > 0) {
if (!denom.unique_write().mul_tiny(base).normalize_bool()) {
if (throw_error) {
diff --git a/crypto/func/abscode.cpp b/crypto/func/abscode.cpp
index 8813bad2..8d73c805 100644
--- a/crypto/func/abscode.cpp
+++ b/crypto/func/abscode.cpp
@@ -138,7 +138,7 @@ void VarDescr::show(std::ostream& os, const char* name) const {
}
void VarDescr::set_const(long long value) {
- return set_const(td::RefInt256{true, value});
+ return set_const(td::make_refint(value));
}
void VarDescr::set_const(td::RefInt256 value) {
@@ -169,7 +169,7 @@ void VarDescr::set_const(td::RefInt256 value) {
}
void VarDescr::set_const_nan() {
- set_const(td::RefInt256{true});
+ set_const(td::make_refint());
}
void VarDescr::operator|=(const VarDescr& y) {
diff --git a/crypto/func/builtins.cpp b/crypto/func/builtins.cpp
index 93f47dec..066da460 100644
--- a/crypto/func/builtins.cpp
+++ b/crypto/func/builtins.cpp
@@ -628,7 +628,7 @@ AsmOp compile_mod(std::vector& res, std::vector& args, int r
if ((*y.int_const == 1 || *y.int_const == -1) && x.always_finite()) {
x.unused();
y.unused();
- r.set_const(td::RefInt256{true, 0});
+ r.set_const(td::zero_refint());
return push_const(r.int_const);
}
int k = is_pos_pow2(y.int_const);
diff --git a/crypto/func/func.h b/crypto/func/func.h
index e9101c68..fd2bffd6 100644
--- a/crypto/func/func.h
+++ b/crypto/func/func.h
@@ -934,7 +934,7 @@ struct AsmOp {
void out_indent_nl(std::ostream& os, bool no_nl = false) const;
std::string to_string() const;
void compute_gconst() {
- gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC"));
+ gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC" || op == "NEWB" || op == "TRUE" || op == "FALSE"));
}
bool is_nop() const {
return t == a_none && op.empty();
@@ -975,6 +975,9 @@ struct AsmOp {
*y = b;
return is_xchg();
}
+ bool is_xchg_short() const {
+ return is_xchg() && (a <= 1 || b <= 1);
+ }
bool is_swap() const {
return is_xchg(0, 1);
}
@@ -1265,10 +1268,14 @@ struct StackTransform {
}
bool is_xchg(int i, int j) const;
bool is_xchg(int* i, int* j) const;
+ bool is_xchg_xchg(int i, int j, int k, int l) const;
+ bool is_xchg_xchg(int* i, int* j, int* k, int* l) const;
bool is_push(int i) const;
bool is_push(int* i) const;
bool is_pop(int i) const;
bool is_pop(int* i) const;
+ bool is_pop_pop(int i, int j) const;
+ bool is_pop_pop(int* i, int* j) const;
bool is_rot() const;
bool is_rotrev() const;
bool is_push_rot(int i) const;
@@ -1407,8 +1414,10 @@ struct Optimizer {
bool is_2swap();
bool is_2over();
bool is_xchg(int* i, int* j);
+ bool is_xchg_xchg(int* i, int* j, int* k, int* l);
bool is_push(int* i);
bool is_pop(int* i);
+ bool is_pop_pop(int* i, int* j);
bool is_nop();
bool is_push_rot(int* i);
bool is_push_rotrev(int* i);
diff --git a/crypto/func/optimize.cpp b/crypto/func/optimize.cpp
index 3d697e5e..85c1fdd3 100644
--- a/crypto/func/optimize.cpp
+++ b/crypto/func/optimize.cpp
@@ -393,6 +393,13 @@ bool Optimizer::is_xchg(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_xchg(i, j) && ((*i < 16 && *j < 16) || (!*i && *j < 256)); });
}
+bool Optimizer::is_xchg_xchg(int* i, int* j, int* k, int* l) {
+ return is_pred([i, j, k, l](const auto& t) {
+ return t.is_xchg_xchg(i, j, k, l) && (*i < 2 && *j < (*i ? 16 : 256) && *k < 2 && *l < (*k ? 16 : 256));
+ }) &&
+ (!(p_ == 2 && op_[0]->is_xchg(*i, *j) && op_[1]->is_xchg(*k, *l)));
+}
+
bool Optimizer::is_push(int* i) {
return is_pred([i](const auto& t) { return t.is_push(i) && *i < 256; });
}
@@ -401,6 +408,10 @@ bool Optimizer::is_pop(int* i) {
return is_pred([i](const auto& t) { return t.is_pop(i) && *i < 256; });
}
+bool Optimizer::is_pop_pop(int* i, int* j) {
+ return is_pred([i, j](const auto& t) { return t.is_pop_pop(i, j) && *i < 256 && *j < 256; }, 3);
+}
+
bool Optimizer::is_push_rot(int* i) {
return is_pred([i](const auto& t) { return t.is_push_rot(i) && *i < 16; }, 3);
}
@@ -543,12 +554,13 @@ bool Optimizer::find_at_least(int pb) {
p_ = q_ = 0;
pb_ = pb;
// show_stack_transforms();
- int i = -100, j = -100, k = -100, c = 0;
+ int i, j, k, l, c;
return (is_push_const(&i, &c) && rewrite_push_const(i, c)) || (is_nop() && rewrite_nop()) ||
(!(mode_ & 1) && is_const_rot(&c) && rewrite_const_rot(c)) ||
(is_const_push_xchgs() && rewrite_const_push_xchgs()) || (is_const_pop(&c, &i) && rewrite_const_pop(c, i)) ||
(is_xchg(&i, &j) && rewrite(AsmOp::Xchg(i, j))) || (is_push(&i) && rewrite(AsmOp::Push(i))) ||
- (is_pop(&i) && rewrite(AsmOp::Pop(i))) ||
+ (is_pop(&i) && rewrite(AsmOp::Pop(i))) || (is_pop_pop(&i, &j) && rewrite(AsmOp::Pop(i), AsmOp::Pop(j))) ||
+ (is_xchg_xchg(&i, &j, &k, &l) && rewrite(AsmOp::Xchg(i, j), AsmOp::Xchg(k, l))) ||
(!(mode_ & 1) &&
((is_rot() && rewrite(AsmOp::Custom("ROT", 3, 3))) || (is_rotrev() && rewrite(AsmOp::Custom("-ROT", 3, 3))) ||
(is_2dup() && rewrite(AsmOp::Custom("2DUP", 2, 4))) ||
@@ -629,10 +641,9 @@ void optimize_code(AsmOpList& ops) {
for (auto it = ops.list_.rbegin(); it < ops.list_.rend(); ++it) {
op_list = AsmOpCons::cons(std::make_unique(std::move(*it)), std::move(op_list));
}
- op_list = optimize_code(std::move(op_list), 1);
- op_list = optimize_code(std::move(op_list), 1);
- op_list = optimize_code(std::move(op_list), 0);
- op_list = optimize_code(std::move(op_list), 0);
+ for (int mode : {1, 1, 1, 1, 0, 0, 0, 0}) {
+ op_list = optimize_code(std::move(op_list), mode);
+ }
ops.list_.clear();
while (op_list) {
ops.list_.push_back(std::move(*(op_list->car)));
diff --git a/crypto/func/stack-transform.cpp b/crypto/func/stack-transform.cpp
index bc8986b6..4d9b6a5f 100644
--- a/crypto/func/stack-transform.cpp
+++ b/crypto/func/stack-transform.cpp
@@ -401,6 +401,57 @@ bool StackTransform::is_xchg(int *i, int *j) const {
return true;
}
+bool StackTransform::is_xchg_xchg(int i, int j, int k, int l) const {
+ if (is_valid() && !d && n <= 4 && (i | j | k | l) >= 0) {
+ StackTransform t;
+ return t.apply_xchg(i, j) && t.apply_xchg(k, l) && t <= *this;
+ } else {
+ return false;
+ }
+}
+
+bool StackTransform::is_xchg_xchg(int *i, int *j, int *k, int *l) const {
+ if (!is_valid() || d || n > 4 || !dp || !is_permutation()) {
+ return false;
+ }
+ if (!n) {
+ *i = *j = *k = *l = 0;
+ return true;
+ }
+ if (n <= 2) {
+ *k = *l = 0;
+ return is_xchg(i, j);
+ }
+ if (n == 3) {
+ // rotation: a -> b -> c -> a
+ int a = A[0].first;
+ int b = A[0].second;
+ int s = (b == A[2].first ? 2 : 1);
+ int c = A[s].second;
+ if (b != A[s].first || c != A[3 - s].first || a != A[3 - s].second) {
+ return false;
+ }
+ // implement as XCHG s(a),s(c) ; XCHG s(a),s(b)
+ *i = *k = a;
+ *j = c;
+ *l = b;
+ return is_xchg_xchg(*i, *j, *k, *l);
+ }
+ *i = A[0].first;
+ *j = A[0].second;
+ if (get(*j) != *i) {
+ return false;
+ }
+ for (int s = 1; s < 4; s++) {
+ if (A[s].first != *j) {
+ *k = A[s].first;
+ *l = A[s].second;
+ return get(*l) == *k && is_xchg_xchg(*i, *j, *k, *l);
+ }
+ }
+ return false;
+}
+
bool StackTransform::is_push(int i) const {
return is_valid() && d == -1 && n == 1 && A[0].first == -1 && A[0].second == i;
}
@@ -418,6 +469,7 @@ bool StackTransform::is_push(int *i) const {
// 0 2 3 4 .. = pop1
// 1 0 3 4 .. = pop2
// 1 2 0 4 .. = pop3
+// POP s(i) : 1 2 ... i-1 0 i+1 ... ; d=1, n=1, {(i,0)}
bool StackTransform::is_pop(int i) const {
if (!is_valid() || d != 1 || n > 1 || i < 0) {
return false;
@@ -443,6 +495,38 @@ bool StackTransform::is_pop(int *i) const {
return false;
}
+// POP s(i) ; POP s(j) : 2 ... i-1 0 i+1 ... j 1 j+2 ... ; d=2, n=2, {(i,0),(j+1,1)} if i <> j+1
+bool StackTransform::is_pop_pop(int i, int j) const {
+ if (is_valid() && d == 2 && n <= 2 && i >= 0 && j >= 0) {
+ StackTransform t;
+ return t.apply_pop(i) && t.apply_pop(j) && t <= *this;
+ } else {
+ return false;
+ }
+}
+
+bool StackTransform::is_pop_pop(int *i, int *j) const {
+ if (!is_valid() || d != 2 || n > 2) {
+ return false;
+ }
+ if (!n) {
+ *i = *j = 0; // 2DROP
+ } else if (n == 2) {
+ *i = A[0].first - A[0].second;
+ *j = A[1].first - A[1].second;
+ if (A[0].second > A[1].second) {
+ std::swap(*i, *j);
+ }
+ } else if (!A[0].second) {
+ *i = A[0].first;
+ *j = 0;
+ } else {
+ *i = 0;
+ *j = A[0].first - 1;
+ }
+ return is_pop_pop(*i, *j);
+}
+
const StackTransform StackTransform::rot{2, 0, 1, 3};
const StackTransform StackTransform::rot_rev{1, 2, 0, 3};
@@ -519,10 +603,9 @@ bool StackTransform::is_xchg2(int *i, int *j) const {
if (*i < 0 || *j < 0) {
return false;
}
- if (n != 3) {
- return is_xchg2(*i, *j);
- }
- if (*i) {
+ if (n == 2 && !*i) {
+ *j = *i; // XCHG s0,s1 = XCHG2 s0,s0
+ } else if (n == 3 && *i) {
// XCHG2 s(i),s(i) = XCHG s1,s(i) ; XCHG s0,s(i) : 0->1, 1->i
*j = *i;
} // XCHG2 s0,s(i) = XCHG s0,s1 ; XCHG s0,s(i) : 0->i, 1->0
diff --git a/crypto/smartcont/auto-dns.fif b/crypto/smartcont/auto-dns.fif
new file mode 100644
index 00000000..6ef2ef0e
--- /dev/null
+++ b/crypto/smartcont/auto-dns.fif
@@ -0,0 +1,115 @@
+#!/usr/bin/fift -s
+"TonUtil.fif" include
+"GetOpt.fif" include
+
+{ show-options-help 1 halt } : usage
+
+"dns-msg-body.boc" =: savefile
+
+begin-options
+ " [-o] (add|update|prolong) ... " +cr +tab
+ +"Creates the internal message body containing a request to automatic DNS smart contract created by new-auto-dns.fif, "
+ +"to be sent later with a suitable payment from a wallet to , and saves it into ('" savefile $+ +"' by default). "
+ +"The operation to be performed is one of" +cr +tab
+ +"add { owner | cat (smc | next | adnl | text ) }" +cr +tab
+ +"update { owner | cat (smc | next | adnl | text ) }" +cr +tab
+ +"prolong "
+ disable-digit-options generic-help-setopt
+ "o" "--output" { =: savefile } short-long-option-arg
+ "Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help
+ "h" "--help" { usage } short-long-option
+ "Shows a help message" option-help
+parse-options
+
+$# 4 < ' usage if
+4 :$1..n
+
+$1 true parse-load-address =: bounce 2=: dest-addr
+$2 dup =: main-op-name atom =: main-op
+$3 dup =: subdomain $len 127 > abort"subdomain name too long"
+$4 parse-int dup 30 1<< < { now + } if =: expire-at
+
+{ $* @ dup null? { second $@ ! } { drop } cond } : @skip
+{ $* @ null? } : @end?
+{ $* @ uncons $* ! } : @next
+{ @next drop } 4 times
+
+main-op dup `add eq? over `update eq? or swap `prolong eq? or
+{ "unknown main operation '" main-op-name $+ +"'; one of 'add', 'update' or 'prolong' expected" abort } ifnot
+main-op `prolong eq? not =: need-params
+
+$# 4 > need-params <> abort"extra parameters, or no parameters for chosen main operation"
+
+variable Values dictnew Values !
+// ( i c -- )
+{ over 0= abort"category cannot be zero"
+ idict!+ not abort"duplicate category id"
+ Values !
+} : register-value
+
+{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer"
+ dup 16 fits not abort"category does not fit into 16 bit integer"
+ dup 0= abort"category must be non-zero"
+} : parse-cat-num
+{ @end? abort"smart contract address expected"
+ @next false parse-load-address drop
+} : cl-parse-smc-addr
+{ @end? abort"adnl address expected"
+ @next parse-adnl-addr
+} : cl-parse-adnl-addr
+{ } : serialize-smc-addr
+{ } : serialize-next-resolver
+{ } : serialize-adnl-addr
+{ } : serialize-text
+{ @end? abort"subdomain record value expected" @next
+ dup "smc" $= { drop cl-parse-smc-addr serialize-smc-addr } {
+ dup "next" $= { drop cl-parse-smc-addr serialize-next-resolver } {
+ dup "adnl" $= { drop cl-parse-adnl-addr serialize-adnl-addr } {
+ dup "text" $= { drop @next serialize-text } {
+ "unknown record type "' swap $+ +"'" abort
+ } cond } cond } cond } cond
+} : parse-value
+{ @next dup "owner" $= { drop -2 cl-parse-smc-addr serialize-smc-addr } {
+ dup "cat" $= { drop parse-cat-num parse-value } {
+ "unknown action '" swap $+ +"'" abort
+ } cond } cond
+ register-value
+} : parse-action
+{ { @end? not } { parse-action } while } : parse-actions
+parse-actions
+
+// ( S -- S1 .. Sn n )
+{ 1 swap { dup "." $pos dup 0>= } { $| 1 $| nip rot 1+ swap } while drop swap
+} : split-by-dots
+// ( S -- s )
+{ dup $len dup 0= abort"subdomain cannot be empty" 126 > abort"subdomain too long"
+ dup 0 chr $pos 1+ abort"subdomain contains null characters"
+ split-by-dots s
+
+main-op ( _( `add 0x72656764 ) _( `update 0x75706464 ) _( `prolong 0x70726f6c ) )
+assq-val not abort"unknown main operation"
+=: op-id
+
+."Automatic DNS smart contract address = " dest-addr 2dup .addr cr 6 .Addr cr
+
+."Action: " main-op .l subdomain type space expire-at . cr
+."Operation code: 0x" op-id 8 0X. cr
+."Value: "
+Values @ dup null? { drop ."(none)" } { =: actions-builder
+
+// create an internal message
+now 32 << actions-builder hashu 32 1<<1- and + =: query_id
+s tuck sbits 8 / 7 i, swap s,
+ main-op `prolong eq? { Values @ ref, } ifnot
+ expire-at 32 u, b>
+dup ."Internal message body is: " B dup Bx. cr
+."Query_id is " query_id dup . ."= 0x" X. cr
+savefile tuck B>file
+."(Saved to file " type .")" cr
diff --git a/crypto/smartcont/dns-auto-code.fc b/crypto/smartcont/dns-auto-code.fc
index 854f4f25..e548a70a 100644
--- a/crypto/smartcont/dns-auto-code.fc
+++ b/crypto/smartcont/dns-auto-code.fc
@@ -107,22 +107,24 @@ global var query_info;
;; no iterating and deleting all to not put too much gas gc
;; burden on any random specific user request
;; over time it will do the garbage collection required
- (int mkey, cell domain, int found?) = gc.udict_get_min_ref?(32 + 128);
+ (int mkey, _, int found?) = gc.udict_get_min?(256);
while (found? & max_steps) { ;; no short circuit optimization, two nested ifs
- nhk = (mkey >> 128);
+ nhk = (mkey >> (256 - 32));
if (nhk < n) {
- slice sdomain = domain.begin_parse();
- (_, slice val, _, found?) = dd.pfxdict_get?(1023, sdomain);
+ int key = mkey % (1 << (256 - 32));
+ (slice val, found?) = dd.udict_get?(256 - 32, key);
if (found?) {
int exp = val.preload_uint(32);
if (exp <= n) {
- dd~pfxdict_delete?(1023, sdomain);
+ dd~udict_delete?(256 - 32, key);
}
}
- gc~udict_delete?(32 + 128, mkey);
- (mkey, domain, found?) = gc.udict_get_min_ref?(32 + 128);
- nhk = (found? ? mkey >> 32 : 0xffffffff);
+ gc~udict_delete?(256, mkey);
+ (mkey, _, found?) = gc.udict_get_min?(256);
+ nhk = (found? ? mkey >> (256 - 32) : 0xffffffff);
max_steps -= 1;
+ } else {
+ found? = false;
}
}
store_data(ctl, dd, gc, prices, nhk, n);
@@ -134,16 +136,15 @@ int calcprice_internal(slice domain, cell data, ppc, ppb) inline_ref { ;; only f
return ppc * (refs + 2) + ppb * bits;
}
-int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
- if (cat_table.null?()) { ;; domain not found: return notf | 2^31
+int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int strict) inline_ref {
+ if (strict & cat_table.null?()) { ;; domain not found: return notf | 2^31
return 0xee6f7466;
}
- cell cown = cat_table.idict_get_ref(16, -2);
- if (cown.null?()) { ;; no owner on this domain: no-2
- return 0xee6f2d32;
+ if (owner_info.null?()) { ;; no owner on this domain: no-2 (in strict mode), ok else
+ return strict & 0xee6f2d32;
}
var ERR_BAD2 = 0xe2616432;
- slice sown = cown.begin_parse();
+ slice sown = owner_info.begin_parse();
if (sown.slice_bits() < 16 + 3 + 8 + 256) { ;; bad owner record: bad2
return ERR_BAD2;
}
@@ -272,38 +273,38 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
return send_error(0xee6f5c30);
}
- int zeros = 0;
- slice cdomain = domain;
- repeat (cdomain.slice_bits() ^>> 3) {
- int c = cdomain~load_uint(8);
- zeros -= (c == 0);
- }
-
- ;; if (zeros != 1) { ;; too much zero chars (overflow): ov\0
- ;; return send_error(0xef765c30); }
-
- domain = begin_cell().store_uint(zeros, 7).store_slice(domain).end_cell().begin_parse();
-
- (slice pfx, slice val, slice tail, int found?) = domdata.pfxdict_get?(1023, domain);
int n = now();
- cell cat_table = null();
- int exp = 0;
-
- if (found?) {
- exp = val~load_uint(32);
- if (n > exp) { ;; expired domains behave as not registered
- found? = false;
- } else {
- cat_table = val.preload_ref();
+ cell cat_table = cell owner_info = null();
+ int key = int exp = int zeros = 0;
+ slice tail = domain;
+ repeat (tail.slice_bits() ^>> 3) {
+ cat_table = null();
+ int z = (tail~load_uint(8) == 0);
+ zeros -= z;
+ if (z) {
+ key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32);
+ var (val, found?) = domdata.udict_get?(256 - 32, key);
+ if (found?) {
+ exp = val~load_uint(32);
+ if (exp >= n) { ;; entry not expired
+ cell cat_table = val~load_ref();
+ val.end_parse();
+ var (cown, ok) = cat_table.idict_get_ref?(16, -2);
+ if (ok) {
+ owner_info = cown;
+ }
+ }
+ }
}
}
+ if (zeros > 4) { ;; too much zero chars (overflow): ov\0
+ return send_error(0xef765c30);
+ }
+
;; ##########################################################################
- int err = 0;
- if (qt != 1) { ;; not a "register", check that domain exists and is controlled by correct smc
- err = check_owner(cat_table, src_wc, src_addr);
- }
+ int err = check_owner(cat_table, owner_info, src_wc, src_addr, qt != 1);
if (err) {
return send_error(err);
}
@@ -317,8 +318,14 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
data = in_msg~load_ref();
;; basic integrity check of (client-provided) dictionary
ifnot (data.dict_empty?()) { ;; 1000 gas!
- (_, _, int minok) = idict_get_min?(data, 16);
- (_, _, int maxok) = idict_get_max?(data, 16);
+ var (oinfo, ok) = data.idict_get_ref?(16, -2);
+ if (ok) {
+ var cs = oinfo.begin_parse();
+ throw_unless(31, cs.slice_bits() >= 16 + 3 + 8 + 256);
+ throw_unless(31, cs.preload_uint(19) == 0x9fd3 * 8 + 4);
+ }
+ (_, _, int minok) = data.idict_get_min?(16);
+ (_, _, int maxok) = data.idict_get_max?(16);
throw_unless(31, minok & maxok);
}
} else {
@@ -345,17 +352,12 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
if (exp > n + stdper) { ;; does not expire soon, cannot prolong
return send_error(0xf365726f);
}
- slice value = begin_cell().store_uint(exp + stdper, 32).store_ref(data).end_cell().begin_parse();
-
- ifnot (domdata~pfxdict_set?(1023, domain, value)) { ;; Set ERR | 2^31
- return send_error(0xf3657272);
- }
-
- int sh_low = domain.slice_hash() & ((1 << 128) - 1);
- int gckeyO = (exp << 128) + sh_low;
- int gckeyN = gckeyO + (stdper << 128);
- gc~udict_delete?(32 + 128, gckeyO); ;; delete old gc entry, add new
- gc~udict_set_ref(32 + 128, gckeyN, begin_cell().store_slice(domain).end_cell());
+ domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp + stdper, 32).store_ref(data));
+
+ int gckeyO = (exp << (256 - 32)) + key;
+ int gckeyN = gckeyO + (stdper << (256 - 32));
+ gc~udict_delete?(256, gckeyO); ;; delete old gc entry, add new
+ gc~udict_set_builder(256, gckeyN, begin_cell());
housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1);
return send_ok(price);
@@ -363,29 +365,22 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
;; ##########################################################################
if (qt == 1) { ;; 0x72656764 -> regd | register domain
- if (found?) { ;; domain already exists: return alre | 2^31
+ ifnot (cat_table.null?()) { ;; domain already exists: return alre | 2^31
return send_error(0xe16c7265);
}
int expires_at = n + stdper;
- slice value = begin_cell().store_uint(expires_at, 32).store_ref(data).end_cell().begin_parse();
- ifnot (domdata~pfxdict_set?(1023, domain, value)) { ;; Set ERR | 2^31
- return send_error(0xf3657272);
- }
- int gckey = (expires_at << 128) | (domain.slice_hash() & ((1 << 128) - 1));
- gc~udict_set_ref(32 + 128, gckey, begin_cell().store_slice(domain).end_cell());
- ;; using ref requires additional cell, but using value (DICTUSET) may
- ;; cause problems with very long domains or complex dictionaries
+ domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(expires_at, 32).store_ref(data));
+
+ int gckey = (expires_at << (256 - 32)) | key;
+ gc~udict_set_builder(256, gckey, begin_cell());
+
housekeeping(ctl, domdata, gc, prices, min(nhk, expires_at), lhk, 1);
return send_ok(price);
}
;; ##########################################################################
if (qt == 4) { ;; 0x75706464 -> updd | update domain (data)
- slice value = begin_cell().store_uint(exp, 32).store_ref(data).end_cell().begin_parse();
-
- ifnot (domdata~pfxdict_set?(1023, domain, value)) { ;; Set ERR | 2^31
- return send_error(0xf3657272);
- }
+ domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp, 32).store_ref(data));
housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1);
return send_ok(price);
}
@@ -412,54 +407,46 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
;;===========================================================================;;
(int, cell, int, slice) dnsdictlookup(slice domain, int nowtime) inline_ref {
- int bits = domain.slice_bits();
+ (int bits, int refs) = domain.slice_bits_refs();
+ throw_if(30, refs | (bits & 7)); ;; malformed input (~ 8n-bit)
ifnot (bits) {
return (0, null(), 0, null()); ;; zero-length input
}
- throw_if(30, bits & 7); ;; malformed input (~ 8n-bit)
int domain_last_byte = domain.slice_last(8).preload_uint(8);
if (domain_last_byte) {
domain = begin_cell().store_slice(domain) ;; append zero byte
- .store_uint(0, 8).end_cell().begin_parse();
+ .store_uint(0, 8).end_cell().begin_parse();
bits += 8;
}
if (bits == 8) {
return (0, null(), 0, null()); ;; zero-length input, but with zero byte
}
- (_, cell root) = get_data().begin_parse().load_dict();
+ var ds = get_data().begin_parse();
+ (_, cell root) = (ds~load_ref(), ds~load_dict());
- slice sd_tail = domain;
- int zeros = 0;
- repeat (bits >> 3) {
- int c = sd_tail~load_uint(8);
- zeros -= (c == 0);
- }
-
- ;; can't move these declarations lower, will cause errors!
- slice tail = slice pfx = sd_tail;
slice val = null();
- int exp = 0;
+ int tail_bits = -1;
+ slice tail = domain;
- do {
- slice pfxname = begin_cell().store_uint(zeros, 7)
- .store_slice(domain).end_cell().begin_parse();
- (pfx, val, tail, int succ) = root.pfxdict_get?(1023, pfxname);
- if (succ) {
- int exp = val~load_uint(32);
- if (nowtime > exp) { ;; entry expired, skip
- succ = false;
+ repeat (bits >> 3) {
+ if (tail~load_uint(8) == 0) {
+ var key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32);
+ var (v, found?) = root.udict_get?(256 - 32, key);
+ if (found?) {
+ if (v.preload_uint(32) >= nowtime) { ;; entry not expired
+ val = v;
+ tail_bits = tail.slice_bits();
+ }
}
}
- zeros = succ ^ (zeros - 1); ;; break on success
- } until (zeros <= 0);
-
- ifnot (zeros) {
- return (0, null(), 0, null()); ;; failed to find entry in prefix dictionary
}
- zeros = - zeros;
- return (exp, val.preload_ref(), tail.slice_empty?(), pfx);
+ if (val.null?()) {
+ return (0, null(), 0, null()); ;; failed to find entry in subdomain dictionary
+ }
+
+ return (val~load_uint(32), val~load_ref(), tail_bits == 0, domain.skip_last_bits(tail_bits));
}
;;8m dns-record-value
@@ -472,12 +459,12 @@ int check_owner(cell cat_table, int src_wc, int src_addr) inline_ref {
category = -1;
}
- int pfx_bits = pfx.slice_bits() - 7;
+ int pfx_bits = pfx.slice_bits();
;; pfx.slice_bits() will contain 8m, where m is number of bytes in subdomain
;; COUNTING the zero byte (if structurally correct: no multiple-ZB keys)
;; which corresponds to 8m, m=one plus the number of bytes in the subdomain found)
- if (category == 0) {
+ ifnot (category) {
return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0
} else {
cell cat_found = cat_table.idict_get_ref(16, category);
diff --git a/crypto/smartcont/manual-dns-manage.fif b/crypto/smartcont/manual-dns-manage.fif
index f8d4a3fb..ef18127c 100644
--- a/crypto/smartcont/manual-dns-manage.fif
+++ b/crypto/smartcont/manual-dns-manage.fif
@@ -94,8 +94,8 @@ file-base +"-dns" +contractid +".addr" load-address
// ( b V -- b' )
{ dup first
dup `smc eq? { drop untriple 2swap drop x{9fd3} s, -rot Addr, 0 8 u, } {
- dup `next eq? { drop untriple 2swap drop x{ba93} s, -rot Addr, 0 8 u, } {
- dup `adnl eq? { drop second swap x{ad01} s, swap 256 u, } {
+ dup `next eq? { drop untriple 2swap drop x{ba93} s, -rot Addr, } {
+ dup `adnl eq? { drop second swap x{ad01} s, swap 256 u, 0 8 u, } {
dup `text eq? { drop second swap x{1eda01} s, over $len 8 u, swap $, } {
abort"unknown value type"
} cond } cond } cond } cond
diff --git a/crypto/smartcont/stdlib.fc b/crypto/smartcont/stdlib.fc
index 2d1a47c4..ca8337e1 100644
--- a/crypto/smartcont/stdlib.fc
+++ b/crypto/smartcont/stdlib.fc
@@ -6,6 +6,11 @@ forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
forall X -> X car(tuple list) asm "CAR";
tuple cdr(tuple list) asm "CDR";
+tuple empty_tuple() asm "NIL";
+forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
+forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
+forall X -> [X] single(X x) asm "SINGLE";
+forall X -> X unsingle([X] t) asm "UNSINGLE";
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
@@ -22,6 +27,7 @@ forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
forall X -> X null() asm "PUSHNULL";
+forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
int now() asm "NOW";
slice my_address() asm "MYADDR";
@@ -115,7 +121,8 @@ cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value inde
cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
-cell udict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETOPTREF";
+(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF";
+(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF";
(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
diff --git a/crypto/smc-envelope/ManualDns.cpp b/crypto/smc-envelope/ManualDns.cpp
index 8acba1c8..00f1becb 100644
--- a/crypto/smc-envelope/ManualDns.cpp
+++ b/crypto/smc-envelope/ManualDns.cpp
@@ -146,6 +146,23 @@ td::Result DnsInterface::EntryData::from_cellslice(vm::
return td::Status::Error("Unknown entry data");
}
+SmartContract::Args DnsInterface::resolve_args_raw(td::Slice encoded_name, td::int16 category) {
+ SmartContract::Args res;
+ res.set_method_id("dnsresolve");
+ res.set_stack(
+ {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes(encoded_name).finalize()), td::make_refint(category)});
+ return res;
+}
+
+td::Result DnsInterface::resolve_args(td::Slice name, td::int32 category_big) {
+ TRY_RESULT(category, td::narrow_cast_safe(category_big));
+ if (name.size() > get_default_max_name_size()) {
+ return td::Status::Error("Name is too long");
+ }
+ auto encoded_name = encode_name(name);
+ return resolve_args_raw(encoded_name, category);
+}
+
td::Result> DnsInterface::resolve(td::Slice name, td::int32 category) const {
TRY_RESULT(raw_entries, resolve_raw(name, category));
std::vector entries;
@@ -375,7 +392,7 @@ td::Ref ManualDns::create_init_data_fast(const td::Ed25519::PublicKey&
}
size_t ManualDns::get_max_name_size() const {
- return 128;
+ return get_default_max_name_size();
}
td::Result> ManualDns::resolve_raw(td::Slice name, td::int32 category_big) const {
@@ -388,9 +405,7 @@ td::Result> ManualDns::resolve_raw_or_throw(td:
return td::Status::Error("Name is too long");
}
auto encoded_name = encode_name(name);
- auto res = run_get_method(
- "dnsresolve",
- {vm::load_cell_slice_ref(vm::CellBuilder().store_bytes(encoded_name).finalize()), td::make_refint(category)});
+ auto res = run_get_method(resolve_args_raw(encoded_name, category));
if (!res.success) {
return td::Status::Error("get method failed");
}
@@ -471,7 +486,7 @@ td::Result> ManualDns::create_update_query(td::Ed25519::Privat
return sign(pk, std::move(prepared));
}
-std::string ManualDns::encode_name(td::Slice name) {
+std::string DnsInterface::encode_name(td::Slice name) {
std::string res;
while (!name.empty()) {
auto pos = name.rfind('.');
@@ -487,7 +502,7 @@ std::string ManualDns::encode_name(td::Slice name) {
return res;
}
-std::string ManualDns::decode_name(td::Slice name) {
+std::string DnsInterface::decode_name(td::Slice name) {
std::string res;
if (!name.empty() && name.back() == 0) {
name.remove_suffix(1);
diff --git a/crypto/smc-envelope/ManualDns.h b/crypto/smc-envelope/ManualDns.h
index 74977c31..fbf12e74 100644
--- a/crypto/smc-envelope/ManualDns.h
+++ b/crypto/smc-envelope/ManualDns.h
@@ -165,6 +165,15 @@ class DnsInterface {
td::uint32 valid_until = std::numeric_limits::max()) const = 0;
td::Result> resolve(td::Slice name, td::int32 category) const;
+
+ static std::string encode_name(td::Slice name);
+ static std::string decode_name(td::Slice name);
+
+ static size_t get_default_max_name_size() {
+ return 128;
+ }
+ static SmartContract::Args resolve_args_raw(td::Slice encoded_name, td::int16 category);
+ static td::Result resolve_args(td::Slice name, td::int32 category);
};
class ManualDns : public ton::SmartContract, public DnsInterface {
@@ -223,9 +232,6 @@ class ManualDns : public ton::SmartContract, public DnsInterface {
td::Ed25519::PrivateKey& pk, td::Span actions,
td::uint32 valid_until = std::numeric_limits::max()) const override;
- static std::string encode_name(td::Slice name);
- static std::string decode_name(td::Slice name);
-
template
struct CombinedActions {
std::string name;
diff --git a/crypto/smc-envelope/MultisigWallet.cpp b/crypto/smc-envelope/MultisigWallet.cpp
index ce1795ee..5a9fab6a 100644
--- a/crypto/smc-envelope/MultisigWallet.cpp
+++ b/crypto/smc-envelope/MultisigWallet.cpp
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2019-2020 Telegram Systems LLP
+*/
#include "MultisigWallet.h"
#include "SmartContractCode.h"
diff --git a/crypto/smc-envelope/MultisigWallet.h b/crypto/smc-envelope/MultisigWallet.h
index 17395e47..96da297a 100644
--- a/crypto/smc-envelope/MultisigWallet.h
+++ b/crypto/smc-envelope/MultisigWallet.h
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2019-2020 Telegram Systems LLP
+*/
#pragma once
#include "vm/cells.h"
diff --git a/crypto/smc-envelope/SmartContract.cpp b/crypto/smc-envelope/SmartContract.cpp
index 17477de9..36ba2730 100644
--- a/crypto/smc-envelope/SmartContract.cpp
+++ b/crypto/smc-envelope/SmartContract.cpp
@@ -24,19 +24,21 @@
#include "block/block-auto.h"
#include "vm/cellslice.h"
#include "vm/cp0.h"
+#include "vm/memo.h"
#include "vm/vm.h"
#include "td/utils/crypto.h"
namespace ton {
namespace {
+
td::Ref prepare_vm_stack(td::Ref body) {
td::Ref stack_ref{true};
td::RefInt256 acc_addr{true};
//CHECK(acc_addr.write().import_bits(account.addr.cbits(), 256));
vm::Stack& stack = stack_ref.write();
- stack.push_int(td::RefInt256{true, 10000000000});
- stack.push_int(td::RefInt256{true, 10000000000});
+ stack.push_int(td::make_refint(10000000000));
+ stack.push_int(td::make_refint(10000000000));
stack.push_cell(vm::CellBuilder().finalize());
stack.push_cellslice(std::move(body));
return stack_ref;
@@ -90,6 +92,11 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref= VERBOSITY_NAME(DEBUG)) {
+ std::ostringstream os;
+ stack->dump(os, 2);
+ LOG(DEBUG) << "VM stack:\n" << os.str();
+ }
vm::VmState vm{state.code, std::move(stack), gas, 1, state.data, log};
vm.set_c7(std::move(c7));
vm.set_chksig_always_succeed(ignore_chksig);
@@ -124,6 +131,21 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref SmartContract::Args::get_serialized_stack() {
+ if (!stack) {
+ return td::Status::Error("Args has no stack");
+ }
+ vm::FakeVmStateLimits fstate(1000); // limit recursive (de)serialization calls
+ vm::VmStateInterface::Guard guard(&fstate);
+ // serialize parameters
+ vm::CellBuilder cb;
+ td::Ref cell;
+ if (!(stack.value()->serialize(cb) && cb.finalize_to(cell))) {
+ return td::Status::Error("Cannot serialize stack in args");
+ }
+ return vm::std_boc_serialize(std::move(cell));
+}
+
td::Ref SmartContract::empty_slice() {
return vm::load_cell_slice_ref(vm::CellBuilder().finalize());
}
diff --git a/crypto/smc-envelope/SmartContract.h b/crypto/smc-envelope/SmartContract.h
index 14b5b947..24c2d132 100644
--- a/crypto/smc-envelope/SmartContract.h
+++ b/crypto/smc-envelope/SmartContract.h
@@ -90,6 +90,14 @@ class SmartContract : public td::CntObject {
this->ignore_chksig = ignore_chksig;
return std::move(*this);
}
+
+ td::Result get_method_id() const {
+ if (!method_id) {
+ return td::Status::Error("Args has no method id");
+ }
+ return method_id.value();
+ }
+ td::Result get_serialized_stack();
};
Answer run_method(Args args = {});
diff --git a/crypto/smc-envelope/SmartContractCode.cpp b/crypto/smc-envelope/SmartContractCode.cpp
index eea5ac21..6256dcc0 100644
--- a/crypto/smc-envelope/SmartContractCode.cpp
+++ b/crypto/smc-envelope/SmartContractCode.cpp
@@ -25,12 +25,12 @@
namespace ton {
namespace {
-constexpr static int WALLET_REVISION = 2;
-constexpr static int WALLET2_REVISION = 2;
-constexpr static int WALLET3_REVISION = 2;
-constexpr static int HIGHLOAD_WALLET_REVISION = 2;
-constexpr static int HIGHLOAD_WALLET2_REVISION = 2;
-constexpr static int DNS_REVISION = 1;
+// WALLET_REVISION = 2;
+// WALLET2_REVISION = 2;
+// WALLET3_REVISION = 2;
+// HIGHLOAD_WALLET_REVISION = 2;
+// HIGHLOAD_WALLET2_REVISION = 2;
+// DNS_REVISION = 1;
const auto& get_map() {
static auto map = [] {
std::map, std::less<>> map;
diff --git a/crypto/smc-envelope/WalletInterface.h b/crypto/smc-envelope/WalletInterface.h
index e0e439c3..2c7760a1 100644
--- a/crypto/smc-envelope/WalletInterface.h
+++ b/crypto/smc-envelope/WalletInterface.h
@@ -31,8 +31,11 @@ class WalletInterface {
struct Gift {
block::StdAddress destination;
td::int64 gramms;
+
bool is_encrypted{false};
std::string message;
+
+ td::Ref body;
};
virtual ~WalletInterface() {
@@ -50,6 +53,13 @@ class WalletInterface {
return make_a_gift_message(private_key, valid_until, {});
}
static void store_gift_message(vm::CellBuilder &cb, const Gift &gift) {
+ if (gift.body.not_null()) {
+ auto body = vm::load_cell_slice(gift.body);
+ //TODO: handle error
+ cb.append_cellslice_bool(body);
+ return;
+ }
+
if (gift.is_encrypted) {
cb.store_long(1, 32);
} else {
diff --git a/crypto/tl/tlbc-gen-cpp.cpp b/crypto/tl/tlbc-gen-cpp.cpp
index 3de92bd5..dedec15d 100644
--- a/crypto/tl/tlbc-gen-cpp.cpp
+++ b/crypto/tl/tlbc-gen-cpp.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "tlbc-gen-cpp.h"
#include "td/utils/bits.h"
@@ -94,6 +94,7 @@ void init_forbidden_cpp_idents() {
l.insert("get_size");
l.insert("pack");
l.insert("unpack");
+ l.insert("ops");
l.insert("cs");
l.insert("cb");
l.insert("cell_ref");
@@ -2014,7 +2015,7 @@ void CppTypeCode::generate_skip_field(const Constructor& constr, const Field& fi
output_cpp_expr(ss, expr, 100, true);
ss << '.';
}
- ss << (validating ? "validate_skip(cs, weak" : "skip(cs");
+ ss << (validating ? "validate_skip(ops, cs, weak" : "skip(cs");
output_negative_type_arguments(ss, expr);
ss << ")";
actions += Action{std::move(ss)};
@@ -2054,7 +2055,7 @@ void CppTypeCode::generate_skip_field(const Constructor& constr, const Field& fi
output_cpp_expr(ss, expr, 100);
ss << '.';
}
- ss << (validating ? "validate_skip(cs, weak)" : "skip(cs)") << tail;
+ ss << (validating ? "validate_skip(ops, cs, weak)" : "skip(cs)") << tail;
actions += Action{std::move(ss)};
return;
}
@@ -2074,7 +2075,7 @@ void CppTypeCode::generate_skip_field(const Constructor& constr, const Field& fi
output_cpp_expr(ss, expr, 100);
ss << '.';
}
- ss << "validate_skip_ref(cs, weak)" << tail;
+ ss << "validate_skip_ref(ops, cs, weak)" << tail;
actions += Action{ss.str()};
}
@@ -2101,8 +2102,8 @@ void CppTypeCode::generate_skip_cons_method(std::ostream& os, std::string nl, in
void CppTypeCode::generate_skip_method(std::ostream& os, int options) {
bool validate = options & 1;
bool ret_ext = options & 2;
- os << "\nbool " << cpp_type_class_name << "::" << (validate ? "validate_" : "") << "skip(vm::CellSlice& cs"
- << (validate ? ", bool weak" : "");
+ os << "\nbool " << cpp_type_class_name
+ << "::" << (validate ? "validate_skip(int* ops, vm::CellSlice& cs, bool weak" : "skip(vm::CellSlice& cs");
if (ret_ext) {
os << skip_extra_args;
}
@@ -2470,7 +2471,7 @@ void CppTypeCode::generate_unpack_field(const CppTypeCode::ConsField& fi, const
output_cpp_expr(ss, expr, 100, true);
ss << '.';
}
- ss << (validating ? "validate_fetch_to(cs, weak, " : "fetch_to(cs, ") << field_vars.at(i);
+ ss << (validating ? "validate_fetch_to(ops, cs, weak, " : "fetch_to(cs, ") << field_vars.at(i);
output_negative_type_arguments(ss, expr);
ss << ")";
actions += Action{std::move(ss)};
@@ -2514,8 +2515,8 @@ void CppTypeCode::generate_unpack_field(const CppTypeCode::ConsField& fi, const
output_cpp_expr(ss, expr, 100);
ss << '.';
}
- ss << (validating ? "validate_" : "") << "fetch_" << (cvt == ct_enum ? "enum_" : "") << "to(cs, "
- << (validating ? "weak, " : "") << field_vars.at(i) << ")" << tail;
+ ss << (validating ? "validate_" : "") << "fetch_" << (cvt == ct_enum ? "enum_" : "")
+ << (validating ? "to(ops, cs, weak, " : "to(cs, ") << field_vars.at(i) << ")" << tail;
field_var_set[i] = true;
actions += Action{std::move(ss)};
return;
@@ -2540,7 +2541,7 @@ void CppTypeCode::generate_unpack_field(const CppTypeCode::ConsField& fi, const
output_cpp_expr(ss, expr, 100);
ss << '.';
}
- ss << "validate_ref(" << field_vars.at(i) << "))" << tail;
+ ss << "validate_ref(ops, " << field_vars.at(i) << "))" << tail;
actions += Action{ss.str()};
}
@@ -2559,7 +2560,11 @@ void CppTypeCode::generate_unpack_method(std::ostream& os, CppTypeCode::ConsReco
<< "\n auto cs = load_cell_slice(std::move(cell_ref));"
<< "\n return " << (options & 1 ? "validate_" : "") << "unpack";
if (!(options & 8)) {
- os << "(cs, data";
+ os << "(";
+ if (options & 1) {
+ os << "ops, ";
+ }
+ os << "cs, data";
} else {
os << "_" << cons_enum_name.at(rec.cons_idx) << "(cs";
for (const auto& f : rec.cpp_fields) {
@@ -2773,7 +2778,7 @@ void CppTypeCode::generate_pack_field(const CppTypeCode::ConsField& fi, const Co
output_cpp_expr(ss, expr, 100);
ss << '.';
}
- ss << "validate_ref(" << field_vars.at(i) << "))" << tail;
+ ss << "validate_ref(ops, " << field_vars.at(i) << "))" << tail;
actions += Action{ss.str()};
}
@@ -3093,7 +3098,7 @@ void CppTypeCode::generate_header(std::ostream& os, int options) {
if (ret_params) {
os << " bool skip(vm::CellSlice& cs" << skip_extra_args << ") const;\n";
}
- os << " bool validate_skip(vm::CellSlice& cs, bool weak = false) const override";
+ os << " bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override";
if (!inline_validate_skip) {
os << ";\n";
} else if (sz) {
@@ -3102,7 +3107,7 @@ void CppTypeCode::generate_header(std::ostream& os, int options) {
os << " {\n return true;\n }\n";
}
if (ret_params) {
- os << " bool validate_skip(vm::CellSlice& cs, bool weak" << skip_extra_args << ") const;\n";
+ os << " bool validate_skip(int *ops, vm::CellSlice& cs, bool weak" << skip_extra_args << ") const;\n";
os << " bool fetch_to(vm::CellSlice& cs, Ref& res" << skip_extra_args << ") const;\n";
}
if (type.is_simple_enum) {
diff --git a/crypto/tl/tlblib.cpp b/crypto/tl/tlblib.cpp
index 4a9475ea..617c298b 100644
--- a/crypto/tl/tlblib.cpp
+++ b/crypto/tl/tlblib.cpp
@@ -114,38 +114,43 @@ bool TupleT::skip(vm::CellSlice& cs) const {
return !i;
}
-bool TupleT::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool TupleT::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int i = n;
for (; i > 0; --i) {
- if (!X.validate_skip(cs, weak)) {
+ if (!X.validate_skip(ops, cs, weak)) {
break;
}
}
return !i;
}
-bool TLB::validate_ref_internal(Ref cell_ref, bool weak) const {
+bool TLB::validate_ref_internal(int* ops, Ref cell_ref, bool weak) const {
+ if (ops && --*ops < 0) {
+ return false;
+ }
bool is_special;
auto cs = load_cell_slice_special(std::move(cell_ref), is_special);
- return always_special() ? is_special : (is_special ? weak : (validate_skip(cs) && cs.empty_ext()));
+ return always_special() ? is_special : (is_special ? weak : (validate_skip(ops, cs) && cs.empty_ext()));
}
bool TLB::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
pp.open("raw@");
pp << *this << ' ';
vm::CellSlice cs_copy{cs};
- if (!validate_skip(cs) || !cs_copy.cut_tail(cs)) {
+ int size_limit = pp.limit;
+ if (!validate_skip(&size_limit, cs) || !cs_copy.cut_tail(cs)) {
return pp.fail("invalid value");
}
pp.raw_nl();
- return cs_copy.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close();
+ return (cs_copy.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close()) ||
+ pp.fail("raw value too long");
}
bool TLB::print_special(PrettyPrinter& pp, vm::CellSlice& cs) const {
pp.open("raw@");
pp << *this << ' ';
pp.raw_nl();
- return cs.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close();
+ return (cs.print_rec(pp.os, &pp.limit, pp.indent) && pp.mkindent() && pp.close()) || pp.fail("raw value too long");
}
bool TLB::print_ref(PrettyPrinter& pp, Ref cell_ref) const {
@@ -217,7 +222,7 @@ PrettyPrinter::~PrettyPrinter() {
}
bool PrettyPrinter::fail(std::string msg) {
- os << "";
+ os << "" << std::endl;
failed = true;
return false;
}
diff --git a/crypto/tl/tlblib.hpp b/crypto/tl/tlblib.hpp
index 407df292..7543d38f 100644
--- a/crypto/tl/tlblib.hpp
+++ b/crypto/tl/tlblib.hpp
@@ -30,6 +30,7 @@ struct PrettyPrinter;
class TLB {
public:
+ enum { default_validate_max_cells = 1024 };
virtual ~TLB() = default;
virtual int get_size(const vm::CellSlice& cs) const {
return -1;
@@ -37,14 +38,26 @@ class TLB {
virtual bool skip(vm::CellSlice& cs) const {
return cs.skip_ext(get_size(cs));
}
- virtual bool validate(const vm::CellSlice& cs, bool weak = false) const {
+ virtual bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const {
return cs.have_ext(get_size(cs));
}
- virtual bool validate_exact(const vm::CellSlice& cs, bool weak = false) const {
+ virtual bool validate_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const {
return (int)cs.size_ext() == get_size(cs);
}
+ bool validate_upto(int ops, const vm::CellSlice& cs, bool weak = false) const {
+ return validate(&ops, cs, weak);
+ }
+ bool validate_exact_upto(int ops, const vm::CellSlice& cs, bool weak = false) const {
+ return validate_exact(&ops, cs, weak);
+ }
+ bool validate_csr(int* ops, Ref cs_ref, bool weak = false) const {
+ return cs_ref.not_null() && validate_skip_exact(ops, cs_ref.write(), weak);
+ }
+ bool validate_csr(int ops, Ref cs_ref, bool weak = false) const {
+ return validate_csr(&ops, std::move(cs_ref), weak);
+ }
bool validate_csr(Ref cs_ref, bool weak = false) const {
- return cs_ref.not_null() && validate_skip_exact(cs_ref.write(), weak);
+ return validate_csr(default_validate_max_cells, std::move(cs_ref), weak);
}
Ref fetch(vm::CellSlice& cs) const {
return cs.fetch_subslice_ext(get_size(cs));
@@ -52,67 +65,71 @@ class TLB {
Ref prefetch(const vm::CellSlice& cs) const {
return cs.prefetch_subslice_ext(get_size(cs));
}
- virtual Ref validate_fetch(vm::CellSlice& cs, bool weak = false) const {
- return validate(cs, weak) ? cs.fetch_subslice_ext(get_size(cs)) : Ref{};
+ virtual Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate(ops, cs, weak) ? cs.fetch_subslice_ext(get_size(cs)) : Ref{};
}
- virtual Ref validate_prefetch(const vm::CellSlice& cs, bool weak = false) const {
- return validate(cs, weak) ? cs.prefetch_subslice_ext(get_size(cs)) : Ref{};
+ virtual Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const {
+ return validate(ops, cs, weak) ? cs.prefetch_subslice_ext(get_size(cs)) : Ref{};
}
bool fetch_to(vm::CellSlice& cs, Ref& res) const {
return (res = fetch(cs)).not_null();
}
- bool validate_fetch_to(vm::CellSlice& cs, Ref& res, bool weak = false) const {
- return (res = validate_fetch(cs, weak)).not_null();
+ bool validate_fetch_to(int* ops, vm::CellSlice& cs, Ref& res, bool weak = false) const {
+ return (res = validate_fetch(ops, cs, weak)).not_null();
}
bool store_from(vm::CellBuilder& cb, Ref field) const {
return field.not_null() && get_size(*field) == (int)field->size_ext() && cb.append_cellslice_bool(std::move(field));
}
- bool validate_store_from(vm::CellBuilder& cb, Ref field, bool weak = false) const {
+ bool validate_store_from(int* ops, vm::CellBuilder& cb, Ref field, bool weak = false) const {
if (field.is_null()) {
return false;
}
vm::CellSlice cs{*field};
- return validate_skip(cs, weak) && cs.empty_ext() && cb.append_cellslice_bool(std::move(field));
+ return validate_skip(ops, cs, weak) && cs.empty_ext() && cb.append_cellslice_bool(std::move(field));
}
virtual bool extract(vm::CellSlice& cs) const {
return cs.only_ext(get_size(cs));
}
- virtual bool validate_extract(vm::CellSlice& cs, bool weak = false) const {
- return validate(cs, weak) && extract(cs);
+ virtual bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate(ops, cs, weak) && extract(cs);
}
int get_size_by_skip(const vm::CellSlice& cs) const {
vm::CellSlice copy{cs};
return skip(copy) ? copy.subtract_base_ext(cs) : -1;
}
- virtual bool validate_skip(vm::CellSlice& cs, bool weak = false) const {
- return validate(cs, weak) && skip(cs);
+ virtual bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate(ops, cs, weak) && skip(cs);
}
- bool validate_skip_exact(vm::CellSlice& cs, bool weak = false) const {
- return validate_skip(cs, weak) && cs.empty_ext();
+ bool validate_skip_upto(int ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate_skip(&ops, cs, weak);
}
- bool validate_by_skip(const vm::CellSlice& cs, bool weak = false) const {
+ bool validate_skip_exact(int* ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate_skip(ops, cs, weak) && cs.empty_ext();
+ }
+ bool validate_by_skip(int* ops, const vm::CellSlice& cs, bool weak = false) const {
vm::CellSlice copy{cs};
- return validate_skip(copy, weak);
+ return validate_skip(ops, copy, weak);
}
- bool validate_by_skip_exact(const vm::CellSlice& cs, bool weak = false) const {
+ bool validate_by_skip_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const {
vm::CellSlice copy{cs};
- return validate_skip_exact(copy, weak);
+ return validate_skip_exact(ops, copy, weak);
}
bool extract_by_skip(vm::CellSlice& cs) const {
vm::CellSlice copy{cs};
return skip(copy) && cs.cut_tail(copy);
}
- bool validate_extract_by_skip(vm::CellSlice& cs, bool weak = false) const {
+ bool validate_extract_by_skip(int* ops, vm::CellSlice& cs, bool weak = false) const {
vm::CellSlice copy{cs};
- return validate_skip(copy, weak) && cs.cut_tail(copy);
+ return validate_skip(ops, copy, weak) && cs.cut_tail(copy);
}
- Ref validate_fetch_by_skip(vm::CellSlice& cs, bool weak = false) const {
+ Ref validate_fetch_by_skip(int* ops, vm::CellSlice& cs, bool weak = false) const {
Ref copy{true, cs};
- return validate_skip(cs, weak) && copy.unique_write().cut_tail(cs) ? copy : Ref{};
+ return validate_skip(ops, cs, weak) && copy.unique_write().cut_tail(cs) ? copy : Ref{};
}
- Ref validate_prefetch_by_skip(const vm::CellSlice& cs, bool weak = false) const {
+ Ref validate_prefetch_by_skip(int* ops, const vm::CellSlice& cs, bool weak = false) const {
vm::CellSlice copy{cs};
- return validate_skip(copy, false) ? cs.prefetch_subslice_ext(copy.subtract_base_ext(cs)) : Ref{};
+ return validate_skip(ops, copy, false) ? cs.prefetch_subslice_ext(copy.subtract_base_ext(cs))
+ : Ref{};
}
virtual bool skip_copy(vm::CellBuilder& cb, vm::CellSlice& cs) const {
return cb.append_cellslice_bool(fetch(cs));
@@ -156,14 +173,29 @@ class TLB {
bool as_integer_to(Ref cs_ref, td::RefInt256& res) const {
return (res = as_integer(std::move(cs_ref))).not_null();
}
+ bool validate_ref(int* ops, Ref cell_ref, bool weak = false) const {
+ return cell_ref.not_null() && validate_ref_internal(ops, std::move(cell_ref), weak);
+ }
+ bool validate_ref(int ops, Ref cell_ref, bool weak = false) const {
+ return validate_ref(&ops, std::move(cell_ref), weak);
+ }
bool validate_ref(Ref cell_ref, bool weak = false) const {
- return cell_ref.not_null() && validate_ref_internal(std::move(cell_ref), weak);
+ return validate_ref(default_validate_max_cells, std::move(cell_ref), weak);
+ }
+ bool force_validate_ref(int* ops, Ref cell_ref) const {
+ return cell_ref.not_null() && validate_ref_internal(ops, std::move(cell_ref), false);
+ }
+ bool force_validate_ref(int ops, Ref cell_ref) const {
+ return force_validate_ref(&ops, std::move(cell_ref));
}
bool force_validate_ref(Ref cell_ref) const {
- return cell_ref.not_null() && validate_ref_internal(std::move(cell_ref), false);
+ return force_validate_ref(default_validate_max_cells, std::move(cell_ref));
}
- bool validate_skip_ref(vm::CellSlice& cs, bool weak = false) const {
- return validate_ref(cs.fetch_ref(), weak);
+ bool validate_skip_ref(int* ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate_ref(ops, cs.fetch_ref(), weak);
+ }
+ bool validate_skip_ref(int ops, vm::CellSlice& cs, bool weak = false) const {
+ return validate_skip_ref(&ops, cs, weak);
}
virtual bool null_value(vm::CellBuilder& cb) const {
return false;
@@ -214,6 +246,9 @@ class TLB {
return print(os, *cs_ref, indent, rec_limit);
}
bool print_ref(std::ostream& os, Ref cell_ref, int indent = 0, int rec_limit = 0) const;
+ bool print_ref(int rec_limit, std::ostream& os, Ref cell_ref, int indent = 0) const {
+ return print_ref(os, std::move(cell_ref), indent, rec_limit);
+ }
std::string as_string_skip(vm::CellSlice& cs, int indent = 0) const;
std::string as_string(const vm::CellSlice& cs, int indent = 0) const;
std::string as_string(Ref cs_ref, int indent = 0) const {
@@ -225,7 +260,7 @@ class TLB {
}
protected:
- bool validate_ref_internal(Ref cell_ref, bool weak = false) const;
+ bool validate_ref_internal(int* ops, Ref cell_ref, bool weak = false) const;
};
static inline std::ostream& operator<<(std::ostream& os, const TLB& type) {
@@ -234,29 +269,29 @@ static inline std::ostream& operator<<(std::ostream& os, const TLB& type) {
struct TLB_Complex : TLB {
bool skip(vm::CellSlice& cs) const override {
- return validate_skip(cs);
+ return validate_skip(nullptr, cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override = 0;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override = 0;
int get_size(const vm::CellSlice& cs) const override {
return get_size_by_skip(cs);
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
- return validate_by_skip(cs, weak);
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return validate_by_skip(ops, cs, weak);
}
- bool validate_exact(const vm::CellSlice& cs, bool weak = false) const override {
- return validate_by_skip_exact(cs, weak);
+ bool validate_exact(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return validate_by_skip_exact(ops, cs, weak);
}
bool extract(vm::CellSlice& cs) const override {
return extract_by_skip(cs);
}
- bool validate_extract(vm::CellSlice& cs, bool weak = false) const override {
- return validate_extract_by_skip(cs, weak);
+ bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return validate_extract_by_skip(ops, cs, weak);
}
- Ref validate_fetch(vm::CellSlice& cs, bool weak = false) const override {
- return validate_fetch_by_skip(cs, weak);
+ Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return validate_fetch_by_skip(ops, cs, weak);
}
- Ref validate_prefetch(const vm::CellSlice& cs, bool weak = false) const override {
- return validate_prefetch_by_skip(cs, weak);
+ Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return validate_prefetch_by_skip(ops, cs, weak);
}
td::RefInt256 as_integer(const vm::CellSlice& cs) const override {
vm::CellSlice copy{cs};
@@ -615,23 +650,23 @@ struct FwdT final : TLB {
bool skip(vm::CellSlice& cs) const override {
return X.skip(cs);
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
- return X.validate(cs, weak);
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate(ops, cs, weak);
}
- Ref validate_fetch(vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_fetch(cs, weak);
+ Ref validate_fetch(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_fetch(ops, cs, weak);
}
- Ref validate_prefetch(const vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_prefetch(cs, weak);
+ Ref validate_prefetch(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_prefetch(ops, cs, weak);
}
bool extract(vm::CellSlice& cs) const override {
return X.extract(cs);
}
- bool validate_extract(vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_extract(cs, weak);
+ bool validate_extract(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_extract(ops, cs, weak);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_skip(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_skip(ops, cs, weak);
}
bool skip_copy(vm::CellBuilder& cb, vm::CellSlice& cs) const override {
return X.skip_copy(cb, cs);
@@ -726,10 +761,10 @@ struct NatLess final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return n >= 0 ? w : -1;
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
return n >= 0 && (unsigned)cs.prefetch_ulong(w) <= (unsigned)n;
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return n >= 0 && (unsigned)cs.fetch_ulong(w) <= (unsigned)n;
}
unsigned long long as_uint(const vm::CellSlice& cs) const override {
@@ -749,10 +784,10 @@ struct NatLeq final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return n >= 0 ? w : -1;
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
return n >= 0 && (unsigned)cs.prefetch_ulong(w) <= (unsigned)n;
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return n >= 0 && (unsigned)cs.fetch_ulong(w) <= (unsigned)n;
}
unsigned long long as_uint(const vm::CellSlice& cs) const override {
@@ -771,7 +806,7 @@ struct TupleT final : TLB_Complex {
TupleT(int _n, const TLB& _X) : n(_n), X(_X) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
@@ -786,8 +821,8 @@ struct CondT final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return !n || X.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return !n || (n > 0 && X.validate_skip(cs, weak));
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return !n || (n > 0 && X.validate_skip(ops, cs, weak));
}
int get_tag(const vm::CellSlice& cs) const override {
return 0;
@@ -808,8 +843,8 @@ struct Cond final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return !n || field_type.skip(cs);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return !n || (n > 0 && field_type.validate_skip(cs, weak));
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return !n || (n > 0 && field_type.validate_skip(ops, cs, weak));
}
int get_tag(const vm::CellSlice& cs) const override {
return 0;
@@ -905,7 +940,7 @@ struct Maybe : TLB_Complex {
Maybe(Args... args) : field_type(args...) {
}
bool skip(vm::CellSlice& cs) const override;
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return cs.have(1) ? (int)cs.prefetch_ulong(1) : -1;
}
@@ -928,10 +963,10 @@ bool Maybe::skip(vm::CellSlice& cs) const {
}
template
-bool Maybe::validate_skip(vm::CellSlice& cs, bool weak) const {
+bool Maybe::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int t = get_tag(cs);
if (t > 0) {
- return cs.advance(1) && field_type.validate_skip(cs, weak);
+ return cs.advance(1) && field_type.validate_skip(ops, cs, weak);
} else if (!t) {
return cs.advance(1);
} else {
@@ -979,11 +1014,11 @@ struct RefTo final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return 0x10000;
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
- return cs.size_refs() ? ref_type.validate_ref(cs.prefetch_ref(), weak) : false;
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return cs.size_refs() ? ref_type.validate_ref(ops, cs.prefetch_ref(), weak) : false;
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return ref_type.validate_skip_ref(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return ref_type.validate_skip_ref(ops, cs, weak);
}
std::ostream& print_type(std::ostream& os) const override {
return os << '^' << ref_type;
@@ -1000,11 +1035,11 @@ struct RefT final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return 0x10000;
}
- bool validate(const vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_ref(cs.prefetch_ref(), weak);
+ bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_ref(ops, cs.prefetch_ref(), weak);
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return X.validate_skip_ref(cs, weak);
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return X.validate_skip_ref(ops, cs, weak);
}
std::ostream& print_type(std::ostream& os) const override {
return os << '^' << X;
@@ -1021,9 +1056,10 @@ struct Either final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.have(1) ? (cs.fetch_ulong(1) ? right_type.skip(cs) : left_type.skip(cs)) : false;
}
- bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
- return cs.have(1) ? (cs.fetch_ulong(1) ? right_type.validate_skip(cs, weak) : left_type.validate_skip(cs, weak))
- : false;
+ bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
+ return cs.have(1)
+ ? (cs.fetch_ulong(1) ? right_type.validate_skip(ops, cs, weak) : left_type.validate_skip(ops, cs, weak))
+ : false;
}
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
diff --git a/crypto/vm/arithops.cpp b/crypto/vm/arithops.cpp
index 69e6f083..25b67353 100644
--- a/crypto/vm/arithops.cpp
+++ b/crypto/vm/arithops.cpp
@@ -389,7 +389,7 @@ int exec_muldivmod(VmState* st, unsigned args, int quiet) {
auto x = stack.pop_int();
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
switch ((args >> 2) & 3) {
case 1:
@@ -401,7 +401,7 @@ int exec_muldivmod(VmState* st, unsigned args, int quiet) {
stack.push_int_quiet(std::move(q), quiet);
// fallthrough
case 2:
- stack.push_int_quiet(td::RefInt256{true, tmp}, quiet);
+ stack.push_int_quiet(td::make_refint(tmp), quiet);
break;
}
return 0;
@@ -450,17 +450,17 @@ int exec_mulshrmod(VmState* st, unsigned args, int mode) {
switch ((args >> 2) & 3) {
case 1:
tmp.rshift(z, round_mode).normalize();
- stack.push_int_quiet(td::RefInt256{true, tmp}, mode & 1);
+ stack.push_int_quiet(td::make_refint(tmp), mode & 1);
break;
case 3: {
typename td::BigInt256::DoubleInt tmp2{tmp};
tmp2.rshift(z, round_mode).normalize();
- stack.push_int_quiet(td::RefInt256{true, tmp2}, mode & 1);
+ stack.push_int_quiet(td::make_refint(tmp2), mode & 1);
}
// fallthrough
case 2:
tmp.mod_pow2(z, round_mode).normalize();
- stack.push_int_quiet(td::RefInt256{true, tmp}, mode & 1);
+ stack.push_int_quiet(td::make_refint(tmp), mode & 1);
break;
}
return 0;
@@ -524,24 +524,24 @@ int exec_shldivmod(VmState* st, unsigned args, int mode) {
tmp <<= y;
switch ((args >> 2) & 3) {
case 1: {
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int_quiet(std::move(q), mode & 1);
break;
}
case 3: {
- auto q = td::RefInt256{true};
+ auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int_quiet(std::move(q), mode & 1);
- stack.push_int_quiet(td::RefInt256{true, tmp}, mode & 1);
+ stack.push_int_quiet(td::make_refint(tmp), mode & 1);
break;
}
case 2: {
typename td::BigInt256::DoubleInt tmp2;
tmp.mod_div(*z, tmp2, round_mode);
- stack.push_int_quiet(td::RefInt256{true, tmp}, mode & 1);
+ stack.push_int_quiet(td::make_refint(tmp), mode & 1);
break;
}
}
@@ -740,7 +740,7 @@ int exec_bitsize(VmState* st, bool sgnd, bool quiet) {
} else if (!quiet) {
throw VmError{Excno::range_chk, "CHKSIZE for negative integer"};
} else {
- stack.push_int_quiet(td::RefInt256{true}, quiet);
+ stack.push_int_quiet(td::make_refint(), quiet);
}
return 0;
}
diff --git a/crypto/vm/cells/CellSlice.cpp b/crypto/vm/cells/CellSlice.cpp
index 8f1e606f..0d539c74 100644
--- a/crypto/vm/cells/CellSlice.cpp
+++ b/crypto/vm/cells/CellSlice.cpp
@@ -594,8 +594,7 @@ td::RefInt256 CellSlice::fetch_int256(unsigned bits, bool sgnd) {
if (!have(bits)) {
return {};
} else if (bits < td::BigInt256::word_shift) {
- long long val = sgnd ? fetch_long(bits) : fetch_ulong(bits);
- return td::RefInt256{true, val};
+ return td::make_refint(sgnd ? fetch_long(bits) : fetch_ulong(bits));
} else {
td::RefInt256 res{true};
res.unique_write().import_bits(data_bits(), bits, sgnd);
@@ -608,8 +607,7 @@ td::RefInt256 CellSlice::prefetch_int256(unsigned bits, bool sgnd) const {
if (!have(bits)) {
return {};
} else if (bits < td::BigInt256::word_shift) {
- long long val = sgnd ? prefetch_long(bits) : prefetch_ulong(bits);
- return td::RefInt256{true, val};
+ return td::make_refint(sgnd ? prefetch_long(bits) : prefetch_ulong(bits));
} else {
td::RefInt256 res{true};
res.unique_write().import_bits(data_bits(), bits, sgnd);
@@ -619,15 +617,15 @@ td::RefInt256 CellSlice::prefetch_int256(unsigned bits, bool sgnd) const {
td::RefInt256 CellSlice::prefetch_int256_zeroext(unsigned bits, bool sgnd) const {
if (bits > 256u + sgnd) {
- return td::RefInt256{false};
+ return td::make_refint();
} else {
unsigned ld_bits = std::min(bits, size());
if (bits < td::BigInt256::word_shift) {
long long val = sgnd ? prefetch_long(ld_bits) : prefetch_ulong(ld_bits);
val <<= bits - ld_bits;
- return td::RefInt256{true, val};
+ return td::make_refint(val);
} else {
- td::RefInt256 res{true};
+ auto res = td::make_refint();
res.unique_write().import_bits(data_bits(), ld_bits, sgnd);
res <<= bits - ld_bits;
return res;
diff --git a/crypto/vm/stack.cpp b/crypto/vm/stack.cpp
index 84ed4b83..43099927 100644
--- a/crypto/vm/stack.cpp
+++ b/crypto/vm/stack.cpp
@@ -556,7 +556,7 @@ void Stack::push_int_quiet(td::RefInt256 val, bool quiet) {
if (!quiet) {
throw VmError{Excno::int_ov};
} else if (val->is_valid()) {
- push(td::RefInt256{true});
+ push(td::make_refint());
return;
}
}
@@ -592,7 +592,7 @@ void Stack::push_builder(Ref cb) {
}
void Stack::push_smallint(long long val) {
- push(td::RefInt256{true, val});
+ push(td::make_refint(val));
}
void Stack::push_bool(bool val) {
@@ -763,7 +763,7 @@ bool StackEntry::deserialize(CellSlice& cs, int mode) {
t = (int)cs.prefetch_ulong(16) & 0x1ff;
if (t == 0xff) {
// vm_stk_nan#02ff = VmStackValue;
- return cs.advance(16) && set_int(td::RefInt256{true});
+ return cs.advance(16) && set_int(td::make_refint());
} else {
// vm_stk_int#0201_ value:int257 = VmStackValue;
td::RefInt256 val;
diff --git a/crypto/vm/stack.hpp b/crypto/vm/stack.hpp
index 75540fb0..3fadce6b 100644
--- a/crypto/vm/stack.hpp
+++ b/crypto/vm/stack.hpp
@@ -147,6 +147,15 @@ class StackEntry {
bool is_atom() const {
return tp == t_atom;
}
+ bool is_int() const {
+ return tp == t_int;
+ }
+ bool is_cell() const {
+ return tp == t_cell;
+ }
+ bool is_null() const {
+ return tp == t_null;
+ }
bool is(int wanted) const {
return tp == wanted;
}
@@ -433,6 +442,12 @@ class Stack : public td::CntObject {
}
return *this;
}
+ std::vector extract_contents() const & {
+ return stack;
+ }
+ std::vector extract_contents() && {
+ return std::move(stack);
+ }
template
const Stack& check_underflow(Args... args) const {
if (!at_least(args...)) {
diff --git a/crypto/vm/tonops.cpp b/crypto/vm/tonops.cpp
index 84ff5b6b..ca8e4b00 100644
--- a/crypto/vm/tonops.cpp
+++ b/crypto/vm/tonops.cpp
@@ -260,7 +260,7 @@ int exec_rand_int(VmState* st) {
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
tmp.rshift(256, -1).normalize();
- stack.push_int(td::RefInt256{true, tmp});
+ stack.push_int(td::make_refint(tmp));
return 0;
}
@@ -607,15 +607,15 @@ bool parse_maybe_anycast(CellSlice& cs, StackEntry& res) {
bool parse_message_addr(CellSlice& cs, std::vector& res) {
res.clear();
switch ((unsigned)cs.fetch_ulong(2)) {
- case 0: // addr_none$00 = MsgAddressExt;
- res.emplace_back(td::RefInt256{true, 0}); // -> (0)
+ case 0: // addr_none$00 = MsgAddressExt;
+ res.emplace_back(td::zero_refint()); // -> (0)
return true;
case 1: { // addr_extern$01
unsigned len;
Ref addr;
if (cs.fetch_uint_to(9, len) // len:(## 9)
&& cs.fetch_subslice_to(len, addr)) { // external_address:(bits len) = MsgAddressExt;
- res.emplace_back(td::RefInt256{true, 1});
+ res.emplace_back(td::make_refint(1));
res.emplace_back(std::move(addr));
return true;
}
@@ -628,9 +628,9 @@ bool parse_message_addr(CellSlice& cs, std::vector& res) {
if (parse_maybe_anycast(cs, v) // anycast:(Maybe Anycast)
&& cs.fetch_int_to(8, workchain) // workchain_id:int8
&& cs.fetch_subslice_to(256, addr)) { // address:bits256 = MsgAddressInt;
- res.emplace_back(td::RefInt256{true, 2});
+ res.emplace_back(td::make_refint(2));
res.emplace_back(std::move(v));
- res.emplace_back(td::RefInt256{true, workchain});
+ res.emplace_back(td::make_refint(workchain));
res.emplace_back(std::move(addr));
return true;
}
@@ -644,9 +644,9 @@ bool parse_message_addr(CellSlice& cs, std::vector& res) {
&& cs.fetch_uint_to(9, len) // addr_len:(## 9)
&& cs.fetch_int_to(32, workchain) // workchain_id:int32
&& cs.fetch_subslice_to(len, addr)) { // address:(bits addr_len) = MsgAddressInt;
- res.emplace_back(td::RefInt256{true, 3});
+ res.emplace_back(td::make_refint(3));
res.emplace_back(std::move(v));
- res.emplace_back(td::RefInt256{true, workchain});
+ res.emplace_back(td::make_refint(workchain));
res.emplace_back(std::move(addr));
return true;
}
diff --git a/crypto/vm/utils.cpp b/crypto/vm/utils.cpp
index 25e01f21..783bf132 100644
--- a/crypto/vm/utils.cpp
+++ b/crypto/vm/utils.cpp
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2019-2020 Telegram Systems LLP
+*/
#include "utils.h"
namespace vm {
@@ -88,7 +106,7 @@ td::Result convert_stack_entry(td::Slice str) {
return vm::StackEntry{
Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}};
}
- auto num = td::RefInt256{true};
+ auto num = td::make_refint();
auto& x = num.unique_write();
if (l >= 3 && str[0] == '0' && str[1] == 'x') {
if (x.parse_hex(str.data() + 2, l - 2) != l - 2) {
diff --git a/crypto/vm/utils.h b/crypto/vm/utils.h
index e1afe60c..34d761b1 100644
--- a/crypto/vm/utils.h
+++ b/crypto/vm/utils.h
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2019-2020 Telegram Systems LLP
+*/
#pragma once
#include "stack.hpp"
diff --git a/crypto/vm/vm.cpp b/crypto/vm/vm.cpp
index 5ddc16b8..395e01d3 100644
--- a/crypto/vm/vm.cpp
+++ b/crypto/vm/vm.cpp
@@ -385,11 +385,13 @@ int VmState::step() {
if (code->size()) {
return dispatch->dispatch(this, code.write());
} else if (code->size_refs()) {
- VM_LOG(this) << "execute implicit JMPREF\n";
+ VM_LOG(this) << "execute implicit JMPREF";
+ gas.consume_chk(implicit_jmpref_gas_price);
Ref cont = Ref{true, load_cell_slice_ref(code->prefetch_ref()), get_cp()};
return jump(std::move(cont));
} else {
- VM_LOG(this) << "execute implicit RET\n";
+ VM_LOG(this) << "execute implicit RET";
+ gas.consume_chk(implicit_ret_gas_price);
return ret();
}
}
@@ -404,25 +406,27 @@ int VmState::run() {
// LOG(INFO) << "[BS] data cells: " << DataCell::get_total_data_cells();
try {
try {
- res = step();
- gas.check();
- } catch (vm::CellBuilder::CellWriteError) {
- throw VmError{Excno::cell_ov};
- } catch (vm::CellBuilder::CellCreateError) {
- throw VmError{Excno::cell_ov};
- } catch (vm::CellSlice::CellReadError) {
- throw VmError{Excno::cell_und};
- }
- } catch (const VmError& vme) {
- VM_LOG(this) << "handling exception code " << vme.get_errno() << ": " << vme.get_msg();
- try {
- // LOG(INFO) << "[EX] data cells: " << DataCell::get_total_data_cells();
- ++steps;
- res = throw_exception(vme.get_errno());
- } catch (const VmError& vme2) {
- VM_LOG(this) << "exception " << vme2.get_errno() << " while handling exception: " << vme.get_msg();
- // LOG(INFO) << "[EXX] data cells: " << DataCell::get_total_data_cells();
- return ~vme2.get_errno();
+ try {
+ res = step();
+ gas.check();
+ } catch (vm::CellBuilder::CellWriteError) {
+ throw VmError{Excno::cell_ov};
+ } catch (vm::CellBuilder::CellCreateError) {
+ throw VmError{Excno::cell_ov};
+ } catch (vm::CellSlice::CellReadError) {
+ throw VmError{Excno::cell_und};
+ }
+ } catch (const VmError& vme) {
+ VM_LOG(this) << "handling exception code " << vme.get_errno() << ": " << vme.get_msg();
+ try {
+ // LOG(INFO) << "[EX] data cells: " << DataCell::get_total_data_cells();
+ ++steps;
+ res = throw_exception(vme.get_errno());
+ } catch (const VmError& vme2) {
+ VM_LOG(this) << "exception " << vme2.get_errno() << " while handling exception: " << vme.get_msg();
+ // LOG(INFO) << "[EXX] data cells: " << DataCell::get_total_data_cells();
+ return ~vme2.get_errno();
+ }
}
} catch (VmNoGas vmoog) {
++steps;
diff --git a/crypto/vm/vm.h b/crypto/vm/vm.h
index 78087d88..19c3829f 100644
--- a/crypto/vm/vm.h
+++ b/crypto/vm/vm.h
@@ -104,6 +104,8 @@ class VmState final : public VmStateInterface {
cell_create_gas_price = 500,
exception_gas_price = 50,
tuple_entry_gas_price = 1,
+ implicit_jmpref_gas_price = 10,
+ implicit_ret_gas_price = 5,
max_data_depth = 512
};
VmState();
diff --git a/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTest.kt b/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTest.kt
index f2b94f9d..84f703e1 100644
--- a/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTest.kt
+++ b/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTest.kt
@@ -49,8 +49,8 @@ class TonTest {
"workchain": -1,
"shard": -9223372036854775808,
"seqno": 0,
- "root_hash": "VCSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
- "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
+ "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=",
+ "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24="
}
}
}"""
@@ -58,29 +58,27 @@ class TonTest {
fun createTestWallet() {
val client = ClientKotlin()
val dir = getContext().getExternalFilesDir(null).toString() + "/";
+ val words = getContext().getString(R.string.wallet_mnemonic_words).split(" ").toTypedArray();
runBlocking {
- client.send(TonApi.Init(TonApi.Options(TonApi.Config(config, "", false, false), dir)))
+ val info = client.send(TonApi.Init(TonApi.Options(TonApi.Config(config, "", false, false), TonApi.KeyStoreTypeDirectory(dir)))) as TonApi.OptionsInfo;
val key = client.send(TonApi.CreateNewKey("local password".toByteArray(), "mnemonic password".toByteArray(), "".toByteArray())) as TonApi.Key
- val walletAddress = client.send(TonApi.TestWalletGetAccountAddress(TonApi.TestWalletInitialAccountState(key.publicKey))) as TonApi.AccountAddress;
- val testGiverState = client.send(TonApi.TestGiverGetAccountState()) as TonApi.TestGiverAccountState
+ val inputKey = TonApi.InputKeyRegular(key, "local password".toByteArray())
+ val walletAddress = client.send(TonApi.GetAccountAddress(TonApi.WalletV3InitialAccountState(key.publicKey, info.configInfo.defaultWalletId), 1)) as TonApi.AccountAddress
- client.send(TonApi.TestGiverSendGrams(walletAddress, testGiverState.seqno, 6660000000, "".toByteArray())) as TonApi.Ok
+ val giverKey = client.send(TonApi.ImportKey("local password".toByteArray(), "".toByteArray(), TonApi.ExportedKey(words))) as TonApi.Key
+ val giverInputKey = TonApi.InputKeyRegular(giverKey, "local password".toByteArray())
+ val giverAddress = client.send(TonApi.GetAccountAddress(TonApi.WalletV3InitialAccountState(giverKey.publicKey, info.configInfo.defaultWalletId), 1)) as TonApi.AccountAddress;
- while ((client.send(TonApi.GenericGetAccountState(walletAddress)) as TonApi.GenericAccountStateUninited).accountState.balance <= 0L) {
+ val queryInfo = client.send(TonApi.CreateQuery(giverInputKey, giverAddress, 60, TonApi.ActionMsg(arrayOf(TonApi.MsgMessage(walletAddress, 6660000000, TonApi.MsgDataText("Helo") )), true))) as TonApi.QueryInfo;
+ client.send(TonApi.QuerySend(queryInfo.id)) as TonApi.Ok;
+
+ while ((client.send(TonApi.GetAccountState(walletAddress)) as TonApi.FullAccountState).balance <= 0L) {
delay(1000L)
}
- val inputKey = TonApi.InputKey(key, "local password".toByteArray());
- client.send(TonApi.TestWalletInit(inputKey)) as TonApi.Ok
-
- while (client.send(TonApi.GenericGetAccountState(walletAddress)) !is TonApi.GenericAccountStateTestWallet) {
- delay(1000L)
- }
-
- val state = client.send(TonApi.GenericGetAccountState(walletAddress)) as TonApi.GenericAccountStateTestWallet
- val balance = state.accountState.balance
- client.send(TonApi.GenericSendGrams(inputKey, walletAddress, walletAddress, 10, 0, true, "hello".toByteArray())) as TonApi.Ok
- while ((client.send(TonApi.GenericGetAccountState(walletAddress)) as TonApi.GenericAccountStateTestWallet).accountState.balance == balance) {
+ val queryInfo2 = client.send(TonApi.CreateQuery(inputKey, walletAddress, 60, TonApi.ActionMsg(arrayOf(), true))) as TonApi.QueryInfo;
+ client.send(TonApi.QuerySend(queryInfo2.id)) as TonApi.Ok;
+ while ((client.send(TonApi.GetAccountState(walletAddress)) as TonApi.FullAccountState).accountState !is TonApi.WalletV3AccountState) {
delay(1000L)
}
}
diff --git a/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTestJava.java b/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTestJava.java
index 0c61abc4..3c34099f 100644
--- a/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTestJava.java
+++ b/example/android/test/ton/src/androidTest/java/drinkless/org/ton/TonTestJava.java
@@ -53,29 +53,28 @@ public class TonTestJava {
return result[0];
}
}
-
- String config = "{\n" +
- " \"liteservers\": [\n" +
- " {\n" +
- " \"ip\": 1137658550,\n" +
- " \"port\": 4924,\n" +
- " \"id\": {\n" +
- " \"@type\": \"pub.ed25519\",\n" +
- " \"key\": \"peJTw/arlRfssgTuf9BMypJzqOi7SXEqSPSWiEw2U1M=\"\n" +
- " }\n" +
- " }\n" +
- " ],\n" +
- " \"validator\": {\n" +
- " \"@type\": \"validator.config.global\",\n" +
- " \"zero_state\": {\n" +
- " \"workchain\": -1,\n" +
- " \"shard\": -9223372036854775808,\n" +
- " \"seqno\": 0,\n" +
- " \"root_hash\": \"VCSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=\",\n" +
- " \"file_hash\": \"eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo=\"\n" +
- " }\n" +
- " }\n" +
- "}";
+ String config = "{\n"+
+ " \"liteservers\": [\n"+
+ " {\n"+
+ " \"ip\": 1137658550,\n"+
+ " \"port\": 4924,\n"+
+ " \"id\": {\n"+
+ " \"@type\": \"pub.ed25519\",\n"+
+ " \"key\": \"peJTw/arlRfssgTuf9BMypJzqOi7SXEqSPSWiEw2U1M=\"\n"+
+ " }\n"+
+ " }\n"+
+ " ],\n"+
+ " \"validator\": {\n"+
+ " \"@type\": \"validator.config.global\",\n"+
+ " \"zero_state\": {\n"+
+ " \"workchain\": -1,\n"+
+ " \"shard\": -9223372036854775808,\n"+
+ " \"seqno\": 0,\n"+
+ " \"root_hash\": \"F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=\",\n"+
+ " \"file_hash\": \"XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=\"\n"+
+ " }\n"+
+ " }\n"+
+ "}";
private void appendLog(String log) {
Log.w("XX", log);
@@ -84,85 +83,45 @@ public class TonTestJava {
@Test
public void createTestWallet() {
appendLog("start...");
+ String dir = getContext().getExternalFilesDir(null) + "/";
+ String[] words = getContext().getString(R.string.wallet_mnemonic_words).split(" ");
+ JavaClient client = new JavaClient();
+ Object result = client.send(new TonApi.Init(new TonApi.Options(new TonApi.Config(config, "", false, false), new TonApi.KeyStoreTypeDirectory((dir)))));
+ if (!(result instanceof TonApi.OptionsInfo)) {
+ appendLog("failed to set config");
+ return;
+ }
+ appendLog("config set ok");
+ TonApi.OptionsInfo info = (TonApi.OptionsInfo)result;
+ TonApi.Key key = (TonApi.Key) client.send(new TonApi.CreateNewKey("local password".getBytes(), "mnemonic password".getBytes(), "".getBytes()));
+ TonApi.InputKey inputKey = new TonApi.InputKeyRegular(key, "local password".getBytes());
+ TonApi.AccountAddress walletAddress = (TonApi.AccountAddress)client.send(new TonApi.GetAccountAddress(new TonApi.WalletV3InitialAccountState(key.publicKey, info.configInfo.defaultWalletId), 1));
- JavaClient client = new JavaClient();
- Object result = client.send(new TonApi.Init(new TonApi.Options(new TonApi.Config(config, "", false, false), getContext().getExternalFilesDir(null) + "/")));
- if (!(result instanceof TonApi.Ok)) {
- appendLog("failed to set config");
- return;
- }
- appendLog("config set ok");
- TonApi.Key key = (TonApi.Key) client.send(new TonApi.CreateNewKey("local password".getBytes(), "mnemonic password".getBytes(), "".getBytes()));
- appendLog("got private key");
- TonApi.AccountAddress walletAddress = (TonApi.AccountAddress) client.send(new TonApi.TestWalletGetAccountAddress(new TonApi.TestWalletInitialAccountState(key.publicKey)));
- appendLog("got account address");
- appendLog("sending grams...");
- TonApi.TestGiverAccountState testGiverState = (TonApi.TestGiverAccountState) client.send(new TonApi.TestGiverGetAccountState());
- result = client.send(new TonApi.TestGiverSendGrams(walletAddress, testGiverState.seqno, 6660000000L, "".getBytes()));
- if (!(result instanceof TonApi.Ok)) {
- appendLog("failed to send grams");
- return;
- }
- appendLog("grams sent, getting balance");
+ TonApi.Key giverKey = (TonApi.Key)client.send(new TonApi.ImportKey("local password".getBytes(), "".getBytes(), new TonApi.ExportedKey(words))) ;
+ TonApi.InputKey giverInputKey = new TonApi.InputKeyRegular(giverKey, "local password".getBytes());
+ TonApi.AccountAddress giverAddress = (TonApi.AccountAddress)client.send(new TonApi.GetAccountAddress(new TonApi.WalletV3InitialAccountState(giverKey.publicKey, info.configInfo.defaultWalletId), 1));
- while (true) {
- TonApi.GenericAccountStateUninited accountStateUninited = (TonApi.GenericAccountStateUninited) client.send(new TonApi.GenericGetAccountState(walletAddress));
- if (accountStateUninited == null || accountStateUninited.accountState.balance <= 0L) {
- try {
- Thread.sleep(1000);
- } catch (Throwable e) {
- appendLog(e.toString());
- }
- } else {
- appendLog(String.format("balance = %d", accountStateUninited.accountState.balance));
- break;
+ appendLog("sending grams...");
+ TonApi.QueryInfo queryInfo = (TonApi.QueryInfo)client.send(new TonApi.CreateQuery(giverInputKey, giverAddress, 60, new TonApi.ActionMsg(new TonApi.MsgMessage[]{new TonApi.MsgMessage(walletAddress, 6660000000L, new TonApi.MsgDataText("Helo") )}, true)));
+ result = client.send(new TonApi.QuerySend(queryInfo.id));
+ if (!(result instanceof TonApi.Ok)) {
+ appendLog("failed to send grams");
+ return;
+ }
+ appendLog("grams sent, getting balance");
+
+ while (true) {
+ TonApi.FullAccountState state = (TonApi.FullAccountState) client.send(new TonApi.GetAccountState(walletAddress));
+ if (state.balance <= 0L) {
+ try {
+ Thread.sleep(1000);
+ } catch (Throwable e) {
+ appendLog(e.toString());
}
+ } else {
+ appendLog(String.format("balance = %d", state.balance));
+ break;
}
-
- TonApi.InputKey inputKey = new TonApi.InputKey(key, "local password".getBytes());
- result = client.send(new TonApi.TestWalletInit(inputKey));
- if (!(result instanceof TonApi.Ok)) {
- return;
- }
- appendLog("init test wallet ok, getting state...");
-
- while (true) {
- TonApi.GenericAccountState accountState = (TonApi.GenericAccountState) client.send(new TonApi.GenericGetAccountState(walletAddress));
- if (!(accountState instanceof TonApi.GenericAccountStateTestWallet)) {
- try {
- Thread.sleep(1000);
- } catch (Throwable e) {
- appendLog(e.toString());
- }
- } else {
- appendLog("got account state");
- break;
- }
- }
-
- appendLog("sending grams...");
- TonApi.GenericAccountStateTestWallet state = (TonApi.GenericAccountStateTestWallet) client.send(new TonApi.GenericGetAccountState(walletAddress));
- long balance = state.accountState.balance;
- result = client.send(new TonApi.GenericSendGrams(inputKey, walletAddress, walletAddress, 10, 0, true, "hello".getBytes()));
- if (!(result instanceof TonApi.Ok)) {
- return;
- }
- appendLog(String.format("grams sent, current balance %d, receving...", balance));
-
- while (true) {
- TonApi.GenericAccountStateTestWallet wallet = (TonApi.GenericAccountStateTestWallet) client.send(new TonApi.GenericGetAccountState(walletAddress));
- if (wallet == null || wallet.accountState.balance == balance) {
- try {
- Thread.sleep(1000);
- } catch (Throwable e) {
- appendLog(e.toString());
- }
- } else {
- appendLog(String.format("grams received, balance = %d", balance));
- break;
- }
- }
- appendLog("OK");
-
+ }
}
}
diff --git a/example/android/test/ton/src/main/res/values/strings.xml b/example/android/test/ton/src/main/res/values/strings.xml
index b9200763..76b1bac9 100644
--- a/example/android/test/ton/src/main/res/values/strings.xml
+++ b/example/android/test/ton/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
tonlib
+
+
diff --git a/lite-client/lite-client-common.cpp b/lite-client/lite-client-common.cpp
index 184dfba3..5bc8ca73 100644
--- a/lite-client/lite-client-common.cpp
+++ b/lite-client/lite-client-common.cpp
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2017-2020 Telegram Systems LLP
+*/
#include "lite-client-common.h"
#include "auto/tl/lite_api.hpp"
diff --git a/lite-client/lite-client-common.h b/lite-client/lite-client-common.h
index 54948ead..a73dab91 100644
--- a/lite-client/lite-client-common.h
+++ b/lite-client/lite-client-common.h
@@ -1,3 +1,21 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2017-2020 Telegram Systems LLP
+*/
#pragma once
#include "crypto/block/block.h"
diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp
index ed1d9782..3dedabe2 100644
--- a/lite-client/lite-client.cpp
+++ b/lite-client/lite-client.cpp
@@ -61,6 +61,7 @@
#include "ton/ton-shard.h"
#include "openssl/rand.hpp"
#include "crypto/vm/utils.h"
+#include "crypto/common/util.h"
#if TD_DARWIN || TD_LINUX
#include
@@ -142,6 +143,8 @@ void TestNode::got_result() {
parse_line(std::move(data));
}
if (ex_mode_ && !running_queries_ && ex_queries_.size() == 0) {
+ std::cout.flush();
+ std::cerr.flush();
std::_Exit(0);
}
}
@@ -179,6 +182,14 @@ bool TestNode::envelope_send_query(td::BufferSlice query, td::Promise TestNode::trivial_promise() {
+ return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result res) {
+ if (res.is_error()) {
+ LOG(ERROR) << "error: " << res.move_as_error();
+ }
+ });
+}
+
bool TestNode::register_blkid(const ton::BlockIdExt& blkid) {
for (const auto& id : known_blk_ids_) {
if (id == blkid) {
@@ -570,8 +581,13 @@ bool TestNode::seekeoln() {
return eoln();
}
-bool TestNode::parse_account_addr(ton::WorkchainId& wc, ton::StdSmcAddress& addr) {
- return block::parse_std_account_addr(get_word(), wc, addr) || set_error("cannot parse account address");
+bool TestNode::parse_account_addr(ton::WorkchainId& wc, ton::StdSmcAddress& addr, bool allow_none) {
+ auto word = get_word();
+ if (allow_none && (word == "none" || word == "root")) {
+ wc = ton::workchainInvalid;
+ return true;
+ }
+ return block::parse_std_account_addr(word, wc, addr) || set_error("cannot parse account address");
}
bool TestNode::convert_uint64(td::Slice word, td::uint64& val) {
@@ -634,6 +650,14 @@ bool TestNode::parse_uint32(td::uint32& val) {
return convert_uint32(get_word(), val) || set_error("cannot parse 32-bit unsigned integer");
}
+bool TestNode::parse_int32(td::int32& val) {
+ return convert_int32(get_word(), val) || set_error("cannot parse 32-bit integer");
+}
+
+bool TestNode::parse_int16(int& val) {
+ return (convert_int32(get_word(), val) && val == (td::int16)val) || set_error("cannot parse 16-bit integer");
+}
+
bool TestNode::set_error(td::Status error) {
if (error.is_ok()) {
return true;
@@ -801,8 +825,12 @@ bool TestNode::show_help(std::string command) {
"saveaccount[code|data] []\tSaves into specified file the most recent state "
"(StateInit) or just the code or data of specified account; is in "
"[:] format\n"
- "runmethod[x] [] ...\tRuns GET method