mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated tonlib + fixes in vm
This commit is contained in:
parent
28735ddc9e
commit
efd47af432
42 changed files with 750 additions and 307 deletions
|
@ -814,6 +814,9 @@ void register_cell_serialize_ops(OpcodeTable& cp0) {
|
|||
compute_len_store_const_ref))
|
||||
.insert(OpcodeInstr::mksimple(0xcf23, 16, "ENDXC", exec_builder_to_special_cell))
|
||||
.insert(OpcodeInstr::mkfixed(0xcf28 >> 2, 14, 2, dump_store_le_int, exec_store_le_int))
|
||||
.insert(OpcodeInstr::mksimple(
|
||||
0xcf30, 16, "BDEPTH",
|
||||
std::bind(exec_int_builder_func, _1, "BDEPTH", [](Ref<CellBuilder> b) { return b->get_depth(); })))
|
||||
.insert(OpcodeInstr::mksimple(
|
||||
0xcf31, 16, "BBITS",
|
||||
std::bind(exec_int_builder_func, _1, "BBITS", [](Ref<CellBuilder> b) { return b->size(); })))
|
||||
|
@ -1321,6 +1324,22 @@ int exec_load_same(VmState* st, const char* name, int x) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int exec_cell_depth(VmState* st) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute CDEPTH";
|
||||
auto cell = stack.pop_maybe_cell();
|
||||
stack.push_smallint(cell.not_null() ? cell->get_depth() : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_slice_depth(VmState* st) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute SDEPTH";
|
||||
auto cs = stack.pop_cellslice();
|
||||
stack.push_smallint(cs->get_depth());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void register_cell_deserialize_ops(OpcodeTable& cp0) {
|
||||
using namespace std::placeholders;
|
||||
cp0.insert(OpcodeInstr::mksimple(0xd0, 8, "CTOS", exec_cell_to_slice))
|
||||
|
@ -1407,7 +1426,9 @@ void register_cell_deserialize_ops(OpcodeTable& cp0) {
|
|||
.insert(OpcodeInstr::mkfixed(0xd75, 12, 4, dump_load_le_int, exec_load_le_int))
|
||||
.insert(OpcodeInstr::mksimple(0xd760, 16, "LDZEROES", std::bind(exec_load_same, _1, "LDZEROES", 0)))
|
||||
.insert(OpcodeInstr::mksimple(0xd761, 16, "LDONES", std::bind(exec_load_same, _1, "LDONES", 1)))
|
||||
.insert(OpcodeInstr::mksimple(0xd762, 16, "LDSAME", std::bind(exec_load_same, _1, "LDSAME", -1)));
|
||||
.insert(OpcodeInstr::mksimple(0xd762, 16, "LDSAME", std::bind(exec_load_same, _1, "LDSAME", -1)))
|
||||
.insert(OpcodeInstr::mksimple(0xd764, 16, "SDEPTH", exec_slice_depth))
|
||||
.insert(OpcodeInstr::mksimple(0xd765, 16, "CDEPTH", exec_cell_depth));
|
||||
}
|
||||
|
||||
void register_cell_ops(OpcodeTable& cp0) {
|
||||
|
|
|
@ -52,7 +52,7 @@ Ref<DataCell> CellBuilder::finalize_copy(bool special) const {
|
|||
}
|
||||
auto res = DataCell::create(data, size(), td::span(refs.data(), size_refs()), special);
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << res.error();
|
||||
LOG(DEBUG) << res.error();
|
||||
throw CellWriteError{};
|
||||
}
|
||||
auto cell = res.move_as_ok();
|
||||
|
@ -60,7 +60,7 @@ Ref<DataCell> CellBuilder::finalize_copy(bool special) const {
|
|||
if (vm_state_interface) {
|
||||
vm_state_interface->register_new_cell(cell);
|
||||
if (cell.is_null()) {
|
||||
LOG(ERROR) << "cannot register new data cell";
|
||||
LOG(DEBUG) << "cannot register new data cell";
|
||||
throw CellWriteError{};
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ Ref<DataCell> CellBuilder::finalize_novm(bool special) {
|
|||
auto res = DataCell::create(data, size(), td::mutable_span(refs.data(), size_refs()), special);
|
||||
bits = refs_cnt = 0;
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << res.error();
|
||||
LOG(DEBUG) << res.error();
|
||||
throw CellWriteError{};
|
||||
}
|
||||
CHECK(res.ok().not_null());
|
||||
|
@ -87,7 +87,7 @@ Ref<DataCell> CellBuilder::finalize(bool special) {
|
|||
auto cell = finalize_novm(special);
|
||||
vm_state_interface->register_new_cell(cell);
|
||||
if (cell.is_null()) {
|
||||
LOG(ERROR) << "cannot register new data cell";
|
||||
LOG(DEBUG) << "cannot register new data cell";
|
||||
throw CellWriteError{};
|
||||
}
|
||||
return cell;
|
||||
|
@ -102,6 +102,7 @@ Ref<Cell> CellBuilder::create_pruned_branch(Ref<Cell> cell, td::uint32 new_level
|
|||
}
|
||||
return do_create_pruned_branch(std::move(cell), new_level, virt_level);
|
||||
}
|
||||
|
||||
Ref<DataCell> CellBuilder::do_create_pruned_branch(Ref<Cell> cell, td::uint32 new_level, td::uint32 virt_level) {
|
||||
auto level_mask = cell->get_level_mask().apply(virt_level);
|
||||
auto level = level_mask.get_level();
|
||||
|
@ -386,6 +387,14 @@ CellBuilder& CellBuilder::store_ref(Ref<Cell> ref) {
|
|||
return ensure_pass(store_ref_bool(std::move(ref)));
|
||||
}
|
||||
|
||||
td::uint16 CellBuilder::get_depth() const {
|
||||
int d = 0;
|
||||
for (unsigned i = 0; i < refs_cnt; i++) {
|
||||
d = std::max(d, 1 + refs[i]->get_depth());
|
||||
}
|
||||
return static_cast<td::uint16>(d);
|
||||
}
|
||||
|
||||
bool CellBuilder::append_data_cell_bool(const DataCell& cell) {
|
||||
unsigned len = cell.size();
|
||||
if (can_extend_by(len, cell.size_refs())) {
|
||||
|
|
|
@ -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/cells/DataCell.h"
|
||||
|
@ -78,6 +78,7 @@ class CellBuilder : public td::CntObject {
|
|||
const unsigned char* get_data() const {
|
||||
return data;
|
||||
}
|
||||
td::uint16 get_depth() const;
|
||||
td::ConstBitPtr data_bits() const {
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -776,6 +776,14 @@ bool CellSlice::fetch_maybe_ref(Ref<vm::Cell>& res) {
|
|||
}
|
||||
}
|
||||
|
||||
td::uint16 CellSlice::get_depth() const {
|
||||
int d = 0;
|
||||
for (unsigned i = 0; i < size_refs(); ++i) {
|
||||
d = std::max(d, prefetch_ref(i)->get_depth() + 1);
|
||||
}
|
||||
return static_cast<td::uint16>(d);
|
||||
}
|
||||
|
||||
bool CellSlice::begins_with(unsigned bits, unsigned long long value) const {
|
||||
return have(bits) && !((prefetch_ulong(bits) ^ value) & ((1ULL << bits) - 1));
|
||||
}
|
||||
|
@ -980,13 +988,18 @@ void CellSlice::dump_hex(std::ostream& os, int mode, bool endl) const {
|
|||
}
|
||||
}
|
||||
|
||||
void CellSlice::print_rec(std::ostream& os, int indent) const {
|
||||
bool CellSlice::print_rec(std::ostream& os, int* limit, int indent) const {
|
||||
for (int i = 0; i < indent; i++) {
|
||||
os << ' ';
|
||||
}
|
||||
if (!limit || *limit <= 0) {
|
||||
os << "<cell output limit reached>" << std::endl;
|
||||
return false;
|
||||
}
|
||||
--*limit;
|
||||
if (cell.is_null()) {
|
||||
os << "NULL" << std::endl;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (is_special()) {
|
||||
os << "SPECIAL ";
|
||||
|
@ -994,8 +1007,20 @@ void CellSlice::print_rec(std::ostream& os, int indent) const {
|
|||
os << "x{" << as_bitslice().to_hex() << '}' << std::endl;
|
||||
for (unsigned i = 0; i < size_refs(); i++) {
|
||||
CellSlice cs{NoVm(), prefetch_ref(i)};
|
||||
cs.print_rec(os, indent + 1);
|
||||
if (!cs.print_rec(os, limit, indent + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellSlice::print_rec(std::ostream& os, int indent) const {
|
||||
int limit = default_recursive_print_limit;
|
||||
return print_rec(os, &limit, indent);
|
||||
}
|
||||
|
||||
bool CellSlice::print_rec(int limit, std::ostream& os, int indent) const {
|
||||
return print_rec(os, &limit, indent);
|
||||
}
|
||||
|
||||
td::StringBuilder& operator<<(td::StringBuilder& sb, const CellSlice& cs) {
|
||||
|
|
|
@ -44,6 +44,7 @@ class CellSlice : public td::CntObject {
|
|||
public:
|
||||
static constexpr long long fetch_long_eof = (static_cast<unsigned long long>(-1LL) << 63);
|
||||
static constexpr unsigned long long fetch_ulong_eof = (unsigned long long)-1LL;
|
||||
enum { default_recursive_print_limit = 100 };
|
||||
struct CellReadError {};
|
||||
|
||||
CellSlice(NoVm, Ref<Cell> cell_ref);
|
||||
|
@ -129,6 +130,7 @@ class CellSlice : public td::CntObject {
|
|||
const unsigned char* data() const {
|
||||
return cell->get_data();
|
||||
}
|
||||
td::uint16 get_depth() const;
|
||||
td::ConstBitPtr data_bits() const {
|
||||
return td::ConstBitPtr{data(), (int)cur_pos()};
|
||||
}
|
||||
|
@ -252,7 +254,9 @@ class CellSlice : public td::CntObject {
|
|||
bool contents_equal(const CellSlice& cs2) const;
|
||||
void dump(std::ostream& os, int level = 0, bool endl = true) const;
|
||||
void dump_hex(std::ostream& os, int mode = 0, bool endl = false) const;
|
||||
void print_rec(std::ostream& os, int indent = 0) const;
|
||||
bool print_rec(std::ostream& os, int indent = 0) const;
|
||||
bool print_rec(std::ostream& os, int* limit, int indent = 0) const;
|
||||
bool print_rec(int limit, std::ostream& os, int indent = 0) const;
|
||||
void error() const {
|
||||
throw CellReadError{};
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ int exec_set_gas_limit(VmState* st) {
|
|||
|
||||
int exec_commit(VmState* st) {
|
||||
VM_LOG(st) << "execute COMMIT";
|
||||
st->commit();
|
||||
st->force_commit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -434,12 +434,33 @@ int VmState::run() {
|
|||
}
|
||||
} while (!res);
|
||||
// LOG(INFO) << "[EN] data cells: " << DataCell::get_total_data_cells();
|
||||
if ((res | 1) == -1) {
|
||||
commit();
|
||||
if ((res | 1) == -1 && !try_commit()) {
|
||||
VM_LOG(this) << "automatic commit failed (new data or action cells too deep)";
|
||||
get_stack().clear();
|
||||
get_stack().push_smallint(0);
|
||||
return ~(int)Excno::cell_ov;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool VmState::try_commit() {
|
||||
if (cr.d[0].not_null() && cr.d[1].not_null() && cr.d[0]->get_depth() <= max_data_depth &&
|
||||
cr.d[1]->get_depth() <= max_data_depth) {
|
||||
cstate.c4 = cr.d[0];
|
||||
cstate.c5 = cr.d[1];
|
||||
cstate.committed = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void VmState::force_commit() {
|
||||
if (!try_commit()) {
|
||||
throw VmError{Excno::cell_ov, "cannot commit too deep cells as new data/actions"};
|
||||
}
|
||||
}
|
||||
|
||||
ControlData* force_cdata(Ref<Continuation>& cont) {
|
||||
if (!cont->get_cdata()) {
|
||||
cont = Ref<ArgContExt>{true, cont};
|
||||
|
|
|
@ -103,7 +103,8 @@ class VmState final : public VmStateInterface {
|
|||
cell_reload_gas_price = 25,
|
||||
cell_create_gas_price = 500,
|
||||
exception_gas_price = 50,
|
||||
tuple_entry_gas_price = 1
|
||||
tuple_entry_gas_price = 1,
|
||||
max_data_depth = 512
|
||||
};
|
||||
VmState();
|
||||
VmState(Ref<CellSlice> _code);
|
||||
|
@ -291,11 +292,8 @@ class VmState final : public VmStateInterface {
|
|||
return cont->is_unique() ? cont.unique_write().jump_w(this) : cont->jump(this);
|
||||
}
|
||||
static Ref<CellSlice> convert_code_cell(Ref<Cell> code_cell);
|
||||
void commit() {
|
||||
cstate.c4 = cr.d[0];
|
||||
cstate.c5 = cr.d[1];
|
||||
cstate.committed = true;
|
||||
}
|
||||
bool try_commit();
|
||||
void force_commit();
|
||||
|
||||
void set_chksig_always_succeed(bool flag) {
|
||||
chksig_always_succeed = flag;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue