Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tvm v9 #1482

Merged
merged 7 commits into from
Jan 22, 2025
Merged

Tvm v9 #1482

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions crypto/block/mc-config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2292,7 +2292,8 @@ Ref<vm::Cell> ConfigInfo::lookup_library(td::ConstBitPtr root_hash) const {
td::Result<Ref<vm::Tuple>> ConfigInfo::get_prev_blocks_info() const {
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
// [ last_mc_blocks:[BlockId...]
// prev_key_block:BlockId ] : PrevBlocksInfo
// prev_key_block:BlockId
// last_mc_blocks_100[BlockId...] ] : PrevBlocksInfo
auto block_id_to_tuple = [](const ton::BlockIdExt& block_id) -> vm::Ref<vm::Tuple> {
td::RefInt256 shard = td::make_refint(block_id.id.shard);
if (shard->sgn() < 0) {
Expand All @@ -2302,25 +2303,44 @@ td::Result<Ref<vm::Tuple>> ConfigInfo::get_prev_blocks_info() const {
td::make_refint(block_id.id.seqno), td::bits_to_refint(block_id.root_hash.bits(), 256),
td::bits_to_refint(block_id.file_hash.bits(), 256));
};
std::vector<vm::StackEntry> last_mc_blocks;
std::vector<vm::StackEntry> tuple;

std::vector<vm::StackEntry> last_mc_blocks;
last_mc_blocks.push_back(block_id_to_tuple(block_id));
for (ton::BlockSeqno seqno = block_id.id.seqno; seqno > 0 && last_mc_blocks.size() < 16;) {
--seqno;
ton::BlockIdExt block_id;
if (!get_old_mc_block_id(seqno, block_id)) {
ton::BlockIdExt id;
if (!get_old_mc_block_id(seqno, id)) {
return td::Status::Error("cannot fetch old mc block");
}
last_mc_blocks.push_back(block_id_to_tuple(block_id));
last_mc_blocks.push_back(block_id_to_tuple(id));
}
tuple.push_back(td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks)));

ton::BlockIdExt last_key_block;
ton::LogicalTime last_key_block_lt;
if (!get_last_key_block(last_key_block, last_key_block_lt)) {
return td::Status::Error("cannot fetch last key block");
}
return vm::make_tuple_ref(td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks)),
block_id_to_tuple(last_key_block));
tuple.push_back(block_id_to_tuple(last_key_block));

if (get_global_version() >= 9) {
std::vector<vm::StackEntry> last_mc_blocks_100;
for (ton::BlockSeqno seqno = block_id.id.seqno / 100 * 100; last_mc_blocks_100.size() < 16;) {
ton::BlockIdExt id;
if (!get_old_mc_block_id(seqno, id)) {
return td::Status::Error("cannot fetch old mc block");
}
last_mc_blocks_100.push_back(block_id_to_tuple(id));
if (seqno < 100) {
break;
}
seqno -= 100;
}
tuple.push_back(td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks_100)));
}

return td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
}

td::optional<PrecompiledContractsConfig::Contract> PrecompiledContractsConfig::get_contract(
Expand Down
67 changes: 51 additions & 16 deletions crypto/block/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,31 +1145,64 @@ td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const {
namespace transaction {

/**
* Checks if it is required to increase gas_limit (from GasLimitsPrices config) to special_gas_limit * 2
* from masterchain GasLimitsPrices config for the transaction.
* Checks if it is required to increase gas_limit (from GasLimitsPrices config) for the transaction
*
* In January 2024 a highload wallet of @wallet Telegram bot in mainnet was stuck because current gas limit (1M) is
* not enough to clean up old queires, thus locking funds inside.
* See comment in crypto/smartcont/highload-wallet-v2-code.fc for details on why this happened.
* Account address: EQD_v9j1rlsuHHw2FIhcsCFFSD367ldfDdCKcsNmNpIRzUlu
* It was proposed to validators to increase gas limit for this account for a limited amount of time (until 2024-02-29).
* It was proposed to validators to increase gas limit for this account to 70M for a limited amount
* of time (until 2024-02-29).
* It is activated by setting global version to 5 in ConfigParam 8.
* This config change also activates new behavior for special accounts in masterchain.
*
* In Augost 2024 it was decided to unlock other old highload wallets that got into the same situation.
* See https://t.me/tondev_news/129
* It is activated by setting global version to 9.
*
* @param cfg The compute phase configuration.
* @param now The Unix time of the transaction.
* @param account The account of the transaction.
*
* @returns True if gas_limit override is required, false otherwise
* @returns Overridden gas limit or empty td::optional
*/
static bool override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now, const Account& account) {
if (!cfg.special_gas_full) {
return false;
static td::optional<td::uint64> override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now,
const Account& account) {
struct OverridenGasLimit {
td::uint64 new_limit;
int from_version;
ton::UnixTime until;
};
static std::map<std::pair<ton::WorkchainId, ton::StdSmcAddress>, OverridenGasLimit> accounts = []() {
auto parse_addr = [](const char* s) -> std::pair<ton::WorkchainId, ton::StdSmcAddress> {
auto r_addr = StdAddress::parse(td::Slice(s));
r_addr.ensure();
return {r_addr.ok().workchain, r_addr.ok().addr};
};
std::map<std::pair<ton::WorkchainId, ton::StdSmcAddress>, OverridenGasLimit> accounts;

// Increase limit for EQD_v9j1rlsuHHw2FIhcsCFFSD367ldfDdCKcsNmNpIRzUlu until 2024-02-29 00:00:00 UTC
accounts[parse_addr("0:FFBFD8F5AE5B2E1C7C3614885CB02145483DFAEE575F0DD08A72C366369211CD")] = {
.new_limit = 70'000'000, .from_version = 5, .until = 1709164800};

// Increase limit for multiple accounts (https://t.me/tondev_news/129) until 2025-03-01 00:00:00 UTC
accounts[parse_addr("UQBeSl-dumOHieZ3DJkNKVkjeso7wZ0VpzR4LCbLGTQ8xr57")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQC3VcQ-43klww9UfimR58TBjBzk7GPupXQ3CNuthoNp-uTR")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQBhwBb8jvokGvfreHRRoeVxI237PrOJgyrsAhLA-4rBC_H5")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQCkoRp4OE-SFUoMEnYfL3vF43T3AzNfW8jyTC4yzk8cJqMS")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQBDanbCeUqI4_v-xrnAN0_I2wRvEIaLg1Qg2ZN5c6Zl1KOh")] = {
.new_limit = 225'000'000, .from_version = 9, .until = 1740787200};
return accounts;
}();
auto it = accounts.find({account.workchain, account.addr});
if (it == accounts.end() || cfg.global_version < it->second.from_version || now >= it->second.until) {
return {};
}
ton::UnixTime until = 1709164800; // 2024-02-29 00:00:00 UTC
ton::WorkchainId wc = 0;
const char* addr_hex = "FFBFD8F5AE5B2E1C7C3614885CB02145483DFAEE575F0DD08A72C366369211CD";
return now < until && account.workchain == wc && account.addr.to_hex() == addr_hex;
return it->second.new_limit;
}

/**
Expand All @@ -1183,10 +1216,12 @@ static bool override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now,
* @returns The amount of gas.
*/
td::uint64 Transaction::gas_bought_for(const ComputePhaseConfig& cfg, td::RefInt256 nanograms) {
if (override_gas_limit(cfg, now, account)) {
if (auto new_limit = override_gas_limit(cfg, now, account)) {
gas_limit_overridden = true;
// Same as ComputePhaseConfig::gas_bought for, but with other gas_limit and max_gas_threshold
auto gas_limit = cfg.mc_gas_prices.special_gas_limit * 2;
auto gas_limit = new_limit.value();
LOG(INFO) << "overridding gas limit for account " << account.workchain << ":" << account.addr.to_hex() << " to "
<< gas_limit;
auto max_gas_threshold =
compute_max_gas_threshold(cfg.gas_price256, gas_limit, cfg.flat_gas_limit, cfg.flat_gas_price);
if (nanograms.is_null() || sgn(nanograms) < 0) {
Expand Down Expand Up @@ -1336,7 +1371,8 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
// See crypto/block/mc-config.cpp#2223 (get_prev_blocks_info)
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
// [ last_mc_blocks:[BlockId...]
// prev_key_block:BlockId ] : PrevBlocksInfo
// prev_key_block:BlockId
// last_mc_blocks_100:[BlockId...] ] : PrevBlocksInfo
// The only context where PrevBlocksInfo (13 parameter of c7) is null is inside emulator
// where it need to be set via transaction_emulator_set_prev_blocks_info (see emulator/emulator-extern.cpp)
// Inside validator, collator and liteserver checking external message contexts
Expand Down Expand Up @@ -1691,9 +1727,8 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
}
}
}
vm::VmState vm{new_code, std::move(stack), gas, 1, new_data, vm_log, compute_vm_libraries(cfg)};
vm::VmState vm{new_code, cfg.global_version, std::move(stack), gas, 1, new_data, vm_log, compute_vm_libraries(cfg)};
vm.set_max_data_depth(cfg.max_vm_data_depth);
vm.set_global_version(cfg.global_version);
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
vm.set_chksig_always_succeed(cfg.ignore_chksig);
vm.set_stop_on_accept_message(cfg.stop_on_accept_message);
Expand Down
1 change: 1 addition & 0 deletions crypto/fift/lib/Asm.fif
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,7 @@ x{F832} @Defop CONFIGPARAM
x{F833} @Defop CONFIGOPTPARAM
x{F83400} @Defop PREVMCBLOCKS
x{F83401} @Defop PREVKEYBLOCK
x{F83402} @Defop PREVMCBLOCKS_100
x{F835} @Defop GLOBALID
x{F836} @Defop GETGASFEE
x{F837} @Defop GETSTORAGEFEE
Expand Down
4 changes: 2 additions & 2 deletions crypto/smc-envelope/SmartContract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,14 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref<vm::Stac
stack->dump(os, 2);
LOG(DEBUG) << "VM stack:\n" << os.str();
}
vm::VmState vm{state.code, std::move(stack), gas, 1, state.data, log};
int global_version = config ? config->get_global_version() : 0;
vm::VmState vm{state.code, global_version, std::move(stack), gas, 1, state.data, log};
vm.set_c7(std::move(c7));
vm.set_chksig_always_succeed(ignore_chksig);
if (!libraries.is_null()) {
vm.register_library_collection(libraries);
}
if (config) {
vm.set_global_version(config->get_global_version());
auto r_limits = config->get_size_limits_config();
if (r_limits.is_ok()) {
vm.set_max_data_depth(r_limits.ok().max_vm_data_depth);
Expand Down
6 changes: 3 additions & 3 deletions crypto/vm/contops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ int exec_runvm_common(VmState* st, unsigned mode) {
vm::GasLimits gas{gas_limit, gas_max};

VmStateInterface::Guard guard{nullptr}; // Don't consume gas for creating/loading cells during VM init
VmState new_state{std::move(code), std::move(new_stack), gas, (int)mode & 3, std::move(data),
VmLog{}, std::vector<Ref<Cell>>{}, std::move(c7)};
VmState new_state{
std::move(code), st->get_global_version(), std::move(new_stack), gas, (int)mode & 3, std::move(data),
VmLog{}, std::vector<Ref<Cell>>{}, std::move(c7)};
new_state.set_chksig_always_succeed(st->get_chksig_always_succeed());
new_state.set_global_version(st->get_global_version());
st->run_child_vm(std::move(new_state), with_data, mode & 32, mode & 8, mode & 128, ret_vals);
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions crypto/vm/dictops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ int exec_dict_getnear(VmState* st, unsigned args) {
int exec_pfx_dict_set(VmState* st, Dictionary::SetMode mode, const char* name) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute PFXDICT" << name;
stack.check_underflow(3);
stack.check_underflow(st->get_global_version() >= 9 ? 4 : 3);
int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits);
PrefixDictionary dict{stack.pop_maybe_cell(), n};
auto key_slice = stack.pop_cellslice();
Expand All @@ -580,7 +580,7 @@ int exec_pfx_dict_set(VmState* st, Dictionary::SetMode mode, const char* name) {
int exec_pfx_dict_delete(VmState* st) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute PFXDICTDEL\n";
stack.check_underflow(2);
stack.check_underflow(st->get_global_version() >= 9 ? 3 : 2);
int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits);
PrefixDictionary dict{stack.pop_maybe_cell(), n};
auto key_slice = stack.pop_cellslice();
Expand Down
10 changes: 9 additions & 1 deletion crypto/vm/tonops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ int exec_get_global_id(VmState* st) {
int exec_get_gas_fee(VmState* st) {
VM_LOG(st) << "execute GETGASFEE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0);
bool is_masterchain = stack.pop_bool();
td::uint64 gas = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
block::GasLimitsPrices prices = util::get_gas_prices(get_unpacked_config_tuple(st), is_masterchain);
Expand All @@ -289,6 +290,7 @@ int exec_get_gas_fee(VmState* st) {
int exec_get_storage_fee(VmState* st) {
VM_LOG(st) << "execute GETSTORAGEFEE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 4 : 0);
bool is_masterchain = stack.pop_bool();
td::int64 delta = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
td::uint64 bits = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
Expand All @@ -302,6 +304,7 @@ int exec_get_storage_fee(VmState* st) {
int exec_get_forward_fee(VmState* st) {
VM_LOG(st) << "execute GETFORWARDFEE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 3 : 0);
bool is_masterchain = stack.pop_bool();
td::uint64 bits = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
td::uint64 cells = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
Expand All @@ -320,6 +323,7 @@ int exec_get_precompiled_gas(VmState* st) {
int exec_get_original_fwd_fee(VmState* st) {
VM_LOG(st) << "execute GETORIGINALFWDFEE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0);
bool is_masterchain = stack.pop_bool();
td::RefInt256 fwd_fee = stack.pop_int_finite();
if (fwd_fee->sgn() < 0) {
Expand All @@ -333,6 +337,7 @@ int exec_get_original_fwd_fee(VmState* st) {
int exec_get_gas_fee_simple(VmState* st) {
VM_LOG(st) << "execute GETGASFEESIMPLE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0);
bool is_masterchain = stack.pop_bool();
td::uint64 gas = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
block::GasLimitsPrices prices = util::get_gas_prices(get_unpacked_config_tuple(st), is_masterchain);
Expand All @@ -343,6 +348,7 @@ int exec_get_gas_fee_simple(VmState* st) {
int exec_get_forward_fee_simple(VmState* st) {
VM_LOG(st) << "execute GETFORWARDFEESIMPLE";
Stack& stack = st->get_stack();
stack.check_underflow(st->get_global_version() >= 9 ? 3 : 0);
bool is_masterchain = stack.pop_bool();
td::uint64 bits = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
td::uint64 cells = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
Expand Down Expand Up @@ -373,6 +379,7 @@ void register_ton_config_ops(OpcodeTable& cp0) {
.insert(OpcodeInstr::mksimple(0xf833, 16, "CONFIGOPTPARAM", std::bind(exec_get_config_param, _1, true)))
.insert(OpcodeInstr::mksimple(0xf83400, 24, "PREVMCBLOCKS", std::bind(exec_get_prev_blocks_info, _1, 0, "PREVMCBLOCKS"))->require_version(4))
.insert(OpcodeInstr::mksimple(0xf83401, 24, "PREVKEYBLOCK", std::bind(exec_get_prev_blocks_info, _1, 1, "PREVKEYBLOCK"))->require_version(4))
.insert(OpcodeInstr::mksimple(0xf83402, 24, "PREVMCBLOCKS_100", std::bind(exec_get_prev_blocks_info, _1, 2, "PREVMCBLOCKS_100"))->require_version(9))
.insert(OpcodeInstr::mksimple(0xf835, 16, "GLOBALID", exec_get_global_id)->require_version(4))
.insert(OpcodeInstr::mksimple(0xf836, 16, "GETGASFEE", exec_get_gas_fee)->require_version(6))
.insert(OpcodeInstr::mksimple(0xf837, 16, "GETSTORAGEFEE", exec_get_storage_fee)->require_version(6))
Expand Down Expand Up @@ -538,9 +545,10 @@ int exec_hash_ext(VmState* st, unsigned args) {
VM_LOG(st) << "execute HASHEXT" << (append ? "A" : "") << (rev ? "R" : "") << " " << (hash_id == 255 ? -1 : hash_id);
Stack& stack = st->get_stack();
if (hash_id == 255) {
stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0);
hash_id = stack.pop_smallint_range(254);
}
int cnt = stack.pop_smallint_range(stack.depth() - 1);
int cnt = stack.pop_smallint_range(stack.depth() - 1 - (st->get_global_version() >= 9 ? (int)append : 0));
Hasher hasher{hash_id};
size_t total_bits = 0;
long long gas_consumed = 0;
Expand Down
54 changes: 22 additions & 32 deletions crypto/vm/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "vm/log.h"
#include "vm/vm.h"
#include "cp0.h"
#include "memo.h"

#include <sodium.h>

namespace vm {
Expand All @@ -31,33 +33,8 @@ VmState::VmState() : cp(-1), dispatch(&dummy_dispatch_table), quit0(true, 0), qu
init_cregs();
}

VmState::VmState(Ref<CellSlice> _code)
: code(std::move(_code)), cp(-1), dispatch(&dummy_dispatch_table), quit0(true, 0), quit1(true, 1) {
ensure_throw(init_cp(0));
init_cregs();
}

VmState::VmState(Ref<CellSlice> _code, Ref<Stack> _stack, int flags, Ref<Cell> _data, VmLog log,
std::vector<Ref<Cell>> _libraries, Ref<Tuple> init_c7)
: code(std::move(_code))
, stack(std::move(_stack))
, cp(-1)
, dispatch(&dummy_dispatch_table)
, quit0(true, 0)
, quit1(true, 1)
, log(log)
, libraries(std::move(_libraries))
, stack_trace((flags >> 2) & 1) {
ensure_throw(init_cp(0));
set_c4(std::move(_data));
if (init_c7.not_null()) {
set_c7(std::move(init_c7));
}
init_cregs(flags & 1, flags & 2);
}

VmState::VmState(Ref<CellSlice> _code, Ref<Stack> _stack, const GasLimits& gas, int flags, Ref<Cell> _data, VmLog log,
std::vector<Ref<Cell>> _libraries, Ref<Tuple> init_c7)
VmState::VmState(Ref<CellSlice> _code, int global_version, Ref<Stack> _stack, const GasLimits& gas, int flags,
Ref<Cell> _data, VmLog log, std::vector<Ref<Cell>> _libraries, Ref<Tuple> init_c7)
: code(std::move(_code))
, stack(std::move(_stack))
, cp(-1)
Expand All @@ -67,7 +44,8 @@ VmState::VmState(Ref<CellSlice> _code, Ref<Stack> _stack, const GasLimits& gas,
, log(log)
, gas(gas)
, libraries(std::move(_libraries))
, stack_trace((flags >> 2) & 1) {
, stack_trace((flags >> 2) & 1)
, global_version(global_version) {
ensure_throw(init_cp(0));
set_c4(std::move(_data));
if (init_c7.not_null()) {
Expand Down Expand Up @@ -102,12 +80,24 @@ void VmState::init_cregs(bool same_c3, bool push_0) {
}
}

Ref<CellSlice> VmState::convert_code_cell(Ref<Cell> code_cell) {
Ref<CellSlice> VmState::convert_code_cell(Ref<Cell> code_cell, int global_version,
const std::vector<Ref<Cell>>& libraries) {
if (code_cell.is_null()) {
return {};
}
Ref<CellSlice> csr{true, NoVmOrd(), code_cell};
if (csr->is_valid()) {
Ref<CellSlice> csr;
if (global_version >= 9) {
// Use DummyVmState instead of this to avoid consuming gas for cell loading
DummyVmState dummy{libraries, global_version};
Guard guard(&dummy);
try {
csr = load_cell_slice_ref(code_cell);
} catch (VmError&) { // NOLINT(*-empty-catch)
}
} else {
csr = td::Ref<CellSlice>{true, NoVmOrd(), code_cell};
}
if (csr.not_null() && csr->is_valid()) {
return csr;
}
return load_cell_slice_ref(CellBuilder{}.store_ref(std::move(code_cell)).finalize());
Expand Down Expand Up @@ -577,14 +567,14 @@ int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* da
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr,
int global_version) {
VmState vm{code,
global_version,
std::move(stack),
gas_limits ? *gas_limits : GasLimits{},
flags,
data_ptr ? *data_ptr : Ref<Cell>{},
log,
std::move(libraries),
std::move(init_c7)};
vm.set_global_version(global_version);
int res = vm.run();
stack = vm.get_stack_ref();
if (vm.committed() && data_ptr) {
Expand Down
Loading
Loading