mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
new db
new database fift/func bugfixes
This commit is contained in:
parent
950e292264
commit
e30d98eb30
110 changed files with 6102 additions and 2075 deletions
|
@ -438,3 +438,94 @@ TEST(Tonlib, KeysApi) {
|
|||
CHECK(new_imported_key->public_key_ == key->public_key_);
|
||||
CHECK(new_imported_key->secret_ != key->secret_);
|
||||
}
|
||||
|
||||
TEST(Tonlib, ConfigCache) {
|
||||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
||||
td::mkdir("testdir").ignore();
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("testdir"))))
|
||||
.ensure();
|
||||
|
||||
auto testnet = R"abc({
|
||||
"liteservers": [
|
||||
],
|
||||
"validator": {
|
||||
"@type": "validator.config.global",
|
||||
"zero_state": {
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808,
|
||||
"seqno": 0,
|
||||
"root_hash": "VCSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
|
||||
"file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
|
||||
}
|
||||
}
|
||||
})abc";
|
||||
auto testnet2 = R"abc({
|
||||
"liteservers": [
|
||||
],
|
||||
"validator": {
|
||||
"@type": "validator.config.global",
|
||||
"zero_state": {
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808,
|
||||
"seqno": 0,
|
||||
"root_hash": "VXSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
|
||||
"file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
|
||||
}
|
||||
}
|
||||
})abc";
|
||||
auto testnet3 = R"abc({
|
||||
"liteservers": [
|
||||
],
|
||||
"validator": {
|
||||
"@type": "validator.config.global",
|
||||
"zero_state": {
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808,
|
||||
"seqno": 0,
|
||||
"root_hash": "ZXSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
|
||||
"file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
|
||||
}
|
||||
}
|
||||
})abc";
|
||||
auto bad = R"abc({
|
||||
"liteservers": [
|
||||
],
|
||||
"validator": {
|
||||
"@type": "validator.config.global",
|
||||
"zero_state": {
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808,
|
||||
"seqno": 0,
|
||||
"file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
|
||||
}
|
||||
}
|
||||
})abc";
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(bad, "", true, false)))
|
||||
.ensure_error();
|
||||
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet, "", true, false)))
|
||||
.ensure();
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet2, "", true, false)))
|
||||
.ensure();
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::options_validateConfig>(make_object<tonlib_api::config>(testnet3, "", true, false)))
|
||||
.ensure();
|
||||
|
||||
sync_send(client, make_object<tonlib_api::options_validateConfig>(
|
||||
make_object<tonlib_api::config>(testnet2, "testnet", true, false)))
|
||||
.ensure_error();
|
||||
|
||||
sync_send(client, make_object<tonlib_api::options_setConfig>(
|
||||
make_object<tonlib_api::config>(testnet2, "testnet2", true, false)))
|
||||
.ensure();
|
||||
sync_send(client, make_object<tonlib_api::options_setConfig>(
|
||||
make_object<tonlib_api::config>(testnet3, "testnet2", true, false)))
|
||||
.ensure_error();
|
||||
}
|
||||
|
|
|
@ -533,14 +533,12 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
Client client;
|
||||
{
|
||||
auto info = sync_send(client, make_object<tonlib_api::options_validateConfig>(
|
||||
make_object<tonlib_api::config>(global_config_str, "", false, false)))
|
||||
auto info = sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
make_object<tonlib_api::config>(global_config_str, "", false, false),
|
||||
make_object<tonlib_api::keyStoreTypeDirectory>(keystore_dir))))
|
||||
.move_as_ok();
|
||||
default_wallet_id = static_cast<td::uint32>(info->default_wallet_id_);
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
make_object<tonlib_api::config>(global_config_str, "", false, false),
|
||||
make_object<tonlib_api::keyStoreTypeDirectory>(keystore_dir))))
|
||||
.ensure();
|
||||
default_wallet_id = static_cast<td::uint32>(info->config_info_->default_wallet_id_);
|
||||
LOG(ERROR) << default_wallet_id;
|
||||
}
|
||||
|
||||
// wait till client is synchronized with blockchain.
|
||||
|
|
|
@ -66,6 +66,16 @@ struct SendMessage {
|
|||
};
|
||||
} // namespace int_api
|
||||
|
||||
template <class R, class O, class F>
|
||||
R downcast_call2(O&& o, F&& f, R res = {}) {
|
||||
downcast_call(o, [&](auto& x) { res = f(x); });
|
||||
return res;
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::options_configInfo> to_tonlib_api(const TonlibClient::FullConfig& full_config) {
|
||||
return tonlib_api::make_object<tonlib_api::options_configInfo>(full_config.wallet_id);
|
||||
}
|
||||
|
||||
class TonlibQueryActor : public td::actor::Actor {
|
||||
public:
|
||||
TonlibQueryActor(td::actor::ActorShared<TonlibClient> client) : client_(std::move(client)) {
|
||||
|
@ -867,7 +877,7 @@ void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 conf
|
|||
return;
|
||||
}
|
||||
|
||||
last_block_storage_.save_state(blockchain_name_, state);
|
||||
last_block_storage_.save_state(last_state_key_, state);
|
||||
}
|
||||
|
||||
void TonlibClient::update_sync_state(LastBlockSyncState state, td::uint32 config_generation) {
|
||||
|
@ -889,7 +899,7 @@ void TonlibClient::update_sync_state(LastBlockSyncState state, td::uint32 config
|
|||
}
|
||||
}
|
||||
|
||||
void TonlibClient::init_last_block(td::optional<Config> o_master_config) {
|
||||
void TonlibClient::init_last_block(LastBlockState state) {
|
||||
ref_cnt_++;
|
||||
class Callback : public LastBlock::Callback {
|
||||
public:
|
||||
|
@ -907,31 +917,8 @@ void TonlibClient::init_last_block(td::optional<Config> o_master_config) {
|
|||
td::actor::ActorShared<TonlibClient> client_;
|
||||
td::uint32 config_generation_;
|
||||
};
|
||||
LastBlockState state;
|
||||
|
||||
td::Result<LastBlockState> r_state;
|
||||
if (!ignore_cache_) {
|
||||
r_state = last_block_storage_.get_state(blockchain_name_);
|
||||
}
|
||||
if (ignore_cache_ || r_state.is_error()) {
|
||||
LOG_IF(WARNING, !ignore_cache_) << "Unknown LastBlockState: " << r_state.error();
|
||||
state.zero_state_id = ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
|
||||
config_.zero_state_id.file_hash),
|
||||
state.last_block_id = config_.zero_state_id;
|
||||
state.last_key_block_id = config_.zero_state_id;
|
||||
last_block_storage_.save_state(blockchain_name_, state);
|
||||
} else {
|
||||
state = r_state.move_as_ok();
|
||||
}
|
||||
|
||||
if (o_master_config) {
|
||||
auto master_config = o_master_config.unwrap();
|
||||
if (master_config.init_block_id.is_valid() &&
|
||||
state.last_key_block_id.id.seqno < master_config.init_block_id.id.seqno) {
|
||||
state.last_key_block_id = master_config.init_block_id;
|
||||
LOG(INFO) << "Use init block from MASTER config: " << master_config.init_block_id.to_str();
|
||||
}
|
||||
}
|
||||
last_block_storage_.save_state(last_state_key_, state);
|
||||
|
||||
raw_last_block_ = td::actor::create_actor<LastBlock>(
|
||||
td::actor::ActorOptions().with_name("LastBlock").with_poll(false), get_client_ref(), std::move(state), config_,
|
||||
|
@ -1013,8 +1000,8 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::static_request(
|
|||
return tonlib_api::make_object<tonlib_api::error>(400, "Request is empty");
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> response;
|
||||
downcast_call(*function, [&response](auto& request) { response = TonlibClient::do_static_request(request); });
|
||||
auto response = downcast_call2<tonlib_api::object_ptr<tonlib_api::Object>>(
|
||||
*function, [](auto& request) { return TonlibClient::do_static_request(request); });
|
||||
VLOG(tonlib_query) << " answer static query " << to_string(response);
|
||||
return response;
|
||||
}
|
||||
|
@ -1029,7 +1016,6 @@ bool TonlibClient::is_static_request(td::int32 id) {
|
|||
case tonlib_api::testGiver_getAccountAddress::ID:
|
||||
case tonlib_api::packAccountAddress::ID:
|
||||
case tonlib_api::unpackAccountAddress::ID:
|
||||
case tonlib_api::options_validateConfig::ID:
|
||||
case tonlib_api::getBip39Hints::ID:
|
||||
case tonlib_api::setLogStream::ID:
|
||||
case tonlib_api::getLogStream::ID:
|
||||
|
@ -1190,7 +1176,7 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(tonli
|
|||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::init& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
td::Promise<object_ptr<tonlib_api::options_info>>&& promise) {
|
||||
if (state_ != State::Uninited) {
|
||||
return td::Status::Error(400, "Tonlib is already inited");
|
||||
}
|
||||
|
@ -1201,23 +1187,24 @@ td::Status TonlibClient::do_request(const tonlib_api::init& request,
|
|||
return TonlibError::EmptyField("options.keystore_type");
|
||||
}
|
||||
|
||||
td::Result<td::unique_ptr<KeyValue>> r_kv;
|
||||
downcast_call(
|
||||
auto r_kv = downcast_call2<td::Result<td::unique_ptr<KeyValue>>>(
|
||||
*request.options_->keystore_type_,
|
||||
td::overloaded(
|
||||
[&](tonlib_api::keyStoreTypeDirectory& directory) { r_kv = KeyValue::create_dir(directory.directory_); },
|
||||
[&](tonlib_api::keyStoreTypeInMemory& inmemory) { r_kv = KeyValue::create_inmemory(); }));
|
||||
[](tonlib_api::keyStoreTypeDirectory& directory) { return KeyValue::create_dir(directory.directory_); },
|
||||
[](tonlib_api::keyStoreTypeInMemory& inmemory) { return KeyValue::create_inmemory(); }));
|
||||
TRY_RESULT(kv, std::move(r_kv));
|
||||
kv_ = std::shared_ptr<KeyValue>(kv.release());
|
||||
|
||||
key_storage_.set_key_value(kv_);
|
||||
last_block_storage_.set_key_value(kv_);
|
||||
auto res = tonlib_api::make_object<tonlib_api::options_info>();
|
||||
if (request.options_->config_) {
|
||||
TRY_RESULT(full_config, validate_config(std::move(request.options_->config_)));
|
||||
res->config_info_ = to_tonlib_api(full_config);
|
||||
set_config(std::move(full_config));
|
||||
}
|
||||
state_ = State::Running;
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
promise.set_value(std::move(res));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
@ -1291,21 +1278,55 @@ td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::o
|
|||
}
|
||||
|
||||
td::optional<Config> o_master_config;
|
||||
std::string last_state_key;
|
||||
if (config->blockchain_name_.empty()) {
|
||||
last_state_key = new_config.zero_state_id.root_hash.as_slice().str();
|
||||
o_master_config = get_default_master_config().by_root_hash(new_config.zero_state_id.root_hash);
|
||||
} else {
|
||||
last_state_key = config->blockchain_name_;
|
||||
o_master_config = get_default_master_config().by_name(config->blockchain_name_);
|
||||
}
|
||||
|
||||
if (o_master_config && o_master_config.value().zero_state_id != new_config.zero_state_id) {
|
||||
return TonlibError::InvalidConfig("zero_state differs from embedded zero_state");
|
||||
}
|
||||
|
||||
LastBlockState state;
|
||||
td::Result<LastBlockState> r_state;
|
||||
if (!config->ignore_cache_) {
|
||||
r_state = last_block_storage_.get_state(last_state_key);
|
||||
}
|
||||
auto zero_state = ton::ZeroStateIdExt(new_config.zero_state_id.id.workchain, new_config.zero_state_id.root_hash,
|
||||
new_config.zero_state_id.file_hash);
|
||||
if (config->ignore_cache_ || r_state.is_error()) {
|
||||
LOG_IF(WARNING, !config->ignore_cache_) << "Unknown LastBlockState: " << r_state.error();
|
||||
state.zero_state_id = zero_state;
|
||||
state.last_block_id = new_config.zero_state_id;
|
||||
state.last_key_block_id = new_config.zero_state_id;
|
||||
} else {
|
||||
state = r_state.move_as_ok();
|
||||
if (state.zero_state_id != zero_state) {
|
||||
LOG(ERROR) << state.zero_state_id.to_str() << " " << zero_state.to_str();
|
||||
return TonlibError::InvalidConfig("zero_state differs from cached zero_state");
|
||||
}
|
||||
}
|
||||
|
||||
if (o_master_config) {
|
||||
auto master_config = o_master_config.unwrap();
|
||||
if (master_config.init_block_id.is_valid() &&
|
||||
state.last_key_block_id.id.seqno < master_config.init_block_id.id.seqno) {
|
||||
state.last_key_block_id = master_config.init_block_id;
|
||||
LOG(INFO) << "Use init block from MASTER config: " << master_config.init_block_id.to_str();
|
||||
}
|
||||
}
|
||||
|
||||
FullConfig res;
|
||||
res.config = std::move(new_config);
|
||||
res.o_master_config = std::move(o_master_config);
|
||||
res.ignore_cache = config->ignore_cache_;
|
||||
res.use_callbacks_for_network = config->use_callbacks_for_network_;
|
||||
res.wallet_id = td::as<td::uint32>(res.config.zero_state_id.root_hash.as_slice().data());
|
||||
res.last_state_key = std::move(last_state_key);
|
||||
res.last_state = std::move(state);
|
||||
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
|
@ -1313,12 +1334,11 @@ void TonlibClient::set_config(FullConfig full_config) {
|
|||
config_ = std::move(full_config.config);
|
||||
config_generation_++;
|
||||
wallet_id_ = full_config.wallet_id;
|
||||
blockchain_name_ = config_.zero_state_id.root_hash.as_slice().str();
|
||||
last_state_key_ = full_config.last_state_key;
|
||||
|
||||
use_callbacks_for_network_ = full_config.use_callbacks_for_network;
|
||||
ignore_cache_ = full_config.ignore_cache;
|
||||
init_ext_client();
|
||||
init_last_block(std::move(full_config.o_master_config));
|
||||
init_last_block(std::move(full_config.last_state));
|
||||
init_last_config();
|
||||
client_.set_client(get_client_ref());
|
||||
}
|
||||
|
@ -1332,23 +1352,23 @@ td::Status TonlibClient::do_request(const tonlib_api::close& request,
|
|||
return td::Status::OK();
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
tonlib_api::options_validateConfig& request) {
|
||||
auto r_config = validate_config(std::move(request.config_));
|
||||
if (r_config.is_error()) {
|
||||
return status_to_tonlib_api(r_config.move_as_error());
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::options_configInfo>(r_config.ok().wallet_id);
|
||||
td::Status TonlibClient::do_request(tonlib_api::options_validateConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::options_configInfo>>&& promise) {
|
||||
TRY_RESULT(config, validate_config(std::move(request.config_)));
|
||||
auto res = to_tonlib_api(config);
|
||||
promise.set_value(std::move(res));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(tonlib_api::options_setConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
td::Promise<object_ptr<tonlib_api::options_configInfo>>&& promise) {
|
||||
if (!request.config_) {
|
||||
return TonlibError::EmptyField("config");
|
||||
}
|
||||
TRY_RESULT(config, validate_config(std::move(request.config_)));
|
||||
auto res = to_tonlib_api(config);
|
||||
set_config(std::move(config));
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
promise.set_value(std::move(res));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
@ -1603,11 +1623,9 @@ td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::inputKeyRegular& input_
|
|||
}
|
||||
|
||||
td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::InputKey& input_key) {
|
||||
td::Result<KeyStorage::InputKey> r_key;
|
||||
tonlib_api::downcast_call(
|
||||
input_key, td::overloaded([&](tonlib_api::inputKeyRegular& input_key) { r_key = from_tonlib(input_key); },
|
||||
[&](tonlib_api::inputKeyFake&) { r_key = KeyStorage::fake_input_key(); }));
|
||||
return r_key;
|
||||
return downcast_call2<td::Result<KeyStorage::InputKey>>(
|
||||
input_key, td::overloaded([&](tonlib_api::inputKeyRegular& input_key) { return from_tonlib(input_key); },
|
||||
[&](tonlib_api::inputKeyFake&) { return KeyStorage::fake_input_key(); }));
|
||||
}
|
||||
|
||||
// ton::TestWallet
|
||||
|
@ -2195,6 +2213,98 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_getState& request,
|
|||
return td::Status::OK();
|
||||
}
|
||||
|
||||
bool is_list(vm::StackEntry entry) {
|
||||
while (true) {
|
||||
if (entry.type() == vm::StackEntry::Type::t_null) {
|
||||
return true;
|
||||
}
|
||||
if (entry.type() != vm::StackEntry::Type::t_tuple) {
|
||||
return false;
|
||||
}
|
||||
if (entry.as_tuple()->size() != 2) {
|
||||
return false;
|
||||
}
|
||||
entry = entry.as_tuple()->at(1);
|
||||
}
|
||||
};
|
||||
auto to_tonlib_api(const vm::StackEntry& entry) -> tonlib_api::object_ptr<tonlib_api::tvm_StackEntry> {
|
||||
switch (entry.type()) {
|
||||
case vm::StackEntry::Type::t_int:
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryNumber>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_numberDecimal>(dec_string(entry.as_int())));
|
||||
case vm::StackEntry::Type::t_slice:
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(tonlib_api::make_object<tonlib_api::tvm_cell>(
|
||||
to_bytes(vm::CellBuilder().append_cellslice(entry.as_slice()).finalize())));
|
||||
case vm::StackEntry::Type::t_cell:
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(entry.as_cell())));
|
||||
case vm::StackEntry::Type::t_null:
|
||||
case vm::StackEntry::Type::t_tuple: {
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>> elements;
|
||||
if (is_list(entry)) {
|
||||
auto node = entry;
|
||||
while (node.type() == vm::StackEntry::Type::t_tuple) {
|
||||
elements.push_back(to_tonlib_api(node.as_tuple()->at(0)));
|
||||
node = node.as_tuple()->at(1);
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryList>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_list>(std::move(elements)));
|
||||
|
||||
} else {
|
||||
for (auto& element : *entry.as_tuple()) {
|
||||
elements.push_back(to_tonlib_api(element));
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryTuple>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_tuple>(std::move(elements)));
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return tonlib_api::make_object<tonlib_api::tvm_stackEntryUnsupported>();
|
||||
}
|
||||
};
|
||||
|
||||
td::Result<vm::StackEntry> from_tonlib_api(tonlib_api::tvm_StackEntry& entry) {
|
||||
// TODO: error codes
|
||||
// downcast_call
|
||||
return downcast_call2<td::Result<vm::StackEntry>>(
|
||||
entry,
|
||||
td::overloaded(
|
||||
[&](tonlib_api::tvm_stackEntryUnsupported& cell) { return td::Status::Error("Unsuppored stack entry"); },
|
||||
[&](tonlib_api::tvm_stackEntrySlice& cell) -> td::Result<vm::StackEntry> {
|
||||
TRY_RESULT(res, vm::std_boc_deserialize(cell.slice_->bytes_));
|
||||
return vm::StackEntry{std::move(res)};
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryCell& cell) -> td::Result<vm::StackEntry> {
|
||||
TRY_RESULT(res, vm::std_boc_deserialize(cell.cell_->bytes_));
|
||||
return vm::StackEntry{std::move(res)};
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryTuple& tuple) -> td::Result<vm::StackEntry> {
|
||||
std::vector<vm::StackEntry> elements;
|
||||
for (auto& element : tuple.tuple_->elements_) {
|
||||
TRY_RESULT(new_element, from_tonlib_api(*element));
|
||||
elements.push_back(std::move(new_element));
|
||||
}
|
||||
return td::Ref<vm::Tuple>(true, std::move(elements));
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryList& tuple) -> td::Result<vm::StackEntry> {
|
||||
vm::StackEntry tail;
|
||||
for (auto& element : td::reversed(tuple.list_->elements_)) {
|
||||
TRY_RESULT(new_element, from_tonlib_api(*element));
|
||||
tail = vm::make_tuple_ref(std::move(new_element), std::move(tail));
|
||||
}
|
||||
return tail;
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryNumber& number) -> td::Result<vm::StackEntry> {
|
||||
auto& dec = *number.number_;
|
||||
auto num = td::dec_string_to_int256(dec.number_);
|
||||
if (num.is_null()) {
|
||||
return td::Status::Error("Failed to parse dec string to int256");
|
||||
}
|
||||
return num;
|
||||
}));
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request,
|
||||
td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise) {
|
||||
auto it = smcs_.find(request.id_);
|
||||
|
@ -2209,65 +2319,17 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request,
|
|||
[&](tonlib_api::smc_methodIdName& name) { args.set_method_id(name.name_); }));
|
||||
td::Ref<vm::Stack> stack(true);
|
||||
td::Status status;
|
||||
// TODO: error codes
|
||||
// downcast_call
|
||||
for (auto& entry : request.stack_) {
|
||||
downcast_call(*entry, td::overloaded(
|
||||
[&](tonlib_api::tvm_stackEntryUnsupported& cell) {
|
||||
status = td::Status::Error("Unsuppored stack entry");
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntrySlice& cell) {
|
||||
auto r_cell = vm::std_boc_deserialize(cell.slice_->bytes_);
|
||||
if (r_cell.is_error()) {
|
||||
status = r_cell.move_as_error();
|
||||
return;
|
||||
}
|
||||
stack.write().push_cell(r_cell.move_as_ok());
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryCell& cell) {
|
||||
auto r_cell = vm::std_boc_deserialize(cell.cell_->bytes_);
|
||||
if (r_cell.is_error()) {
|
||||
status = r_cell.move_as_error();
|
||||
return;
|
||||
}
|
||||
stack.write().push_cell(r_cell.move_as_ok());
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryNumber& number) {
|
||||
[&](tonlib_api::tvm_numberDecimal& dec) {
|
||||
auto num = td::dec_string_to_int256(dec.number_);
|
||||
if (num.is_null()) {
|
||||
status = td::Status::Error("Failed to parse dec string to int256");
|
||||
return;
|
||||
}
|
||||
stack.write().push_int(std::move(num));
|
||||
}(*number.number_);
|
||||
}));
|
||||
TRY_RESULT(e, from_tonlib_api(*entry));
|
||||
stack.write().push(std::move(e));
|
||||
}
|
||||
TRY_STATUS(std::move(status));
|
||||
args.set_stack(std::move(stack));
|
||||
auto res = smc->run_get_method(std::move(args));
|
||||
|
||||
// smc.runResult gas_used:int53 stack:vector<tvm.StackEntry> exit_code:int32 = smc.RunResult;
|
||||
std::vector<object_ptr<tonlib_api::tvm_StackEntry>> res_stack;
|
||||
for (auto& entry : res.stack->as_span()) {
|
||||
switch (entry.type()) {
|
||||
case vm::StackEntry::Type::t_int:
|
||||
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryNumber>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_numberDecimal>(dec_string(entry.as_int()))));
|
||||
break;
|
||||
case vm::StackEntry::Type::t_slice:
|
||||
res_stack.push_back(
|
||||
tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(tonlib_api::make_object<tonlib_api::tvm_cell>(
|
||||
to_bytes(vm::CellBuilder().append_cellslice(entry.as_slice()).finalize()))));
|
||||
break;
|
||||
case vm::StackEntry::Type::t_cell:
|
||||
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(entry.as_cell()))));
|
||||
break;
|
||||
default:
|
||||
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryUnsupported>());
|
||||
break;
|
||||
}
|
||||
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();
|
||||
|
@ -2576,11 +2638,6 @@ td::Status TonlibClient::do_request(const tonlib_api::unpackAccountAddress& requ
|
|||
return TonlibError::Internal();
|
||||
}
|
||||
template <class P>
|
||||
td::Status TonlibClient::do_request(const tonlib_api::options_validateConfig& request, P&&) {
|
||||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
}
|
||||
template <class P>
|
||||
td::Status TonlibClient::do_request(tonlib_api::getBip39Hints& request, P&&) {
|
||||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
|
|
|
@ -58,6 +58,14 @@ class TonlibClient : public td::actor::Actor {
|
|||
|
||||
~TonlibClient();
|
||||
|
||||
struct FullConfig {
|
||||
Config config;
|
||||
bool use_callbacks_for_network;
|
||||
LastBlockState last_state;
|
||||
std::string last_state_key;
|
||||
td::uint32 wallet_id;
|
||||
};
|
||||
|
||||
private:
|
||||
enum class State { Uninited, Running, Closed } state_ = State::Uninited;
|
||||
td::unique_ptr<TonlibCallback> callback_;
|
||||
|
@ -66,8 +74,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
Config config_;
|
||||
td::uint32 config_generation_{0};
|
||||
td::uint32 wallet_id_;
|
||||
std::string blockchain_name_;
|
||||
bool ignore_cache_{false};
|
||||
std::string last_state_key_;
|
||||
bool use_callbacks_for_network_{false};
|
||||
|
||||
// KeyStorage
|
||||
|
@ -89,7 +96,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
|
||||
ExtClientRef get_client_ref();
|
||||
void init_ext_client();
|
||||
void init_last_block(td::optional<Config> o_master_config);
|
||||
void init_last_block(LastBlockState state);
|
||||
void init_last_config();
|
||||
|
||||
bool is_closing_{false};
|
||||
|
@ -128,7 +135,6 @@ class TonlibClient : public td::actor::Actor {
|
|||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::packAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::unpackAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::options_validateConfig& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::getBip39Hints& request);
|
||||
|
||||
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::setLogStream& request);
|
||||
|
@ -161,8 +167,6 @@ class TonlibClient : public td::actor::Actor {
|
|||
template <class P>
|
||||
td::Status do_request(const tonlib_api::unpackAccountAddress& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::options_validateConfig& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(tonlib_api::getBip39Hints& request, P&&);
|
||||
|
||||
template <class P>
|
||||
|
@ -197,18 +201,14 @@ class TonlibClient : public td::actor::Actor {
|
|||
}
|
||||
}
|
||||
|
||||
struct FullConfig {
|
||||
Config config;
|
||||
td::optional<Config> o_master_config;
|
||||
bool use_callbacks_for_network;
|
||||
bool ignore_cache;
|
||||
td::uint32 wallet_id;
|
||||
};
|
||||
static td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
|
||||
td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
|
||||
void set_config(FullConfig config);
|
||||
td::Status do_request(const tonlib_api::init& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(const tonlib_api::init& request, td::Promise<object_ptr<tonlib_api::options_info>>&& promise);
|
||||
td::Status do_request(const tonlib_api::close& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(tonlib_api::options_setConfig& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(tonlib_api::options_validateConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::options_configInfo>>&& promise);
|
||||
td::Status do_request(tonlib_api::options_setConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::options_configInfo>>&& promise);
|
||||
|
||||
td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(const tonlib_api::raw_createAndSendMessage& request,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "td/utils/OptionsParser.h"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/utils/Parser.h"
|
||||
#include "td/utils/port/signals.h"
|
||||
#include "td/utils/port/path.h"
|
||||
|
@ -177,10 +178,6 @@ class TonlibCli : public td::actor::Actor {
|
|||
? make_object<tonlib_api::config>(options_.config, options_.name,
|
||||
options_.use_callbacks_for_network, options_.ignore_cache)
|
||||
: nullptr;
|
||||
auto config2 = !options_.config.empty()
|
||||
? make_object<tonlib_api::config>(options_.config, options_.name,
|
||||
options_.use_callbacks_for_network, options_.ignore_cache)
|
||||
: nullptr;
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
|
||||
if (options_.in_memory) {
|
||||
|
@ -188,18 +185,13 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else {
|
||||
ks_type = make_object<tonlib_api::keyStoreTypeDirectory>(options_.key_dir);
|
||||
}
|
||||
auto obj =
|
||||
tonlib::TonlibClient::static_request(make_object<tonlib_api::options_validateConfig>(std::move(config2)));
|
||||
if (obj->get_id() != tonlib_api::error::ID) {
|
||||
auto info = ton::move_tl_object_as<tonlib_api::options_configInfo>(obj);
|
||||
wallet_id_ = static_cast<td::uint32>(info->default_wallet_id_);
|
||||
} else {
|
||||
LOG(ERROR) << "Invalid config";
|
||||
}
|
||||
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(std::move(config), std::move(ks_type))),
|
||||
[](auto r_ok) {
|
||||
[&](auto r_ok) {
|
||||
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
|
||||
td::TerminalIO::out() << "Tonlib is inited\n";
|
||||
if (r_ok.is_ok()) {
|
||||
wallet_id_ = static_cast<td::uint32>(r_ok.ok()->config_info_->default_wallet_id_);
|
||||
td::TerminalIO::out() << "Tonlib is inited\n";
|
||||
}
|
||||
});
|
||||
if (options_.one_shot) {
|
||||
td::actor::send_closure(actor_id(this), &TonlibCli::parse_line, td::BufferSlice(options_.cmd));
|
||||
|
@ -482,6 +474,73 @@ class TonlibCli : public td::actor::Actor {
|
|||
tonlib_api::make_object<tonlib_api::tvm_numberDecimal>(dec_string(num)));
|
||||
}
|
||||
|
||||
td::Result<std::vector<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>>> parse_stack(td::ConstParser& parser,
|
||||
td::Slice end_token) {
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>> stack;
|
||||
while (true) {
|
||||
auto word = parser.read_word();
|
||||
LOG(ERROR) << word << " vs " << end_token;
|
||||
if (word == end_token) {
|
||||
break;
|
||||
}
|
||||
if (word == "[") {
|
||||
TRY_RESULT(elements, parse_stack(parser, "]"));
|
||||
stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryTuple>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_tuple>(std::move(elements))));
|
||||
} else if (word == "(") {
|
||||
TRY_RESULT(elements, parse_stack(parser, ")"));
|
||||
stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryList>(
|
||||
tonlib_api::make_object<tonlib_api::tvm_list>(std::move(elements))));
|
||||
} else {
|
||||
TRY_RESULT(stack_entry, parse_stack_entry(word));
|
||||
stack.push_back(std::move(stack_entry));
|
||||
}
|
||||
}
|
||||
return std::move(stack);
|
||||
}
|
||||
|
||||
static void store_entry(td::StringBuilder& sb, tonlib_api::tvm_StackEntry& entry) {
|
||||
downcast_call(entry, td::overloaded(
|
||||
[&](tonlib_api::tvm_stackEntryCell& cell) {
|
||||
auto r_cell = vm::std_boc_deserialize(cell.cell_->bytes_);
|
||||
if (r_cell.is_error()) {
|
||||
sb << "<INVALID_CELL>";
|
||||
}
|
||||
auto cs = vm::load_cell_slice(r_cell.move_as_ok());
|
||||
std::stringstream ss;
|
||||
cs.print_rec(ss);
|
||||
sb << ss.str();
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntrySlice& cell) {
|
||||
auto r_cell = vm::std_boc_deserialize(cell.slice_->bytes_);
|
||||
if (r_cell.is_error()) {
|
||||
sb << "<INVALID_CELL>";
|
||||
}
|
||||
auto cs = vm::load_cell_slice(r_cell.move_as_ok());
|
||||
std::stringstream ss;
|
||||
cs.print_rec(ss);
|
||||
sb << ss.str();
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryNumber& cell) { sb << cell.number_->number_; },
|
||||
[&](tonlib_api::tvm_stackEntryTuple& cell) {
|
||||
sb << "(";
|
||||
for (auto& element : cell.tuple_->elements_) {
|
||||
sb << " ";
|
||||
store_entry(sb, *element);
|
||||
}
|
||||
sb << " )";
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryList& cell) {
|
||||
sb << "[";
|
||||
for (auto& element : cell.list_->elements_) {
|
||||
sb << " ";
|
||||
store_entry(sb, *element);
|
||||
}
|
||||
sb << " ]";
|
||||
},
|
||||
[&](tonlib_api::tvm_stackEntryUnsupported& cell) { sb << "<UNSUPPORTED>"; }));
|
||||
}
|
||||
|
||||
void run_method(td::ConstParser& parser, td::Promise<td::Unit> promise) {
|
||||
TRY_RESULT_PROMISE(promise, addr, to_account_address(parser.read_word(), false));
|
||||
|
||||
|
@ -492,15 +551,15 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else {
|
||||
method = tonlib_api::make_object<tonlib_api::smc_methodIdName>(method_str.str());
|
||||
}
|
||||
std::vector<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>> stack;
|
||||
while (true) {
|
||||
auto word = parser.read_word();
|
||||
if (word.empty()) {
|
||||
break;
|
||||
}
|
||||
TRY_RESULT_PROMISE(promise, stack_entry, parse_stack_entry(word));
|
||||
stack.push_back(std::move(stack_entry));
|
||||
TRY_RESULT_PROMISE(promise, stack, parse_stack(parser, ""));
|
||||
td::StringBuilder sb;
|
||||
for (auto& entry : stack) {
|
||||
store_entry(sb, *entry);
|
||||
sb << "\n";
|
||||
}
|
||||
|
||||
td::TerminalIO::out() << "Run " << to_string(method) << "With stack:\n" << sb.as_cslice();
|
||||
|
||||
auto to_run =
|
||||
tonlib_api::make_object<tonlib_api::smc_runGetMethod>(0 /*fixme*/, std::move(method), std::move(stack));
|
||||
|
||||
|
@ -513,9 +572,16 @@ class TonlibCli : public td::actor::Actor {
|
|||
to_run->id_ = info->id_;
|
||||
send_query(std::move(to_run), promise.send_closure(actor_id(this), &TonlibCli::run_method_3));
|
||||
}
|
||||
|
||||
void run_method_3(tonlib_api::object_ptr<tonlib_api::smc_runResult> info, td::Promise<td::Unit> promise) {
|
||||
td::TerminalIO::out() << "Got smc result " << to_string(info);
|
||||
td::StringBuilder sb;
|
||||
for (auto& entry : info->stack_) {
|
||||
store_entry(sb, *entry);
|
||||
sb << "\n";
|
||||
}
|
||||
|
||||
td::TerminalIO::out() << "Got smc result. exit code: " << info->exit_code_ << ", gas_used: " << info->gas_used_
|
||||
<< "\n"
|
||||
<< sb.as_cslice();
|
||||
promise.set_value({});
|
||||
}
|
||||
|
||||
|
@ -972,7 +1038,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
|
||||
void import_key(std::vector<td::SecureString> words, td::Slice password) {
|
||||
using tonlib_api::make_object;
|
||||
send_query(make_object<tonlib_api::importKey>(td::SecureString(password), td::SecureString(),
|
||||
send_query(make_object<tonlib_api::importKey>(td::SecureString(password), td::SecureString(" test mnemonic"),
|
||||
make_object<tonlib_api::exportedKey>(std::move(words))),
|
||||
[this, password = td::SecureString(password)](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
|
@ -1147,7 +1213,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
return;
|
||||
}
|
||||
td::TerminalIO::out() << to_string(r_res.ok());
|
||||
self->on_ok();
|
||||
//self->on_ok();
|
||||
});
|
||||
|
||||
self->send_query(make_object<tonlib_api::query_send>(r_res.ok()->id_), [self](auto r_res) {
|
||||
|
@ -1160,7 +1226,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
self->on_ok();
|
||||
});
|
||||
|
||||
self->on_ok();
|
||||
//self->on_ok();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue