1
0
Fork 0
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:
ton 2020-02-28 14:28:47 +04:00
parent 9e4816e7f6
commit e27fb1e09c
100 changed files with 3692 additions and 1299 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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...)) {

View file

@ -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;
}

View file

@ -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) {

View file

@ -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"

View file

@ -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;

View file

@ -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();