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:
parent
a5521a60aa
commit
28f9a9b159
9 changed files with 56 additions and 29 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}";
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue