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

Tonlib uses partial liteservers

This commit is contained in:
SpyCheese 2022-10-06 15:13:10 +03:00
parent 89771e2a2c
commit 0e428af807
17 changed files with 555 additions and 83 deletions

View file

@ -183,7 +183,7 @@ smc.runResult gas_used:int53 stack:vector<tvm.StackEntry> exit_code:int32 = smc.
smc.libraryEntry hash:int256 data:bytes = smc.LibraryEntry;
smc.libraryResult result:(vector smc.libraryEntry) = smc.LibraryResult;
updateSendLiteServerQuery id:int64 data:bytes = Update;
updateSendLiteServerQuery id:int64 data:bytes workchain:int32 shard:int64 = Update;
updateSyncState sync_state:SyncState = Update;
//@class LogStream @description Describes a stream to which tonlib internal log is written

Binary file not shown.

View file

@ -8,6 +8,7 @@ set(TONLIB_SOURCE
tonlib/Client.cpp
tonlib/Config.cpp
tonlib/ExtClient.cpp
tonlib/ExtClientMulti.cpp
tonlib/ExtClientLazy.cpp
tonlib/ExtClientOutbound.cpp
tonlib/KeyStorage.cpp
@ -22,7 +23,8 @@ set(TONLIB_SOURCE
tonlib/Client.h
tonlib/Config.h
tonlib/ExtClient.h
tonlib/ExtClientLazy.h
tonlib/ExtClientMulti.h
tonlib/ExtClientRaw.h
tonlib/ExtClientOutbound.h
tonlib/KeyStorage.h
tonlib/KeyValue.h

View file

@ -65,24 +65,21 @@ td::Result<Config> Config::parse(std::string str) {
if (json.type() != td::JsonValue::Type::Object) {
return td::Status::Error("Invalid config (1)");
}
//TRY_RESULT(main_type, td::get_json_object_string_field(json.get_object(), "@type", false));
//if (main_type != "config.global") {
//return td::Status::Error("Invalid config (3)");
//}
td::JsonArray empty_array;
TRY_RESULT(lite_clients_obj,
td::get_json_object_field(json.get_object(), "liteservers", td::JsonValue::Type::Array, false));
auto &lite_clients = lite_clients_obj.get_array();
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,
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;
Config res;
for (auto &value : lite_clients) {
auto parse_desc = [&](td::JsonValue& value) -> td::Result<Config::LiteClient> {
if (value.type() != td::JsonValue::Type::Object) {
return td::Status::Error("Invalid config (2)");
}
auto &object = value.get_object();
//TRY_RESULT(value_type, td::get_json_object_string_field(object, "@type", false));
//if (value_type != "liteclient.config.global") {
//return td::Status::Error("Invalid config (4)");
//}
TRY_RESULT(ip, td::get_json_object_long_field(object, "ip", false));
TRY_RESULT(port, td::get_json_object_int_field(object, "port", false));
@ -93,15 +90,41 @@ td::Result<Config> Config::parse(std::string str) {
auto &id = id_obj.get_object();
TRY_RESULT(id_type, td::get_json_object_string_field(id, "@type", false));
if (id_type != "pub.ed25519") {
return td::Status::Error("Invalid config (5)");
return td::Status::Error("Invalid config (3)");
}
TRY_RESULT(key_base64, td::get_json_object_string_field(id, "key", false));
TRY_RESULT(key, td::base64_decode(key_base64));
if (key.size() != 32) {
return td::Status::Error("Invalid config (6)");
return td::Status::Error("Invalid config (4)");
}
client.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin())));
return client;
};
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_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 &shard : shards_obj.get_array()) {
if (shard.type() != td::JsonValue::Type::Object) {
return td::Status::Error("Invalid config (5)");
}
auto &shard_obj = shard.get_object();
TRY_RESULT(workchain, td::get_json_object_int_field(shard_obj, "workchain", false));
TRY_RESULT(shard_id, td::get_json_object_long_field(shard_obj, "shard", false));
if (shard_id == 0) {
return td::Status::Error("Invalid config (6)");
}
client.shards.emplace_back(workchain, shard_id);
}
res.lite_clients.push_back(std::move(client));
}

View file

@ -26,6 +26,8 @@ struct Config {
struct LiteClient {
ton::adnl::AdnlNodeIdFull adnl_id;
td::IPAddress address;
bool is_full = true;
std::vector<ton::ShardIdFull> shards;
};
ton::BlockIdExt zero_state_id;
ton::BlockIdExt init_block_id;

View file

@ -54,7 +54,7 @@ void ExtClient::with_last_block(td::Promise<LastBlockState> 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<td::BufferSlice> promise) {
void ExtClient::send_raw_query(td::BufferSlice query, ton::ShardIdFull shard, td::Promise<td::BufferSlice> promise) {
auto query_id = queries_.create(std::move(promise));
td::Promise<td::BufferSlice> P = [query_id, self = this,
actor_id = td::actor::actor_id()](td::Result<td::BufferSlice> result) {
@ -62,10 +62,10 @@ void ExtClient::send_raw_query(td::BufferSlice query, td::Promise<td::BufferSlic
self->queries_.extract(query_id).set_result(std::move(result));
});
};
if (client_.adnl_ext_client_.empty()) {
if (client_.raw_client_.empty()) {
return P.set_error(TonlibError::NoLiteServers());
}
td::actor::send_closure(client_.adnl_ext_client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(query),
td::actor::send_closure(client_.raw_client_, &ExtClientRaw::send_query, "query", std::move(query), shard,
td::Timestamp::in(10.0), std::move(P));
}
} // namespace tonlib

View file

@ -28,9 +28,11 @@
#include "td/utils/Container.h"
#include "td/utils/Random.h"
#include "ExtClientLazy.h"
#include "ExtClientRaw.h"
#include "TonlibError.h"
#include "utils.h"
#include "QueryTraits.h"
#include "ExtClientRaw.h"
namespace tonlib {
class LastBlock;
@ -38,7 +40,7 @@ class LastConfig;
struct LastBlockState;
struct LastConfigState;
struct ExtClientRef {
td::actor::ActorId<ExtClientLazy> adnl_ext_client_;
td::actor::ActorId<ExtClientRaw> raw_client_;
td::actor::ActorId<LastBlock> last_block_actor_;
td::actor::ActorId<LastConfig> last_config_actor_;
};
@ -64,6 +66,7 @@ class ExtClient {
template <class QueryT>
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise, td::int32 seq_no = -1) {
ton::ShardIdFull shard = QueryTraits<QueryT>::get_shard(query);
auto raw_query = ton::serialize_tl_object(&query, true);
td::uint32 tag = td::Random::fast_uint32();
VLOG(lite_server) << "send query to liteserver: " << tag << " " << to_string(query);
@ -77,7 +80,7 @@ class ExtClient {
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
send_raw_query(
std::move(liteserver_query), [promise = std::move(promise), tag](td::Result<td::BufferSlice> R) mutable {
std::move(liteserver_query), shard, [promise = std::move(promise), tag](td::Result<td::BufferSlice> R) mutable {
auto res = [&]() -> td::Result<typename QueryT::ReturnType> {
TRY_RESULT_PREFIX(data, std::move(R), TonlibError::LiteServerNetwork());
auto r_error = ton::fetch_tl_object<ton::lite_api::liteServer_error>(data.clone(), true);
@ -96,8 +99,8 @@ class ExtClient {
}
void force_change_liteserver() {
if (!client_.adnl_ext_client_.empty()) {
td::actor::send_closure(client_.adnl_ext_client_, &ExtClientLazy::force_change_liteserver);
if (!client_.raw_client_.empty()) {
td::actor::send_closure(client_.raw_client_, &ExtClientRaw::force_change_liteserver);
}
}
@ -107,6 +110,6 @@ class ExtClient {
td::Container<td::Promise<LastBlockState>> last_block_queries_;
td::Container<td::Promise<LastConfigState>> last_config_queries_;
void send_raw_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise);
void send_raw_query(td::BufferSlice query, ton::ShardIdFull shard, td::Promise<td::BufferSlice> promise);
};
} // namespace tonlib

View file

@ -16,15 +16,15 @@
Copyright 2017-2020 Telegram Systems LLP
*/
#include "ExtClientLazy.h"
#include "ExtClientRaw.h"
#include "TonlibError.h"
#include "td/utils/Random.h"
namespace tonlib {
class ExtClientLazyImp : public ExtClientLazy {
class ExtClientLazyImp : public ExtClientRaw {
public:
ExtClientLazyImp(std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers,
td::unique_ptr<ExtClientLazy::Callback> callback)
td::unique_ptr<ExtClientRaw::Callback> callback)
: servers_(std::move(servers)), callback_(std::move(callback)) {
CHECK(!servers_.empty());
}
@ -34,15 +34,7 @@ class ExtClientLazyImp : public ExtClientLazy {
td::random_shuffle(td::as_mutable_span(servers_), rnd);
}
void check_ready(td::Promise<td::Unit> 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<td::BufferSlice> promise) override {
before_query();
if (client_.empty()) {
@ -109,7 +101,7 @@ class ExtClientLazyImp : public ExtClientLazy {
bool cur_server_bad_force_ = false;
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client_;
td::unique_ptr<ExtClientLazy::Callback> callback_;
td::unique_ptr<ExtClientRaw::Callback> callback_;
static constexpr double MAX_NO_QUERIES_TIMEOUT = 100;
bool is_closing_{false};
@ -140,12 +132,12 @@ class ExtClientLazyImp : public ExtClientLazy {
}
};
td::actor::ActorOwn<ExtClientLazy> ExtClientLazy::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback) {
td::actor::ActorOwn<ExtClientRaw> ExtClientRaw::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback) {
return create({std::make_pair(dst, dst_addr)}, std::move(callback));
}
td::actor::ActorOwn<ExtClientLazy> ExtClientLazy::create(
td::actor::ActorOwn<ExtClientRaw> ExtClientRaw::create(
std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers, td::unique_ptr<Callback> callback) {
return td::actor::create_actor<ExtClientLazyImp>("ExtClientLazy", std::move(servers), std::move(callback));
}

View file

@ -0,0 +1,169 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#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<Config::LiteClient> clients, td::unique_ptr<Callback> 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<td::BufferSlice> 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<td::BufferSlice> 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<td::BufferSlice> P = [SelfId = actor_id(this), idx = server_idx,
promise = std::move(promise)](td::Result<td::BufferSlice> 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<ExtClientMulti> 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<ExtClientMulti> 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<Callback>(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

View file

@ -0,0 +1,61 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "td/actor/actor.h"
#include "adnl/adnl-ext-client.h"
#include "Config.h"
#include "ExtClientRaw.h"
#include <map>
namespace tonlib {
class ExtClientMulti : public ExtClientRaw {
public:
ExtClientMulti(std::vector<Config::LiteClient> clients, td::unique_ptr<Callback> callback);
void start_up() override;
void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout,
td::Promise<td::BufferSlice> 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<td::BufferSlice> promise);
void start_client(int server_idx);
struct Server {
Config::LiteClient desc;
td::actor::ActorOwn<ton::adnl::AdnlExtClient> 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> callback_;
std::vector<Server> servers_;
int mc_server_idx_ = -1;
std::map<ton::ShardIdFull, int> shard_server_idx_cached_;
};
} // namespace tonlib

View file

@ -27,15 +27,11 @@ class ExtClientOutboundImp : public ExtClientOutbound {
ExtClientOutboundImp(td::unique_ptr<ExtClientOutbound::Callback> callback) : callback_(std::move(callback)) {
}
void check_ready(td::Promise<td::Unit> promise) override {
promise.set_error(td::Status::Error("Not supported"));
}
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<td::BufferSlice> promise) override {
auto query_id = next_query_id_++;
queries_[query_id] = std::move(promise);
callback_->request(query_id, data.as_slice().str());
callback_->request(query_id, data.as_slice().str(), shard);
}
void force_change_liteserver() override {

View file

@ -19,16 +19,16 @@
#pragma once
#include "td/actor/actor.h"
#include "ExtClientLazy.h"
#include "ExtClientRaw.h"
namespace tonlib {
class ExtClientOutbound : public ExtClientLazy {
class ExtClientOutbound : public ExtClientRaw {
public:
class Callback {
public:
virtual ~Callback() {
}
virtual void request(td::int64 id, std::string data) = 0;
virtual void request(td::int64 id, std::string data, ton::ShardIdFull shard) = 0;
};
virtual void on_query_result(td::int64 id, td::Result<td::BufferSlice> r_data, td::Promise<td::Unit> promise) = 0;
static td::actor::ActorOwn<ExtClientOutbound> create(td::unique_ptr<Callback> callback);

View file

@ -18,23 +18,24 @@
*/
#pragma once
#include "td/actor/actor.h"
#include "adnl/adnl-ext-client.h"
#include "ton/ton-types.h"
namespace tonlib {
class ExtClientLazy : public ton::adnl::AdnlExtClient {
class ExtClientRaw : public td::actor::Actor {
public:
class Callback {
public:
virtual ~Callback() {
}
virtual ~Callback() = default;
};
virtual void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout,
td::Promise<td::BufferSlice> promise) = 0;
virtual void force_change_liteserver() = 0;
static td::actor::ActorOwn<ExtClientLazy> create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback);
static td::actor::ActorOwn<ExtClientLazy> create(
static td::actor::ActorOwn<ExtClientRaw> create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback);
static td::actor::ActorOwn<ExtClientRaw> create(
std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers, td::unique_ptr<Callback> callback);
};

202
tonlib/tonlib/QueryTraits.h Normal file
View file

@ -0,0 +1,202 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "ton/ton-types.h"
#include "auto/tl/lite_api.h"
#include "vm/boc.h"
#include "vm/cellslice.h"
#include "block/block-auto.h"
#include "block/block-parse.h"
namespace tonlib {
template <typename Query>
struct QueryTraits {
static ton::ShardIdFull get_shard(const Query& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getMasterchainInfo> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getMasterchainInfo& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getMasterchainInfoExt> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getMasterchainInfoExt& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getTime> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getTime& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getVersion> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getVersion& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getBlock> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getBlock& q) {
return ton::ShardIdFull(q.id_->workchain_, q.id_->shard_);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getState> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getState& q) {
return ton::ShardIdFull(q.id_->workchain_, q.id_->shard_);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getBlockHeader> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getBlockHeader& q) {
return ton::ShardIdFull(q.id_->workchain_, q.id_->shard_);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_sendMessage> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_sendMessage& q) {
auto shard = [&]() -> td::Result<ton::ShardIdFull> {
vm::BagOfCells boc;
TRY_STATUS(boc.deserialize(q.body_.as_slice()));
if (boc.get_root_count() != 1) {
return td::Status::Error("external message is not a valid bag of cells");
}
block::gen::CommonMsgInfo::Record_ext_in_msg_info info;
if (!tlb::unpack_cell_inexact(boc.get_root_cell(), info)) {
return td::Status::Error("cannot unpack external message header");
}
auto dest_prefix = block::tlb::t_MsgAddressInt.get_prefix(info.dest);
if (!dest_prefix.is_valid()) {
return td::Status::Error("destination of an inbound external message is an invalid blockchain address");
}
return dest_prefix.as_leaf_shard();
}();
if (shard.is_error()) {
LOG(DEBUG) << "Failed to get shard from query liteServer.sendMessage: " << shard.move_as_error();
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
return shard.move_as_ok();
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getAccountState> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getAccountState& q) {
return ton::AccountIdPrefixFull(q.account_->workchain_, q.account_->id_.bits().get_uint(64)).as_leaf_shard();
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_runSmcMethod> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_runSmcMethod& q) {
return ton::AccountIdPrefixFull(q.account_->workchain_, q.account_->id_.bits().get_uint(64)).as_leaf_shard();
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getShardInfo> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getShardInfo& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getAllShardsInfo> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getAllShardsInfo& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getOneTransaction> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getOneTransaction& q) {
return ton::AccountIdPrefixFull(q.account_->workchain_, q.account_->id_.bits().get_uint(64)).as_leaf_shard();
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getTransactions> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getTransactions& q) {
return ton::AccountIdPrefixFull(q.account_->workchain_, q.account_->id_.bits().get_uint(64)).as_leaf_shard();
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_lookupBlock> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_lookupBlock& q) {
return ton::ShardIdFull(q.id_->workchain_, q.id_->shard_);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_listBlockTransactions> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_listBlockTransactions& q) {
return ton::ShardIdFull(q.id_->workchain_, q.id_->shard_);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getBlockProof> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getBlockProof& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getConfigAll> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getConfigAll& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getConfigParams> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getConfigParams& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getValidatorStats> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getValidatorStats& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
template<>
struct QueryTraits<ton::lite_api::liteServer_getLibraries> {
static ton::ShardIdFull get_shard(const ton::lite_api::liteServer_getLibraries& q) {
return ton::ShardIdFull(ton::masterchainId, ton::shardIdAll);
}
};
} // namespace tonlib

View file

@ -18,7 +18,7 @@
*/
#include "TonlibClient.h"
#include "tonlib/ExtClientLazy.h"
#include "tonlib/ExtClientRaw.h"
#include "tonlib/ExtClientOutbound.h"
#include "tonlib/LastBlock.h"
#include "tonlib/LastConfig.h"
@ -27,6 +27,7 @@
#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"
@ -1649,15 +1650,16 @@ void TonlibClient::hangup() {
ExtClientRef TonlibClient::get_client_ref() {
ExtClientRef ref;
ref.adnl_ext_client_ = raw_client_.get();
ref.raw_client_ = raw_client_.get();
ref.last_block_actor_ = raw_last_block_.get();
ref.last_config_actor_ = raw_last_config_.get();
return ref;
}
void TonlibClient::proxy_request(td::int64 query_id, std::string data) {
on_update(tonlib_api::make_object<tonlib_api::updateSendLiteServerQuery>(query_id, data));
void TonlibClient::proxy_request(td::int64 query_id, std::string data, ton::ShardIdFull shard) {
on_update(
tonlib_api::make_object<tonlib_api::updateSendLiteServerQuery>(query_id, data, shard.workchain, shard.shard));
}
void TonlibClient::init_ext_client() {
@ -1668,9 +1670,9 @@ void TonlibClient::init_ext_client() {
: parent_(std::move(parent)), config_generation_(config_generation) {
}
void request(td::int64 id, std::string data) override {
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));
std::move(data), shard);
}
private:
@ -1683,21 +1685,29 @@ void TonlibClient::init_ext_client() {
ext_client_outbound_ = client.get();
raw_client_ = std::move(client);
} else {
std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers;
for (const auto& s : config_.lite_clients) {
servers.emplace_back(s.adnl_id, s.address);
}
class Callback : public ExtClientLazy::Callback {
class Callback : public ExtClientRaw::Callback {
public:
explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
}
private:
td::actor::ActorShared<> parent_;
};
std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> 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<Callback>(td::actor::actor_shared()));
} else {
CHECK(!config_.lite_clients.empty());
raw_client_ = td::actor::create_actor<ExtClientMulti>("ExtClientMulti", config_.lite_clients,
td::make_unique<Callback>(td::actor::actor_shared()));
}
ext_client_outbound_ = {};
ref_cnt_++;
raw_client_ = ExtClientLazy::create(std::move(servers), td::make_unique<Callback>(td::actor::actor_shared()));
}
}
@ -2826,7 +2836,7 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getTransactionsV2& request,
auto actor_id = actor_id_++;
actors_[actor_id] = td::actor::create_actor<GetTransactionHistory>(
"GetTransactionHistory", client_.get_client(), account_address, lt, hash, count, actor_shared(this, actor_id),
"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));
}));

View file

@ -110,7 +110,7 @@ class TonlibClient : public td::actor::Actor {
vm::Dictionary libraries{256};
// network
td::actor::ActorOwn<ExtClientLazy> raw_client_;
td::actor::ActorOwn<ExtClientRaw> raw_client_;
td::actor::ActorId<ExtClientOutbound> ext_client_outbound_;
td::actor::ActorOwn<LastBlock> raw_last_block_;
td::actor::ActorOwn<LastConfig> raw_last_config_;
@ -372,7 +372,7 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(const tonlib_api::getConfigParam& request,
td::Promise<object_ptr<tonlib_api::configInfo>>&& promise);
void proxy_request(td::int64 query_id, std::string data);
void proxy_request(td::int64 query_id, std::string data, ton::ShardIdFull shard);
void load_libs_from_disk();
void store_libs_to_disk();

View file

@ -47,7 +47,7 @@
#include "tonlib/TonlibClient.h"
#include "tonlib/TonlibCallback.h"
#include "tonlib/ExtClientLazy.h"
#include "tonlib/ExtClientRaw.h"
#include "smc-envelope/ManualDns.h"
#include "smc-envelope/PaymentChannel.h"
@ -62,6 +62,7 @@
#include <iostream>
#include <map>
#include "git.h"
#include "ExtClientMulti.h"
using tonlib_api::make_object;
@ -174,7 +175,7 @@ class TonlibCli : public td::actor::Actor {
std::map<std::uint64_t, td::Promise<tonlib_api::object_ptr<tonlib_api::Object>>> query_handlers_;
td::actor::ActorOwn<tonlib::ExtClientLazy> raw_client_;
td::actor::ActorOwn<tonlib::ExtClientRaw> raw_client_;
bool is_closing_{false};
td::uint32 ref_cnt_{1};
@ -223,11 +224,7 @@ class TonlibCli : public td::actor::Actor {
if (options_.use_callbacks_for_network) {
auto config = tonlib::Config::parse(options_.config).move_as_ok();
auto lite_clients_size = config.lite_clients.size();
CHECK(lite_clients_size != 0);
auto lite_client_id = td::Random::fast(0, td::narrow_cast<int>(lite_clients_size) - 1);
auto& lite_client = config.lite_clients[lite_client_id];
class Callback : public tonlib::ExtClientLazy::Callback {
class Callback : public tonlib::ExtClientRaw::Callback {
public:
explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
}
@ -235,9 +232,22 @@ class TonlibCli : public td::actor::Actor {
private:
td::actor::ActorShared<> parent_;
};
std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> 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<Callback>(td::actor::actor_shared()));
} else {
CHECK(!config.lite_clients.empty());
raw_client_ = td::actor::create_actor<tonlib::ExtClientMulti>(
"ExtClientMulti", config.lite_clients, td::make_unique<Callback>(td::actor::actor_shared()));
}
ref_cnt_++;
raw_client_ = tonlib::ExtClientLazy::create(lite_client.adnl_id, lite_client.address,
td::make_unique<Callback>(td::actor::actor_shared()));
}
auto config = !options_.config.empty()
@ -1534,7 +1544,8 @@ class TonlibCli : public td::actor::Actor {
auto update = tonlib_api::move_object_as<tonlib_api::updateSendLiteServerQuery>(std::move(result));
CHECK(!raw_client_.empty());
snd_bytes_ += update->data_.size();
send_closure(raw_client_, &ton::adnl::AdnlExtClient::send_query, "query", td::BufferSlice(update->data_),
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),
[actor_id = actor_id(this), id = update->id_](td::Result<td::BufferSlice> res) {
send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res));