diff --git a/crypto/block/transaction.cpp b/crypto/block/transaction.cpp index 379d899e..dbf0199e 100644 --- a/crypto/block/transaction.cpp +++ b/crypto/block/transaction.cpp @@ -1661,7 +1661,12 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { std::unique_ptr logger; auto vm_log = vm::VmLog(); if (cfg.with_vm_log) { - size_t log_max_size = cfg.vm_log_verbosity > 0 ? 1024 * 1024 : 256; + size_t log_max_size = 256; + if (cfg.vm_log_verbosity > 4) { + log_max_size = 32 << 20; + } else if (cfg.vm_log_verbosity > 0) { + log_max_size = 1 << 20; + } logger = std::make_unique(log_max_size); vm_log.log_interface = logger.get(); vm_log.log_options = td::LogOptions(VERBOSITY_NAME(DEBUG), true, false); @@ -1673,6 +1678,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { vm_log.log_mask |= vm::VmLog::DumpStack; if (cfg.vm_log_verbosity > 4) { vm_log.log_mask |= vm::VmLog::DumpStackVerbose; + vm_log.log_mask |= vm::VmLog::DumpC5; } } } diff --git a/crypto/common/bitstring.cpp b/crypto/common/bitstring.cpp index 5135cdf0..52e57c9a 100644 --- a/crypto/common/bitstring.cpp +++ b/crypto/common/bitstring.cpp @@ -640,11 +640,11 @@ long parse_bitstring_hex_literal(unsigned char* buff, std::size_t buff_size, con return bits; } -long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size, const char* str, const char* str_end) { +long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size_bits, const char* str, const char* str_end) { const char* ptr = str; - while (ptr < str_end && buff_size && (*ptr == '0' || *ptr == '1')) { + while (ptr < str_end && buff_size_bits && (*ptr == '0' || *ptr == '1')) { *buff++ = (bool)(*ptr++ & 1); - --buff_size; + --buff_size_bits; } return td::narrow_cast(ptr == str_end ? ptr - str : str - ptr - 1); } diff --git a/crypto/common/bitstring.h b/crypto/common/bitstring.h index dc3a2fa5..25776478 100644 --- a/crypto/common/bitstring.h +++ b/crypto/common/bitstring.h @@ -58,7 +58,7 @@ unsigned long long bits_load_long_top(ConstBitPtr from, unsigned top_bits); long long bits_load_long(ConstBitPtr from, unsigned bits); unsigned long long bits_load_ulong(ConstBitPtr from, unsigned bits); long parse_bitstring_hex_literal(unsigned char* buff, std::size_t buff_size, const char* str, const char* str_end); -long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size, const char* str, const char* str_end); +long parse_bitstring_binary_literal(BitPtr buff, std::size_t buff_size_bits, const char* str, const char* str_end); void bits_sha256(BitPtr to, ConstBitPtr from, std::size_t size); diff --git a/crypto/fift/words.cpp b/crypto/fift/words.cpp index 8d652afc..43721bf3 100644 --- a/crypto/fift/words.cpp +++ b/crypto/fift/words.cpp @@ -2077,23 +2077,23 @@ void interpret_bitstring_hex_literal(IntCtx& ctx) { auto s = ctx.parser->scan_word_to('}'); unsigned char buff[128]; int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), s.begin(), s.end()); - if (bits < 0) { + vm::CellBuilder cb; + if (bits < 0 || !cb.store_bits_bool(td::ConstBitPtr{buff}, bits)) { throw IntError{"Invalid hex bitstring constant"}; } - auto cs = Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}; - ctx.stack.push(std::move(cs)); + ctx.stack.push(cb.as_cellslice_ref()); push_argcount(ctx, 1); } void interpret_bitstring_binary_literal(IntCtx& ctx) { auto s = ctx.parser->scan_word_to('}'); unsigned char buff[128]; - int bits = (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), s.begin(), s.end()); - if (bits < 0) { + int bits = (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff) * 8, s.begin(), s.end()); + vm::CellBuilder cb; + if (bits < 0 || !cb.store_bits_bool(td::ConstBitPtr{buff}, bits)) { throw IntError{"Invalid binary bitstring constant"}; } - auto cs = Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}; - ctx.stack.push(std::move(cs)); + ctx.stack.push(cb.as_cellslice_ref()); push_argcount(ctx, 1); } diff --git a/crypto/vm/log.h b/crypto/vm/log.h index dc0199b5..c8486324 100644 --- a/crypto/vm/log.h +++ b/crypto/vm/log.h @@ -31,7 +31,7 @@ namespace vm { struct VmLog { td::LogInterface *log_interface{td::log_interface}; td::LogOptions log_options{td::log_options}; - enum { DumpStack = 2, ExecLocation = 4, GasRemaining = 8, DumpStackVerbose = 16 }; + enum { DumpStack = 2, ExecLocation = 4, GasRemaining = 8, DumpStackVerbose = 16, DumpC5 = 32 }; int log_mask{1}; static VmLog Null() { VmLog res; diff --git a/crypto/vm/stack.cpp b/crypto/vm/stack.cpp index 69760524..aac1b6b5 100644 --- a/crypto/vm/stack.cpp +++ b/crypto/vm/stack.cpp @@ -83,6 +83,14 @@ std::string StackEntry::to_lisp_string() const { return std::move(os).str(); } +static std::string cell_to_hex(const td::Ref &cell) { + auto boc = vm::std_boc_serialize(cell); + if (boc.is_ok()) { + return td::buffer_to_hex(boc.move_as_ok().as_slice()); + } + return "???"; +} + void StackEntry::dump(std::ostream& os, bool verbose) const { switch (tp) { case t_null: @@ -94,12 +102,7 @@ void StackEntry::dump(std::ostream& os, bool verbose) const { case t_cell: if (ref.not_null()) { if (verbose) { - std::string serialized = "???"; - auto boc = vm::std_boc_serialize(as_cell()); - if (boc.is_ok()) { - serialized = td::buffer_to_hex(boc.move_as_ok().as_slice()); - } - os << "C{" << serialized << "}"; + os << "C{" << cell_to_hex(as_cell()) << "}"; } else { os << "C{" << *as_cell() << "}"; } @@ -109,7 +112,12 @@ void StackEntry::dump(std::ostream& os, bool verbose) const { break; case t_builder: if (ref.not_null()) { - os << "BC{" << *as_builder() << "}"; + if (verbose) { + Ref cb = as_builder(); + os << "BC{" << cell_to_hex(cb.write().finalize_novm()) << "}"; + } else { + os << "BC{" << *as_builder() << "}"; + } } else { os << "BC{null}"; } @@ -117,7 +125,13 @@ void StackEntry::dump(std::ostream& os, bool verbose) const { case t_slice: { if (ref.not_null()) { os << "CS{"; - static_cast>(ref)->dump(os, 1, false); + if (verbose) { + CellBuilder cb; + cb.append_cellslice(as_slice()); + os << cell_to_hex(cb.finalize_novm()); + } else { + static_cast>(ref)->dump(os, 1, false); + } os << '}'; } else { os << "CS{null}"; diff --git a/crypto/vm/utils.cpp b/crypto/vm/utils.cpp index 783bf132..52bfb0d4 100644 --- a/crypto/vm/utils.cpp +++ b/crypto/vm/utils.cpp @@ -96,10 +96,10 @@ td::Result convert_stack_entry(td::Slice str) { } if (l >= 3 && (str[0] == 'x' || str[0] == 'b') && str[1] == '{' && str.back() == '}') { unsigned char buff[128]; - int bits = - (str[0] == 'x') - ? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1) - : (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1); + int bits = (str[0] == 'x') + ? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1) + : (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff) * 8, str.begin() + 2, + str.end() - 1); if (bits < 0) { return td::Status::Error("failed to parse raw b{...}/x{...} number"); } diff --git a/crypto/vm/vm.cpp b/crypto/vm/vm.cpp index d21ce974..fb774f80 100644 --- a/crypto/vm/vm.cpp +++ b/crypto/vm/vm.cpp @@ -529,6 +529,13 @@ int VmState::run() { res = vmoog.get_errno(); // no ~ for unhandled exceptions (to make their faking impossible) } if (!parent) { + if ((log.log_mask & VmLog::DumpC5) && cstate.committed) { + std::stringstream ss; + ss << "final c5: "; + StackEntry::maybe(cstate.c5).dump(ss, true); + ss << "\n"; + VM_LOG(this) << ss.str(); + } return res; } restore_parent = true; diff --git a/tonlib/tonlib/tonlib-cli.cpp b/tonlib/tonlib/tonlib-cli.cpp index 5a32b50f..f955adb5 100644 --- a/tonlib/tonlib/tonlib-cli.cpp +++ b/tonlib/tonlib/tonlib-cli.cpp @@ -1361,10 +1361,10 @@ class TonlibCli : public td::actor::Actor { } if (l >= 3 && (str[0] == 'x' || str[0] == 'b') && str[1] == '{' && str.back() == '}') { unsigned char buff[128]; - int bits = - (str[0] == 'x') - ? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1) - : (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1); + int bits = (str[0] == 'x') ? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, + str.end() - 1) + : (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff) * 8, + str.begin() + 2, str.end() - 1); if (bits < 0) { return td::Status::Error("Failed to parse slice"); }