diff --git a/crypto/smc-envelope/SmartContract.cpp b/crypto/smc-envelope/SmartContract.cpp index 46e90093..7ba768a4 100644 --- a/crypto/smc-envelope/SmartContract.cpp +++ b/crypto/smc-envelope/SmartContract.cpp @@ -168,9 +168,9 @@ td::Ref prepare_vm_c7(SmartContract::Args args) { } SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref stack, td::Ref c7, - vm::GasLimits gas, bool ignore_chksig, td::Ref libraries, int vm_log_verbosity) { + vm::GasLimits gas, bool ignore_chksig, td::Ref libraries, int vm_log_verbosity, bool debug_enabled) { auto gas_credit = gas.gas_credit; - vm::init_op_cp0(); + vm::init_op_cp0(debug_enabled); vm::DictionaryBase::get_empty_dictionary(); class Logger : public td::LogInterface { @@ -289,7 +289,7 @@ SmartContract::Answer SmartContract::run_method(Args args) { args.stack.value().write().push_smallint(args.method_id.unwrap()); auto res = run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig, - args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref{}, args.vm_log_verbosity_level); + args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref{}, args.vm_log_verbosity_level, args.debug_enabled); state_ = res.new_state; return res; } @@ -307,7 +307,7 @@ SmartContract::Answer SmartContract::run_get_method(Args args) const { CHECK(args.method_id); args.stack.value().write().push_smallint(args.method_id.unwrap()); return run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig, - args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref{}, args.vm_log_verbosity_level); + args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref{}, args.vm_log_verbosity_level, args.debug_enabled); } SmartContract::Answer SmartContract::run_get_method(td::Slice method, Args args) const { diff --git a/crypto/smc-envelope/SmartContract.h b/crypto/smc-envelope/SmartContract.h index 6da74bc6..ce349de3 100644 --- a/crypto/smc-envelope/SmartContract.h +++ b/crypto/smc-envelope/SmartContract.h @@ -65,6 +65,7 @@ class SmartContract : public td::CntObject { td::uint64 amount{0}; td::uint64 balance{0}; int vm_log_verbosity_level{0}; + bool debug_enabled{false}; td::optional address; td::optional> config; @@ -135,6 +136,10 @@ class SmartContract : public td::CntObject { this->vm_log_verbosity_level = vm_log_verbosity_level; return std::move(*this); } + Args&& set_debug_enabled(bool debug_enabled) { + this->debug_enabled = debug_enabled; + return std::move(*this); + } td::Result get_method_id() const { if (!method_id) { diff --git a/emulator/emulator-emscripten.cpp b/emulator/emulator-emscripten.cpp index f0f2c903..881664bd 100644 --- a/emulator/emulator-emscripten.cpp +++ b/emulator/emulator-emscripten.cpp @@ -12,6 +12,7 @@ struct TransactionEmulationParams { uint64_t lt; td::optional rand_seed_hex; bool ignore_chksig; + bool debug_enabled; }; td::Result decode_transaction_emulation_params(const char* json) { @@ -37,6 +38,9 @@ td::Result decode_transaction_emulation_params(const TRY_RESULT(ignore_chksig, td::get_json_object_bool_field(obj, "ignore_chksig", false)); params.ignore_chksig = ignore_chksig; + TRY_RESULT(debug_enabled, td::get_json_object_bool_field(obj, "debug_enabled", false)); + params.debug_enabled = debug_enabled; + return params; } @@ -51,6 +55,7 @@ struct GetMethodParams { std::string rand_seed_hex; int64_t gas_limit; int method_id; + bool debug_enabled; }; td::Result decode_get_method_params(const char* json) { @@ -95,6 +100,9 @@ td::Result decode_get_method_params(const char* json) { TRY_RESULT(method_id, td::get_json_object_int_field(obj, "method_id", false)); params.method_id = method_id; + TRY_RESULT(debug_enabled, td::get_json_object_bool_field(obj, "debug_enabled", false)); + params.debug_enabled = debug_enabled; + return params; } @@ -123,6 +131,7 @@ const char *emulate(const char *config, const char* libs, int verbosity, const c !transaction_emulator_set_lt(em, decoded_params.lt) || !transaction_emulator_set_unixtime(em, decoded_params.utime) || !transaction_emulator_set_ignore_chksig(em, decoded_params.ignore_chksig) || + !transaction_emulator_set_debug_enabled(em, decoded_params.debug_enabled) || !rand_seed_set) { transaction_emulator_destroy(em); return strdup(R"({"fail":true,"message":"Can't set params"})"); @@ -163,7 +172,8 @@ const char *run_get_method(const char *params, const char* stack, const char* co if ((decoded_params.libs && !tvm_emulator_set_libraries(tvm, decoded_params.libs.value().c_str())) || !tvm_emulator_set_c7(tvm, decoded_params.address.c_str(), decoded_params.unixtime, decoded_params.balance, decoded_params.rand_seed_hex.c_str(), config) || - (decoded_params.gas_limit > 0 && !tvm_emulator_set_gas_limit(tvm, decoded_params.gas_limit))) { + (decoded_params.gas_limit > 0 && !tvm_emulator_set_gas_limit(tvm, decoded_params.gas_limit)) || + !tvm_emulator_set_debug_enabled(tvm, decoded_params.debug_enabled)) { tvm_emulator_destroy(tvm); return strdup(R"({"fail":true,"message":"Can't set params"})"); } diff --git a/emulator/emulator-extern.cpp b/emulator/emulator-extern.cpp index 238ff670..31a7b649 100644 --- a/emulator/emulator-extern.cpp +++ b/emulator/emulator-extern.cpp @@ -249,6 +249,14 @@ bool transaction_emulator_set_libs(void *transaction_emulator, const char* shard return true; } +bool transaction_emulator_set_debug_enabled(void *transaction_emulator, bool debug_enabled) { + auto emulator = static_cast(transaction_emulator); + + emulator->set_debug_enabled(debug_enabled); + + return true; +} + void transaction_emulator_destroy(void *transaction_emulator) { delete static_cast(transaction_emulator); } @@ -337,6 +345,12 @@ bool tvm_emulator_set_gas_limit(void *tvm_emulator, int64_t gas_limit) { return true; } +bool tvm_emulator_set_debug_enabled(void *tvm_emulator, bool debug_enabled) { + auto emulator = static_cast(tvm_emulator); + emulator->set_debug_enabled(debug_enabled); + return true; +} + const char *tvm_emulator_run_get_method(void *tvm_emulator, int method_id, const char *stack_boc) { auto stack_cell = boc_b64_to_cell(stack_boc); if (stack_cell.is_error()) { diff --git a/emulator/emulator-extern.h b/emulator/emulator-extern.h index ad5972de..db59a822 100644 --- a/emulator/emulator-extern.h +++ b/emulator/emulator-extern.h @@ -64,6 +64,14 @@ EMULATOR_EXPORT bool transaction_emulator_set_config(void *transaction_emulator, */ EMULATOR_EXPORT bool transaction_emulator_set_libs(void *transaction_emulator, const char* libs_boc); +/** + * @brief Enable or disable TVM debug primitives + * @param transaction_emulator Pointer to TransactionEmulator object + * @param debug_enabled Whether debug primitives should be enabled or not + * @return true in case of success, false in case of error + */ +EMULATOR_EXPORT bool transaction_emulator_set_debug_enabled(void *transaction_emulator, bool debug_enabled); + /** * @brief Emulate transaction * @param transaction_emulator Pointer to TransactionEmulator object @@ -134,6 +142,14 @@ EMULATOR_EXPORT bool tvm_emulator_set_c7(void *tvm_emulator, const char *address */ EMULATOR_EXPORT bool tvm_emulator_set_gas_limit(void *tvm_emulator, int64_t gas_limit); +/** + * @brief Enable or disable TVM debug primitives + * @param tvm_emulator Pointer to TVM emulator + * @param debug_enabled Whether debug primitives should be enabled or not + * @return true in case of success, false in case of error + */ +EMULATOR_EXPORT bool tvm_emulator_set_debug_enabled(void *tvm_emulator, bool debug_enabled); + /** * @brief Run get method * @param tvm_emulator Pointer to TVM emulator diff --git a/emulator/emulator_export_list b/emulator/emulator_export_list index 0e9fd51a..64d4ff59 100644 --- a/emulator/emulator_export_list +++ b/emulator/emulator_export_list @@ -5,6 +5,7 @@ _transaction_emulator_set_rand_seed _transaction_emulator_set_ignore_chksig _transaction_emulator_set_config _transaction_emulator_set_libs +_transaction_emulator_set_debug_enabled _transaction_emulator_emulate_transaction _transaction_emulator_destroy _emulator_set_verbosity_level @@ -12,6 +13,7 @@ _tvm_emulator_create _tvm_emulator_set_libraries _tvm_emulator_set_c7 _tvm_emulator_set_gas_limit +_tvm_emulator_set_debug_enabled _tvm_emulator_run_get_method _tvm_emulator_send_external_message _tvm_emulator_send_internal_message diff --git a/emulator/transaction-emulator.cpp b/emulator/transaction-emulator.cpp index a5fea51c..7c8ade62 100644 --- a/emulator/transaction-emulator.cpp +++ b/emulator/transaction-emulator.cpp @@ -34,7 +34,7 @@ td::Result> TransactionEmu return fetch_res.move_as_error_prefix("cannot fetch config params "); } - vm::init_op_cp0(); + vm::init_op_cp0(debug_enabled_); if (!lt) { lt = lt_; @@ -257,4 +257,8 @@ void TransactionEmulator::set_libs(vm::Dictionary &&libs) { libraries_ = std::forward(libs); } +void TransactionEmulator::set_debug_enabled(bool debug_enabled) { + debug_enabled_ = debug_enabled; +} + } // namespace emulator diff --git a/emulator/transaction-emulator.h b/emulator/transaction-emulator.h index 02f875e2..08343cb8 100644 --- a/emulator/transaction-emulator.h +++ b/emulator/transaction-emulator.h @@ -16,11 +16,12 @@ class TransactionEmulator { ton::LogicalTime lt_; td::BitArray<256> rand_seed_; bool ignore_chksig_; + bool debug_enabled_; public: TransactionEmulator(block::Config&& config, int vm_log_verbosity = 0) : config_(std::move(config)), libraries_(256), vm_log_verbosity_(vm_log_verbosity), - unixtime_(0), lt_(0), rand_seed_(td::BitArray<256>::zero()), ignore_chksig_(false) { + unixtime_(0), lt_(0), rand_seed_(td::BitArray<256>::zero()), ignore_chksig_(false), debug_enabled_(false) { } struct EmulationResult { @@ -70,6 +71,7 @@ public: void set_ignore_chksig(bool ignore_chksig); void set_config(block::Config &&config); void set_libs(vm::Dictionary &&libs); + void set_debug_enabled(bool debug_enabled); private: bool check_state_update(const block::Account& account, const block::gen::Transaction::Record& trans); diff --git a/emulator/tvm-emulator.hpp b/emulator/tvm-emulator.hpp index dfbc20b1..0236f0ca 100644 --- a/emulator/tvm-emulator.hpp +++ b/emulator/tvm-emulator.hpp @@ -31,6 +31,10 @@ public: args_.set_config(config); } + void set_debug_enabled(bool debug_enabled) { + args_.set_debug_enabled(debug_enabled); + } + Answer run_get_method(int method_id, td::Ref stack) { return smc_.run_get_method(args_.set_stack(stack).set_method_id(method_id)); }