mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-12 11:12:16 +00:00
Fix loading library cell in contract code
This commit is contained in:
parent
a01c7e2e75
commit
0fff1bd8c7
10 changed files with 49 additions and 56 deletions
|
@ -1692,9 +1692,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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -222,14 +222,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);
|
||||
|
|
|
@ -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),
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "vm/log.h"
|
||||
#include "vm/vm.h"
|
||||
#include "cp0.h"
|
||||
#include "memo.h"
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
namespace vm {
|
||||
|
@ -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)
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -577,6 +567,7 @@ 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,
|
||||
|
@ -584,7 +575,6 @@ int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* da
|
|||
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) {
|
||||
|
|
|
@ -164,14 +164,12 @@ class VmState final : public VmStateInterface {
|
|||
bls_pairing_element_gas_price = 11800
|
||||
};
|
||||
VmState();
|
||||
VmState(Ref<CellSlice> _code);
|
||||
VmState(Ref<CellSlice> _code, Ref<Stack> _stack, int flags = 0, Ref<Cell> _data = {}, VmLog log = {},
|
||||
std::vector<Ref<Cell>> _libraries = {}, Ref<Tuple> init_c7 = {});
|
||||
VmState(Ref<CellSlice> _code, Ref<Stack> _stack, const GasLimits& _gas, int flags = 0, Ref<Cell> _data = {},
|
||||
VmState(Ref<CellSlice> _code, int global_version, Ref<Stack> _stack, const GasLimits& _gas, int flags = 0, Ref<Cell> _data = {},
|
||||
VmLog log = {}, std::vector<Ref<Cell>> _libraries = {}, Ref<Tuple> init_c7 = {});
|
||||
template <typename... Args>
|
||||
VmState(Ref<Cell> code_cell, Args&&... args)
|
||||
: VmState(convert_code_cell(std::move(code_cell)), std::forward<Args>(args)...) {
|
||||
VmState(Ref<Cell> _code, int global_version, Ref<Stack> _stack, const GasLimits& _gas, int flags = 0,
|
||||
Ref<Cell> _data = {}, VmLog log = {}, std::vector<Ref<Cell>> _libraries = {}, Ref<Tuple> init_c7 = {})
|
||||
: VmState(convert_code_cell(std::move(_code), global_version, _libraries), global_version, std::move(_stack),
|
||||
_gas, flags, std::move(_data), std::move(log), _libraries, std::move(init_c7)) {
|
||||
}
|
||||
VmState(const VmState&) = delete;
|
||||
VmState(VmState&&) = default;
|
||||
|
@ -345,9 +343,6 @@ class VmState final : public VmStateInterface {
|
|||
int get_global_version() const override {
|
||||
return global_version;
|
||||
}
|
||||
void set_global_version(int version) {
|
||||
global_version = version;
|
||||
}
|
||||
int call(Ref<Continuation> cont);
|
||||
int call(Ref<Continuation> cont, int pass_args, int ret_args = -1);
|
||||
int jump(Ref<Continuation> cont);
|
||||
|
@ -382,7 +377,8 @@ class VmState final : public VmStateInterface {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
static Ref<CellSlice> convert_code_cell(Ref<Cell> code_cell);
|
||||
static Ref<CellSlice> convert_code_cell(Ref<Cell> code_cell, int global_version,
|
||||
const std::vector<Ref<Cell>>& libraries);
|
||||
bool try_commit();
|
||||
void force_commit();
|
||||
|
||||
|
|
|
@ -131,3 +131,4 @@ Example: if the last masterchain block seqno is `19071` then the list contains b
|
|||
- Jumps to nested continuations of depth more than 8 consume 1 gas for eact subsequent continuation (this does not affect most of TVM code).
|
||||
- Fix exception code in some TVM instructions: now `stk_und` has priority over other error codes.
|
||||
- `PFXDICTADD`, `PFXDICTSET`, `PFXDICTREPLACE`, `PFXDICTDEL`, `GETGASFEE`, `GETSTORAGEFEE`, `GETFORWARDFEE`, `GETORIGINALFWDFEE`, `GETGASFEESIMPLE`, `GETFORWARDFEESIMPLE`, `HASHEXT`
|
||||
- Now setting the contract code to a library cell does not consume additional gas on execution of the code.
|
|
@ -2227,7 +2227,7 @@ void TestNode::run_smc_method(int mode, ton::BlockIdExt ref_blk, ton::BlockIdExt
|
|||
// auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
|
||||
vm::GasLimits gas{gas_limit};
|
||||
LOG(DEBUG) << "creating VM";
|
||||
vm::VmState vm{code, std::move(stack), gas, 1, data, vm::VmLog()};
|
||||
vm::VmState vm{code, ton::SUPPORTED_VERSION, std::move(stack), gas, 1, data, vm::VmLog()};
|
||||
vm.set_c7(liteclient::prepare_vm_c7(info.gen_utime, info.gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()),
|
||||
balance)); // tuple with SmartContractInfo
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
|
|
|
@ -135,8 +135,8 @@ runInfo time_run_vm(td::Slice command, td::Ref<vm::Stack> stack) {
|
|||
CHECK(stack.is_unique());
|
||||
try {
|
||||
vm::GasLimits gas_limit;
|
||||
vm::VmState vm{vm::load_cell_slice_ref(cell), std::move(stack), gas_limit, 0, {}, vm::VmLog{}, {}, c7};
|
||||
vm.set_global_version(ton::SUPPORTED_VERSION);
|
||||
vm::VmState vm{
|
||||
vm::load_cell_slice_ref(cell), ton::SUPPORTED_VERSION, std::move(stack), gas_limit, 0, {}, vm::VmLog{}, {}, c7};
|
||||
std::clock_t cStart = std::clock();
|
||||
int ret = ~vm.run();
|
||||
std::clock_t cEnd = std::clock();
|
||||
|
|
|
@ -1520,11 +1520,17 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice
|
|||
libraries.push_back(acc_libs);
|
||||
}
|
||||
vm::GasLimits gas{gas_limit, gas_limit};
|
||||
vm::VmState vm{code, std::move(stack_), gas, 1, std::move(data), vm::VmLog::Null(), std::move(libraries)};
|
||||
vm::VmState vm{code,
|
||||
config->get_global_version(),
|
||||
std::move(stack_),
|
||||
gas,
|
||||
1,
|
||||
std::move(data),
|
||||
vm::VmLog::Null(),
|
||||
std::move(libraries)};
|
||||
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance, config.get(),
|
||||
std::move(code), due_payment);
|
||||
vm.set_c7(c7); // tuple with SmartContractInfo
|
||||
vm.set_global_version(config->get_global_version());
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
LOG(INFO) << "starting VM to run GET-method of smart contract " << acc_workchain_ << ":" << acc_addr_.to_hex();
|
||||
// **** RUN VM ****
|
||||
|
|
Loading…
Reference in a new issue