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

More verbose vm logs, fix parsing slice literals (#1076)

* More verbose VM logs

* Fix parsing slice literals in fift
This commit is contained in:
SpyCheese 2024-07-26 16:09:43 +03:00 committed by GitHub
parent a5521a60aa
commit 28f9a9b159
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 56 additions and 29 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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:
@ -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<CellBuilder> 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<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}";

View file

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

View file

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

View file

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