1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

bugfixes + doc update

This commit is contained in:
ton 2020-02-08 23:24:24 +04:00
parent 77842f9b63
commit 1de39f5d7c
44 changed files with 652 additions and 272 deletions

View file

@ -55,8 +55,16 @@ Ref<DataCell> CellBuilder::finalize_copy(bool special) const {
LOG(ERROR) << res.error();
throw CellWriteError{};
}
CHECK(res.ok().not_null());
return res.move_as_ok();
auto cell = res.move_as_ok();
CHECK(cell.not_null());
if (vm_state_interface) {
vm_state_interface->register_new_cell(cell);
if (cell.is_null()) {
LOG(ERROR) << "cannot register new data cell";
throw CellWriteError{};
}
}
return cell;
}
Ref<DataCell> CellBuilder::finalize_novm(bool special) {
@ -72,10 +80,17 @@ Ref<DataCell> CellBuilder::finalize_novm(bool special) {
Ref<DataCell> CellBuilder::finalize(bool special) {
auto* vm_state_interface = VmStateInterface::get();
if (vm_state_interface) {
vm_state_interface->register_cell_create();
if (!vm_state_interface) {
return finalize_novm(special);
}
return finalize_novm(special);
vm_state_interface->register_cell_create();
auto cell = finalize_novm(special);
vm_state_interface->register_new_cell(cell);
if (cell.is_null()) {
LOG(ERROR) << "cannot register new data cell";
throw CellWriteError{};
}
return cell;
}
Ref<Cell> CellBuilder::create_pruned_branch(Ref<Cell> cell, td::uint32 new_level, td::uint32 virt_level) {

View file

@ -21,6 +21,7 @@
#include "vm/dict.h"
#include "vm/log.h"
#include "vm/vm.h"
#include "vm/vmstate.h"
namespace vm {
@ -190,6 +191,10 @@ bool ControlData::deserialize(CellSlice& cs, int mode) {
}
bool Continuation::serialize_ref(CellBuilder& cb) const {
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return false;
}
vm::CellBuilder cb2;
return serialize(cb2) && cb.store_ref_bool(cb2.finalize());
}
@ -198,6 +203,11 @@ Ref<Continuation> Continuation::deserialize(CellSlice& cs, int mode) {
if (mode & 0x1002) {
return {};
}
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return {};
}
mode |= 0x1000;
switch (cs.bselect_ext(6, 0x100f011100010001ULL)) {
case 0:

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "cp0.h"
#include "opctable.h"
@ -29,7 +29,8 @@
namespace vm {
const OpcodeTable* init_op_cp0() {
const OpcodeTable* init_op_cp0(bool enable_debug) {
set_debug_enabled(enable_debug);
static const OpcodeTable* static_op_cp0 = [] {
auto op_cp0 = new OpcodeTable("TEST CODEPAGE", Codepage::test_cp);
register_stack_ops(*op_cp0); // stackops.cpp

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "vm/dispatch.h"
@ -23,6 +23,6 @@ namespace vm {
class OpcodeTable;
const OpcodeTable* init_op_cp0();
const OpcodeTable* init_op_cp0(bool debug_enabled = false);
} // namespace vm

View file

@ -28,6 +28,10 @@ namespace vm {
bool vm_debug_enabled = true;
void set_debug_enabled(bool enable_debug) {
vm_debug_enabled = enable_debug;
}
int exec_dummy_debug(VmState* st, int args) {
VM_LOG(st) << "execute DEBUG " << (args & 0xff);
return 0;
@ -66,6 +70,9 @@ int compute_len_debug_str(const CellSlice& cs, unsigned args, int pfx_bits) {
int exec_dump_stack(VmState* st) {
VM_LOG(st) << "execute DUMPSTK";
if (!vm_debug_enabled) {
return 0;
}
Stack& stack = st->get_stack();
int d = stack.depth();
std::cerr << "#DEBUG#: stack(" << d << " values) : ";
@ -84,6 +91,9 @@ int exec_dump_stack(VmState* st) {
int exec_dump_value(VmState* st, unsigned arg) {
arg &= 15;
VM_LOG(st) << "execute DUMP s" << arg;
if (!vm_debug_enabled) {
return 0;
}
Stack& stack = st->get_stack();
if ((int)arg < stack.depth()) {
std::cerr << "#DEBUG#: s" << arg << " = ";

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
@ -25,5 +25,6 @@ class OpcodeTable;
extern bool vm_debug_enabled;
void register_debug_ops(OpcodeTable& cp0);
void set_debug_enabled(bool enable_debug);
} // namespace vm

33
crypto/vm/memo.cpp Normal file
View file

@ -0,0 +1,33 @@
/*
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 2020 Telegram Systems LLP
*/
#include "vm/memo.h"
#include "vm/excno.hpp"
namespace vm {
using td::Ref;
bool FakeVmStateLimits::register_op(int op_units) {
bool ok = (ops_remaining -= op_units) >= 0;
if (!ok && !quiet) {
throw VmError{Excno::out_of_gas, "too many operations"};
}
return ok;
}
} // namespace vm

37
crypto/vm/memo.h Normal file
View file

@ -0,0 +1,37 @@
/*
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 2020 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
#include "vm/cells.h"
#include "vm/vmstate.h"
namespace vm {
using td::Ref;
class FakeVmStateLimits : public VmStateInterface {
long long ops_remaining;
bool quiet;
public:
FakeVmStateLimits(long long max_ops = 1LL << 62, bool _quiet = true) : ops_remaining(max_ops), quiet(_quiet) {
}
bool register_op(int op_units = 1) override;
};
} // namespace vm

View file

@ -20,6 +20,7 @@
#include "vm/continuation.h"
#include "vm/box.hpp"
#include "vm/atom.h"
#include "vm/vmstate.h"
namespace td {
template class td::Cnt<std::string>;
@ -678,6 +679,10 @@ void Stack::push_maybe_cellslice(Ref<CellSlice> cs) {
*/
bool StackEntry::serialize(vm::CellBuilder& cb, int mode) const {
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return false;
}
switch (tp) {
case t_null:
return cb.store_long_bool(0, 8); // vm_stk_null#00 = VmStackValue;
@ -739,6 +744,10 @@ bool StackEntry::serialize(vm::CellBuilder& cb, int mode) const {
}
bool StackEntry::deserialize(CellSlice& cs, int mode) {
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return false;
}
clear();
int t = (mode & 0xf000) ? ((mode >> 12) & 15) : (int)cs.prefetch_ulong(8);
switch (t) {
@ -843,6 +852,10 @@ bool StackEntry::deserialize(Ref<Cell> cell, int mode) {
}
bool Stack::serialize(vm::CellBuilder& cb, int mode) const {
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return false;
}
// vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;
unsigned n = depth();
if (!cb.store_ulong_rchk_bool(n, 24)) { // vm_stack#_ depth:(## 24)
@ -863,6 +876,10 @@ bool Stack::serialize(vm::CellBuilder& cb, int mode) const {
}
bool Stack::deserialize(vm::CellSlice& cs, int mode) {
auto* vsi = VmStateInterface::get();
if (vsi && !vsi->register_op()) {
return false;
}
clear();
// vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;
int n;

View file

@ -53,6 +53,23 @@ int exec_null_swap_if(VmState* st, bool cond, int depth) {
return 0;
}
int exec_null_swap_if_many(VmState* st, bool cond, int depth, int count) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute NULL" << (depth ? "ROTR" : "SWAP") << (cond ? "IF" : "IFNOT") << count;
stack.check_underflow(depth + 1);
auto x = stack.pop_int_finite();
if (!x->sgn() != cond) {
for (int i = 0; i < count; i++) {
stack.push({});
}
for (int i = 0; i < depth; i++) {
swap(stack[i], stack[i + count]);
}
}
stack.push_int(std::move(x));
return 0;
}
int exec_mktuple_common(VmState* st, unsigned n) {
Stack& stack = st->get_stack();
stack.check_underflow(n);
@ -374,6 +391,10 @@ void register_tuple_ops(OpcodeTable& cp0) {
.insert(OpcodeInstr::mksimple(0x6fa1, 16, "NULLSWAPIFNOT", std::bind(exec_null_swap_if, _1, false, 0)))
.insert(OpcodeInstr::mksimple(0x6fa2, 16, "NULLROTRIF", std::bind(exec_null_swap_if, _1, true, 1)))
.insert(OpcodeInstr::mksimple(0x6fa3, 16, "NULLROTRIFNOT", std::bind(exec_null_swap_if, _1, false, 1)))
.insert(OpcodeInstr::mksimple(0x6fa4, 16, "NULLSWAPIF2", std::bind(exec_null_swap_if_many, _1, true, 0, 2)))
.insert(OpcodeInstr::mksimple(0x6fa5, 16, "NULLSWAPIFNOT2", std::bind(exec_null_swap_if_many, _1, false, 0, 2)))
.insert(OpcodeInstr::mksimple(0x6fa6, 16, "NULLROTRIF2", std::bind(exec_null_swap_if_many, _1, true, 1, 2)))
.insert(OpcodeInstr::mksimple(0x6fa7, 16, "NULLROTRIFNOT2", std::bind(exec_null_swap_if_many, _1, false, 1, 2)))
.insert(OpcodeInstr::mkfixed(0x6fb, 12, 4, dump_tuple_index2, exec_tuple_index2))
.insert(OpcodeInstr::mkfixed(0x6fc >> 2, 10, 6, dump_tuple_index3, exec_tuple_index3));
}

View file

@ -28,12 +28,16 @@ using td::Ref;
class VmStateInterface : public td::Context<VmStateInterface> {
public:
virtual ~VmStateInterface() = default;
virtual Ref<vm::Cell> load_library(
virtual Ref<Cell> load_library(
td::ConstBitPtr hash) { // may throw a dictionary exception; returns nullptr if library is not found
return {};
}
virtual void register_cell_load(const CellHash& cell_hash){};
virtual void register_cell_create(){};
virtual void register_new_cell(Ref<DataCell>& cell){};
virtual bool register_op(int op_units = 1) {
return true;
};
};
} // namespace vm