Skip to content

Commit

Permalink
More verbose vm logs, fix parsing slice literals (ton-blockchain#1076)
Browse files Browse the repository at this point in the history
* More verbose VM logs

* Fix parsing slice literals in fift
  • Loading branch information
SpyCheese authored Jul 26, 2024
1 parent a5521a6 commit 28f9a9b
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 29 deletions.
8 changes: 7 additions & 1 deletion crypto/block/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,12 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
std::unique_ptr<StringLoggerTail> 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<StringLoggerTail>(log_max_size);
vm_log.log_interface = logger.get();
vm_log.log_options = td::LogOptions(VERBOSITY_NAME(DEBUG), true, false);
Expand All @@ -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;
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions crypto/common/bitstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<long>(ptr == str_end ? ptr - str : str - ptr - 1);
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/common/bitstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
14 changes: 7 additions & 7 deletions crypto/fift/words.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<vm::CellSlice>{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<vm::CellSlice>{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);
}

Expand Down
2 changes: 1 addition & 1 deletion crypto/vm/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 22 additions & 8 deletions crypto/vm/stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<vm::Cell> &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:
Expand All @@ -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() << "}";
}
Expand All @@ -109,15 +112,26 @@ void StackEntry::dump(std::ostream& os, bool verbose) const {
break;
case t_builder:
if (ref.not_null()) {
os << "BC{" << *as_builder() << "}";
if (verbose) {
Ref<CellBuilder> cb = as_builder();
os << "BC{" << cell_to_hex(cb.write().finalize_novm()) << "}";
} else {
os << "BC{" << *as_builder() << "}";
}
} else {
os << "BC{null}";
}
break;
case t_slice: {
if (ref.not_null()) {
os << "CS{";
static_cast<Ref<CellSlice>>(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<CellSlice>>(ref)->dump(os, 1, false);
}
os << '}';
} else {
os << "CS{null}";
Expand Down
8 changes: 4 additions & 4 deletions crypto/vm/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ td::Result<vm::StackEntry> 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");
}
Expand Down
7 changes: 7 additions & 0 deletions crypto/vm/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Cell>(cstate.c5).dump(ss, true);
ss << "\n";
VM_LOG(this) << ss.str();
}
return res;
}
restore_parent = true;
Expand Down
8 changes: 4 additions & 4 deletions tonlib/tonlib/tonlib-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down

0 comments on commit 28f9a9b

Please sign in to comment.