diff --git a/crypto/smc-envelope/SmartContract.cpp b/crypto/smc-envelope/SmartContract.cpp index 5f284b57..83e6a4e3 100644 --- a/crypto/smc-envelope/SmartContract.cpp +++ b/crypto/smc-envelope/SmartContract.cpp @@ -52,30 +52,51 @@ td::Ref prepare_vm_stack(td::RefInt256 amount, td::Ref return stack_ref; } -td::Ref prepare_vm_c7(td::uint32 now, td::uint64 balance) { - // TODO: fix initialization of c7 +td::Ref prepare_vm_c7(SmartContract::Args args) { td::BitArray<256> rand_seed; rand_seed.as_slice().fill(0); td::RefInt256 rand_seed_int{true}; rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false); + + td::uint32 now = 0; + if (args.now) { + now = args.now.unwrap(); + } + + vm::CellBuilder cb; + if (args.address) { + td::BigInt256 dest_addr; + dest_addr.import_bits((*args.address).addr.as_bitslice()); + cb.store_ones(1) + .store_zeroes(2) + .store_long((*args.address).workchain, 8) + .store_int256(dest_addr, 256); + } + auto address = cb.finalize(); + auto config = td::Ref(); + + if (args.config) { + config = (*args.config)->get_root_cell(); + } + auto tuple = vm::make_tuple_ref( td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea td::make_refint(0), // actions:Integer td::make_refint(0), // msgs_sent:Integer td::make_refint(now), // unixtime:Integer - td::make_refint(0), // block_lt:Integer - td::make_refint(0), // trans_lt:Integer + td::make_refint(0), //TODO: // block_lt:Integer + td::make_refint(0), //TODO: // trans_lt:Integer std::move(rand_seed_int), // rand_seed:Integer - block::CurrencyCollection(balance).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] - vm::load_cell_slice_ref(vm::CellBuilder().finalize()) // myself:MsgAddressInt - //vm::StackEntry::maybe(td::Ref()) + block::CurrencyCollection(args.balance).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] + vm::load_cell_slice_ref(address), // myself:MsgAddressInt + vm::StackEntry::maybe(config) //vm::StackEntry::maybe(td::Ref()) ); // global_config:(Maybe Cell) ] = SmartContractInfo; //LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); return vm::make_tuple_ref(std::move(tuple)); } SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref stack, td::Ref c7, - vm::GasLimits gas, bool ignore_chksig) { + vm::GasLimits gas, bool ignore_chksig, td::Ref libraries) { auto gas_credit = gas.gas_credit; vm::init_op_cp0(); vm::DictionaryBase::get_empty_dictionary(); @@ -108,11 +129,14 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref SmartContract::get_init_state() const { } SmartContract::Answer SmartContract::run_method(Args args) { - td::uint32 now = 0; - if (args.now) { - now = args.now.unwrap(); - } if (!args.c7) { - args.c7 = prepare_vm_c7(now, args.balance); + args.c7 = prepare_vm_c7(args); } if (!args.limits) { bool is_internal = args.get_method_id().ok() == 0; @@ -193,18 +217,15 @@ SmartContract::Answer SmartContract::run_method(Args args) { CHECK(args.method_id); 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); + 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{}); state_ = res.new_state; return res; } SmartContract::Answer SmartContract::run_get_method(Args args) const { - td::uint32 now = 0; - if (args.now) { - now = args.now.unwrap(); - } if (!args.c7) { - args.c7 = prepare_vm_c7(now, args.balance); + args.c7 = prepare_vm_c7(args); } if (!args.limits) { args.limits = vm::GasLimits{1000000, 1000000}; @@ -214,7 +235,8 @@ 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); + 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{}); } 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 b26f4885..95dd2e84 100644 --- a/crypto/smc-envelope/SmartContract.h +++ b/crypto/smc-envelope/SmartContract.h @@ -26,6 +26,7 @@ #include "td/utils/crypto.h" #include "block/block.h" +#include "block/mc-config.h" namespace ton { class SmartContract : public td::CntObject { @@ -48,6 +49,7 @@ class SmartContract : public td::CntObject { td::Ref actions; td::int32 code; td::int64 gas_used; + td::ConstBitPtr missing_library{0}; static int output_actions_count(td::Ref list); }; @@ -61,6 +63,10 @@ class SmartContract : public td::CntObject { td::uint64 amount{0}; td::uint64 balance{0}; + td::optional address; + td::optional> config; + td::optional libraries; + Args() { } Args(std::initializer_list stack) @@ -106,6 +112,18 @@ class SmartContract : public td::CntObject { this->balance = balance; return std::move(*this); } + Args&& set_address(block::StdAddress address) { + this->address = address; + return std::move(*this); + } + Args&& set_config(std::shared_ptr& config) { + this->config = config; + return std::move(*this); + } + Args&& set_libraries(vm::Dictionary libraries) { + this->libraries = libraries; + return std::move(*this); + } td::Result get_method_id() const { if (!method_id) { diff --git a/crypto/vm/vm.cpp b/crypto/vm/vm.cpp index 038640a5..fb2f4d1e 100644 --- a/crypto/vm/vm.cpp +++ b/crypto/vm/vm.cpp @@ -604,6 +604,7 @@ Ref VmState::load_library(td::ConstBitPtr hash) { return lib; } } + missing_library = hash; return {}; } diff --git a/crypto/vm/vm.h b/crypto/vm/vm.h index 0fef9642..44aa7f23 100644 --- a/crypto/vm/vm.h +++ b/crypto/vm/vm.h @@ -96,6 +96,7 @@ class VmState final : public VmStateInterface { td::int64 loaded_cells_count{0}; int stack_trace{0}, debug_off{0}; bool chksig_always_succeed{false}; + td::ConstBitPtr missing_library{0}; public: enum { @@ -321,6 +322,9 @@ class VmState final : public VmStateInterface { Ref ref_to_cont(Ref cell) const { return td::make_ref(load_cell_slice_ref(std::move(cell)), get_cp()); } + td::ConstBitPtr get_missing_library() const { + return missing_library; + } private: void init_cregs(bool same_c3 = false, bool push_0 = true); diff --git a/tonlib/tonlib/LastConfig.cpp b/tonlib/tonlib/LastConfig.cpp index d07482ce..0111095b 100644 --- a/tonlib/tonlib/LastConfig.cpp +++ b/tonlib/tonlib/LastConfig.cpp @@ -62,9 +62,7 @@ void LastConfig::with_last_block(td::Result r_last_block) { } auto last_block = r_last_block.move_as_ok(); - auto params = params_; - client_.send_query(ton::lite_api::liteServer_getConfigParams(0, create_tl_lite_block_id(last_block.last_block_id), - std::move(params)), + client_.send_query(ton::lite_api::liteServer_getConfigAll(0, create_tl_lite_block_id(last_block.last_block_id)), [this](auto r_config) { this->on_config(std::move(r_config)); }); } diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp index 1ac3a0d7..422dae12 100644 --- a/tonlib/tonlib/TonlibClient.cpp +++ b/tonlib/tonlib/TonlibClient.cpp @@ -861,13 +861,13 @@ class Query { } return res; } - td::Result>> estimate_fees(bool ignore_chksig, const block::Config& cfg) { + td::Result>> estimate_fees(bool ignore_chksig, std::shared_ptr& cfg, vm::Dictionary& libraries) { // gas fees bool is_masterchain = raw_.source->get_address().workchain == ton::masterchainId; - TRY_RESULT(gas_limits_prices, cfg.get_gas_limits_prices(is_masterchain)); - TRY_RESULT(storage_prices, cfg.get_storage_prices()); - TRY_RESULT(masterchain_msg_prices, cfg.get_msg_prices(true)); - TRY_RESULT(basechain_msg_prices, cfg.get_msg_prices(false)); + TRY_RESULT(gas_limits_prices, cfg->get_gas_limits_prices(is_masterchain)); + TRY_RESULT(storage_prices, cfg->get_storage_prices()); + TRY_RESULT(masterchain_msg_prices, cfg->get_msg_prices(true)); + TRY_RESULT(basechain_msg_prices, cfg->get_msg_prices(false)); block::MsgPrices* msg_prices[2] = {&basechain_msg_prices, &masterchain_msg_prices}; auto storage_fee_256 = block::StoragePrices::compute_storage_fees( raw_.source->get_sync_time(), storage_prices, raw_.source->raw().storage_stat, @@ -888,7 +888,9 @@ class Query { .set_limits(gas_limits) .set_balance(raw_.source->get_balance()) .set_now(raw_.source->get_sync_time()) - .set_ignore_chksig(ignore_chksig)); + .set_ignore_chksig(ignore_chksig) + .set_address(raw_.source->get_address()) + .set_config(cfg).set_libraries(libraries)); td::int64 fwd_fee = 0; if (res.success) { LOG(DEBUG) << "output actions:\n" @@ -910,7 +912,7 @@ class Query { for (auto& destination : raw_.destinations) { bool dest_is_masterchain = destination && destination->get_address().workchain == ton::masterchainId; - TRY_RESULT(dest_gas_limits_prices, cfg.get_gas_limits_prices(dest_is_masterchain)); + TRY_RESULT(dest_gas_limits_prices, cfg->get_gas_limits_prices(dest_is_masterchain)); auto dest_storage_fee_256 = destination ? block::StoragePrices::compute_storage_fees( destination->get_sync_time(), storage_prices, destination->raw().storage_stat, @@ -3266,7 +3268,7 @@ void TonlibClient::query_estimate_fees(td::int64 id, bool ignore_chksig, td::Res return; } TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - TRY_RESULT_PROMISE_PREFIX(promise, fees, TRY_VM(it->second->estimate_fees(ignore_chksig, *state.config)), + TRY_RESULT_PROMISE_PREFIX(promise, fees, TRY_VM(it->second->estimate_fees(ignore_chksig, state.config, libraries)), TonlibError::Internal()); promise.set_value(tonlib_api::make_object( fees.first.to_tonlib_api(), td::transform(fees.second, [](auto& x) { return x.to_tonlib_api(); }))); @@ -3493,14 +3495,29 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request, args.set_stack(std::move(stack)); args.set_balance(it->second->get_balance()); args.set_now(it->second->get_sync_time()); - auto res = smc->run_get_method(std::move(args)); + args.set_address(it->second->get_address()); - // smc.runResult gas_used:int53 stack:vector exit_code:int32 = smc.RunResult; - std::vector> res_stack; - for (auto& entry : res.stack->as_span()) { - res_stack.push_back(to_tonlib_api(entry)); + auto code = smc->get_state().code; + if (code.not_null()) { + std::vector libraryList; } - promise.set_value(tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); + + args.set_libraries(libraries); + + client_.with_last_config([smc=std::move(smc), args=std::move(args), + promise = std::move(promise)](td::Result r_state) mutable { + TRY_RESULT_PROMISE(promise, state, std::move(r_state)); + args.set_config(state.config); + + auto res = smc->run_get_method(std::move(args)); + + // smc.runResult gas_used:int53 stack:vector exit_code:int32 = smc.RunResult; + std::vector> res_stack; + for (auto& entry : res.stack->as_span()) { + res_stack.push_back(to_tonlib_api(entry)); + } + promise.set_value(tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); + }); return td::Status::OK(); } diff --git a/tonlib/tonlib/TonlibClient.h b/tonlib/tonlib/TonlibClient.h index bedc1d49..4dfbe8c6 100644 --- a/tonlib/tonlib/TonlibClient.h +++ b/tonlib/tonlib/TonlibClient.h @@ -107,6 +107,7 @@ class TonlibClient : public td::actor::Actor { td::optional block_id; }; QueryContext query_context_; + vm::Dictionary libraries{256}; // network td::actor::ActorOwn raw_client_;