mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated vm (breaking compatibility)
- updated vm - new actor scheduler - updated tonlib - updated DNS smartcontract
This commit is contained in:
parent
9e4816e7f6
commit
e27fb1e09c
100 changed files with 3692 additions and 1299 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<CellBuilder> 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;
|
||||
|
|
|
@ -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<StackEntry> extract_contents() const & {
|
||||
return stack;
|
||||
}
|
||||
std::vector<StackEntry> extract_contents() && {
|
||||
return std::move(stack);
|
||||
}
|
||||
template <typename... Args>
|
||||
const Stack& check_underflow(Args... args) const {
|
||||
if (!at_least(args...)) {
|
||||
|
|
|
@ -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<StackEntry>& 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<CellSlice> 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<StackEntry>& 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<StackEntry>& 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;
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "utils.h"
|
||||
|
||||
namespace vm {
|
||||
|
@ -88,7 +106,7 @@ td::Result<vm::StackEntry> convert_stack_entry(td::Slice str) {
|
|||
return vm::StackEntry{
|
||||
Ref<vm::CellSlice>{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) {
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2019-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "stack.hpp"
|
||||
|
||||
|
|
|
@ -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<Continuation> cont = Ref<OrdCont>{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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue