From 2ea17ec03b8b116e24c800b3389e34b5ae2e21f9 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Wed, 11 Jan 2023 19:14:03 +0300 Subject: [PATCH] Use partial liteservers in tonlib and lite-client --- lite-client/lite-client.cpp | 757 ++++++++++-------- lite-client/lite-client.h | 9 +- tl/generate/scheme/ton_api.tlo | Bin 83196 -> 87748 bytes tl/generate/scheme/tonlib_api.tlo | Bin 31016 -> 31084 bytes tonlib/CMakeLists.txt | 4 +- tonlib/tonlib/Config.cpp | 41 +- tonlib/tonlib/Config.h | 4 +- tonlib/tonlib/ExtClient.cpp | 6 +- tonlib/tonlib/ExtClient.h | 1 - tonlib/tonlib/ExtClientLazy.cpp | 174 ++-- .../{ExtClientRaw.h => ExtClientLazy.h} | 14 +- tonlib/tonlib/ExtClientMulti.cpp | 169 ---- tonlib/tonlib/ExtClientMulti.h | 61 -- tonlib/tonlib/ExtClientOutbound.cpp | 10 +- tonlib/tonlib/ExtClientOutbound.h | 1 + tonlib/tonlib/TonlibClient.cpp | 581 +++++++------- tonlib/tonlib/tonlib-cli.cpp | 33 +- 17 files changed, 891 insertions(+), 974 deletions(-) rename tonlib/tonlib/{ExtClientRaw.h => ExtClientLazy.h} (72%) delete mode 100644 tonlib/tonlib/ExtClientMulti.cpp delete mode 100644 tonlib/tonlib/ExtClientMulti.h diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp index feedbe40..c6988ef3 100644 --- a/lite-client/lite-client.cpp +++ b/lite-client/lite-client.cpp @@ -29,22 +29,16 @@ #include "lite-client-common.h" -#include "adnl/adnl-ext-client.h" #include "tl-utils/lite-utils.hpp" #include "auto/tl/ton_api_json.h" #include "auto/tl/lite_api.hpp" #include "td/utils/OptionParser.h" #include "td/utils/Time.h" #include "td/utils/filesystem.h" -#include "td/utils/format.h" #include "td/utils/Random.h" #include "td/utils/crypto.h" -#include "td/utils/overloaded.h" #include "td/utils/port/signals.h" -#include "td/utils/port/stacktrace.h" -#include "td/utils/port/StdStreams.h" #include "td/utils/port/FileFd.h" -#include "terminal/terminal.h" #include "ton/lite-tl.hpp" #include "block/block-db.h" #include "block/block.h" @@ -58,18 +52,14 @@ #include "vm/vm.h" #include "vm/cp0.h" #include "vm/memo.h" -#include "ton/ton-shard.h" -#include "openssl/rand.hpp" #include "crypto/vm/utils.h" #include "crypto/common/util.h" #include "common/checksum.h" #if TD_DARWIN || TD_LINUX #include -#include #endif #include -#include #include "git.h" using namespace std::literals::string_literals; @@ -77,22 +67,10 @@ using td::Ref; int verbosity; -std::unique_ptr TestNode::make_callback() { - class Callback : public ton::adnl::AdnlExtClient::Callback { - public: - void on_ready() override { - td::actor::send_closure(id_, &TestNode::conn_ready); - } - void on_stop_ready() override { - td::actor::send_closure(id_, &TestNode::conn_closed); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - return std::make_unique(actor_id(this)); +bool TestNode::LiteServer::supports(ton::ShardIdFull shard) const { + return is_full || shard.is_masterchain() || + std::any_of(shards.begin(), shards.end(), + [&](const ton::ShardIdFull& our_shard) { return ton::shard_intersects(shard, our_shard); }); } void TestNode::run() { @@ -110,31 +88,57 @@ void TestNode::run() { io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique(actor_id(this))); td::actor::send_closure(io_, &td::TerminalIO::set_log_interface); - if (remote_public_key_.empty()) { - auto G = td::read_file(global_config_).move_as_ok(); - auto gc_j = td::json_decode(G.as_slice()).move_as_ok(); - ton::ton_api::liteclient_config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - CHECK(gc.liteservers_.size() > 0); - auto idx = liteserver_idx_ >= 0 ? liteserver_idx_ - : td::Random::fast(0, static_cast(gc.liteservers_.size() - 1)); - CHECK(idx >= 0 && static_cast(idx) <= gc.liteservers_.size()); - auto& cli = gc.liteservers_[idx]; - remote_addr_.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure(); - remote_public_key_ = ton::PublicKey{cli->id_}; - td::TerminalIO::out() << "using liteserver " << idx << " with addr " << remote_addr_ << "\n"; - if (gc.validator_ && gc.validator_->zero_state_) { - zstate_id_.workchain = gc.validator_->zero_state_->workchain_; - if (zstate_id_.workchain != ton::workchainInvalid) { - zstate_id_.root_hash = gc.validator_->zero_state_->root_hash_; - zstate_id_.file_hash = gc.validator_->zero_state_->file_hash_; - td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n"; - } + if (!single_remote_public_key_.empty()) { // Use single provided liteserver + LiteServer s; + s.addr = single_remote_addr_; + s.public_key = single_remote_public_key_; + single_liteserver_idx_ = 0; + td::TerminalIO::out() << "using liteserver " << s.addr << "\n"; + servers_.push_back(std::move(s)); + run_init_queries(); + return; + } + + auto G = td::read_file(global_config_).move_as_ok(); + auto gc_j = td::json_decode(G.as_slice()).move_as_ok(); + ton::ton_api::liteclient_config_global gc; + ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); + CHECK(gc.liteservers_.size() + gc.liteservers_v2_.size() > 0); + + if (gc.validator_ && gc.validator_->zero_state_) { + zstate_id_.workchain = gc.validator_->zero_state_->workchain_; + if (zstate_id_.workchain != ton::workchainInvalid) { + zstate_id_.root_hash = gc.validator_->zero_state_->root_hash_; + zstate_id_.file_hash = gc.validator_->zero_state_->file_hash_; + td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n"; } } - client_ = - ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_, make_callback()); + for (auto& server : gc.liteservers_) { + LiteServer s; + s.addr.init_host_port(td::IPAddress::ipv4_to_str(server->ip_), server->port_).ensure(); + s.public_key = ton::PublicKey{server->id_}; + servers_.push_back(std::move(s)); + } + for (auto& server : gc.liteservers_v2_) { + LiteServer s; + s.addr.init_host_port(td::IPAddress::ipv4_to_str(server->ip_), server->port_).ensure(); + s.public_key = ton::PublicKey{server->id_}; + s.is_full = false; + for (const auto& shard : server->shards_) { + s.shards.emplace_back(shard->workchain_, shard->shard_); + CHECK(s.shards.back().is_valid_ext()); + } + servers_.push_back(std::move(s)); + } + + if (single_liteserver_idx_ != -1) { // Use single liteserver from config + CHECK(single_liteserver_idx_ >= 0 && (size_t)single_liteserver_idx_ < gc.liteservers_.size()); + td::TerminalIO::out() << "using liteserver " << single_liteserver_idx_ << " with addr " + << servers_[single_liteserver_idx_].addr << "\n"; + } + + run_init_queries(); } void TestNode::got_result(td::Result R, td::Promise promise) { @@ -179,23 +183,142 @@ void TestNode::after_got_result(bool ok) { } } -bool TestNode::envelope_send_query(td::BufferSlice query, td::Promise promise) { - running_queries_++; - if (!ready_ || client_.empty()) { - got_result(td::Status::Error("failed to send query to server: not ready"), std::move(promise)); +bool TestNode::envelope_send_query_to_any(td::BufferSlice query, td::Promise promise) { + return envelope_send_query_to_shard(ton::ShardIdFull(ton::masterchainId), std::move(query), std::move(promise)); +} + +bool TestNode::envelope_send_query_to_account(ton::AccountIdPrefixFull prefix, td::BufferSlice query, + td::Promise promise) { + return envelope_send_query_to_shard(prefix.as_leaf_shard(), std::move(query), std::move(promise)); +} + +bool TestNode::envelope_send_query_to_shard(ton::ShardIdFull shard, td::BufferSlice query, + td::Promise promise) { + if (single_liteserver_idx_ >= 0) { + return envelope_send_query_to_server(single_liteserver_idx_, std::move(query), std::move(promise)); + } + if (shard.is_masterchain() && mc_server_idx_ != -1) { + return envelope_send_query_to_server(mc_server_idx_, std::move(query), std::move(promise)); + } + auto it = shard_server_idx_cached_.find(shard); + if (it != shard_server_idx_cached_.end()) { + return envelope_send_query_to_server(it->second, std::move(query), std::move(promise)); + } + int server_idx = -1; + int random_idx = -1; + int cnt = 0; + bool selected_full = false; + for (int i = 0; i < (int)servers_.size(); ++i) { + const LiteServer& server = servers_[i]; + if (!server.supports(shard)) { + continue; + } + if (server.is_full && !selected_full) { + selected_full = true; + server_idx = -1; + cnt = 0; + } + if (!server.is_full && selected_full) { + continue; + } + if (!server.client.empty()) { + server_idx = i; + } + if (td::Random::fast(0, cnt) == 0) { + random_idx = i; + } + ++cnt; + } + if (server_idx == -1) { + server_idx = random_idx; + } + if (server_idx == -1) { + running_queries_++; + got_result(td::Status::Error(PSTRING() << "failed to select a suitable server for " << shard.to_str()), + std::move(promise)); return false; } + shard_server_idx_cached_[shard] = server_idx; + if (shard.is_masterchain()) { + mc_server_idx_ = server_idx; + } + return envelope_send_query_to_server(server_idx, std::move(query), std::move(promise)); +} + +bool TestNode::envelope_send_query_to_server(td::int32 server_idx, td::BufferSlice query, + td::Promise promise) { + running_queries_++; + LiteServer& server = servers_.at(server_idx); + if (server.client.empty()) { + start_client(server_idx); + } + CHECK(!server.client.empty()); + auto P = td::PromiseCreator::lambda( [SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { td::actor::send_closure(SelfId, &TestNode::got_result, std::move(R), std::move(promise)); }); td::BufferSlice b = ton::serialize_tl_object(ton::create_tl_object(std::move(query)), true); - td::actor::send_closure(client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), - td::Timestamp::in(10.0), std::move(P)); + if (server.client_ready) { + td::actor::send_closure(server.client, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), + td::Timestamp::in(10.0), std::move(P)); + } else { + server.wait_client_ready.push_back( + [client = server.client.get(), b = std::move(b), P = std::move(P)](td::Result R) mutable { + if (R.is_ok()) { + td::actor::send_closure(client, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), + td::Timestamp::in(10.0), std::move(P)); + } else { + P.set_error(R.move_as_error_prefix("failed to connect: ")); + } + }); + } return true; } +void TestNode::start_client(int server_idx) { + LiteServer& server = servers_[server_idx]; + CHECK(server.client.empty()); + class Callback : public ton::adnl::AdnlExtClient::Callback { + public: + void on_ready() override { + td::actor::send_closure(id_, &TestNode::conn_ready, server_idx_); + } + void on_stop_ready() override { + td::actor::send_closure(id_, &TestNode::conn_closed, server_idx_); + } + Callback(td::actor::ActorId id, int server_idx) : id_(std::move(id)), server_idx_(server_idx) { + } + + private: + td::actor::ActorId id_; + int server_idx_; + }; + server.client_ready = false; + server.wait_client_ready.clear(); + LOG(INFO) << "Connecting to " << server.addr << " (liteserver #" << server_idx << ")"; + server.client = ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{server.public_key}, server.addr, + std::make_unique(actor_id(this), server_idx)); +} + +void TestNode::conn_ready(int server_idx) { + LiteServer& server = servers_[server_idx]; + LOG(INFO) << "Connection to " << server.addr << " (liteserver #" << server_idx << ") is ready"; + server.client_ready = true; + for (auto& p : server.wait_client_ready) { + p.set_result(td::Unit()); + } + server.wait_client_ready.clear(); +} + +void TestNode::conn_closed(int server_idx) { + LiteServer& server = servers_[server_idx]; + LOG(INFO) << "Connection to " << server.addr << " (liteserver #" << server_idx << ") closed"; + server.client_ready = false; + server.wait_client_ready.clear(); +} + td::Promise TestNode::trivial_promise() { return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result res) { if (res.is_error()) { @@ -310,7 +433,7 @@ bool TestNode::dump_cached_cell(td::Slice hash_pfx, td::Slice type_name) { bool TestNode::get_server_time() { auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [&, Self = actor_id(this)](td::Result res) -> void { + return envelope_send_query_to_any(std::move(b), [&, Self = actor_id(this)](td::Result res) -> void { if (res.is_error()) { LOG(ERROR) << "cannot get server time"; return; @@ -319,9 +442,10 @@ bool TestNode::get_server_time() { if (F.is_error()) { LOG(ERROR) << "cannot parse answer to liteServer.getTime"; } else { - server_time_ = F.move_as_ok()->now_; - server_time_got_at_ = now(); - LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; + mc_server_time_ = F.move_as_ok()->now_; + mc_server_time_got_at_ = now(); + LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_ + << ")"; } } }); @@ -329,13 +453,13 @@ bool TestNode::get_server_time() { bool TestNode::get_server_version(int mode) { auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result res) { + return envelope_send_query_to_any(std::move(b), [Self = actor_id(this), mode](td::Result res) { td::actor::send_closure_later(Self, &TestNode::got_server_version, std::move(res), mode); }); }; void TestNode::got_server_version(td::Result res, int mode) { - server_ok_ = false; + mc_server_ok_ = false; if (res.is_error()) { LOG(ERROR) << "cannot get server version and time (server too old?)"; } else { @@ -344,11 +468,11 @@ void TestNode::got_server_version(td::Result res, int mode) { LOG(ERROR) << "cannot parse answer to liteServer.getVersion"; } else { auto a = F.move_as_ok(); - set_server_version(a->version_, a->capabilities_); - set_server_time(a->now_); + set_mc_server_version(a->version_, a->capabilities_); + set_mc_server_time(a->now_); } } - if (!server_ok_) { + if (!mc_server_ok_) { LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff) << " with capabilities " << min_ls_capabilities << " required), some queries are unavailable"; } @@ -357,27 +481,27 @@ void TestNode::got_server_version(td::Result res, int mode) { } } -void TestNode::set_server_version(td::int32 version, td::int64 capabilities) { - if (server_version_ != version || server_capabilities_ != capabilities) { - server_version_ = version; - server_capabilities_ = capabilities; - LOG(WARNING) << "server version is " << (server_version_ >> 8) << "." << (server_version_ & 0xff) - << ", capabilities " << server_capabilities_; +void TestNode::set_mc_server_version(td::int32 version, td::int64 capabilities) { + if (mc_server_version_ != version || mc_server_capabilities_ != capabilities) { + mc_server_version_ = version; + mc_server_capabilities_ = capabilities; + LOG(WARNING) << "server version is " << (mc_server_version_ >> 8) << "." << (mc_server_version_ & 0xff) + << ", capabilities " << mc_server_capabilities_; } - server_ok_ = (server_version_ >= min_ls_version) && !(~server_capabilities_ & min_ls_capabilities); + mc_server_ok_ = (mc_server_version_ >= min_ls_version) && !(~mc_server_capabilities_ & min_ls_capabilities); } -void TestNode::set_server_time(int server_utime) { - server_time_ = server_utime; - server_time_got_at_ = now(); - LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; +void TestNode::set_mc_server_time(int server_utime) { + mc_server_time_ = server_utime; + mc_server_time_got_at_ = now(); + LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_ << ")"; } bool TestNode::get_server_mc_block_id() { - int mode = (server_capabilities_ & 2) ? 0 : -1; + int mode = (mc_server_capabilities_ & 2) ? 0 : -1; if (mode < 0) { auto b = ton::serialize_tl_object(ton::create_tl_object(), true); - return envelope_send_query(std::move(b), [Self = actor_id(this)](td::Result res) -> void { + return envelope_send_query_to_any(std::move(b), [Self = actor_id(this)](td::Result res) -> void { if (res.is_error()) { LOG(ERROR) << "cannot get masterchain info from server"; return; @@ -397,24 +521,25 @@ bool TestNode::get_server_mc_block_id() { } else { auto b = ton::serialize_tl_object(ton::create_tl_object(mode), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot get extended masterchain info from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getMasterchainInfoExt"; - } else { - auto f = F.move_as_ok(); - auto blk_id = create_block_id(f->last_); - auto zstate_id = create_zero_state_id(f->init_); - LOG(INFO) << "last masterchain block is " << blk_id.to_str(); - td::actor::send_closure_later(Self, &TestNode::got_server_mc_block_id_ext, blk_id, zstate_id, mode, - f->version_, f->capabilities_, f->last_utime_, f->now_); - } - } - }); + return envelope_send_query_to_any( + std::move(b), [Self = actor_id(this), mode](td::Result res) -> void { + if (res.is_error()) { + LOG(ERROR) << "cannot get extended masterchain info from server"; + return; + } else { + auto F = ton::fetch_tl_object(res.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getMasterchainInfoExt"; + } else { + auto f = F.move_as_ok(); + auto blk_id = create_block_id(f->last_); + auto zstate_id = create_zero_state_id(f->init_); + LOG(INFO) << "last masterchain block is " << blk_id.to_str(); + td::actor::send_closure_later(Self, &TestNode::got_server_mc_block_id_ext, blk_id, zstate_id, mode, + f->version_, f->capabilities_, f->last_utime_, f->now_); + } + } + }); } } @@ -448,8 +573,8 @@ void TestNode::got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version, long long capabilities, int last_utime, int server_now) { - set_server_version(version, capabilities); - set_server_time(server_now); + set_mc_server_version(version, capabilities); + set_mc_server_time(server_now); if (last_utime > server_now) { LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime << " (" << last_utime - server_now << " seconds in the future)"; @@ -457,10 +582,10 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI LOG(WARNING) << "server appears to be out of sync: its newest masterchain block is " << blkid.to_str() << " created at " << last_utime << " (" << server_now - last_utime << " seconds ago according to the server's clock)"; - } else if (last_utime < server_time_got_at_ - 60) { + } else if (last_utime < mc_server_time_got_at_ - 60) { LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain " "block known to server is " - << blkid.to_str() << " created at " << last_utime << " (" << server_now - server_time_got_at_ + << blkid.to_str() << " created at " << last_utime << " (" << server_now - mc_server_time_got_at_ << " seconds ago according to the local clock)"; } got_server_mc_block_id(blkid, zstateid, last_utime); @@ -469,52 +594,54 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI bool TestNode::request_block(ton::BlockIdExt blkid) { auto b = ton::serialize_tl_object( ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getBlock"; - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained block " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected data for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { + if (res.is_error()) { + LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server"; + return; + } else { + auto F = ton::fetch_tl_object(res.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getBlock"; + } else { + auto f = F.move_as_ok(); + auto blk_id = ton::create_block_id(f->id_); + LOG(INFO) << "obtained block " << blk_id.to_str() << " from server"; + if (blk_id != blkid) { + LOG(ERROR) << "block id mismatch: expected data for block " << blkid.to_str() << ", obtained for " + << blk_id.to_str(); + } + td::actor::send_closure_later(Self, &TestNode::got_mc_block, blk_id, std::move(f->data_)); + } } - td::actor::send_closure_later(Self, &TestNode::got_mc_block, blk_id, std::move(f->data_)); - } - } - }); + }); } bool TestNode::request_state(ton::BlockIdExt blkid) { auto b = ton::serialize_tl_object( ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server"; - return; - } else { - auto F = ton::fetch_tl_object(res.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getState"; - } else { - auto f = F.move_as_ok(); - auto blk_id = ton::create_block_id(f->id_); - LOG(INFO) << "obtained state " << blk_id.to_str() << " from server"; - if (blk_id != blkid) { - LOG(ERROR) << "block id mismatch: expected state for block " << blkid.to_str() << ", obtained for " - << blk_id.to_str(); + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid](td::Result res) -> void { + if (res.is_error()) { + LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server"; + return; + } else { + auto F = ton::fetch_tl_object(res.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getState"; + } else { + auto f = F.move_as_ok(); + auto blk_id = ton::create_block_id(f->id_); + LOG(INFO) << "obtained state " << blk_id.to_str() << " from server"; + if (blk_id != blkid) { + LOG(ERROR) << "block id mismatch: expected state for block " << blkid.to_str() << ", obtained for " + << blk_id.to_str(); + } + td::actor::send_closure_later(Self, &TestNode::got_mc_state, blk_id, f->root_hash_, f->file_hash_, + std::move(f->data_)); + } } - td::actor::send_closure_later(Self, &TestNode::got_mc_state, blk_id, f->root_hash_, f->file_hash_, - std::move(f->data_)); - } - } - }); + }); } void TestNode::got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data) { @@ -1150,27 +1277,34 @@ td::Status TestNode::send_ext_msg_from_filename(std::string filename) { LOG(ERROR) << "failed to read file `" << filename << "`: " << err.to_string(); return err; } - if (ready_ && !client_.empty()) { - LOG(ERROR) << "sending query from file " << filename; - auto P = td::PromiseCreator::lambda([](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.sendMessage"; - } else { - int status = F.move_as_ok()->status_; - LOG(INFO) << "external message status is " << status; - } - }); - auto b = - ton::serialize_tl_object(ton::create_tl_object(F.move_as_ok()), true); - return envelope_send_query(std::move(b), std::move(P)) ? td::Status::OK() - : td::Status::Error("cannot send query to server"); - } else { - return td::Status::Error("server connection not ready"); + LOG(ERROR) << "sending query from file " << filename; + + TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(F.ok().as_slice()), "invalid boc: "); + block::gen::CommonMsgInfo::Record_ext_in_msg_info info; + if (!tlb::unpack_cell_inexact(root, info)) { + return td::Status::Error("failed to unpack external message header"); } + auto dest_prefix = block::tlb::MsgAddressInt::get_prefix(info.dest); + if (!dest_prefix.is_valid()) { + return td::Status::Error("destination of the message is invalid"); + } + + auto P = td::PromiseCreator::lambda([](td::Result R) { + if (R.is_error()) { + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.sendMessage"; + } else { + int status = F.move_as_ok()->status_; + LOG(INFO) << "external message status is " << status; + } + }); + auto b = ton::serialize_tl_object(ton::create_tl_object(F.move_as_ok()), true); + return envelope_send_query_to_account(dest_prefix, std::move(b), std::move(P)) + ? td::Status::OK() + : td::Status::Error("cannot send query to server"); } bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, @@ -1178,9 +1312,6 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress if (!ref_blkid.is_valid()) { return set_error("must obtain last block information before making other queries"); } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } if (addr_ext) { return get_special_smc_addr( addr_ext, [this, ref_blkid, filename, mode, prunned](td::Result res) { @@ -1202,24 +1333,26 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress ton::create_tl_lite_block_id(ref_blkid), std::move(a)), true); } + ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64)); LOG(INFO) << "requesting " << (prunned ? "prunned " : "") << "account state for " << workchain << ":" << addr.to_hex() << " with respect to " << ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode; - return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode, - prunned](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_account_state, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_), workchain, addr, filename, mode, - prunned); - } - }); + return envelope_send_query_to_account( + account_prefix, std::move(b), + [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode, prunned](td::Result R) { + if (R.is_error()) { + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; + } else { + auto f = F.move_as_ok(); + td::actor::send_closure_later(Self, &TestNode::got_account_state, ref_blkid, ton::create_block_id(f->id_), + ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), + std::move(f->proof_), std::move(f->state_), workchain, addr, filename, mode, + prunned); + } + }); } td::int64 TestNode::compute_method_id(std::string method) { @@ -1285,19 +1418,18 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a if (!ref_blkid.is_valid()) { return set_error("must obtain last block information before making other queries"); } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } auto a = ton::create_tl_object(workchain, addr); + ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64)); if (!mode) { auto b = ton::serialize_tl_object(ton::create_tl_object( ton::create_tl_lite_block_id(ref_blkid), std::move(a)), true); LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters"; - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params), - promise = std::move(promise)](td::Result R) mutable { + return envelope_send_query_to_account( + account_prefix, std::move(b), + [Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params), + promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { promise.set_error(R.move_as_error()); return; @@ -1337,26 +1469,27 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a LOG(INFO) << "requesting remote get-method execution for " << workchain << ":" << addr.to_hex() << " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters"; - return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, - params = std::move(params), - promise = std::move(promise)](td::Result R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.runSmcMethod"; - promise.set_error(td::Status::Error("cannot parse answer to liteServer.runSmcMethod")); - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_proof_), workchain, addr, method_name, - std::move(params), std::move(f->init_c7_), std::move(f->lib_extras_), - std::move(f->result_), f->exit_code_, std::move(promise)); - } - }); + return envelope_send_query_to_account( + account_prefix, std::move(b), + [Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, params = std::move(params), + promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(R.move_as_error()); + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.runSmcMethod"; + promise.set_error(td::Status::Error("cannot parse answer to liteServer.runSmcMethod")); + } else { + auto f = F.move_as_ok(); + td::actor::send_closure_later( + Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_), + ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), std::move(f->proof_), + std::move(f->state_proof_), workchain, addr, method_name, std::move(params), std::move(f->init_c7_), + std::move(f->lib_extras_), std::move(f->result_), f->exit_code_, std::move(promise)); + } + }); } } @@ -1586,8 +1719,8 @@ void TestNode::send_compute_complaint_price_query(ton::StdSmcAddress elector_add params.emplace_back(td::make_refint(bits)); params.emplace_back(td::make_refint(refs)); params.emplace_back(td::make_refint(expires_in)); - auto P = td::PromiseCreator::lambda( - [this, expires_in, bits, refs, chash, filename](td::Result> R) { + auto P = + td::PromiseCreator::lambda([expires_in, bits, refs, chash, filename](td::Result> R) { if (R.is_error()) { LOG(ERROR) << R.move_as_error(); return; @@ -1649,10 +1782,6 @@ bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress return set_error("domain name too long"); } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } - if (workchain == ton::workchainInvalid) { if (dns_root_queried_) { workchain = ton::masterchainId; @@ -1861,17 +1990,16 @@ bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workc if (!ton::shard_contains(blkid.shard_full(), ton::extract_addr_prefix(workchain, addr))) { return set_error("the shard of this block cannot contain this account"); } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } auto a = ton::create_tl_object(workchain, addr); auto b = ton::serialize_tl_object(ton::create_tl_object( ton::create_tl_lite_block_id(blkid), std::move(a), lt), true); + ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64)); LOG(INFO) << "requesting transaction " << lt << " of " << workchain << ":" << addr.to_hex() << " from block " << blkid.to_str(); - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result R) -> void { + return envelope_send_query_to_account( + account_prefix, std::move(b), + [Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result R) -> void { if (R.is_error()) { return; } @@ -1888,16 +2016,15 @@ bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workc bool TestNode::get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, ton::Bits256 hash, unsigned count, bool dump) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } auto a = ton::create_tl_object(workchain, addr); auto b = ton::serialize_tl_object( ton::create_tl_object(count, std::move(a), lt, hash), true); + ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64)); LOG(INFO) << "requesting " << count << " last transactions from " << lt << ":" << hash.to_hex() << " of " << workchain << ":" << addr.to_hex(); - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result R) { + return envelope_send_query_to_account( + account_prefix, std::move(b), + [Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result R) { if (R.is_error()) { return; } @@ -2257,10 +2384,10 @@ void TestNode::got_one_transaction(ton::BlockIdExt req_blkid, ton::BlockIdExt bl << " but received data has " << root->get_hash().bits().to_hex(256); return; } - } catch (vm::VmError err) { + } catch (vm::VmError& err) { LOG(ERROR) << "error while traversing block transaction proof : " << err.get_msg(); return; - } catch (vm::VmVirtError err) { + } catch (vm::VmVirtError& err) { LOG(ERROR) << "virtualization error while traversing block transaction proof : " << err.get_msg(); return; } @@ -2439,32 +2566,30 @@ void TestNode::got_last_transactions(std::vector blkids, td::Bu bool TestNode::get_block_transactions(ton::BlockIdExt blkid, int mode, unsigned count, ton::Bits256 acc_addr, ton::LogicalTime lt) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } auto a = ton::create_tl_object(acc_addr, lt); auto b = ton::serialize_tl_object(ton::create_tl_object( ton::create_tl_lite_block_id(blkid), mode, count, std::move(a), false, false), true); LOG(INFO) << "requesting " << count << " transactions from block " << blkid.to_str() << " starting from account " << acc_addr.to_hex() << " lt " << lt; - return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.listBlockTransactions"; - } else { - auto f = F.move_as_ok(); - std::vector transactions; - for (auto& id : f->ids_) { - transactions.emplace_back(id->account_, id->lt_, id->hash_); - } - td::actor::send_closure_later(Self, &TestNode::got_block_transactions, ton::create_block_id(f->id_), mode, - f->req_count_, f->incomplete_, std::move(transactions), std::move(f->proof_)); - } - }); + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), [Self = actor_id(this), mode](td::Result R) { + if (R.is_error()) { + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.listBlockTransactions"; + } else { + auto f = F.move_as_ok(); + std::vector transactions; + for (auto& id : f->ids_) { + transactions.emplace_back(id->account_, id->lt_, id->hash_); + } + td::actor::send_closure_later(Self, &TestNode::got_block_transactions, ton::create_block_id(f->id_), mode, + f->req_count_, f->incomplete_, std::move(transactions), std::move(f->proof_)); + } + }); } void TestNode::got_block_transactions(ton::BlockIdExt blkid, int mode, unsigned req_count, bool incomplete, @@ -2490,25 +2615,23 @@ bool TestNode::get_all_shards(std::string filename, bool use_last, ton::BlockIdE if (!blkid.is_masterchain()) { return set_error("only masterchain blocks contain shard configuration"); } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } auto b = ton::serialize_tl_object( ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); LOG(INFO) << "requesting recent shard configuration"; - return envelope_send_query(std::move(b), [Self = actor_id(this), filename](td::Result R) -> void { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAllShardsInfo"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_), std::move(f->proof_), - std::move(f->data_), filename); - } - }); + return envelope_send_query_to_any( + std::move(b), [Self = actor_id(this), filename](td::Result R) -> void { + if (R.is_error()) { + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getAllShardsInfo"; + } else { + auto f = F.move_as_ok(); + td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_), + std::move(f->proof_), std::move(f->data_), filename); + } + }); } void TestNode::got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data, std::string filename) { @@ -2572,9 +2695,6 @@ bool TestNode::parse_get_config_params(ton::BlockIdExt blkid, int mode, std::str params.push_back(x); } } - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } if (!blkid.is_masterchain_ext()) { return set_error("only masterchain blocks contain configuration"); } @@ -2593,10 +2713,6 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, td::Promise promise, int mode, std::string filename, std::vector params) { - if (!(ready_ && !client_.empty())) { - promise.set_error(td::Status::Error("server connection not ready")); - return false; - } if (!blkid.is_masterchain_ext()) { promise.set_error(td::Status::Error("masterchain reference block expected")); return false; @@ -2614,11 +2730,12 @@ bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise R) mutable { - td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params), - std::move(R), std::move(promise)); - }); + return envelope_send_query_to_any( + std::move(b), [Self = actor_id(this), mode, filename, blkid, params = std::move(params), + promise = std::move(promise)](td::Result R) mutable { + td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params), + std::move(R), std::move(promise)); + }); } void TestNode::got_config_params(ton::BlockIdExt req_blkid, int mode, std::string filename, std::vector params, @@ -2806,8 +2923,8 @@ bool TestNode::get_block(ton::BlockIdExt blkid, bool dump) { LOG(INFO) << "got block download request for " << blkid.to_str(); auto b = ton::serialize_tl_object( ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query( - std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { if (res.is_error()) { LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server : " << res.move_as_error().to_string(); @@ -2835,8 +2952,8 @@ bool TestNode::get_state(ton::BlockIdExt blkid, bool dump) { LOG(INFO) << "got state download request for " << blkid.to_str(); auto b = ton::serialize_tl_object( ton::create_tl_object(ton::create_tl_lite_block_id(blkid)), true); - return envelope_send_query( - std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result res) -> void { if (res.is_error()) { LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server : " << res.move_as_error().to_string(); @@ -2973,7 +3090,7 @@ void TestNode::got_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::Fi } bool TestNode::get_show_block_header(ton::BlockIdExt blkid, int mode) { - return get_block_header(blkid, mode, [this, blkid](td::Result R) { + return get_block_header(blkid, mode, [this](td::Result R) { if (R.is_error()) { LOG(ERROR) << "unable to fetch block header: " << R.move_as_error(); } else { @@ -2988,8 +3105,9 @@ bool TestNode::get_block_header(ton::BlockIdExt blkid, int mode, td::Promise(ton::create_tl_lite_block_id(blkid), mode), true); - return envelope_send_query( - std::move(b), [this, blkid, promise = std::move(promise)](td::Result R) mutable -> void { + return envelope_send_query_to_shard( + blkid.shard_full(), std::move(b), + [this, blkid, promise = std::move(promise)](td::Result R) mutable -> void { TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), PSLICE() << "cannot obtain block header for " << blkid.to_str() << " from server :"); got_block_header_raw(std::move(res), std::move(promise), blkid); @@ -3015,8 +3133,9 @@ bool TestNode::lookup_block(ton::ShardIdFull shard, int mode, td::uint64 arg, auto b = ton::serialize_tl_object(ton::create_tl_object( mode, ton::create_tl_lite_block_id_simple(id), arg, (td::uint32)arg), true); - return envelope_send_query( - std::move(b), [this, id, mode, arg, promise = std::move(promise)](td::Result R) mutable -> void { + return envelope_send_query_to_shard( + shard, std::move(b), + [this, id, mode, arg, promise = std::move(promise)](td::Result R) mutable -> void { TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), PSLICE() << "cannot look up block header for " << id.to_str() << " with mode " << mode << " and argument " << arg << " from server :"); @@ -3130,9 +3249,9 @@ void TestNode::got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int return; } show_block_header(blkid, std::move(virt_root), mode); - } catch (vm::VmError err) { + } catch (vm::VmError& err) { LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); - } catch (vm::VmVirtError err) { + } catch (vm::VmVirtError& err) { LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); } show_new_blkids(); @@ -3161,14 +3280,15 @@ bool TestNode::get_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mod ton::serialize_tl_object(ton::create_tl_object( mode & 0xfff, ton::create_tl_lite_block_id(from), ton::create_tl_lite_block_id(to)), true); - return envelope_send_query(std::move(b), [Self = actor_id(this), from, to, mode](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "cannot obtain block proof for " << ((mode & 1) ? to.to_str() : "last masterchain block") - << " starting from " << from.to_str() << " from server : " << res.move_as_error().to_string(); - } else { - td::actor::send_closure_later(Self, &TestNode::got_block_proof, from, to, mode, res.move_as_ok()); - } - }); + return envelope_send_query_to_any( + std::move(b), [Self = actor_id(this), from, to, mode](td::Result res) { + if (res.is_error()) { + LOG(ERROR) << "cannot obtain block proof for " << ((mode & 1) ? to.to_str() : "last masterchain block") + << " starting from " << from.to_str() << " from server : " << res.move_as_error().to_string(); + } else { + td::actor::send_closure_later(Self, &TestNode::got_block_proof, from, to, mode, res.move_as_ok()); + } + }); } void TestNode::got_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, td::BufferSlice pchain) { @@ -3222,9 +3342,6 @@ void TestNode::got_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mod bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, ton::UnixTime min_utime) { - if (!(ready_ && !client_.empty())) { - return set_error("server connection not ready"); - } if (!blkid.is_masterchain_ext()) { return set_error("only masterchain blocks contain block creator statistics"); } @@ -3235,8 +3352,8 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_c auto& os = *osp; return get_creator_stats( blkid, mode, req_count, start_after, min_utime, - [min_utime, &os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt) -> bool { + [&os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, + const block::DiscountedCounter& shard_cnt) -> bool { os << key.to_hex() << " mc_cnt:" << mc_cnt << " shard_cnt:" << shard_cnt << std::endl; return true; }, @@ -3265,10 +3382,6 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_c bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton::UnixTime min_utime, TestNode::creator_stats_func_t func, std::unique_ptr state, td::Promise> promise) { - if (!(ready_ && !client_.empty())) { - promise.set_error(td::Status::Error("server connection not ready")); - return false; - } if (!state) { promise.set_error(td::Status::Error("null CreatorStatsRes")); return false; @@ -3287,7 +3400,7 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton: LOG(INFO) << "requesting up to " << req_count << " block creator stats records with respect to masterchain block " << blkid.to_str() << " starting from validator public key " << state->last_key.to_hex() << " created after " << min_utime << " (mode=" << state->mode << ")"; - return envelope_send_query( + return envelope_send_query_to_any( std::move(b), [this, blkid, req_count, state = std::move(state), min_utime, func = std::move(func), promise = std::move(promise)](td::Result R) mutable { TRY_RESULT_PROMISE(promise, res, std::move(R)); @@ -3504,8 +3617,8 @@ bool TestNode::load_creator_stats(std::unique_ptr l ton::UnixTime min_utime = info.valid_since - 1000; return get_creator_stats( info.blk_id, 1000, min_utime, - [min_utime, &info](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, - const block::DiscountedCounter& shard_cnt) -> bool { + [&info](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, + const block::DiscountedCounter& shard_cnt) -> bool { info.store_record(key, mc_cnt, shard_cnt); return true; }, @@ -3708,7 +3821,7 @@ bool compute_punishment_default(int interval, bool severe, td::RefInt256& fine, fine = td::make_refint(101 * 1000000000LL); // 101 fine_part = 0; - return true; // todo: (tolya-yanot) temporary reduction of fine + return true; // todo: (tolya-yanot) temporary reduction of fine if (severe) { fine = td::make_refint(2500 * 1000000000LL); // GR$2500 @@ -3730,41 +3843,49 @@ bool compute_punishment_default(int interval, bool severe, td::RefInt256& fine, return true; } -bool compute_punishment(int interval, bool severe, td::RefInt256& fine, unsigned& fine_part, Ref punishment_params) { - if(punishment_params.is_null()) { +bool compute_punishment(int interval, bool severe, td::RefInt256& fine, unsigned& fine_part, + Ref punishment_params) { + if (punishment_params.is_null()) { return compute_punishment_default(interval, severe, fine, fine_part); } block::gen::MisbehaviourPunishmentConfig::Record rec; if (!tlb::unpack_cell(punishment_params, rec)) { - return false; + return false; } - if(interval <= rec.unpunishable_interval) { - return false; + if (interval <= rec.unpunishable_interval) { + return false; } fine = block::tlb::t_Grams.as_integer(rec.default_flat_fine); fine_part = rec.default_proportional_fine; if (severe) { - fine = fine * rec.severity_flat_mult; fine >>= 8; - fine_part = fine_part * rec.severity_proportional_mult; fine_part >>= 8; + fine = fine * rec.severity_flat_mult; + fine >>= 8; + fine_part = fine_part * rec.severity_proportional_mult; + fine_part >>= 8; } if (interval >= rec.long_interval) { - fine = fine * rec.long_flat_mult; fine >>= 8; - fine_part = fine_part * rec.long_proportional_mult; fine_part >>= 8; + fine = fine * rec.long_flat_mult; + fine >>= 8; + fine_part = fine_part * rec.long_proportional_mult; + fine_part >>= 8; return true; } if (interval >= rec.medium_interval) { - fine = fine * rec.medium_flat_mult; fine >>= 8; - fine_part = fine_part * rec.medium_proportional_mult; fine_part >>= 8; + fine = fine * rec.medium_flat_mult; + fine >>= 8; + fine_part = fine_part * rec.medium_proportional_mult; + fine_part >>= 8; return true; } return true; } -bool check_punishment(int interval, bool severe, td::RefInt256 fine, unsigned fine_part, Ref punishment_params) { +bool check_punishment(int interval, bool severe, td::RefInt256 fine, unsigned fine_part, + Ref punishment_params) { td::RefInt256 computed_fine; unsigned computed_fine_part; return compute_punishment(interval, severe, computed_fine, computed_fine_part, punishment_params) && @@ -3800,7 +3921,7 @@ td::Status TestNode::write_val_create_proof(TestNode::ValidatorLoadInfo& info1, int severity = (severe ? 2 : 1); td::RefInt256 fine = td::make_refint(101000000000); - unsigned fine_part = 0; // todo: (tolya-yanot) temporary reduction of fine // 0xffffffff / 16; // 1/16 + unsigned fine_part = 0; // todo: (tolya-yanot) temporary reduction of fine // 0xffffffff / 16; // 1/16 if (!compute_punishment(interval, severe, fine, fine_part, punishment_params)) { return td::Status::Error("cannot compute adequate punishment"); } @@ -3899,7 +4020,7 @@ td::Result> TestNode::ValidatorLoadInfo::build_proof(int idx, td:: block::gen::ValidatorDescr::Record_validator_addr rec2; if (tlb::csr_unpack(entry, rec1)) { pk = std::move(rec1.public_key); - } else if (tlb::csr_unpack(std::move(entry), rec2)) { + } else if (tlb::csr_unpack(entry, rec2)) { pk = std::move(rec2.public_key); } else { return td::Status::Error("cannot unpack ValidatorDescr"); @@ -4115,7 +4236,8 @@ td::Status TestNode::continue_check_validator_load_proof(std::unique_ptrconfig->get_config_param(40))) { + if (!check_punishment(interval, severe, suggested_fine, rec.suggested_fine_part, + info2->config->get_config_param(40))) { LOG(ERROR) << "proposed punishment (fine " << td::dec_string(suggested_fine) << ", fine_part=" << (double)rec.suggested_fine_part / (1LL << 32) << " is too harsh"; show_vote(root->get_hash().bits(), false); @@ -4264,8 +4386,9 @@ int main(int argc, char* argv[]) { return (verbosity >= 0 && verbosity <= 9) ? td::Status::OK() : td::Status::Error("verbosity must be 0..9"); }); p.add_option('V', "version", "shows lite-client build information", [&]() { - std::cout << "lite-client build information: [ Commit: " << GitMetadata::CommitSHA1() << ", Date: " << GitMetadata::CommitDate() << "]\n"; - + std::cout << "lite-client build information: [ Commit: " << GitMetadata::CommitSHA1() + << ", Date: " << GitMetadata::CommitDate() << "]\n"; + std::exit(0); }); p.add_option('i', "idx", "set liteserver idx", [&](td::Slice arg) { diff --git a/lite-client/lite-client.h b/lite-client/lite-client.h index 34d02011..018a9298 100644 --- a/lite-client/lite-client.h +++ b/lite-client/lite-client.h @@ -57,8 +57,7 @@ class TestNode : public td::actor::Actor { bool client_ready = false; std::vector> wait_client_ready; - int max_common_prefix(ton::ShardIdFull shard) const; - bool supports_shard(ton::ShardIdFull shard) const; + bool supports(ton::ShardIdFull shard) const; }; std::vector servers_; @@ -352,9 +351,6 @@ class TestNode : public td::actor::Actor { bool parse_shard_id(ton::ShardIdFull& shard); bool parse_block_id_ext(ton::BlockIdExt& blkid, bool allow_incomplete = false); bool parse_block_id_ext(std::string blk_id_string, ton::BlockIdExt& blkid, bool allow_incomplete = false) const; - bool parse_stack_value(td::Slice str, vm::StackEntry& value); - bool parse_stack_value(vm::StackEntry& value); - bool parse_stack_values(std::vector& values); bool register_blkid(const ton::BlockIdExt& blkid); bool show_new_blkids(bool all = false); bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const; @@ -458,8 +454,7 @@ class TestNode : public td::actor::Actor { void parse_line(td::BufferSlice data); - TestNode() { - } + TestNode() = default; void run(); }; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 6a2e18f1640f473c854f3eb2dabdf8f076537438..97c2bda2df4125bec8281603581b892696097361 100644 GIT binary patch delta 3518 zcma)8Z){Ul6z^SMXUo>D!;ZCUYl|zcV_P>6lqkc=fNe6QIzp68y0^Z|R_)%audf>= z7$F(~K^hgPp{{m z^E-d;x#xFo?lGJ^W+=KeSoeS~{nMl2qIvq#V>idYC}cT4;$MejF}54iW7GbJ%jAH5 zj43}^&;Q^F36TgZ3F4yyhyBf%$093XGAI8Y*<$>}P#Q=SO%-xo{+L9?{Rr_{YXPR{@ zzeS)qSD!t4^uj&=s~rP%a#3%WkJuuJIrjXXYs6aKIj^Gep}LYtn7YSe9~S*k){ToP zt}K<0H3e-j&JyTa6Am?pf_=a5fTZ9uNBg_{rBRF(B{XlR>-Wzw7!-8R$o{W3P`iuJNY+oLpUF0_piL z=eFs|RD+w;?=leAn&#ATkE%DYrao=3#%ogzpxMQy{2F7!OD8~fpxK)NL!@N5I%U$K z5$BPqk!mv1oOVBP+tHF1?^3`5Z1|nMYfi_4A>Lc2JR`Nr&&IKsSS^ZzsK$aQaOHs& z#dc{zP$w!u_M4q*ia~Ewsd!}aowAa|3evL{iw#P#u zdc`^&yjrLhO1cnov|V`mJiKb=s@w)| zA3On+3Jo&y-PW4ihqi<-_u&(X|FArisLySA`M+Sj+k73lqSY2+_g91aYcm7o8JzG( za}F-0hiSb5H#zYjTK+tIY00Wn+Mr+_|eKUttPz`W2fAC<6@5$rEL$n%G_) zH=5F*WXCEGqnJ#*YDIHPl*D5}NeK1|e3W(du@3AmXq}mS#F@#5 zrV0Am5}TCb2E!cLxyo(p9zHXgod{US1B3g}+L77%NNGKF znL6UWVJ96oJf@61IgF6IxQNGFrC?MPxOj-ZDDu#giy8q+d*3s2VRje_7wSNlSo@dQ z03*~H5!#H-VRT&WIuxV3@=jw~bNEr$Hmr32KA9R)`6 z!6UxnWkA^F*@P|PUMdP;Eb8DK;Gt@2PlJpM$)7O5;|KQol4EY-AJXg&8yD+TYkk_-8-`o~%_5GW=jawP{7|#3zxUnCayqco&{F~%9VkGP4D)2?w?8L6 zW>jivhk<=d8<9nPSxPftL1P9($JZ~GP;mRKz<)1AyYmd6_AOj*S4?uFCutm>(XBQV zVGM&WIIdPDStqjAWpC4|nV<{>$VGcCFbhU$k*%H%wdJ(O*)7Yq z#^xPTIgBhn4)k(N){sfqyhCOS)8rNM2BIZ*=7sPS<)joKS;Y)8hebhvNAf_z{;wh> z`FVc%DXDtSi3N#CnK_vynW@E-7jjB(_RtAooP0(1#O4!vA}ow0o9`Nxi?V>+KKa8W zjmZrjDiF>J4;@aB=*?q7KFpH^9p$G#P-JAC{#Ke%8KKC>Q-v9*X!3eTL#QrK6$zLw zQ0Npnv*~cywjBhU|HKn&HjkG9M7e{P3fvN=$%+TGC(rPLsyTomCE*Q~S^{I7@ty)U zXLE|r0Y-?48h$nqp$xwVLYp0u_DD&90v+TFWcPr?CX3YS;FgT2)xa$|1E0=2wFbC# zs?^~zHU*F5=9oqf-pzOVV%We*WU|dv2~JR20r`x3a_rRKnHK!wE`EAU#ZzC$6=h%(G4dB4x2|&gMDmW%wum*|&xTl)NSv zOwyP>!GKW(!uzvd2EvdzFbBfea{wxG=RgQpWb=fB2edgsi4S7_!?)g(N;z0S0-Iyr zJz(A}@wtO(v&^?MGK|&RUkWk$Gi|pKW0YXoen*P&0LwN7#s#d~HPje0n6`h>V9a6J ezD1XjLqP&&9&+q~#I{TLF-~CI9uvTr!3F^N)?rWp diff --git a/tl/generate/scheme/tonlib_api.tlo b/tl/generate/scheme/tonlib_api.tlo index 075c5a3abdf705679b48dd79a799a1f70a9d67a9..1f4dab07974697338e4e299f46e17cda26580488 100644 GIT binary patch delta 101 zcmZ4SiSf-R#tjSDc<1Iw@Fk`cgwt*i2F8LvG diff --git a/tonlib/CMakeLists.txt b/tonlib/CMakeLists.txt index d9984368..f27e00f2 100644 --- a/tonlib/CMakeLists.txt +++ b/tonlib/CMakeLists.txt @@ -8,7 +8,6 @@ set(TONLIB_SOURCE tonlib/Client.cpp tonlib/Config.cpp tonlib/ExtClient.cpp - tonlib/ExtClientMulti.cpp tonlib/ExtClientLazy.cpp tonlib/ExtClientOutbound.cpp tonlib/KeyStorage.cpp @@ -24,8 +23,7 @@ set(TONLIB_SOURCE tonlib/Client.h tonlib/Config.h tonlib/ExtClient.h - tonlib/ExtClientMulti.h - tonlib/ExtClientRaw.h + tonlib/ExtClientLazy.h tonlib/ExtClientOutbound.h tonlib/KeyStorage.h tonlib/KeyValue.h diff --git a/tonlib/tonlib/Config.cpp b/tonlib/tonlib/Config.cpp index dfa9e3f7..73d4e033 100644 --- a/tonlib/tonlib/Config.cpp +++ b/tonlib/tonlib/Config.cpp @@ -66,16 +66,16 @@ td::Result Config::parse(std::string str) { return td::Status::Error("Invalid config (1)"); } td::JsonArray empty_array; - TRY_RESULT(lite_clients_obj, + TRY_RESULT(lite_servers_obj, td::get_json_object_field(json.get_object(), "liteservers", td::JsonValue::Type::Array, true)); - auto &lite_clients = - lite_clients_obj.type() == td::JsonValue::Type::Array ? lite_clients_obj.get_array() : empty_array; - TRY_RESULT(lite_clients_v2_obj, + auto &lite_servers = + lite_servers_obj.type() == td::JsonValue::Type::Array ? lite_servers_obj.get_array() : empty_array; + TRY_RESULT(lite_servers_v2_obj, td::get_json_object_field(json.get_object(), "liteservers_v2", td::JsonValue::Type::Array, true)); - auto &lite_clients_v2 = - lite_clients_v2_obj.type() == td::JsonValue::Type::Array ? lite_clients_v2_obj.get_array() : empty_array; + auto &lite_servers_v2 = + lite_servers_v2_obj.type() == td::JsonValue::Type::Array ? lite_servers_v2_obj.get_array() : empty_array; - auto parse_desc = [&](td::JsonValue& value) -> td::Result { + auto parse_desc = [&](td::JsonValue &value) -> td::Result { if (value.type() != td::JsonValue::Type::Object) { return td::Status::Error("Invalid config (2)"); } @@ -83,8 +83,8 @@ td::Result Config::parse(std::string str) { TRY_RESULT(ip, td::get_json_object_long_field(object, "ip", false)); TRY_RESULT(port, td::get_json_object_int_field(object, "port", false)); - Config::LiteClient client; - TRY_STATUS(client.address.init_host_port(td::IPAddress::ipv4_to_str(static_cast(ip)), port)); + Config::LiteServer server; + TRY_STATUS(server.address.init_host_port(td::IPAddress::ipv4_to_str(static_cast(ip)), port)); TRY_RESULT(id_obj, td::get_json_object_field(object, "id", td::JsonValue::Type::Object, false)); auto &id = id_obj.get_object(); @@ -98,20 +98,19 @@ td::Result Config::parse(std::string str) { return td::Status::Error("Invalid config (4)"); } - client.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin()))); - return client; + server.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin()))); + return server; }; Config res; - for (auto &value : lite_clients) { - TRY_RESULT(client, parse_desc(value)); - res.lite_clients.push_back(std::move(client)); + for (auto &value : lite_servers) { + TRY_RESULT(server, parse_desc(value)); + res.lite_servers.push_back(std::move(server)); } - for (auto &value : lite_clients_v2) { - TRY_RESULT(client, parse_desc(value)); - client.is_full = false; - TRY_RESULT(shards_obj, - td::get_json_object_field(value.get_object(), "shards", td::JsonValue::Type::Array, false)); + for (auto &value : lite_servers_v2) { + TRY_RESULT(server, parse_desc(value)); + server.is_full = false; + TRY_RESULT(shards_obj, td::get_json_object_field(value.get_object(), "shards", td::JsonValue::Type::Array, false)); for (auto &shard : shards_obj.get_array()) { if (shard.type() != td::JsonValue::Type::Object) { return td::Status::Error("Invalid config (5)"); @@ -122,10 +121,10 @@ td::Result Config::parse(std::string str) { if (shard_id == 0) { return td::Status::Error("Invalid config (6)"); } - client.shards.emplace_back(workchain, shard_id); + server.shards.emplace_back(workchain, shard_id); } - res.lite_clients.push_back(std::move(client)); + res.lite_servers.push_back(std::move(server)); } TRY_RESULT(validator_obj, diff --git a/tonlib/tonlib/Config.h b/tonlib/tonlib/Config.h index 420889df..7af1b1c5 100644 --- a/tonlib/tonlib/Config.h +++ b/tonlib/tonlib/Config.h @@ -23,7 +23,7 @@ namespace tonlib { struct Config { - struct LiteClient { + struct LiteServer { ton::adnl::AdnlNodeIdFull adnl_id; td::IPAddress address; bool is_full = true; @@ -32,7 +32,7 @@ struct Config { ton::BlockIdExt zero_state_id; ton::BlockIdExt init_block_id; std::vector hardforks; - std::vector lite_clients; + std::vector lite_servers; std::string name; static td::Result parse(std::string str); }; diff --git a/tonlib/tonlib/ExtClient.cpp b/tonlib/tonlib/ExtClient.cpp index 30a29b59..755be170 100644 --- a/tonlib/tonlib/ExtClient.cpp +++ b/tonlib/tonlib/ExtClient.cpp @@ -54,7 +54,7 @@ void ExtClient::with_last_block(td::Promise promise) { td::actor::send_closure(client_.last_block_actor_, &LastBlock::get_last_block, std::move(P)); } -void ExtClient::send_raw_query(td::BufferSlice query, td::Promise promise) { +void ExtClient::send_raw_query(td::BufferSlice query, ton::ShardIdFull shard, td::Promise promise) { auto query_id = queries_.create(std::move(promise)); td::Promise P = [query_id, self = this, actor_id = td::actor::actor_id()](td::Result result) { @@ -65,7 +65,7 @@ void ExtClient::send_raw_query(td::BufferSlice query, td::Promise + namespace tonlib { -class ExtClientLazyImp : public ExtClientLazy { +class ExtClientLazyImpl : public ExtClientLazy { public: - ExtClientLazyImp(std::vector> servers, - td::unique_ptr callback) - : servers_(std::move(servers)), callback_(std::move(callback)) { - CHECK(!servers_.empty()); + ExtClientLazyImpl(std::vector servers, td::unique_ptr callback) + : callback_(std::move(callback)) { + CHECK(!servers.empty()); + servers_.resize(servers.size()); + for (size_t i = 0; i < servers_.size(); ++i) { + servers_[i].s = std::move(servers[i]); + if (!servers_[i].s.is_full) { + for (auto shard : servers_[i].s.shards) { + CHECK(shard.is_valid_ext()); + max_server_shard_depth_ = std::max(max_server_shard_depth_, shard.pfx_len()); + } + } + } } void start_up() override { @@ -34,29 +46,21 @@ class ExtClientLazyImp : public ExtClientLazy { td::random_shuffle(td::as_mutable_span(servers_), rnd); } - void check_ready(td::Promise promise) override { - before_query(); - if (client_.empty()) { - return promise.set_error(TonlibError::Cancelled()); - } - send_closure(client_, &ton::adnl::AdnlExtClient::check_ready, std::move(promise)); - } - - void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, + void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout, td::Promise promise) override { - before_query(); - if (client_.empty()) { - return promise.set_error(TonlibError::Cancelled()); - } - td::Promise P = [SelfId = actor_id(this), idx = cur_server_idx_, + TRY_RESULT_PROMISE(promise, server_idx, before_query(shard)); + auto& server = servers_[server_idx]; + CHECK(!server.client.empty()); + alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT)); + td::Promise P = [SelfId = actor_id(this), server_idx, promise = std::move(promise)](td::Result R) mutable { if (R.is_error() && (R.error().code() == ton::ErrorCode::timeout || R.error().code() == ton::ErrorCode::cancelled)) { - td::actor::send_closure(SelfId, &ExtClientLazyImp::set_server_bad, idx, true); + td::actor::send_closure(SelfId, &ExtClientLazyImpl::set_server_bad, server_idx); } promise.set_result(std::move(R)); }; - send_closure(client_, &ton::adnl::AdnlExtClient::send_query, std::move(name), std::move(data), timeout, + send_closure(server.client, &ton::adnl::AdnlExtClient::send_query, std::move(name), std::move(data), timeout, std::move(P)); } @@ -64,64 +68,124 @@ class ExtClientLazyImp : public ExtClientLazy { if (servers_.size() == 1) { return; } - cur_server_bad_ = cur_server_bad_force_ = true; + auto it = shard_to_server_.find(ton::ShardIdFull(ton::masterchainId)); + if (it != shard_to_server_.end()) { + set_server_bad(it->second); + } } private: - void before_query() { + td::Result before_query(ton::ShardIdFull shard) { + if (!shard.is_valid_ext()) { + return td::Status::Error("Invalid shard"); + } if (is_closing_) { - return; + return td::Status::Error("Client is closing"); } - alarm_timestamp() = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT); - if (cur_server_bad_) { - ++cur_server_idx_; - } else if (!client_.empty()) { - return; + if (shard.pfx_len() > max_server_shard_depth_) { + shard = shard_prefix(shard, max_server_shard_depth_); } + auto it = shard_to_server_.find(shard); + if (it != shard_to_server_.end()) { + size_t server_idx = it->second; + if (!servers_[server_idx].client.empty()) { + return server_idx; + } + shard_to_server_.erase(it); + } + + size_t server_idx = servers_.size(); + int cnt = 0; + int best_priority = -1; + for (size_t i = 0; i < servers_.size(); ++i) { + Server& server = servers_[i]; + if (!server.supports(shard)) { + continue; + } + int priority = 0; + priority += (server.client.empty() ? 0 : 100); + priority += (server.ignore_until && !server.ignore_until.is_in_past() ? 0 : 10); + priority += (server.s.is_full ? 1 : 0); + if (priority < best_priority) { + continue; + } + if (priority > best_priority) { + best_priority = priority; + cnt = 0; + } + if (td::Random::fast(0, cnt) == 0) { + server_idx = i; + } + ++cnt; + } + if (server_idx == servers_.size()) { + return td::Status::Error(PSTRING() << "No liteserver for shard " << shard.to_str()); + } + Server& server = servers_[server_idx]; + if (!server.client.empty()) { + return server_idx; + } + class Callback : public ton::adnl::AdnlExtClient::Callback { public: - explicit Callback(td::actor::ActorShared parent, size_t idx) + explicit Callback(td::actor::ActorShared parent, size_t idx) : parent_(std::move(parent)), idx_(idx) { } void on_ready() override { - td::actor::send_closure(parent_, &ExtClientLazyImp::set_server_bad, idx_, false); } void on_stop_ready() override { - td::actor::send_closure(parent_, &ExtClientLazyImp::set_server_bad, idx_, true); + td::actor::send_closure(parent_, &ExtClientLazyImpl::set_server_bad, idx_); } private: - td::actor::ActorShared parent_; + td::actor::ActorShared parent_; size_t idx_; }; ref_cnt_++; - cur_server_bad_ = false; - cur_server_bad_force_ = false; - const auto& s = servers_[cur_server_idx_ % servers_.size()]; - LOG(INFO) << "Connecting to liteserver " << s.second; - client_ = ton::adnl::AdnlExtClient::create( - s.first, s.second, std::make_unique(td::actor::actor_shared(this), cur_server_idx_)); + if (shard.is_masterchain()) { + LOG(INFO) << "Connecting to liteserver " << server.s.address << " for masterchain"; + } else { + LOG(INFO) << "Connecting to liteserver " << server.s.address << " for shard " << shard.to_str(); + } + server.client = ton::adnl::AdnlExtClient::create( + server.s.adnl_id, server.s.address, std::make_unique(td::actor::actor_shared(this), server_idx)); + alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT)); + return server_idx; } - std::vector> servers_; - size_t cur_server_idx_ = 0; - bool cur_server_bad_ = false; - bool cur_server_bad_force_ = false; + struct Server { + Config::LiteServer s; + td::actor::ActorOwn client; + td::Timestamp timeout = td::Timestamp::never(); + td::Timestamp ignore_until = td::Timestamp::never(); + + bool supports(const ton::ShardIdFull& shard) const { + return s.is_full || shard.is_masterchain() || + std::any_of(s.shards.begin(), s.shards.end(), + [&](const ton::ShardIdFull s_shard) { return ton::shard_intersects(shard, s_shard); }); + } + }; + std::vector servers_; + std::map shard_to_server_; + int max_server_shard_depth_ = 0; - td::actor::ActorOwn client_; td::unique_ptr callback_; static constexpr double MAX_NO_QUERIES_TIMEOUT = 100; bool is_closing_{false}; td::uint32 ref_cnt_{1}; - void set_server_bad(size_t idx, bool bad) { - if (idx == cur_server_idx_ && servers_.size() > 1 && !cur_server_bad_force_) { - cur_server_bad_ = bad; + void alarm() override { + for (Server& server : servers_) { + if (server.timeout && server.timeout.is_in_past()) { + server.client.reset(); + } } } - void alarm() override { - client_.reset(); + void set_server_bad(size_t idx) { + servers_[idx].client.reset(); + servers_[idx].timeout = td::Timestamp::never(); + servers_[idx].ignore_until = td::Timestamp::in(60.0); } void hangup_shared() override { ref_cnt_--; @@ -130,7 +194,9 @@ class ExtClientLazyImp : public ExtClientLazy { void hangup() override { is_closing_ = true; ref_cnt_--; - client_.reset(); + for (Server& server : servers_) { + server.client.reset(); + } try_stop(); } void try_stop() { @@ -142,11 +208,11 @@ class ExtClientLazyImp : public ExtClientLazy { td::actor::ActorOwn ExtClientLazy::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr, td::unique_ptr callback) { - return create({std::make_pair(dst, dst_addr)}, std::move(callback)); + return create({Config::LiteServer{dst, dst_addr, true, {}}}, std::move(callback)); } -td::actor::ActorOwn ExtClientLazy::create( - std::vector> servers, td::unique_ptr callback) { - return td::actor::create_actor("ExtClientLazy", std::move(servers), std::move(callback)); +td::actor::ActorOwn ExtClientLazy::create(std::vector servers, + td::unique_ptr callback) { + return td::actor::create_actor("ExtClientLazy", std::move(servers), std::move(callback)); } } // namespace tonlib diff --git a/tonlib/tonlib/ExtClientRaw.h b/tonlib/tonlib/ExtClientLazy.h similarity index 72% rename from tonlib/tonlib/ExtClientRaw.h rename to tonlib/tonlib/ExtClientLazy.h index 612995af..6383cec5 100644 --- a/tonlib/tonlib/ExtClientRaw.h +++ b/tonlib/tonlib/ExtClientLazy.h @@ -18,23 +18,27 @@ */ #pragma once #include "td/actor/actor.h" -#include "adnl/adnl-ext-client.h" #include "ton/ton-types.h" +#include "adnl/adnl-ext-client.h" +#include "Config.h" namespace tonlib { -class ExtClientLazy : public ton::adnl::AdnlExtClient { +class ExtClientLazy : public td::actor::Actor { public: class Callback { public: - virtual ~Callback() = default; + virtual ~Callback() { + } }; + virtual void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout, + td::Promise promise) = 0; virtual void force_change_liteserver() = 0; static td::actor::ActorOwn create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr, td::unique_ptr callback); - static td::actor::ActorOwn create( - std::vector> servers, td::unique_ptr callback); + static td::actor::ActorOwn create(std::vector servers, + td::unique_ptr callback); }; } // namespace tonlib diff --git a/tonlib/tonlib/ExtClientMulti.cpp b/tonlib/tonlib/ExtClientMulti.cpp deleted file mode 100644 index 3a6cdf59..00000000 --- a/tonlib/tonlib/ExtClientMulti.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . -*/ -#include "ExtClientMulti.h" -#include "ton/ton-shard.h" -#include "td/utils/Random.h" - -namespace tonlib { - -static const double MAX_NO_QUERIES_TIMEOUT = 120; - -ExtClientMulti::ExtClientMulti(std::vector clients, td::unique_ptr callback) - : callback_(std::move(callback)) { - for (auto &desc : clients) { - servers_.emplace_back(); - servers_.back().desc = std::move(desc); - } -} - -void ExtClientMulti::start_up() { - alarm_timestamp() = td::Timestamp::in(60.0); -} - -void ExtClientMulti::send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout, - td::Promise promise) { - if (shard.is_masterchain() && mc_server_idx_ != -1 && !servers_[mc_server_idx_].is_bad()) { - send_query_to_server(std::move(name), std::move(data), mc_server_idx_, timeout, std::move(promise)); - return; - } - auto it = shard_server_idx_cached_.find(shard); - if (it != shard_server_idx_cached_.end() && !servers_[it->second].is_bad()) { - send_query_to_server(std::move(name), std::move(data), it->second, timeout, std::move(promise)); - return; - } - int server_idx = -1; - int random_idx = -1; - int cnt = 0; - int best_prefix = -1; - for (int i = 0; i < (int)servers_.size(); ++i) { - const Server &server = servers_[i]; - if (server.is_bad()) { - continue; - } - int len = server.desc.is_full ? 65 : server.max_supported_prefix(shard); - if (len > best_prefix) { - best_prefix = len; - server_idx = -1; - random_idx = -1; - cnt = 0; - } else if (len < best_prefix) { - continue; - } - if (!server.client.empty()) { - server_idx = i; - } - if (td::Random::fast(0, cnt) == 0) { - random_idx = i; - } - ++cnt; - } - if (server_idx == -1) { - server_idx = random_idx; - } - if (server_idx == -1) { - promise.set_error(td::Status::Error("failed to select a suitable server")); - return; - } - if (shard.pfx_len() <= ton::max_shard_pfx_len) { - shard_server_idx_cached_[shard] = server_idx; - } - if (shard.is_masterchain() || servers_[server_idx].desc.is_full) { - mc_server_idx_ = server_idx; - } - send_query_to_server(std::move(name), std::move(data), server_idx, timeout, std::move(promise)); -} - -void ExtClientMulti::send_query_to_server(std::string name, td::BufferSlice data, int server_idx, td::Timestamp timeout, - td::Promise promise) { - Server &server = servers_.at(server_idx); - if (server.client.empty()) { - start_client(server_idx); - } - server.ttl = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT); - td::Promise P = [SelfId = actor_id(this), idx = server_idx, - promise = std::move(promise)](td::Result R) mutable { - if (R.is_error() && - (R.error().code() == ton::ErrorCode::timeout || R.error().code() == ton::ErrorCode::cancelled)) { - td::actor::send_closure(SelfId, &ExtClientMulti::set_server_bad, idx); - } - promise.set_result(std::move(R)); - }; - send_closure(server.client, &ton::adnl::AdnlExtClient::send_query, std::move(name), std::move(data), timeout, - std::move(P)); -} - -void ExtClientMulti::force_change_liteserver() { - if (mc_server_idx_ != -1) { - set_server_bad(mc_server_idx_); - mc_server_idx_ = -1; - } -} - -void ExtClientMulti::start_client(int server_idx) { - class Callback : public ton::adnl::AdnlExtClient::Callback { - public: - Callback(td::actor::ActorId parent, int idx) : parent_(std::move(parent)), idx_(idx) { - } - void on_ready() override { - } - void on_stop_ready() override { - td::actor::send_closure(parent_, &ExtClientMulti::set_server_bad, idx_); - } - - private: - td::actor::ActorId parent_; - int idx_; - }; - Server &server = servers_.at(server_idx); - server.client = ton::adnl::AdnlExtClient::create(server.desc.adnl_id, server.desc.address, - std::make_unique(actor_id(this), server_idx)); -} - -void ExtClientMulti::alarm() { - for (Server& server : servers_) { - if (server.ttl && server.ttl.is_in_past()) { - server.client.reset(); - } - } - alarm_timestamp() = td::Timestamp::in(60.0); -} - -void ExtClientMulti::set_server_bad(int idx) { - Server& server = servers_.at(idx); - server.client.reset(); - server.ttl = td::Timestamp::never(); - server.ignore_until = td::Timestamp::in(10.0); -} - -int ExtClientMulti::Server::max_supported_prefix(ton::ShardIdFull shard) const { - if (desc.is_full || shard.is_masterchain()) { - return shard.pfx_len(); - } - int res = -1; - for (const ton::ShardIdFull &our_shard : desc.shards) { - if (ton::shard_is_ancestor(our_shard, shard)) { - return shard.pfx_len(); - } - if (shard.workchain == our_shard.workchain) { - int x = std::min({shard.pfx_len(), our_shard.pfx_len(), ton::count_matching_bits(shard.shard, our_shard.shard)}); - res = std::max(res, x); - } - } - return res; -} - -} // namespace tonlib diff --git a/tonlib/tonlib/ExtClientMulti.h b/tonlib/tonlib/ExtClientMulti.h deleted file mode 100644 index 4c93b00e..00000000 --- a/tonlib/tonlib/ExtClientMulti.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of TON Blockchain Library. - - TON Blockchain Library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - TON Blockchain Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with TON Blockchain Library. If not, see . -*/ -#pragma once -#include "td/actor/actor.h" -#include "adnl/adnl-ext-client.h" -#include "Config.h" -#include "ExtClientRaw.h" -#include - -namespace tonlib { - -class ExtClientMulti : public ExtClientRaw { - public: - ExtClientMulti(std::vector clients, td::unique_ptr callback); - - void start_up() override; - void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout, - td::Promise promise) override; - void alarm() override; - void force_change_liteserver() override; - - private: - void send_query_to_server(std::string name, td::BufferSlice data, int server_idx, td::Timestamp timeout, - td::Promise promise); - void start_client(int server_idx); - - struct Server { - Config::LiteClient desc; - td::actor::ActorOwn client; - td::Timestamp ttl; - td::Timestamp ignore_until = td::Timestamp::never(); - - int max_supported_prefix(ton::ShardIdFull shard) const; - bool is_bad() const { - return ignore_until && !ignore_until.is_in_past(); - } - }; - - void set_server_bad(int idx); - - td::unique_ptr callback_; - std::vector servers_; - int mc_server_idx_ = -1; - std::map shard_server_idx_cached_; -}; - -} // namespace tonlib diff --git a/tonlib/tonlib/ExtClientOutbound.cpp b/tonlib/tonlib/ExtClientOutbound.cpp index d2715b8b..eb923734 100644 --- a/tonlib/tonlib/ExtClientOutbound.cpp +++ b/tonlib/tonlib/ExtClientOutbound.cpp @@ -20,11 +20,12 @@ #include "ExtClientOutbound.h" #include "TonlibError.h" #include + namespace tonlib { -class ExtClientOutboundImp : public ExtClientOutbound { +class ExtClientOutboundImpl : public ExtClientOutbound { public: - ExtClientOutboundImp(td::unique_ptr callback) : callback_(std::move(callback)) { + ExtClientOutboundImpl(td::unique_ptr callback) : callback_(std::move(callback)) { } void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout, @@ -37,9 +38,6 @@ class ExtClientOutboundImp : public ExtClientOutbound { void force_change_liteserver() override { } - void force_change_liteserver() override { - } - void on_query_result(td::int64 id, td::Result r_data, td::Promise promise) override { auto it = queries_.find(id); if (it == queries_.end()) { @@ -65,6 +63,6 @@ class ExtClientOutboundImp : public ExtClientOutbound { }; td::actor::ActorOwn ExtClientOutbound::create(td::unique_ptr callback) { - return td::actor::create_actor("ExtClientOutbound", std::move(callback)); + return td::actor::create_actor("ExtClientOutbound", std::move(callback)); } } // namespace tonlib diff --git a/tonlib/tonlib/ExtClientOutbound.h b/tonlib/tonlib/ExtClientOutbound.h index 4721e872..31f76b97 100644 --- a/tonlib/tonlib/ExtClientOutbound.h +++ b/tonlib/tonlib/ExtClientOutbound.h @@ -30,6 +30,7 @@ class ExtClientOutbound : public ExtClientLazy { } virtual void request(td::int64 id, std::string data, ton::ShardIdFull shard) = 0; }; + virtual void on_query_result(td::int64 id, td::Result r_data, td::Promise promise) = 0; static td::actor::ActorOwn create(td::unique_ptr callback); }; diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp index 0680cebc..05406d50 100644 --- a/tonlib/tonlib/TonlibClient.cpp +++ b/tonlib/tonlib/TonlibClient.cpp @@ -27,7 +27,6 @@ #include "tonlib/keys/Mnemonic.h" #include "tonlib/keys/SimpleEncryption.h" #include "tonlib/TonlibError.h" -#include "tonlib/ExtClientMulti.h" #include "smc-envelope/GenericAccount.h" #include "smc-envelope/ManualDns.h" @@ -863,7 +862,9 @@ class Query { } return res; } - td::Result>> estimate_fees(bool ignore_chksig, std::shared_ptr& cfg, vm::Dictionary& libraries) { + 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)); @@ -892,7 +893,8 @@ class Query { .set_now(raw_.source->get_sync_time()) .set_ignore_chksig(ignore_chksig) .set_address(raw_.source->get_address()) - .set_config(cfg).set_libraries(libraries)); + .set_config(cfg) + .set_libraries(libraries)); td::int64 fwd_fee = 0; if (res.success) { LOG(DEBUG) << "output actions:\n" @@ -962,8 +964,9 @@ td::Result to_balance(td::Ref balance_ref) { class GetTransactionHistory : public td::actor::Actor { public: - GetTransactionHistory(ExtClientRef ext_client_ref, block::StdAddress address, ton::LogicalTime lt, ton::Bits256 hash, td::int32 count, - td::actor::ActorShared<> parent, td::Promise promise) + GetTransactionHistory(ExtClientRef ext_client_ref, block::StdAddress address, ton::LogicalTime lt, ton::Bits256 hash, + td::int32 count, td::actor::ActorShared<> parent, + td::Promise promise) : address_(std::move(address)) , lt_(std::move(lt)) , hash_(std::move(hash)) @@ -1671,8 +1674,8 @@ void TonlibClient::init_ext_client() { } void request(td::int64 id, std::string data, ton::ShardIdFull shard) override { - send_closure(parent_, &TonlibClient::proxy_request, (id << 16) | (config_generation_ & 0xffff), - std::move(data), shard); + send_closure(parent_, &TonlibClient::proxy_request, (id << 16) | (config_generation_ & 0xffff), std::move(data), + shard); } private: @@ -1685,34 +1688,17 @@ void TonlibClient::init_ext_client() { ext_client_outbound_ = client.get(); raw_client_ = std::move(client); } else { - std::vector> servers; - for (const auto& s : config_.lite_clients) { - servers.emplace_back(s.adnl_id, s.address); - } class Callback : public ExtClientLazy::Callback { public: explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) { } + private: td::actor::ActorShared<> parent_; }; - std::vector> full_servers; - for (const auto& s : config_.lite_clients) { - if (s.is_full) { - full_servers.emplace_back(s.adnl_id, s.address); - } - } - if (!full_servers.empty()) { - raw_client_ = - ExtClientRaw::create(std::move(full_servers), td::make_unique(td::actor::actor_shared())); - } else { - CHECK(!config_.lite_clients.empty()); - raw_client_ = td::actor::create_actor("ExtClientMulti", config_.lite_clients, - td::make_unique(td::actor::actor_shared())); - } ext_client_outbound_ = {}; ref_cnt_++; - raw_client_ = ExtClientLazy::create(std::move(servers), td::make_unique(td::actor::actor_shared())); + raw_client_ = ExtClientLazy::create(config_.lite_servers, td::make_unique(td::actor::actor_shared())); } } @@ -2360,7 +2346,7 @@ td::Result TonlibClient::validate_config(tonlib_api::o TRY_RESULT_PREFIX(new_config, Config::parse(std::move(config->config_)), TonlibError::InvalidConfig("can't parse config")); - if (new_config.lite_clients.empty() && !config->use_callbacks_for_network_) { + if (new_config.lite_servers.empty() && !config->use_callbacks_for_network_) { return TonlibError::InvalidConfig("no lite clients"); } td::optional o_master_config; @@ -2427,8 +2413,7 @@ td::Result TonlibClient::validate_config(tonlib_api::o state.vert_seqno = vert_seqno; bool user_defined_init_block = false; - if (new_config.init_block_id.is_valid() && - state.last_key_block_id.id.seqno < new_config.init_block_id.id.seqno) { + if (new_config.init_block_id.is_valid() && state.last_key_block_id.id.seqno < new_config.init_block_id.id.seqno) { state.last_key_block_id = new_config.init_block_id; user_defined_init_block = true; LOG(INFO) << "Use init block from USER config: " << new_config.init_block_id.to_str(); @@ -2524,8 +2509,7 @@ td::Result to_std_address(td::Ref cs) { } struct ToRawTransactions { explicit ToRawTransactions(td::optional private_key, bool try_decode_messages = true) - : private_key_(std::move(private_key)) - , try_decode_messages_(try_decode_messages) { + : private_key_(std::move(private_key)), try_decode_messages_(try_decode_messages) { } td::optional private_key_; @@ -2588,7 +2572,8 @@ struct ToRawTransactions { } } if (!data) { - data = tonlib_api::make_object(to_bytes(std::move(body_cell)), to_bytes(std::move(init_state_cell))); + data = tonlib_api::make_object(to_bytes(std::move(body_cell)), + to_bytes(std::move(init_state_cell))); } return data; }; @@ -2636,7 +2621,8 @@ struct ToRawTransactions { auto created_lt = static_cast(msg_info.created_lt); return tonlib_api::make_object( tonlib_api::make_object(src), - tonlib_api::make_object(), 0, 0, 0, created_lt, std::move(body_hash), get_data(src)); + tonlib_api::make_object(), 0, 0, 0, created_lt, std::move(body_hash), + get_data(src)); } } @@ -2746,10 +2732,9 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessageReturnHash& td::Promise>&& promise) { TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body")); auto hash = body->get_hash().as_slice().str(); - make_request(int_api::SendMessage{std::move(body)}, - promise.wrap([hash = std::move(hash)](auto res) { - return tonlib_api::make_object(std::move(hash)); - })); + make_request(int_api::SendMessage{std::move(body)}, promise.wrap([hash = std::move(hash)](auto res) { + return tonlib_api::make_object(std::move(hash)); + })); return td::Status::OK(); } @@ -2839,7 +2824,7 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getTransactions& request, } td::Status TonlibClient::do_request(tonlib_api::raw_getTransactionsV2& request, - td::Promise>&& promise) { + td::Promise>&& promise) { if (!request.account_address_) { return TonlibError::EmptyField("account_address"); } @@ -2875,9 +2860,10 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getTransactionsV2& request, auto actor_id = actor_id_++; actors_[actor_id] = td::actor::create_actor( "GetTransactionHistory", client_.get_client(), account_address, lt, hash, count, actor_shared(this, actor_id), - promise.wrap([private_key = std::move(private_key), try_decode_messages = request.try_decode_messages_](auto&& x) mutable { - return ToRawTransactions(std::move(private_key), try_decode_messages).to_raw_transactions(std::move(x)); - })); + promise.wrap( + [private_key = std::move(private_key), try_decode_messages = request.try_decode_messages_](auto&& x) mutable { + return ToRawTransactions(std::move(private_key), try_decode_messages).to_raw_transactions(std::move(x)); + })); return td::Status::OK(); } @@ -3044,26 +3030,25 @@ class GenericCreateSendGrams : public TonlibQueryActor { td::Result to_dns_action(tonlib_api::dns_Action& action) { using R = td::Result; - return downcast_call2(action, - td::overloaded( - [&](tonlib_api::dns_actionDeleteAll& del_all) -> R { - return ton::ManualDns::Action{"", td::Bits256::zero(), {}}; - }, - [&](tonlib_api::dns_actionDelete& del) -> R { - return ton::ManualDns::Action{del.name_, del.category_, {}}; - }, - [&](tonlib_api::dns_actionSet& set) -> R { - if (!set.entry_) { - return TonlibError::EmptyField("entry"); - } - if (!set.entry_->entry_) { - return TonlibError::EmptyField("entry.entry"); - } - TRY_RESULT(entry_data, to_dns_entry_data(*set.entry_->entry_)); - TRY_RESULT(data_cell, entry_data.as_cell()); - return ton::ManualDns::Action{set.entry_->name_, set.entry_->category_, - std::move(data_cell)}; - })); + return downcast_call2( + action, td::overloaded( + [&](tonlib_api::dns_actionDeleteAll& del_all) -> R { + return ton::ManualDns::Action{"", td::Bits256::zero(), {}}; + }, + [&](tonlib_api::dns_actionDelete& del) -> R { + return ton::ManualDns::Action{del.name_, del.category_, {}}; + }, + [&](tonlib_api::dns_actionSet& set) -> R { + if (!set.entry_) { + return TonlibError::EmptyField("entry"); + } + if (!set.entry_->entry_) { + return TonlibError::EmptyField("entry.entry"); + } + TRY_RESULT(entry_data, to_dns_entry_data(*set.entry_->entry_)); + TRY_RESULT(data_cell, entry_data.as_cell()); + return ton::ManualDns::Action{set.entry_->name_, set.entry_->category_, std::move(data_cell)}; + })); } td::Status parse_action(tonlib_api::Action& action) { @@ -3471,9 +3456,9 @@ class GenericCreateSendGrams : public TonlibQueryActor { } } -// if (!o_public_key) { // todo: (tolya-yanot) temporary disable msg comment encryption (The exchanges/payment services needs to read the comment of incoming messages). This will be uncommented when a general standard is developed. - return TonlibError::MessageEncryption("Get public key (in destination)"); -// } + // if (!o_public_key) { // todo: (tolya-yanot) temporary disable msg comment encryption (The exchanges/payment services needs to read the comment of incoming messages). This will be uncommented when a general standard is developed. + return TonlibError::MessageEncryption("Get public key (in destination)"); + // } auto addr = source_->get_address(); addr.bounceable = true; @@ -3868,8 +3853,8 @@ td::Result from_tonlib_api(tonlib_api::tvm_StackEntry& entry) { })); } -void deep_library_search(std::set& set, std::set& visited, - vm::Dictionary& libs, td::Ref cell, int depth) { +void deep_library_search(std::set& set, std::set& visited, vm::Dictionary& libs, + td::Ref cell, int depth) { if (depth <= 0 || set.size() >= 16 || visited.size() >= 256) { return; } @@ -3895,7 +3880,7 @@ void deep_library_search(std::set& set, std::set& v } return; } - for (unsigned int i=0; iget_refs_cnt(); i++) { + for (unsigned int i = 0; i < loaded_cell.data_cell->get_refs_cnt(); i++) { deep_library_search(set, visited, libs, loaded_cell.data_cell->get_ref(i), depth - 1); } } @@ -3919,36 +3904,38 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_getLibraries& request, return td::Status::OK(); } - client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(not_cached_hashes)), - promise.wrap([self=this, result_entries = std::move(result_entries)] - (td::Result> r_libraries) mutable - { - if (r_libraries.is_error()) { - LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string(); - } else { - auto libraries = r_libraries.move_as_ok(); - bool updated = false; - for (auto& lr : libraries->result_) { - auto contents = vm::std_boc_deserialize(lr->data_); - if (contents.is_ok() && contents.ok().not_null()) { - if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { - LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); - continue; + client_.send_query( + ton::lite_api::liteServer_getLibraries(std::move(not_cached_hashes)), + promise.wrap( + [self = this, result_entries = std::move(result_entries)]( + td::Result> r_libraries) mutable { + if (r_libraries.is_error()) { + LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string(); + } else { + auto libraries = r_libraries.move_as_ok(); + bool updated = false; + for (auto& lr : libraries->result_) { + auto contents = vm::std_boc_deserialize(lr->data_); + if (contents.is_ok() && contents.ok().not_null()) { + if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { + LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); + continue; + } + result_entries.push_back( + tonlib_api::make_object(lr->hash_, lr->data_.as_slice().str())); + self->libraries.set_ref(lr->hash_, contents.move_as_ok()); + updated = true; + LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); + } else { + LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); + } + if (updated) { + self->store_libs_to_disk(); + } + } } - result_entries.push_back(tonlib_api::make_object(lr->hash_, lr->data_.as_slice().str())); - self->libraries.set_ref(lr->hash_, contents.move_as_ok()); - updated = true; - LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); - } else { - LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); - } - if (updated) { - self->store_libs_to_disk(); - } - } - } - return tonlib_api::make_object(std::move(result_entries)); - })); + return tonlib_api::make_object(std::move(result_entries)); + })); return td::Status::OK(); } @@ -3975,8 +3962,8 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request, args.set_now(it->second->get_sync_time()); args.set_address(it->second->get_address()); - client_.with_last_config([self = this, smc = std::move(smc), args = std::move(args), promise = std::move(promise) - ](td::Result r_state) mutable { + client_.with_last_config([self = this, 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); @@ -3988,41 +3975,39 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request, std::vector libraryList{librarySet.begin(), librarySet.end()}; if (libraryList.size() > 0) { LOG(DEBUG) << "Requesting found libraries in code (" << libraryList.size() << ")"; - self->client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(libraryList)), - [self, smc = std::move(smc), args = std::move(args), promise = std::move(promise)] - (td::Result> r_libraries) mutable - { - if (r_libraries.is_error()) { - LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string(); - } else { - auto libraries = r_libraries.move_as_ok(); - bool updated = false; - for (auto& lr : libraries->result_) { - auto contents = vm::std_boc_deserialize(lr->data_); - if (contents.is_ok() && contents.ok().not_null()) { - if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { - LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); - continue; - } - self->libraries.set_ref(lr->hash_, contents.move_as_ok()); - updated = true; - LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); + self->client_.send_query( + ton::lite_api::liteServer_getLibraries(std::move(libraryList)), + [self, smc = std::move(smc), args = std::move(args), promise = std::move(promise)]( + td::Result> r_libraries) mutable { + if (r_libraries.is_error()) { + LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string(); } else { - LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); + auto libraries = r_libraries.move_as_ok(); + bool updated = false; + for (auto& lr : libraries->result_) { + auto contents = vm::std_boc_deserialize(lr->data_); + if (contents.is_ok() && contents.ok().not_null()) { + if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { + LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); + continue; + } + self->libraries.set_ref(lr->hash_, contents.move_as_ok()); + updated = true; + LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); + } else { + LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); + } + } + if (updated) { + self->store_libs_to_disk(); + } } - } - if (updated) { - self->store_libs_to_disk(); - } - } - self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); - }); - } - else { + self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); + }); + } else { self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); } - } - else { + } else { self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); } }); @@ -4031,7 +4016,6 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request, void TonlibClient::perform_smc_execution(td::Ref smc, ton::SmartContract::Args args, td::Promise>&& promise) { - args.set_libraries(libraries); auto res = smc->run_get_method(args); @@ -4046,45 +4030,46 @@ void TonlibClient::perform_smc_execution(td::Ref smc, ton::S td::Bits256 hash = res.missing_library; LOG(DEBUG) << "Requesting missing library: " << hash.to_hex(); std::vector req = {std::move(hash)}; - client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(req)), - [self = this, res = std::move(res), res_stack = std::move(res_stack), hash = std::move(hash), - smc = std::move(smc), args = std::move(args), promise = std::move(promise)] - (td::Result> r_libraries) mutable - { - if (r_libraries.is_error()) { - LOG(WARNING) << "cannot obtain missing library: " << r_libraries.move_as_error().to_string(); - promise.set_value(tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); - return; - } - bool found = false, updated = false; - auto libraries = r_libraries.move_as_ok(); - for (auto& lr : libraries->result_) { - auto contents = vm::std_boc_deserialize(lr->data_); - if (contents.is_ok() && contents.ok().not_null()) { - if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { - LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); - continue; + client_.send_query( + ton::lite_api::liteServer_getLibraries(std::move(req)), + [self = this, res = std::move(res), res_stack = std::move(res_stack), hash = std::move(hash), + smc = std::move(smc), args = std::move(args), promise = std::move(promise)]( + td::Result> r_libraries) mutable { + if (r_libraries.is_error()) { + LOG(WARNING) << "cannot obtain missing library: " << r_libraries.move_as_error().to_string(); + promise.set_value( + tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); + return; } - found |= (lr->hash_ == hash); - updated = true; - self->libraries.set_ref(lr->hash_, contents.move_as_ok()); - LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); - } else { - LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); - } - } - if (updated) { - self->store_libs_to_disk(); - } - if (!found) { - LOG(WARNING) << "cannot obtain library " << hash.to_hex() << ", it may not exist"; - promise.set_value(tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); - } else { - self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); - } - }); - } - else { + bool found = false, updated = false; + auto libraries = r_libraries.move_as_ok(); + for (auto& lr : libraries->result_) { + auto contents = vm::std_boc_deserialize(lr->data_); + if (contents.is_ok() && contents.ok().not_null()) { + if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) { + LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex(); + continue; + } + found |= (lr->hash_ == hash); + updated = true; + self->libraries.set_ref(lr->hash_, contents.move_as_ok()); + LOG(DEBUG) << "registered library " << lr->hash_.to_hex(); + } else { + LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex(); + } + } + if (updated) { + self->store_libs_to_disk(); + } + if (!found) { + LOG(WARNING) << "cannot obtain library " << hash.to_hex() << ", it may not exist"; + promise.set_value( + tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); + } else { + self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise)); + } + }); + } else { promise.set_value(tonlib_api::make_object(res.gas_used, std::move(res_stack), res.code)); } } @@ -4160,9 +4145,8 @@ void TonlibClient::do_dns_request(std::string name, td::Bits256 category, td::in td::optional block_id, block::StdAddress address, td::Promise>&& promise) { auto block_id_copy = block_id.copy(); - td::Promise new_promise = - promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category, ttl, std::move(block_id), - address); + td::Promise new_promise = promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, + category, ttl, std::move(block_id), address); if (0) { make_request(int_api::GetAccountState{address, std::move(block_id_copy), {}}, @@ -4200,8 +4184,7 @@ td::Status TonlibClient::do_request(const tonlib_api::dns_resolve& request, name += '.'; } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - do_dns_request(name, request.category_, request.ttl_, std::move(block_id), account_address, - std::move(promise)); + do_dns_request(name, request.category_, request.ttl_, std::move(block_id), account_address, std::move(promise)); return td::Status::OK(); } @@ -4639,15 +4622,15 @@ auto to_tonlib_api(const ton::lite_api::tonNode_blockIdExt& blk) -> tonlib_api_p auto to_tonlib_api(const ton::lite_api::tonNode_zeroStateIdExt& zeroStateId) -> tonlib_api_ptr { - return tonlib_api::make_object( //TODO check wether shard indeed 0??? + return tonlib_api::make_object( //TODO check wether shard indeed 0??? zeroStateId.workchain_, 0, 0, zeroStateId.root_hash_.as_slice().str(), zeroStateId.file_hash_.as_slice().str()); } auto to_lite_api(const tonlib_api::ton_blockIdExt& blk) -> td::Result> { TRY_RESULT(root_hash, to_bits256(blk.root_hash_, "blk.root_hash")) TRY_RESULT(file_hash, to_bits256(blk.file_hash_, "blk.file_hash")) - return ton::lite_api::make_object( - blk.workchain_, blk.shard_, blk.seqno_, root_hash, file_hash); + return ton::lite_api::make_object(blk.workchain_, blk.shard_, blk.seqno_, + root_hash, file_hash); } td::Result to_block_id(const tonlib_api::ton_blockIdExt& blk) { @@ -4657,33 +4640,34 @@ td::Result to_block_id(const tonlib_api::ton_blockIdExt& blk) { } td::Status TonlibClient::do_request(const tonlib_api::getConfigParam& request, - td::Promise>&& promise) { + td::Promise>&& promise) { TRY_RESULT(lite_block, to_lite_api(*request.id_)) auto block = create_block_id(std::move(lite_block)); auto param = request.param_; - std::vector params = { param }; + std::vector params = {param}; client_.send_query(ton::lite_api::liteServer_getConfigParams(0, std::move(lite_block), std::move(params)), promise.wrap([block, param](auto r_config) { - auto state = block::check_extract_state_proof(block, r_config->state_proof_.as_slice(), - r_config->config_proof_.as_slice()); - if (state.is_error()) { - LOG(ERROR) << "block::check_extract_state_proof failed: " << state.error(); - } - auto config = block::Config::extract_from_state(std::move(state.move_as_ok()), 0); - if (config.is_error()) { - LOG(ERROR) << "block::Config::extract_from_state failed: " << config.error(); - } - tonlib_api::configInfo config_result; - config_result.config_ = tonlib_api::make_object(to_bytes(config.move_as_ok()->get_config_param(param))); - return tonlib_api::make_object(std::move(config_result)); - })); + auto state = block::check_extract_state_proof(block, r_config->state_proof_.as_slice(), + r_config->config_proof_.as_slice()); + if (state.is_error()) { + LOG(ERROR) << "block::check_extract_state_proof failed: " << state.error(); + } + auto config = block::Config::extract_from_state(std::move(state.move_as_ok()), 0); + if (config.is_error()) { + LOG(ERROR) << "block::Config::extract_from_state failed: " << config.error(); + } + tonlib_api::configInfo config_result; + config_result.config_ = tonlib_api::make_object( + to_bytes(config.move_as_ok()->get_config_param(param))); + return tonlib_api::make_object(std::move(config_result)); + })); return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info, - td::Promise>&& promise) { + td::Promise>&& promise) { client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(), promise.wrap([](lite_api_ptr&& masterchain_info) { return tonlib_api::make_object( @@ -4728,133 +4712,126 @@ td::Status TonlibClient::do_request(const tonlib_api::blocks_getShards& request, return td::Status::OK(); } - td::Status TonlibClient::do_request(const tonlib_api::blocks_lookupBlock& request, - td::Promise>&& promise) { + td::Promise>&& promise) { client_.send_query(ton::lite_api::liteServer_lookupBlock( - request.mode_, - ton::lite_api::make_object((*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_), - (td::uint64)(request.lt_), - (td::uint32)(request.utime_)), + request.mode_, + ton::lite_api::make_object( + (*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_), + (td::uint64)(request.lt_), (td::uint32)(request.utime_)), promise.wrap([](lite_api_ptr&& header) { - const auto& id = header->id_; - return to_tonlib_api(*id); - //tonlib_api::make_object( - // ton::tonlib_api::ton_blockIdExt(id->workchain_, id->) - //); + const auto& id = header->id_; + return to_tonlib_api(*id); + //tonlib_api::make_object( + // ton::tonlib_api::ton_blockIdExt(id->workchain_, id->) + //); })); return td::Status::OK(); } auto to_tonlib_api(const ton::lite_api::liteServer_transactionId& txid) -> tonlib_api_ptr { - return tonlib_api::make_object( - txid.mode_, txid.account_.as_slice().str(), txid.lt_, txid.hash_.as_slice().str()); + return tonlib_api::make_object(txid.mode_, txid.account_.as_slice().str(), txid.lt_, + txid.hash_.as_slice().str()); } td::Status TonlibClient::do_request(const tonlib_api::blocks_getTransactions& request, - td::Promise>&& promise) { + td::Promise>&& promise) { TRY_RESULT(block, to_lite_api(*request.id_)) TRY_RESULT(account, to_bits256((*request.after_).account_, "account")); auto after = ton::lite_api::make_object(account, (*request.after_).lt_); - client_.send_query(ton::lite_api::liteServer_listBlockTransactions( - std::move(block), - request.mode_, - request.count_, - std::move(after), - false, - false), + client_.send_query(ton::lite_api::liteServer_listBlockTransactions(std::move(block), request.mode_, request.count_, + std::move(after), false, false), promise.wrap([](lite_api_ptr&& bTxes) { - const auto& id = bTxes->id_; - //for (auto id : ids) { - tonlib_api::blocks_transactions r; - r.id_ = to_tonlib_api(*id); - r.req_count_ = bTxes->req_count_; - r.incomplete_ = bTxes->incomplete_; - for (auto& id: bTxes->ids_) { - //tonlib_api::blocks_shortTxId txid = tonlib_api::blocks_shortTxId(id->mode_, id->account_.as_slice().str(), id->lt_, id->hash_.as_slice().str()); - //r.transactions_.push_back(txid); - r.transactions_.push_back(to_tonlib_api(*id)); - } - return tonlib_api::make_object(std::move(r)); + const auto& id = bTxes->id_; + //for (auto id : ids) { + tonlib_api::blocks_transactions r; + r.id_ = to_tonlib_api(*id); + r.req_count_ = bTxes->req_count_; + r.incomplete_ = bTxes->incomplete_; + for (auto& id : bTxes->ids_) { + //tonlib_api::blocks_shortTxId txid = tonlib_api::blocks_shortTxId(id->mode_, id->account_.as_slice().str(), id->lt_, id->hash_.as_slice().str()); + //r.transactions_.push_back(txid); + r.transactions_.push_back(to_tonlib_api(*id)); + } + return tonlib_api::make_object(std::move(r)); })); return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::blocks_getBlockHeader& request, - td::Promise>&& promise) { + td::Promise>&& promise) { TRY_RESULT(block, to_lite_api(*request.id_)) - client_.send_query(ton::lite_api::liteServer_getBlockHeader( - std::move(block), - 0xffff), - promise.wrap([](lite_api_ptr&& hdr) { - auto blk_id = ton::create_block_id(hdr->id_); - auto R = vm::std_boc_deserialize(std::move(hdr->header_proof_)); - tonlib_api::blocks_header header; - if (R.is_error()) { - LOG(WARNING) << "R.is_error() "; - } else { - auto root = R.move_as_ok(); - try { - ton::RootHash vhash{root->get_hash().bits()}; - auto virt_root = vm::MerkleProof::virtualize(root, 1); - if (virt_root.is_null()) { - LOG(WARNING) << "virt root is null"; - } else { - std::vector prev; - ton::BlockIdExt mc_blkid; - bool after_split; - auto res = block::unpack_block_prev_blk_ext(virt_root, blk_id, prev, mc_blkid, after_split); - if (res.is_error()) { - LOG(WARNING) << "res.is_error() "; - } else { - block::gen::Block::Record blk; - block::gen::BlockInfo::Record info; - if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info))) { - LOG(WARNING) << "unpack failed"; - } else { - header.id_ = to_tonlib_api(blk_id); - header.global_id_ = blk.global_id; - header.version_ = info.version; - header.flags_ = info.flags; - header.after_merge_ = info.after_merge; - header.after_split_ = info.after_split; - header.before_split_ = info.before_split; - header.want_merge_ = info.want_merge; - header.want_split_ = info.want_split; - header.validator_list_hash_short_ = info.gen_validator_list_hash_short; - header.catchain_seqno_ = info.gen_catchain_seqno; - header.min_ref_mc_seqno_ = info.min_ref_mc_seqno; - header.start_lt_ = info.start_lt; - header.end_lt_ = info.end_lt; - header.gen_utime_ = info.gen_utime; - header.is_key_block_ = info.key_block; - header.vert_seqno_ = info.vert_seq_no; - if(!info.not_master) { - header.prev_key_block_seqno_ = info.prev_key_block_seqno; - } - for (auto id : prev) { - header.prev_blocks_.push_back(to_tonlib_api(id)); - } - //if(info.before_split) { - //} else { - //} - return tonlib_api::make_object(std::move(header)); - } - } - } - } catch (vm::VmError& err) { - auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); - LOG(ERROR) << std::move(E); - } catch (vm::VmVirtError& err) { - auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); - LOG(ERROR) << std::move(E); - } catch (...) { - LOG(WARNING) << "exception catched "; - } - } - return tonlib_api::make_object(std::move(header)); - })); + client_.send_query( + ton::lite_api::liteServer_getBlockHeader(std::move(block), 0xffff), + promise.wrap([](lite_api_ptr&& hdr) { + auto blk_id = ton::create_block_id(hdr->id_); + auto R = vm::std_boc_deserialize(std::move(hdr->header_proof_)); + tonlib_api::blocks_header header; + if (R.is_error()) { + LOG(WARNING) << "R.is_error() "; + } else { + auto root = R.move_as_ok(); + try { + ton::RootHash vhash{root->get_hash().bits()}; + auto virt_root = vm::MerkleProof::virtualize(root, 1); + if (virt_root.is_null()) { + LOG(WARNING) << "virt root is null"; + } else { + std::vector prev; + ton::BlockIdExt mc_blkid; + bool after_split; + auto res = block::unpack_block_prev_blk_ext(virt_root, blk_id, prev, mc_blkid, after_split); + if (res.is_error()) { + LOG(WARNING) << "res.is_error() "; + } else { + block::gen::Block::Record blk; + block::gen::BlockInfo::Record info; + if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info))) { + LOG(WARNING) << "unpack failed"; + } else { + header.id_ = to_tonlib_api(blk_id); + header.global_id_ = blk.global_id; + header.version_ = info.version; + header.flags_ = info.flags; + header.after_merge_ = info.after_merge; + header.after_split_ = info.after_split; + header.before_split_ = info.before_split; + header.want_merge_ = info.want_merge; + header.want_split_ = info.want_split; + header.validator_list_hash_short_ = info.gen_validator_list_hash_short; + header.catchain_seqno_ = info.gen_catchain_seqno; + header.min_ref_mc_seqno_ = info.min_ref_mc_seqno; + header.start_lt_ = info.start_lt; + header.end_lt_ = info.end_lt; + header.gen_utime_ = info.gen_utime; + header.is_key_block_ = info.key_block; + header.vert_seqno_ = info.vert_seq_no; + if (!info.not_master) { + header.prev_key_block_seqno_ = info.prev_key_block_seqno; + } + for (auto id : prev) { + header.prev_blocks_.push_back(to_tonlib_api(id)); + } + //if(info.before_split) { + //} else { + //} + return tonlib_api::make_object(std::move(header)); + } + } + } + } catch (vm::VmError& err) { + auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); + LOG(ERROR) << std::move(E); + } catch (vm::VmVirtError& err) { + auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); + LOG(ERROR) << std::move(E); + } catch (...) { + LOG(WARNING) << "exception catched "; + } + } + return tonlib_api::make_object(std::move(header)); + })); return td::Status::OK(); } @@ -4890,15 +4867,17 @@ void TonlibClient::load_libs_from_disk() { if (r_dict.is_error()) { return; } - libraries = vm::Dictionary(vm::load_cell_slice(vm::CellBuilder().append_cellslice(vm::load_cell_slice( - r_dict.move_as_ok())).finalize()), 256); + libraries = vm::Dictionary( + vm::load_cell_slice(vm::CellBuilder().append_cellslice(vm::load_cell_slice(r_dict.move_as_ok())).finalize()), + 256); // int n = 0; for (auto&& lr : libraries) n++; LOG(DEBUG) << "loaded libraries from disk cache"; } void TonlibClient::store_libs_to_disk() { // NB: Dictionary.get_root_cell does not compute_root, and it is protected - kv_->set("tonlib.libcache", vm::std_boc_serialize(vm::CellBuilder().append_cellslice(libraries.get_root()) - .finalize()).move_as_ok().as_slice()); + kv_->set("tonlib.libcache", vm::std_boc_serialize(vm::CellBuilder().append_cellslice(libraries.get_root()).finalize()) + .move_as_ok() + .as_slice()); // int n = 0; for (auto&& lr : libraries) n++; LOG(DEBUG) << "stored libraries to disk cache"; } diff --git a/tonlib/tonlib/tonlib-cli.cpp b/tonlib/tonlib/tonlib-cli.cpp index 9430b672..1f4d8f5b 100644 --- a/tonlib/tonlib/tonlib-cli.cpp +++ b/tonlib/tonlib/tonlib-cli.cpp @@ -47,7 +47,7 @@ #include "tonlib/TonlibClient.h" #include "tonlib/TonlibCallback.h" -#include "tonlib/ExtClientRaw.h" +#include "tonlib/ExtClientLazy.h" #include "smc-envelope/ManualDns.h" #include "smc-envelope/PaymentChannel.h" @@ -62,7 +62,6 @@ #include #include #include "git.h" -#include "ExtClientMulti.h" using tonlib_api::make_object; @@ -224,7 +223,7 @@ class TonlibCli : public td::actor::Actor { if (options_.use_callbacks_for_network) { auto config = tonlib::Config::parse(options_.config).move_as_ok(); - class Callback : public tonlib::ExtClientRaw::Callback { + class Callback : public tonlib::ExtClientLazy::Callback { public: explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) { } @@ -232,28 +231,15 @@ class TonlibCli : public td::actor::Actor { private: td::actor::ActorShared<> parent_; }; - std::vector> full_servers; - int lite_client_id = -1, cnt = 0; - for (const auto& s : config.lite_clients) { - if (s.is_full) { - full_servers.emplace_back(s.adnl_id, s.address); - } - } - if (!full_servers.empty()) { - raw_client_ = tonlib::ExtClientRaw::create(std::move(full_servers), - td::make_unique(td::actor::actor_shared())); - } else { - CHECK(!config.lite_clients.empty()); - raw_client_ = td::actor::create_actor( - "ExtClientMulti", config.lite_clients, td::make_unique(td::actor::actor_shared())); - } ref_cnt_++; + raw_client_ = tonlib::ExtClientLazy::create(config.lite_servers, + td::make_unique(td::actor::actor_shared())); } auto config = !options_.config.empty() - ? make_object(options_.config, options_.name, - options_.use_callbacks_for_network, options_.ignore_cache) - : nullptr; + ? make_object(options_.config, options_.name, + options_.use_callbacks_for_network, options_.ignore_cache) + : nullptr; tonlib_api::object_ptr ks_type; if (options_.in_memory) { @@ -1544,9 +1530,8 @@ class TonlibCli : public td::actor::Actor { auto update = tonlib_api::move_object_as(std::move(result)); CHECK(!raw_client_.empty()); snd_bytes_ += update->data_.size(); - ton::ShardIdFull shard(update->workchain_, update->shard_); - send_closure(raw_client_, &tonlib::ExtClientRaw::send_query, "query", td::BufferSlice(update->data_), shard, - td::Timestamp::in(5), + send_closure(raw_client_, &tonlib::ExtClientLazy::send_query, "query", td::BufferSlice(update->data_), + ton::ShardIdFull(update->workchain_, update->shard_), td::Timestamp::in(5), [actor_id = actor_id(this), id = update->id_](td::Result res) { send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res)); });