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

tonlib use correct c7: config and address when executing

This commit is contained in:
Starlight Duck 2022-01-20 23:20:56 +02:00 committed by EmelyanenkoK
parent 64615a9766
commit 7dc980562f
7 changed files with 99 additions and 38 deletions

View file

@ -52,30 +52,51 @@ td::Ref<vm::Stack> prepare_vm_stack(td::RefInt256 amount, td::Ref<vm::CellSlice>
return stack_ref;
}
td::Ref<vm::Tuple> prepare_vm_c7(td::uint32 now, td::uint64 balance) {
// TODO: fix initialization of c7
td::Ref<vm::Tuple> 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<vm::Cell>();
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<vm::Cell>())
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<vm::Cell>())
); // 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<vm::Stack> stack, td::Ref<vm::Tuple> c7,
vm::GasLimits gas, bool ignore_chksig) {
vm::GasLimits gas, bool ignore_chksig, td::Ref<vm::Cell> 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<vm::Stac
vm::VmState vm{state.code, std::move(stack), gas, 1, state.data, log};
vm.set_c7(std::move(c7));
vm.set_chksig_always_succeed(ignore_chksig);
if (!libraries.is_null())
vm.register_library_collection(libraries);
try {
res.code = ~vm.run();
} catch (...) {
LOG(FATAL) << "catch unhandled exception";
}
td::ConstBitPtr mlib = vm.get_missing_library();
res.new_state = std::move(state);
res.stack = vm.get_stack_ref();
gas = vm.get_gas_limits();
@ -128,13 +152,17 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref<vm::Stac
LOG(DEBUG) << "VM accepted: " << res.accepted;
LOG(DEBUG) << "VM success: " << res.success;
}
if (!mlib.is_null()) {
LOG(DEBUG) << "Missing library: " << mlib.to_hex(256);
res.missing_library = mlib;
}
if (res.success) {
res.new_state.data = vm.get_c4();
res.actions = vm.get_d(5);
LOG(DEBUG) << "output actions:\n"
<< block::gen::OutList{res.output_actions_count(res.actions)}.as_string_ref(res.actions);
}
LOG_IF(ERROR, gas_credit != 0 && (res.accepted && !res.success))
LOG_IF(ERROR, gas_credit != 0 && (res.accepted && !res.success) && mlib.is_null())
<< "Accepted but failed with code " << res.code << "\n"
<< res.gas_used << "\n";
return res;
@ -176,12 +204,8 @@ td::Ref<vm::Cell> 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<vm::Cell>{});
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<vm::Cell>{});
}
SmartContract::Answer SmartContract::run_get_method(td::Slice method, Args args) const {

View file

@ -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<vm::Cell> actions;
td::int32 code;
td::int64 gas_used;
td::ConstBitPtr missing_library{0};
static int output_actions_count(td::Ref<vm::Cell> list);
};
@ -61,6 +63,10 @@ class SmartContract : public td::CntObject {
td::uint64 amount{0};
td::uint64 balance{0};
td::optional<block::StdAddress> address;
td::optional<std::shared_ptr<const block::Config>> config;
td::optional<vm::Dictionary> libraries;
Args() {
}
Args(std::initializer_list<vm::StackEntry> 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<const block::Config>& config) {
this->config = config;
return std::move(*this);
}
Args&& set_libraries(vm::Dictionary libraries) {
this->libraries = libraries;
return std::move(*this);
}
td::Result<td::int32> get_method_id() const {
if (!method_id) {

View file

@ -604,6 +604,7 @@ Ref<Cell> VmState::load_library(td::ConstBitPtr hash) {
return lib;
}
}
missing_library = hash;
return {};
}

View file

@ -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<OrdCont> ref_to_cont(Ref<Cell> cell) const {
return td::make_ref<OrdCont>(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);

View file

@ -62,9 +62,7 @@ void LastConfig::with_last_block(td::Result<LastBlockState> 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)); });
}

View file

@ -861,13 +861,13 @@ class Query {
}
return res;
}
td::Result<std::pair<Fee, std::vector<Fee>>> estimate_fees(bool ignore_chksig, const block::Config& cfg) {
td::Result<std::pair<Fee, std::vector<Fee>>> estimate_fees(bool ignore_chksig, std::shared_ptr<const block::Config>& 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<tonlib_api::query_fees>(
fees.first.to_tonlib_api(), td::transform(fees.second, [](auto& x) { return x.to_tonlib_api(); })));
@ -3493,6 +3495,20 @@ 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());
args.set_address(it->second->get_address());
auto code = smc->get_state().code;
if (code.not_null()) {
std::vector<td::Bits256> libraryList;
}
args.set_libraries(libraries);
client_.with_last_config([smc=std::move(smc), args=std::move(args),
promise = std::move(promise)](td::Result<LastConfigState> 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<tvm.StackEntry> exit_code:int32 = smc.RunResult;
@ -3501,6 +3517,7 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request,
res_stack.push_back(to_tonlib_api(entry));
}
promise.set_value(tonlib_api::make_object<tonlib_api::smc_runResult>(res.gas_used, std::move(res_stack), res.code));
});
return td::Status::OK();
}

View file

@ -107,6 +107,7 @@ class TonlibClient : public td::actor::Actor {
td::optional<ton::BlockIdExt> block_id;
};
QueryContext query_context_;
vm::Dictionary libraries{256};
// network
td::actor::ActorOwn<ton::adnl::AdnlExtClient> raw_client_;