1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00
new database
fift/func bugfixes
This commit is contained in:
ton 2019-11-15 18:02:37 +04:00
parent 950e292264
commit e30d98eb30
110 changed files with 6102 additions and 2075 deletions

View file

@ -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();
}

View file

@ -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.

View file

@ -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();

View file

@ -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,

View file

@ -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();
});
}