mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	Use partial liteservers in tonlib and lite-client
This commit is contained in:
		
							parent
							
								
									1ccf25d6b7
								
							
						
					
					
						commit
						2ea17ec03b
					
				
					 17 changed files with 891 additions and 974 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -57,8 +57,7 @@ class TestNode : public td::actor::Actor {
 | 
				
			||||||
    bool client_ready = false;
 | 
					    bool client_ready = false;
 | 
				
			||||||
    std::vector<td::Promise<td::Unit>> wait_client_ready;
 | 
					    std::vector<td::Promise<td::Unit>> wait_client_ready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int max_common_prefix(ton::ShardIdFull shard) const;
 | 
					    bool supports(ton::ShardIdFull shard) const;
 | 
				
			||||||
    bool supports_shard(ton::ShardIdFull shard) const;
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  std::vector<LiteServer> servers_;
 | 
					  std::vector<LiteServer> servers_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -352,9 +351,6 @@ class TestNode : public td::actor::Actor {
 | 
				
			||||||
  bool parse_shard_id(ton::ShardIdFull& shard);
 | 
					  bool parse_shard_id(ton::ShardIdFull& shard);
 | 
				
			||||||
  bool parse_block_id_ext(ton::BlockIdExt& blkid, bool allow_incomplete = false);
 | 
					  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_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<vm::StackEntry>& values);
 | 
					 | 
				
			||||||
  bool register_blkid(const ton::BlockIdExt& blkid);
 | 
					  bool register_blkid(const ton::BlockIdExt& blkid);
 | 
				
			||||||
  bool show_new_blkids(bool all = false);
 | 
					  bool show_new_blkids(bool all = false);
 | 
				
			||||||
  bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const;
 | 
					  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);
 | 
					  void parse_line(td::BufferSlice data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TestNode() {
 | 
					  TestNode() = default;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void run();
 | 
					  void run();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -8,7 +8,6 @@ set(TONLIB_SOURCE
 | 
				
			||||||
  tonlib/Client.cpp
 | 
					  tonlib/Client.cpp
 | 
				
			||||||
  tonlib/Config.cpp
 | 
					  tonlib/Config.cpp
 | 
				
			||||||
  tonlib/ExtClient.cpp
 | 
					  tonlib/ExtClient.cpp
 | 
				
			||||||
  tonlib/ExtClientMulti.cpp
 | 
					 | 
				
			||||||
  tonlib/ExtClientLazy.cpp
 | 
					  tonlib/ExtClientLazy.cpp
 | 
				
			||||||
  tonlib/ExtClientOutbound.cpp
 | 
					  tonlib/ExtClientOutbound.cpp
 | 
				
			||||||
  tonlib/KeyStorage.cpp
 | 
					  tonlib/KeyStorage.cpp
 | 
				
			||||||
| 
						 | 
					@ -24,8 +23,7 @@ set(TONLIB_SOURCE
 | 
				
			||||||
  tonlib/Client.h
 | 
					  tonlib/Client.h
 | 
				
			||||||
  tonlib/Config.h
 | 
					  tonlib/Config.h
 | 
				
			||||||
  tonlib/ExtClient.h
 | 
					  tonlib/ExtClient.h
 | 
				
			||||||
  tonlib/ExtClientMulti.h
 | 
					  tonlib/ExtClientLazy.h
 | 
				
			||||||
  tonlib/ExtClientRaw.h
 | 
					 | 
				
			||||||
  tonlib/ExtClientOutbound.h
 | 
					  tonlib/ExtClientOutbound.h
 | 
				
			||||||
  tonlib/KeyStorage.h
 | 
					  tonlib/KeyStorage.h
 | 
				
			||||||
  tonlib/KeyValue.h
 | 
					  tonlib/KeyValue.h
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,16 +66,16 @@ td::Result<Config> Config::parse(std::string str) {
 | 
				
			||||||
    return td::Status::Error("Invalid config (1)");
 | 
					    return td::Status::Error("Invalid config (1)");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  td::JsonArray empty_array;
 | 
					  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));
 | 
					             td::get_json_object_field(json.get_object(), "liteservers", td::JsonValue::Type::Array, true));
 | 
				
			||||||
  auto &lite_clients =
 | 
					  auto &lite_servers =
 | 
				
			||||||
      lite_clients_obj.type() == td::JsonValue::Type::Array ? lite_clients_obj.get_array() : empty_array;
 | 
					      lite_servers_obj.type() == td::JsonValue::Type::Array ? lite_servers_obj.get_array() : empty_array;
 | 
				
			||||||
  TRY_RESULT(lite_clients_v2_obj,
 | 
					  TRY_RESULT(lite_servers_v2_obj,
 | 
				
			||||||
             td::get_json_object_field(json.get_object(), "liteservers_v2", td::JsonValue::Type::Array, true));
 | 
					             td::get_json_object_field(json.get_object(), "liteservers_v2", td::JsonValue::Type::Array, true));
 | 
				
			||||||
  auto &lite_clients_v2 =
 | 
					  auto &lite_servers_v2 =
 | 
				
			||||||
      lite_clients_v2_obj.type() == td::JsonValue::Type::Array ? lite_clients_v2_obj.get_array() : empty_array;
 | 
					      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<Config::LiteClient> {
 | 
					  auto parse_desc = [&](td::JsonValue &value) -> td::Result<Config::LiteServer> {
 | 
				
			||||||
    if (value.type() != td::JsonValue::Type::Object) {
 | 
					    if (value.type() != td::JsonValue::Type::Object) {
 | 
				
			||||||
      return td::Status::Error("Invalid config (2)");
 | 
					      return td::Status::Error("Invalid config (2)");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -83,8 +83,8 @@ td::Result<Config> Config::parse(std::string str) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TRY_RESULT(ip, td::get_json_object_long_field(object, "ip", false));
 | 
					    TRY_RESULT(ip, td::get_json_object_long_field(object, "ip", false));
 | 
				
			||||||
    TRY_RESULT(port, td::get_json_object_int_field(object, "port", false));
 | 
					    TRY_RESULT(port, td::get_json_object_int_field(object, "port", false));
 | 
				
			||||||
    Config::LiteClient client;
 | 
					    Config::LiteServer server;
 | 
				
			||||||
    TRY_STATUS(client.address.init_host_port(td::IPAddress::ipv4_to_str(static_cast<td::int32>(ip)), port));
 | 
					    TRY_STATUS(server.address.init_host_port(td::IPAddress::ipv4_to_str(static_cast<td::int32>(ip)), port));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TRY_RESULT(id_obj, td::get_json_object_field(object, "id", td::JsonValue::Type::Object, false));
 | 
					    TRY_RESULT(id_obj, td::get_json_object_field(object, "id", td::JsonValue::Type::Object, false));
 | 
				
			||||||
    auto &id = id_obj.get_object();
 | 
					    auto &id = id_obj.get_object();
 | 
				
			||||||
| 
						 | 
					@ -98,20 +98,19 @@ td::Result<Config> Config::parse(std::string str) {
 | 
				
			||||||
      return td::Status::Error("Invalid config (4)");
 | 
					      return td::Status::Error("Invalid config (4)");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin())));
 | 
					    server.adnl_id = ton::adnl::AdnlNodeIdFull(ton::pubkeys::Ed25519(td::Bits256(td::Slice(key).ubegin())));
 | 
				
			||||||
    return client;
 | 
					    return server;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Config res;
 | 
					  Config res;
 | 
				
			||||||
  for (auto &value : lite_clients) {
 | 
					  for (auto &value : lite_servers) {
 | 
				
			||||||
    TRY_RESULT(client, parse_desc(value));
 | 
					    TRY_RESULT(server, parse_desc(value));
 | 
				
			||||||
    res.lite_clients.push_back(std::move(client));
 | 
					    res.lite_servers.push_back(std::move(server));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  for (auto &value : lite_clients_v2) {
 | 
					  for (auto &value : lite_servers_v2) {
 | 
				
			||||||
    TRY_RESULT(client, parse_desc(value));
 | 
					    TRY_RESULT(server, parse_desc(value));
 | 
				
			||||||
    client.is_full = false;
 | 
					    server.is_full = false;
 | 
				
			||||||
    TRY_RESULT(shards_obj,
 | 
					    TRY_RESULT(shards_obj, td::get_json_object_field(value.get_object(), "shards", td::JsonValue::Type::Array, false));
 | 
				
			||||||
               td::get_json_object_field(value.get_object(), "shards", td::JsonValue::Type::Array, false));
 | 
					 | 
				
			||||||
    for (auto &shard : shards_obj.get_array()) {
 | 
					    for (auto &shard : shards_obj.get_array()) {
 | 
				
			||||||
      if (shard.type() != td::JsonValue::Type::Object) {
 | 
					      if (shard.type() != td::JsonValue::Type::Object) {
 | 
				
			||||||
        return td::Status::Error("Invalid config (5)");
 | 
					        return td::Status::Error("Invalid config (5)");
 | 
				
			||||||
| 
						 | 
					@ -122,10 +121,10 @@ td::Result<Config> Config::parse(std::string str) {
 | 
				
			||||||
      if (shard_id == 0) {
 | 
					      if (shard_id == 0) {
 | 
				
			||||||
        return td::Status::Error("Invalid config (6)");
 | 
					        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,
 | 
					  TRY_RESULT(validator_obj,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace tonlib {
 | 
					namespace tonlib {
 | 
				
			||||||
struct Config {
 | 
					struct Config {
 | 
				
			||||||
  struct LiteClient {
 | 
					  struct LiteServer {
 | 
				
			||||||
    ton::adnl::AdnlNodeIdFull adnl_id;
 | 
					    ton::adnl::AdnlNodeIdFull adnl_id;
 | 
				
			||||||
    td::IPAddress address;
 | 
					    td::IPAddress address;
 | 
				
			||||||
    bool is_full = true;
 | 
					    bool is_full = true;
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ struct Config {
 | 
				
			||||||
  ton::BlockIdExt zero_state_id;
 | 
					  ton::BlockIdExt zero_state_id;
 | 
				
			||||||
  ton::BlockIdExt init_block_id;
 | 
					  ton::BlockIdExt init_block_id;
 | 
				
			||||||
  std::vector<ton::BlockIdExt> hardforks;
 | 
					  std::vector<ton::BlockIdExt> hardforks;
 | 
				
			||||||
  std::vector<LiteClient> lite_clients;
 | 
					  std::vector<LiteServer> lite_servers;
 | 
				
			||||||
  std::string name;
 | 
					  std::string name;
 | 
				
			||||||
  static td::Result<Config> parse(std::string str);
 | 
					  static td::Result<Config> parse(std::string str);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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));
 | 
					  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));
 | 
					  auto query_id = queries_.create(std::move(promise));
 | 
				
			||||||
  td::Promise<td::BufferSlice> P = [query_id, self = this,
 | 
					  td::Promise<td::BufferSlice> P = [query_id, self = this,
 | 
				
			||||||
                                    actor_id = td::actor::actor_id()](td::Result<td::BufferSlice> result) {
 | 
					                                    actor_id = td::actor::actor_id()](td::Result<td::BufferSlice> result) {
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ void ExtClient::send_raw_query(td::BufferSlice query, td::Promise<td::BufferSlic
 | 
				
			||||||
  if (client_.adnl_ext_client_.empty()) {
 | 
					  if (client_.adnl_ext_client_.empty()) {
 | 
				
			||||||
    return P.set_error(TonlibError::NoLiteServers());
 | 
					    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_.adnl_ext_client_, &ExtClientLazy::send_query, "query", std::move(query),
 | 
				
			||||||
                          td::Timestamp::in(10.0), std::move(P));
 | 
					                          shard, td::Timestamp::in(10.0), std::move(P));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}  // namespace tonlib
 | 
					}  // namespace tonlib
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,6 @@
 | 
				
			||||||
#include "TonlibError.h"
 | 
					#include "TonlibError.h"
 | 
				
			||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
#include "QueryTraits.h"
 | 
					#include "QueryTraits.h"
 | 
				
			||||||
#include "ExtClientRaw.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace tonlib {
 | 
					namespace tonlib {
 | 
				
			||||||
class LastBlock;
 | 
					class LastBlock;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,14 +19,26 @@
 | 
				
			||||||
#include "ExtClientLazy.h"
 | 
					#include "ExtClientLazy.h"
 | 
				
			||||||
#include "TonlibError.h"
 | 
					#include "TonlibError.h"
 | 
				
			||||||
#include "td/utils/Random.h"
 | 
					#include "td/utils/Random.h"
 | 
				
			||||||
 | 
					#include "ton/ton-shard.h"
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace tonlib {
 | 
					namespace tonlib {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExtClientLazyImp : public ExtClientLazy {
 | 
					class ExtClientLazyImpl : public ExtClientLazy {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  ExtClientLazyImp(std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers,
 | 
					  ExtClientLazyImpl(std::vector<Config::LiteServer> servers, td::unique_ptr<ExtClientLazy::Callback> callback)
 | 
				
			||||||
                   td::unique_ptr<ExtClientLazy::Callback> callback)
 | 
					      : callback_(std::move(callback)) {
 | 
				
			||||||
      : servers_(std::move(servers)), callback_(std::move(callback)) {
 | 
					    CHECK(!servers.empty());
 | 
				
			||||||
    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 {
 | 
					  void start_up() override {
 | 
				
			||||||
| 
						 | 
					@ -34,29 +46,21 @@ class ExtClientLazyImp : public ExtClientLazy {
 | 
				
			||||||
    td::random_shuffle(td::as_mutable_span(servers_), rnd);
 | 
					    td::random_shuffle(td::as_mutable_span(servers_), rnd);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void check_ready(td::Promise<td::Unit> promise) override {
 | 
					  void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout,
 | 
				
			||||||
    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,
 | 
					 | 
				
			||||||
                  td::Promise<td::BufferSlice> promise) override {
 | 
					                  td::Promise<td::BufferSlice> promise) override {
 | 
				
			||||||
    before_query();
 | 
					    TRY_RESULT_PROMISE(promise, server_idx, before_query(shard));
 | 
				
			||||||
    if (client_.empty()) {
 | 
					    auto& server = servers_[server_idx];
 | 
				
			||||||
      return promise.set_error(TonlibError::Cancelled());
 | 
					    CHECK(!server.client.empty());
 | 
				
			||||||
    }
 | 
					    alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT));
 | 
				
			||||||
    td::Promise<td::BufferSlice> P = [SelfId = actor_id(this), idx = cur_server_idx_,
 | 
					    td::Promise<td::BufferSlice> P = [SelfId = actor_id(this), server_idx,
 | 
				
			||||||
                                      promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
 | 
					                                      promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
 | 
				
			||||||
      if (R.is_error() &&
 | 
					      if (R.is_error() &&
 | 
				
			||||||
          (R.error().code() == ton::ErrorCode::timeout || R.error().code() == ton::ErrorCode::cancelled)) {
 | 
					          (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));
 | 
					      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));
 | 
					                 std::move(P));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,64 +68,124 @@ class ExtClientLazyImp : public ExtClientLazy {
 | 
				
			||||||
    if (servers_.size() == 1) {
 | 
					    if (servers_.size() == 1) {
 | 
				
			||||||
      return;
 | 
					      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:
 | 
					 private:
 | 
				
			||||||
  void before_query() {
 | 
					  td::Result<size_t> before_query(ton::ShardIdFull shard) {
 | 
				
			||||||
 | 
					    if (!shard.is_valid_ext()) {
 | 
				
			||||||
 | 
					      return td::Status::Error("Invalid shard");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (is_closing_) {
 | 
					    if (is_closing_) {
 | 
				
			||||||
      return;
 | 
					      return td::Status::Error("Client is closing");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    alarm_timestamp() = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT);
 | 
					    if (shard.pfx_len() > max_server_shard_depth_) {
 | 
				
			||||||
    if (cur_server_bad_) {
 | 
					      shard = shard_prefix(shard, max_server_shard_depth_);
 | 
				
			||||||
      ++cur_server_idx_;
 | 
					 | 
				
			||||||
    } else if (!client_.empty()) {
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    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 {
 | 
					    class Callback : public ton::adnl::AdnlExtClient::Callback {
 | 
				
			||||||
     public:
 | 
					     public:
 | 
				
			||||||
      explicit Callback(td::actor::ActorShared<ExtClientLazyImp> parent, size_t idx)
 | 
					      explicit Callback(td::actor::ActorShared<ExtClientLazyImpl> parent, size_t idx)
 | 
				
			||||||
          : parent_(std::move(parent)), idx_(idx) {
 | 
					          : parent_(std::move(parent)), idx_(idx) {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      void on_ready() override {
 | 
					      void on_ready() override {
 | 
				
			||||||
        td::actor::send_closure(parent_, &ExtClientLazyImp::set_server_bad, idx_, false);
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      void on_stop_ready() override {
 | 
					      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:
 | 
					     private:
 | 
				
			||||||
      td::actor::ActorShared<ExtClientLazyImp> parent_;
 | 
					      td::actor::ActorShared<ExtClientLazyImpl> parent_;
 | 
				
			||||||
      size_t idx_;
 | 
					      size_t idx_;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ref_cnt_++;
 | 
					    ref_cnt_++;
 | 
				
			||||||
    cur_server_bad_ = false;
 | 
					    if (shard.is_masterchain()) {
 | 
				
			||||||
    cur_server_bad_force_ = false;
 | 
					      LOG(INFO) << "Connecting to liteserver " << server.s.address << " for masterchain";
 | 
				
			||||||
    const auto& s = servers_[cur_server_idx_ % servers_.size()];
 | 
					    } else {
 | 
				
			||||||
    LOG(INFO) << "Connecting to liteserver " << s.second;
 | 
					      LOG(INFO) << "Connecting to liteserver " << server.s.address << " for shard " << shard.to_str();
 | 
				
			||||||
    client_ = ton::adnl::AdnlExtClient::create(
 | 
					    }
 | 
				
			||||||
        s.first, s.second, std::make_unique<Callback>(td::actor::actor_shared(this), cur_server_idx_));
 | 
					    server.client = ton::adnl::AdnlExtClient::create(
 | 
				
			||||||
 | 
					        server.s.adnl_id, server.s.address, std::make_unique<Callback>(td::actor::actor_shared(this), server_idx));
 | 
				
			||||||
 | 
					    alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT));
 | 
				
			||||||
 | 
					    return server_idx;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers_;
 | 
					  struct Server {
 | 
				
			||||||
  size_t cur_server_idx_ = 0;
 | 
					    Config::LiteServer s;
 | 
				
			||||||
  bool cur_server_bad_ = false;
 | 
					    td::actor::ActorOwn<ton::adnl::AdnlExtClient> client;
 | 
				
			||||||
  bool cur_server_bad_force_ = false;
 | 
					    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<Server> servers_;
 | 
				
			||||||
 | 
					  std::map<ton::ShardIdFull, size_t> shard_to_server_;
 | 
				
			||||||
 | 
					  int max_server_shard_depth_ = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  td::actor::ActorOwn<ton::adnl::AdnlExtClient> client_;
 | 
					 | 
				
			||||||
  td::unique_ptr<ExtClientLazy::Callback> callback_;
 | 
					  td::unique_ptr<ExtClientLazy::Callback> callback_;
 | 
				
			||||||
  static constexpr double MAX_NO_QUERIES_TIMEOUT = 100;
 | 
					  static constexpr double MAX_NO_QUERIES_TIMEOUT = 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool is_closing_{false};
 | 
					  bool is_closing_{false};
 | 
				
			||||||
  td::uint32 ref_cnt_{1};
 | 
					  td::uint32 ref_cnt_{1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_server_bad(size_t idx, bool bad) {
 | 
					  void alarm() override {
 | 
				
			||||||
    if (idx == cur_server_idx_ && servers_.size() > 1 && !cur_server_bad_force_) {
 | 
					    for (Server& server : servers_) {
 | 
				
			||||||
      cur_server_bad_ = bad;
 | 
					      if (server.timeout && server.timeout.is_in_past()) {
 | 
				
			||||||
 | 
					        server.client.reset();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void alarm() override {
 | 
					  void set_server_bad(size_t idx) {
 | 
				
			||||||
    client_.reset();
 | 
					    servers_[idx].client.reset();
 | 
				
			||||||
 | 
					    servers_[idx].timeout = td::Timestamp::never();
 | 
				
			||||||
 | 
					    servers_[idx].ignore_until = td::Timestamp::in(60.0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void hangup_shared() override {
 | 
					  void hangup_shared() override {
 | 
				
			||||||
    ref_cnt_--;
 | 
					    ref_cnt_--;
 | 
				
			||||||
| 
						 | 
					@ -130,7 +194,9 @@ class ExtClientLazyImp : public ExtClientLazy {
 | 
				
			||||||
  void hangup() override {
 | 
					  void hangup() override {
 | 
				
			||||||
    is_closing_ = true;
 | 
					    is_closing_ = true;
 | 
				
			||||||
    ref_cnt_--;
 | 
					    ref_cnt_--;
 | 
				
			||||||
    client_.reset();
 | 
					    for (Server& server : servers_) {
 | 
				
			||||||
 | 
					      server.client.reset();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    try_stop();
 | 
					    try_stop();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void try_stop() {
 | 
					  void try_stop() {
 | 
				
			||||||
| 
						 | 
					@ -142,11 +208,11 @@ class ExtClientLazyImp : public ExtClientLazy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::actor::ActorOwn<ExtClientLazy> ExtClientLazy::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
 | 
					td::actor::ActorOwn<ExtClientLazy> ExtClientLazy::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
 | 
				
			||||||
                                                         td::unique_ptr<Callback> callback) {
 | 
					                                                         td::unique_ptr<Callback> 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> ExtClientLazy::create(
 | 
					td::actor::ActorOwn<ExtClientLazy> ExtClientLazy::create(std::vector<Config::LiteServer> servers,
 | 
				
			||||||
    std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers, td::unique_ptr<Callback> callback) {
 | 
					                                                         td::unique_ptr<Callback> callback) {
 | 
				
			||||||
  return td::actor::create_actor<ExtClientLazyImp>("ExtClientLazy", std::move(servers), std::move(callback));
 | 
					  return td::actor::create_actor<ExtClientLazyImpl>("ExtClientLazy", std::move(servers), std::move(callback));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}  // namespace tonlib
 | 
					}  // namespace tonlib
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,23 +18,27 @@
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "td/actor/actor.h"
 | 
					#include "td/actor/actor.h"
 | 
				
			||||||
#include "adnl/adnl-ext-client.h"
 | 
					 | 
				
			||||||
#include "ton/ton-types.h"
 | 
					#include "ton/ton-types.h"
 | 
				
			||||||
 | 
					#include "adnl/adnl-ext-client.h"
 | 
				
			||||||
 | 
					#include "Config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace tonlib {
 | 
					namespace tonlib {
 | 
				
			||||||
class ExtClientLazy : public ton::adnl::AdnlExtClient {
 | 
					class ExtClientLazy : public td::actor::Actor {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  class Callback {
 | 
					  class Callback {
 | 
				
			||||||
   public:
 | 
					   public:
 | 
				
			||||||
    virtual ~Callback() = default;
 | 
					    virtual ~Callback() {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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;
 | 
					  virtual void force_change_liteserver() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static td::actor::ActorOwn<ExtClientLazy> create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
 | 
					  static td::actor::ActorOwn<ExtClientLazy> create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
 | 
				
			||||||
                                                   td::unique_ptr<Callback> callback);
 | 
					                                                   td::unique_ptr<Callback> callback);
 | 
				
			||||||
  static td::actor::ActorOwn<ExtClientLazy> create(
 | 
					  static td::actor::ActorOwn<ExtClientLazy> create(std::vector<Config::LiteServer> servers,
 | 
				
			||||||
      std::vector<std::pair<ton::adnl::AdnlNodeIdFull, td::IPAddress>> servers, td::unique_ptr<Callback> callback);
 | 
					                                                   td::unique_ptr<Callback> callback);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace tonlib
 | 
					}  // namespace tonlib
 | 
				
			||||||
| 
						 | 
					@ -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 <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
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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 <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
 | 
					 | 
				
			||||||
| 
						 | 
					@ -20,11 +20,12 @@
 | 
				
			||||||
#include "ExtClientOutbound.h"
 | 
					#include "ExtClientOutbound.h"
 | 
				
			||||||
#include "TonlibError.h"
 | 
					#include "TonlibError.h"
 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace tonlib {
 | 
					namespace tonlib {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExtClientOutboundImp : public ExtClientOutbound {
 | 
					class ExtClientOutboundImpl : public ExtClientOutbound {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  ExtClientOutboundImp(td::unique_ptr<ExtClientOutbound::Callback> callback) : callback_(std::move(callback)) {
 | 
					  ExtClientOutboundImpl(td::unique_ptr<ExtClientOutbound::Callback> callback) : callback_(std::move(callback)) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void send_query(std::string name, td::BufferSlice data, ton::ShardIdFull shard, td::Timestamp timeout,
 | 
					  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 force_change_liteserver() override {
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void on_query_result(td::int64 id, td::Result<td::BufferSlice> r_data, td::Promise<td::Unit> promise) override {
 | 
					  void on_query_result(td::int64 id, td::Result<td::BufferSlice> r_data, td::Promise<td::Unit> promise) override {
 | 
				
			||||||
    auto it = queries_.find(id);
 | 
					    auto it = queries_.find(id);
 | 
				
			||||||
    if (it == queries_.end()) {
 | 
					    if (it == queries_.end()) {
 | 
				
			||||||
| 
						 | 
					@ -65,6 +63,6 @@ class ExtClientOutboundImp : public ExtClientOutbound {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::actor::ActorOwn<ExtClientOutbound> ExtClientOutbound::create(td::unique_ptr<Callback> callback) {
 | 
					td::actor::ActorOwn<ExtClientOutbound> ExtClientOutbound::create(td::unique_ptr<Callback> callback) {
 | 
				
			||||||
  return td::actor::create_actor<ExtClientOutboundImp>("ExtClientOutbound", std::move(callback));
 | 
					  return td::actor::create_actor<ExtClientOutboundImpl>("ExtClientOutbound", std::move(callback));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}  // namespace tonlib
 | 
					}  // namespace tonlib
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ class ExtClientOutbound : public ExtClientLazy {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    virtual void request(td::int64 id, std::string data, ton::ShardIdFull shard) = 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;
 | 
					  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);
 | 
					  static td::actor::ActorOwn<ExtClientOutbound> create(td::unique_ptr<Callback> callback);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,6 @@
 | 
				
			||||||
#include "tonlib/keys/Mnemonic.h"
 | 
					#include "tonlib/keys/Mnemonic.h"
 | 
				
			||||||
#include "tonlib/keys/SimpleEncryption.h"
 | 
					#include "tonlib/keys/SimpleEncryption.h"
 | 
				
			||||||
#include "tonlib/TonlibError.h"
 | 
					#include "tonlib/TonlibError.h"
 | 
				
			||||||
#include "tonlib/ExtClientMulti.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "smc-envelope/GenericAccount.h"
 | 
					#include "smc-envelope/GenericAccount.h"
 | 
				
			||||||
#include "smc-envelope/ManualDns.h"
 | 
					#include "smc-envelope/ManualDns.h"
 | 
				
			||||||
| 
						 | 
					@ -863,7 +862,9 @@ class Query {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  td::Result<std::pair<Fee, std::vector<Fee>>> estimate_fees(bool ignore_chksig, std::shared_ptr<const block::Config>& cfg, vm::Dictionary& libraries) {
 | 
					  td::Result<std::pair<Fee, std::vector<Fee>>> estimate_fees(bool ignore_chksig,
 | 
				
			||||||
 | 
					                                                             std::shared_ptr<const block::Config>& cfg,
 | 
				
			||||||
 | 
					                                                             vm::Dictionary& libraries) {
 | 
				
			||||||
    // gas fees
 | 
					    // gas fees
 | 
				
			||||||
    bool is_masterchain = raw_.source->get_address().workchain == ton::masterchainId;
 | 
					    bool is_masterchain = raw_.source->get_address().workchain == ton::masterchainId;
 | 
				
			||||||
    TRY_RESULT(gas_limits_prices, cfg->get_gas_limits_prices(is_masterchain));
 | 
					    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_now(raw_.source->get_sync_time())
 | 
				
			||||||
                                                                        .set_ignore_chksig(ignore_chksig)
 | 
					                                                                        .set_ignore_chksig(ignore_chksig)
 | 
				
			||||||
                                                                        .set_address(raw_.source->get_address())
 | 
					                                                                        .set_address(raw_.source->get_address())
 | 
				
			||||||
                                                                        .set_config(cfg).set_libraries(libraries));
 | 
					                                                                        .set_config(cfg)
 | 
				
			||||||
 | 
					                                                                        .set_libraries(libraries));
 | 
				
			||||||
    td::int64 fwd_fee = 0;
 | 
					    td::int64 fwd_fee = 0;
 | 
				
			||||||
    if (res.success) {
 | 
					    if (res.success) {
 | 
				
			||||||
      LOG(DEBUG) << "output actions:\n"
 | 
					      LOG(DEBUG) << "output actions:\n"
 | 
				
			||||||
| 
						 | 
					@ -962,8 +964,9 @@ td::Result<td::int64> to_balance(td::Ref<vm::CellSlice> balance_ref) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GetTransactionHistory : public td::actor::Actor {
 | 
					class GetTransactionHistory : public td::actor::Actor {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  GetTransactionHistory(ExtClientRef ext_client_ref, block::StdAddress address, ton::LogicalTime lt, ton::Bits256 hash, td::int32 count,
 | 
					  GetTransactionHistory(ExtClientRef ext_client_ref, block::StdAddress address, ton::LogicalTime lt, ton::Bits256 hash,
 | 
				
			||||||
                        td::actor::ActorShared<> parent, td::Promise<block::TransactionList::Info> promise)
 | 
					                        td::int32 count, td::actor::ActorShared<> parent,
 | 
				
			||||||
 | 
					                        td::Promise<block::TransactionList::Info> promise)
 | 
				
			||||||
      : address_(std::move(address))
 | 
					      : address_(std::move(address))
 | 
				
			||||||
      , lt_(std::move(lt))
 | 
					      , lt_(std::move(lt))
 | 
				
			||||||
      , hash_(std::move(hash))
 | 
					      , 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 {
 | 
					      void request(td::int64 id, std::string data, ton::ShardIdFull shard) override {
 | 
				
			||||||
        send_closure(parent_, &TonlibClient::proxy_request, (id << 16) | (config_generation_ & 0xffff),
 | 
					        send_closure(parent_, &TonlibClient::proxy_request, (id << 16) | (config_generation_ & 0xffff), std::move(data),
 | 
				
			||||||
                     std::move(data), shard);
 | 
					                     shard);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     private:
 | 
					     private:
 | 
				
			||||||
| 
						 | 
					@ -1685,34 +1688,17 @@ void TonlibClient::init_ext_client() {
 | 
				
			||||||
    ext_client_outbound_ = client.get();
 | 
					    ext_client_outbound_ = client.get();
 | 
				
			||||||
    raw_client_ = std::move(client);
 | 
					    raw_client_ = std::move(client);
 | 
				
			||||||
  } else {
 | 
					  } 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 ExtClientLazy::Callback {
 | 
				
			||||||
     public:
 | 
					     public:
 | 
				
			||||||
      explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
 | 
					      explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     private:
 | 
					     private:
 | 
				
			||||||
      td::actor::ActorShared<> parent_;
 | 
					      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_ = {};
 | 
					    ext_client_outbound_ = {};
 | 
				
			||||||
    ref_cnt_++;
 | 
					    ref_cnt_++;
 | 
				
			||||||
    raw_client_ = ExtClientLazy::create(std::move(servers), td::make_unique<Callback>(td::actor::actor_shared()));
 | 
					    raw_client_ = ExtClientLazy::create(config_.lite_servers, td::make_unique<Callback>(td::actor::actor_shared()));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2360,7 +2346,7 @@ td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::o
 | 
				
			||||||
  TRY_RESULT_PREFIX(new_config, Config::parse(std::move(config->config_)),
 | 
					  TRY_RESULT_PREFIX(new_config, Config::parse(std::move(config->config_)),
 | 
				
			||||||
                    TonlibError::InvalidConfig("can't parse 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");
 | 
					    return TonlibError::InvalidConfig("no lite clients");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  td::optional<Config> o_master_config;
 | 
					  td::optional<Config> o_master_config;
 | 
				
			||||||
| 
						 | 
					@ -2427,8 +2413,7 @@ td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::o
 | 
				
			||||||
  state.vert_seqno = vert_seqno;
 | 
					  state.vert_seqno = vert_seqno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool user_defined_init_block = false;
 | 
					  bool user_defined_init_block = false;
 | 
				
			||||||
  if (new_config.init_block_id.is_valid() &&
 | 
					  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.id.seqno < new_config.init_block_id.id.seqno) {
 | 
					 | 
				
			||||||
    state.last_key_block_id = new_config.init_block_id;
 | 
					    state.last_key_block_id = new_config.init_block_id;
 | 
				
			||||||
    user_defined_init_block = true;
 | 
					    user_defined_init_block = true;
 | 
				
			||||||
    LOG(INFO) << "Use init block from USER config: " << new_config.init_block_id.to_str();
 | 
					    LOG(INFO) << "Use init block from USER config: " << new_config.init_block_id.to_str();
 | 
				
			||||||
| 
						 | 
					@ -2524,8 +2509,7 @@ td::Result<std::string> to_std_address(td::Ref<vm::CellSlice> cs) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
struct ToRawTransactions {
 | 
					struct ToRawTransactions {
 | 
				
			||||||
  explicit ToRawTransactions(td::optional<td::Ed25519::PrivateKey> private_key, bool try_decode_messages = true)
 | 
					  explicit ToRawTransactions(td::optional<td::Ed25519::PrivateKey> private_key, bool try_decode_messages = true)
 | 
				
			||||||
    : private_key_(std::move(private_key))
 | 
					      : private_key_(std::move(private_key)), try_decode_messages_(try_decode_messages) {
 | 
				
			||||||
    , try_decode_messages_(try_decode_messages) {
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  td::optional<td::Ed25519::PrivateKey> private_key_;
 | 
					  td::optional<td::Ed25519::PrivateKey> private_key_;
 | 
				
			||||||
| 
						 | 
					@ -2588,7 +2572,8 @@ struct ToRawTransactions {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!data) {
 | 
					      if (!data) {
 | 
				
			||||||
        data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(to_bytes(std::move(body_cell)), to_bytes(std::move(init_state_cell)));
 | 
					        data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(to_bytes(std::move(body_cell)),
 | 
				
			||||||
 | 
					                                                                to_bytes(std::move(init_state_cell)));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return data;
 | 
					      return data;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -2636,7 +2621,8 @@ struct ToRawTransactions {
 | 
				
			||||||
        auto created_lt = static_cast<td::int64>(msg_info.created_lt);
 | 
					        auto created_lt = static_cast<td::int64>(msg_info.created_lt);
 | 
				
			||||||
        return tonlib_api::make_object<tonlib_api::raw_message>(
 | 
					        return tonlib_api::make_object<tonlib_api::raw_message>(
 | 
				
			||||||
            tonlib_api::make_object<tonlib_api::accountAddress>(src),
 | 
					            tonlib_api::make_object<tonlib_api::accountAddress>(src),
 | 
				
			||||||
            tonlib_api::make_object<tonlib_api::accountAddress>(), 0, 0, 0, created_lt, std::move(body_hash), get_data(src));
 | 
					            tonlib_api::make_object<tonlib_api::accountAddress>(), 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<object_ptr<tonlib_api::raw_extMessageInfo>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::raw_extMessageInfo>>&& promise) {
 | 
				
			||||||
  TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body"));
 | 
					  TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body"));
 | 
				
			||||||
  auto hash = body->get_hash().as_slice().str();
 | 
					  auto hash = body->get_hash().as_slice().str();
 | 
				
			||||||
  make_request(int_api::SendMessage{std::move(body)},
 | 
					  make_request(int_api::SendMessage{std::move(body)}, promise.wrap([hash = std::move(hash)](auto res) {
 | 
				
			||||||
    promise.wrap([hash = std::move(hash)](auto res) {
 | 
					    return tonlib_api::make_object<tonlib_api::raw_extMessageInfo>(std::move(hash));
 | 
				
			||||||
      return tonlib_api::make_object<tonlib_api::raw_extMessageInfo>(std::move(hash));
 | 
					  }));
 | 
				
			||||||
    }));
 | 
					 | 
				
			||||||
  return td::Status::OK();
 | 
					  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::Status TonlibClient::do_request(tonlib_api::raw_getTransactionsV2& request,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::raw_transactions>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::raw_transactions>>&& promise) {
 | 
				
			||||||
  if (!request.account_address_) {
 | 
					  if (!request.account_address_) {
 | 
				
			||||||
    return TonlibError::EmptyField("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_++;
 | 
					  auto actor_id = actor_id_++;
 | 
				
			||||||
  actors_[actor_id] = td::actor::create_actor<GetTransactionHistory>(
 | 
					  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 {
 | 
					      promise.wrap(
 | 
				
			||||||
        return ToRawTransactions(std::move(private_key), try_decode_messages).to_raw_transactions(std::move(x));
 | 
					          [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();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3044,26 +3030,25 @@ class GenericCreateSendGrams : public TonlibQueryActor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  td::Result<ton::ManualDns::Action> to_dns_action(tonlib_api::dns_Action& action) {
 | 
					  td::Result<ton::ManualDns::Action> to_dns_action(tonlib_api::dns_Action& action) {
 | 
				
			||||||
    using R = td::Result<ton::ManualDns::Action>;
 | 
					    using R = td::Result<ton::ManualDns::Action>;
 | 
				
			||||||
    return downcast_call2<R>(action,
 | 
					    return downcast_call2<R>(
 | 
				
			||||||
                             td::overloaded(
 | 
					        action, td::overloaded(
 | 
				
			||||||
                                 [&](tonlib_api::dns_actionDeleteAll& del_all) -> R {
 | 
					                    [&](tonlib_api::dns_actionDeleteAll& del_all) -> R {
 | 
				
			||||||
                                   return ton::ManualDns::Action{"", td::Bits256::zero(), {}};
 | 
					                      return ton::ManualDns::Action{"", td::Bits256::zero(), {}};
 | 
				
			||||||
                                 },
 | 
					                    },
 | 
				
			||||||
                                 [&](tonlib_api::dns_actionDelete& del) -> R {
 | 
					                    [&](tonlib_api::dns_actionDelete& del) -> R {
 | 
				
			||||||
                                   return ton::ManualDns::Action{del.name_, del.category_, {}};
 | 
					                      return ton::ManualDns::Action{del.name_, del.category_, {}};
 | 
				
			||||||
                                 },
 | 
					                    },
 | 
				
			||||||
                                 [&](tonlib_api::dns_actionSet& set) -> R {
 | 
					                    [&](tonlib_api::dns_actionSet& set) -> R {
 | 
				
			||||||
                                   if (!set.entry_) {
 | 
					                      if (!set.entry_) {
 | 
				
			||||||
                                     return TonlibError::EmptyField("entry");
 | 
					                        return TonlibError::EmptyField("entry");
 | 
				
			||||||
                                   }
 | 
					                      }
 | 
				
			||||||
                                   if (!set.entry_->entry_) {
 | 
					                      if (!set.entry_->entry_) {
 | 
				
			||||||
                                     return TonlibError::EmptyField("entry.entry");
 | 
					                        return TonlibError::EmptyField("entry.entry");
 | 
				
			||||||
                                   }
 | 
					                      }
 | 
				
			||||||
                                   TRY_RESULT(entry_data, to_dns_entry_data(*set.entry_->entry_));
 | 
					                      TRY_RESULT(entry_data, to_dns_entry_data(*set.entry_->entry_));
 | 
				
			||||||
                                   TRY_RESULT(data_cell, entry_data.as_cell());
 | 
					                      TRY_RESULT(data_cell, entry_data.as_cell());
 | 
				
			||||||
                                   return ton::ManualDns::Action{set.entry_->name_, set.entry_->category_,
 | 
					                      return ton::ManualDns::Action{set.entry_->name_, set.entry_->category_, std::move(data_cell)};
 | 
				
			||||||
                                                                 std::move(data_cell)};
 | 
					                    }));
 | 
				
			||||||
                                 }));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  td::Status parse_action(tonlib_api::Action& action) {
 | 
					  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.
 | 
					        //        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)");
 | 
					        return TonlibError::MessageEncryption("Get public key (in destination)");
 | 
				
			||||||
//        }
 | 
					        //        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto addr = source_->get_address();
 | 
					        auto addr = source_->get_address();
 | 
				
			||||||
        addr.bounceable = true;
 | 
					        addr.bounceable = true;
 | 
				
			||||||
| 
						 | 
					@ -3868,8 +3853,8 @@ td::Result<vm::StackEntry> from_tonlib_api(tonlib_api::tvm_StackEntry& entry) {
 | 
				
			||||||
          }));
 | 
					          }));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void deep_library_search(std::set<td::Bits256>& set, std::set<vm::Cell::Hash>& visited,
 | 
					void deep_library_search(std::set<td::Bits256>& set, std::set<vm::Cell::Hash>& visited, vm::Dictionary& libs,
 | 
				
			||||||
                         vm::Dictionary& libs, td::Ref<vm::Cell> cell, int depth) {
 | 
					                         td::Ref<vm::Cell> cell, int depth) {
 | 
				
			||||||
  if (depth <= 0 || set.size() >= 16 || visited.size() >= 256) {
 | 
					  if (depth <= 0 || set.size() >= 16 || visited.size() >= 256) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -3895,7 +3880,7 @@ void deep_library_search(std::set<td::Bits256>& set, std::set<vm::Cell::Hash>& v
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  for (unsigned int i=0; i<loaded_cell.data_cell->get_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);
 | 
					    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();
 | 
					    return td::Status::OK();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(not_cached_hashes)),
 | 
					  client_.send_query(
 | 
				
			||||||
                     promise.wrap([self=this, result_entries = std::move(result_entries)]
 | 
					      ton::lite_api::liteServer_getLibraries(std::move(not_cached_hashes)),
 | 
				
			||||||
                                  (td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable
 | 
					      promise.wrap(
 | 
				
			||||||
    {
 | 
					          [self = this, result_entries = std::move(result_entries)](
 | 
				
			||||||
      if (r_libraries.is_error()) {
 | 
					              td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable {
 | 
				
			||||||
        LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string();
 | 
					            if (r_libraries.is_error()) {
 | 
				
			||||||
      } else {
 | 
					              LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string();
 | 
				
			||||||
        auto libraries = r_libraries.move_as_ok();
 | 
					            } else {
 | 
				
			||||||
        bool updated = false;
 | 
					              auto libraries = r_libraries.move_as_ok();
 | 
				
			||||||
        for (auto& lr : libraries->result_) {
 | 
					              bool updated = false;
 | 
				
			||||||
          auto contents = vm::std_boc_deserialize(lr->data_);
 | 
					              for (auto& lr : libraries->result_) {
 | 
				
			||||||
          if (contents.is_ok() && contents.ok().not_null()) {
 | 
					                auto contents = vm::std_boc_deserialize(lr->data_);
 | 
				
			||||||
            if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) {
 | 
					                if (contents.is_ok() && contents.ok().not_null()) {
 | 
				
			||||||
              LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex();
 | 
					                  if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) {
 | 
				
			||||||
              continue;
 | 
					                    LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex();
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                  result_entries.push_back(
 | 
				
			||||||
 | 
					                      tonlib_api::make_object<tonlib_api::smc_libraryEntry>(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<tonlib_api::smc_libraryEntry>(lr->hash_, lr->data_.as_slice().str()));
 | 
					            return tonlib_api::make_object<tonlib_api::smc_libraryResult>(std::move(result_entries));
 | 
				
			||||||
            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<tonlib_api::smc_libraryResult>(std::move(result_entries));
 | 
					 | 
				
			||||||
    }));
 | 
					 | 
				
			||||||
  return td::Status::OK();
 | 
					  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_now(it->second->get_sync_time());
 | 
				
			||||||
  args.set_address(it->second->get_address());
 | 
					  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)
 | 
					  client_.with_last_config([self = this, smc = std::move(smc), args = std::move(args),
 | 
				
			||||||
  ](td::Result<LastConfigState> r_state) mutable {
 | 
					                            promise = std::move(promise)](td::Result<LastConfigState> r_state) mutable {
 | 
				
			||||||
    TRY_RESULT_PROMISE(promise, state, std::move(r_state));
 | 
					    TRY_RESULT_PROMISE(promise, state, std::move(r_state));
 | 
				
			||||||
    args.set_config(state.config);
 | 
					    args.set_config(state.config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3988,41 +3975,39 @@ td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request,
 | 
				
			||||||
      std::vector<td::Bits256> libraryList{librarySet.begin(), librarySet.end()};
 | 
					      std::vector<td::Bits256> libraryList{librarySet.begin(), librarySet.end()};
 | 
				
			||||||
      if (libraryList.size() > 0) {
 | 
					      if (libraryList.size() > 0) {
 | 
				
			||||||
        LOG(DEBUG) << "Requesting found libraries in code (" << libraryList.size() << ")";
 | 
					        LOG(DEBUG) << "Requesting found libraries in code (" << libraryList.size() << ")";
 | 
				
			||||||
        self->client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(libraryList)),
 | 
					        self->client_.send_query(
 | 
				
			||||||
                    [self, smc = std::move(smc), args = std::move(args), promise = std::move(promise)]
 | 
					            ton::lite_api::liteServer_getLibraries(std::move(libraryList)),
 | 
				
			||||||
                    (td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable
 | 
					            [self, smc = std::move(smc), args = std::move(args), promise = std::move(promise)](
 | 
				
			||||||
        {
 | 
					                td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable {
 | 
				
			||||||
          if (r_libraries.is_error()) {
 | 
					              if (r_libraries.is_error()) {
 | 
				
			||||||
            LOG(WARNING) << "cannot obtain found libraries: " << r_libraries.move_as_error().to_string();
 | 
					                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();
 | 
					 | 
				
			||||||
              } else {
 | 
					              } 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();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					              self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise));
 | 
				
			||||||
            if (updated) {
 | 
					            });
 | 
				
			||||||
              self->store_libs_to_disk();
 | 
					      } 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));
 | 
					        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));
 | 
					      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<ton::SmartContract> smc, ton::SmartContract::Args args,
 | 
					void TonlibClient::perform_smc_execution(td::Ref<ton::SmartContract> smc, ton::SmartContract::Args args,
 | 
				
			||||||
                                         td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise) {
 | 
					                                         td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
  args.set_libraries(libraries);
 | 
					  args.set_libraries(libraries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto res = smc->run_get_method(args);
 | 
					  auto res = smc->run_get_method(args);
 | 
				
			||||||
| 
						 | 
					@ -4046,45 +4030,46 @@ void TonlibClient::perform_smc_execution(td::Ref<ton::SmartContract> smc, ton::S
 | 
				
			||||||
    td::Bits256 hash = res.missing_library;
 | 
					    td::Bits256 hash = res.missing_library;
 | 
				
			||||||
    LOG(DEBUG) << "Requesting missing library: " << hash.to_hex();
 | 
					    LOG(DEBUG) << "Requesting missing library: " << hash.to_hex();
 | 
				
			||||||
    std::vector<td::Bits256> req = {std::move(hash)};
 | 
					    std::vector<td::Bits256> req = {std::move(hash)};
 | 
				
			||||||
    client_.send_query(ton::lite_api::liteServer_getLibraries(std::move(req)),
 | 
					    client_.send_query(
 | 
				
			||||||
                [self = this, res = std::move(res), res_stack = std::move(res_stack), hash = std::move(hash),
 | 
					        ton::lite_api::liteServer_getLibraries(std::move(req)),
 | 
				
			||||||
                 smc = std::move(smc), args = std::move(args), promise = std::move(promise)]
 | 
					        [self = this, res = std::move(res), res_stack = std::move(res_stack), hash = std::move(hash),
 | 
				
			||||||
                (td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable
 | 
					         smc = std::move(smc), args = std::move(args), promise = std::move(promise)](
 | 
				
			||||||
    {
 | 
					            td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResult>> r_libraries) mutable {
 | 
				
			||||||
      if (r_libraries.is_error()) {
 | 
					          if (r_libraries.is_error()) {
 | 
				
			||||||
        LOG(WARNING) << "cannot obtain missing library: " << r_libraries.move_as_error().to_string();
 | 
					            LOG(WARNING) << "cannot obtain missing library: " << r_libraries.move_as_error().to_string();
 | 
				
			||||||
        promise.set_value(tonlib_api::make_object<tonlib_api::smc_runResult>(res.gas_used, std::move(res_stack), res.code));
 | 
					            promise.set_value(
 | 
				
			||||||
        return;
 | 
					                tonlib_api::make_object<tonlib_api::smc_runResult>(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;
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          found |= (lr->hash_ == hash);
 | 
					          bool found = false, updated = false;
 | 
				
			||||||
          updated = true;
 | 
					          auto libraries = r_libraries.move_as_ok();
 | 
				
			||||||
          self->libraries.set_ref(lr->hash_, contents.move_as_ok());
 | 
					          for (auto& lr : libraries->result_) {
 | 
				
			||||||
          LOG(DEBUG) << "registered library " << lr->hash_.to_hex();
 | 
					            auto contents = vm::std_boc_deserialize(lr->data_);
 | 
				
			||||||
        } else {
 | 
					            if (contents.is_ok() && contents.ok().not_null()) {
 | 
				
			||||||
          LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex();
 | 
					              if (contents.ok()->get_hash().bits().compare(lr->hash_.cbits(), 256)) {
 | 
				
			||||||
        }
 | 
					                LOG(WARNING) << "hash mismatch for library " << lr->hash_.to_hex();
 | 
				
			||||||
      }
 | 
					                continue;
 | 
				
			||||||
      if (updated) {
 | 
					              }
 | 
				
			||||||
        self->store_libs_to_disk();
 | 
					              found |= (lr->hash_ == hash);
 | 
				
			||||||
      }
 | 
					              updated = true;
 | 
				
			||||||
      if (!found) {
 | 
					              self->libraries.set_ref(lr->hash_, contents.move_as_ok());
 | 
				
			||||||
        LOG(WARNING) << "cannot obtain library " << hash.to_hex() << ", it may not exist";
 | 
					              LOG(DEBUG) << "registered library " << lr->hash_.to_hex();
 | 
				
			||||||
        promise.set_value(tonlib_api::make_object<tonlib_api::smc_runResult>(res.gas_used, std::move(res_stack), res.code));
 | 
					            } else {
 | 
				
			||||||
      } else {
 | 
					              LOG(WARNING) << "failed to deserialize library: " << lr->hash_.to_hex();
 | 
				
			||||||
        self->perform_smc_execution(std::move(smc), std::move(args), std::move(promise));
 | 
					            }
 | 
				
			||||||
      }
 | 
					          }
 | 
				
			||||||
    });
 | 
					          if (updated) {
 | 
				
			||||||
  }
 | 
					            self->store_libs_to_disk();
 | 
				
			||||||
  else {
 | 
					          }
 | 
				
			||||||
 | 
					          if (!found) {
 | 
				
			||||||
 | 
					            LOG(WARNING) << "cannot obtain library " << hash.to_hex() << ", it may not exist";
 | 
				
			||||||
 | 
					            promise.set_value(
 | 
				
			||||||
 | 
					                tonlib_api::make_object<tonlib_api::smc_runResult>(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<tonlib_api::smc_runResult>(res.gas_used, std::move(res_stack), res.code));
 | 
					    promise.set_value(tonlib_api::make_object<tonlib_api::smc_runResult>(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<ton::BlockIdExt> block_id, block::StdAddress address,
 | 
					                                  td::optional<ton::BlockIdExt> block_id, block::StdAddress address,
 | 
				
			||||||
                                  td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
 | 
					                                  td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise) {
 | 
				
			||||||
  auto block_id_copy = block_id.copy();
 | 
					  auto block_id_copy = block_id.copy();
 | 
				
			||||||
  td::Promise<DnsFinishData> new_promise =
 | 
					  td::Promise<DnsFinishData> new_promise = promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name,
 | 
				
			||||||
      promise.send_closure(actor_id(this), &TonlibClient::finish_dns_resolve, name, category, ttl, std::move(block_id),
 | 
					                                                                category, ttl, std::move(block_id), address);
 | 
				
			||||||
                           address);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (0) {
 | 
					  if (0) {
 | 
				
			||||||
    make_request(int_api::GetAccountState{address, std::move(block_id_copy), {}},
 | 
					    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 += '.';
 | 
					    name += '.';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_));
 | 
					  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,
 | 
					  do_dns_request(name, request.category_, request.ttl_, std::move(block_id), account_address, std::move(promise));
 | 
				
			||||||
                 std::move(promise));
 | 
					 | 
				
			||||||
  return td::Status::OK();
 | 
					  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)
 | 
					auto to_tonlib_api(const ton::lite_api::tonNode_zeroStateIdExt& zeroStateId)
 | 
				
			||||||
    -> tonlib_api_ptr<tonlib_api::ton_blockIdExt> {
 | 
					    -> tonlib_api_ptr<tonlib_api::ton_blockIdExt> {
 | 
				
			||||||
  return tonlib_api::make_object<tonlib_api::ton_blockIdExt>( //TODO check wether shard indeed 0???
 | 
					  return tonlib_api::make_object<tonlib_api::ton_blockIdExt>(  //TODO check wether shard indeed 0???
 | 
				
			||||||
      zeroStateId.workchain_, 0, 0, zeroStateId.root_hash_.as_slice().str(), zeroStateId.file_hash_.as_slice().str());
 | 
					      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<lite_api_ptr<ton::lite_api::tonNode_blockIdExt>> {
 | 
					auto to_lite_api(const tonlib_api::ton_blockIdExt& blk) -> td::Result<lite_api_ptr<ton::lite_api::tonNode_blockIdExt>> {
 | 
				
			||||||
  TRY_RESULT(root_hash, to_bits256(blk.root_hash_, "blk.root_hash"))
 | 
					  TRY_RESULT(root_hash, to_bits256(blk.root_hash_, "blk.root_hash"))
 | 
				
			||||||
  TRY_RESULT(file_hash, to_bits256(blk.file_hash_, "blk.file_hash"))
 | 
					  TRY_RESULT(file_hash, to_bits256(blk.file_hash_, "blk.file_hash"))
 | 
				
			||||||
  return ton::lite_api::make_object<ton::lite_api::tonNode_blockIdExt>(
 | 
					  return ton::lite_api::make_object<ton::lite_api::tonNode_blockIdExt>(blk.workchain_, blk.shard_, blk.seqno_,
 | 
				
			||||||
      blk.workchain_, blk.shard_, blk.seqno_, root_hash, file_hash);
 | 
					                                                                       root_hash, file_hash);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::Result<ton::BlockIdExt> to_block_id(const tonlib_api::ton_blockIdExt& blk) {
 | 
					td::Result<ton::BlockIdExt> to_block_id(const tonlib_api::ton_blockIdExt& blk) {
 | 
				
			||||||
| 
						 | 
					@ -4657,33 +4640,34 @@ td::Result<ton::BlockIdExt> to_block_id(const tonlib_api::ton_blockIdExt& blk) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::Status TonlibClient::do_request(const tonlib_api::getConfigParam& request,
 | 
					td::Status TonlibClient::do_request(const tonlib_api::getConfigParam& request,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::configInfo>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::configInfo>>&& promise) {
 | 
				
			||||||
  TRY_RESULT(lite_block, to_lite_api(*request.id_))
 | 
					  TRY_RESULT(lite_block, to_lite_api(*request.id_))
 | 
				
			||||||
  auto block = create_block_id(std::move(lite_block));
 | 
					  auto block = create_block_id(std::move(lite_block));
 | 
				
			||||||
  auto param = request.param_;
 | 
					  auto param = request.param_;
 | 
				
			||||||
  std::vector<int32_t> params = { param };
 | 
					  std::vector<int32_t> params = {param};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_getConfigParams(0, std::move(lite_block), std::move(params)),
 | 
					  client_.send_query(ton::lite_api::liteServer_getConfigParams(0, std::move(lite_block), std::move(params)),
 | 
				
			||||||
                     promise.wrap([block, param](auto r_config) {
 | 
					                     promise.wrap([block, param](auto r_config) {
 | 
				
			||||||
    auto state = block::check_extract_state_proof(block, r_config->state_proof_.as_slice(),
 | 
					                       auto state = block::check_extract_state_proof(block, r_config->state_proof_.as_slice(),
 | 
				
			||||||
                                                  r_config->config_proof_.as_slice());
 | 
					                                                                     r_config->config_proof_.as_slice());
 | 
				
			||||||
    if (state.is_error()) {
 | 
					                       if (state.is_error()) {
 | 
				
			||||||
      LOG(ERROR) << "block::check_extract_state_proof failed: " << state.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);
 | 
					                       auto config = block::Config::extract_from_state(std::move(state.move_as_ok()), 0);
 | 
				
			||||||
    if (config.is_error()) {
 | 
					                       if (config.is_error()) {
 | 
				
			||||||
      LOG(ERROR) << "block::Config::extract_from_state failed: " << config.error();
 | 
					                         LOG(ERROR) << "block::Config::extract_from_state failed: " << config.error();
 | 
				
			||||||
    }
 | 
					                       }
 | 
				
			||||||
    tonlib_api::configInfo config_result;
 | 
					                       tonlib_api::configInfo config_result;
 | 
				
			||||||
    config_result.config_ = tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(config.move_as_ok()->get_config_param(param)));
 | 
					                       config_result.config_ = tonlib_api::make_object<tonlib_api::tvm_cell>(
 | 
				
			||||||
    return tonlib_api::make_object<tonlib_api::configInfo>(std::move(config_result));
 | 
					                           to_bytes(config.move_as_ok()->get_config_param(param)));
 | 
				
			||||||
  }));
 | 
					                       return tonlib_api::make_object<tonlib_api::configInfo>(std::move(config_result));
 | 
				
			||||||
 | 
					                     }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return td::Status::OK();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::Status TonlibClient::do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info,
 | 
					td::Status TonlibClient::do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::blocks_masterchainInfo>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::blocks_masterchainInfo>>&& promise) {
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
 | 
					  client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
 | 
				
			||||||
                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_masterchainInfo>&& masterchain_info) {
 | 
					                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_masterchainInfo>&& masterchain_info) {
 | 
				
			||||||
                       return tonlib_api::make_object<tonlib_api::blocks_masterchainInfo>(
 | 
					                       return tonlib_api::make_object<tonlib_api::blocks_masterchainInfo>(
 | 
				
			||||||
| 
						 | 
					@ -4728,133 +4712,126 @@ td::Status TonlibClient::do_request(const tonlib_api::blocks_getShards& request,
 | 
				
			||||||
  return td::Status::OK();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
td::Status TonlibClient::do_request(const tonlib_api::blocks_lookupBlock& request,
 | 
					td::Status TonlibClient::do_request(const tonlib_api::blocks_lookupBlock& request,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::ton_blockIdExt>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::ton_blockIdExt>>&& promise) {
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_lookupBlock(
 | 
					  client_.send_query(ton::lite_api::liteServer_lookupBlock(
 | 
				
			||||||
                       request.mode_,
 | 
					                         request.mode_,
 | 
				
			||||||
                       ton::lite_api::make_object<ton::lite_api::tonNode_blockId>((*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_),
 | 
					                         ton::lite_api::make_object<ton::lite_api::tonNode_blockId>(
 | 
				
			||||||
                       (td::uint64)(request.lt_),
 | 
					                             (*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_),
 | 
				
			||||||
                       (td::uint32)(request.utime_)),
 | 
					                         (td::uint64)(request.lt_), (td::uint32)(request.utime_)),
 | 
				
			||||||
                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockHeader>&& header) {
 | 
					                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockHeader>&& header) {
 | 
				
			||||||
                        const auto& id = header->id_;
 | 
					                       const auto& id = header->id_;
 | 
				
			||||||
                        return to_tonlib_api(*id);
 | 
					                       return to_tonlib_api(*id);
 | 
				
			||||||
                        //tonlib_api::make_object<tonlib_api::ton_blockIdExt>(
 | 
					                       //tonlib_api::make_object<tonlib_api::ton_blockIdExt>(
 | 
				
			||||||
                        //  ton::tonlib_api::ton_blockIdExt(id->workchain_, id->)
 | 
					                       //  ton::tonlib_api::ton_blockIdExt(id->workchain_, id->)
 | 
				
			||||||
                        //);
 | 
					                       //);
 | 
				
			||||||
                     }));
 | 
					                     }));
 | 
				
			||||||
  return td::Status::OK();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto to_tonlib_api(const ton::lite_api::liteServer_transactionId& txid)
 | 
					auto to_tonlib_api(const ton::lite_api::liteServer_transactionId& txid)
 | 
				
			||||||
    -> tonlib_api_ptr<tonlib_api::blocks_shortTxId> {
 | 
					    -> tonlib_api_ptr<tonlib_api::blocks_shortTxId> {
 | 
				
			||||||
  return tonlib_api::make_object<tonlib_api::blocks_shortTxId>(
 | 
					  return tonlib_api::make_object<tonlib_api::blocks_shortTxId>(txid.mode_, txid.account_.as_slice().str(), txid.lt_,
 | 
				
			||||||
      txid.mode_, txid.account_.as_slice().str(), txid.lt_, txid.hash_.as_slice().str());
 | 
					                                                               txid.hash_.as_slice().str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::Status TonlibClient::do_request(const tonlib_api::blocks_getTransactions& request,
 | 
					td::Status TonlibClient::do_request(const tonlib_api::blocks_getTransactions& request,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::blocks_transactions>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::blocks_transactions>>&& promise) {
 | 
				
			||||||
  TRY_RESULT(block, to_lite_api(*request.id_))
 | 
					  TRY_RESULT(block, to_lite_api(*request.id_))
 | 
				
			||||||
  TRY_RESULT(account, to_bits256((*request.after_).account_, "account"));
 | 
					  TRY_RESULT(account, to_bits256((*request.after_).account_, "account"));
 | 
				
			||||||
  auto after = ton::lite_api::make_object<ton::lite_api::liteServer_transactionId3>(account, (*request.after_).lt_);
 | 
					  auto after = ton::lite_api::make_object<ton::lite_api::liteServer_transactionId3>(account, (*request.after_).lt_);
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_listBlockTransactions(
 | 
					  client_.send_query(ton::lite_api::liteServer_listBlockTransactions(std::move(block), request.mode_, request.count_,
 | 
				
			||||||
                       std::move(block),
 | 
					                                                                     std::move(after), false, false),
 | 
				
			||||||
                       request.mode_,
 | 
					 | 
				
			||||||
                       request.count_,
 | 
					 | 
				
			||||||
                       std::move(after),
 | 
					 | 
				
			||||||
                       false,
 | 
					 | 
				
			||||||
                       false),
 | 
					 | 
				
			||||||
                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockTransactions>&& bTxes) {
 | 
					                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockTransactions>&& bTxes) {
 | 
				
			||||||
                        const auto& id = bTxes->id_;
 | 
					                       const auto& id = bTxes->id_;
 | 
				
			||||||
                        //for (auto id : ids) {
 | 
					                       //for (auto id : ids) {
 | 
				
			||||||
                        tonlib_api::blocks_transactions r;
 | 
					                       tonlib_api::blocks_transactions r;
 | 
				
			||||||
                        r.id_ = to_tonlib_api(*id);
 | 
					                       r.id_ = to_tonlib_api(*id);
 | 
				
			||||||
                        r.req_count_ = bTxes->req_count_;
 | 
					                       r.req_count_ = bTxes->req_count_;
 | 
				
			||||||
                        r.incomplete_ = bTxes->incomplete_;
 | 
					                       r.incomplete_ = bTxes->incomplete_;
 | 
				
			||||||
                        for (auto& id: bTxes->ids_) {
 | 
					                       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());
 | 
					                         //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(txid);
 | 
				
			||||||
                          r.transactions_.push_back(to_tonlib_api(*id));
 | 
					                         r.transactions_.push_back(to_tonlib_api(*id));
 | 
				
			||||||
                        }
 | 
					                       }
 | 
				
			||||||
                        return tonlib_api::make_object<tonlib_api::blocks_transactions>(std::move(r));
 | 
					                       return tonlib_api::make_object<tonlib_api::blocks_transactions>(std::move(r));
 | 
				
			||||||
                     }));
 | 
					                     }));
 | 
				
			||||||
  return td::Status::OK();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
td::Status TonlibClient::do_request(const tonlib_api::blocks_getBlockHeader& request,
 | 
					td::Status TonlibClient::do_request(const tonlib_api::blocks_getBlockHeader& request,
 | 
				
			||||||
                        td::Promise<object_ptr<tonlib_api::blocks_header>>&& promise) {
 | 
					                                    td::Promise<object_ptr<tonlib_api::blocks_header>>&& promise) {
 | 
				
			||||||
  TRY_RESULT(block, to_lite_api(*request.id_))
 | 
					  TRY_RESULT(block, to_lite_api(*request.id_))
 | 
				
			||||||
  client_.send_query(ton::lite_api::liteServer_getBlockHeader(
 | 
					  client_.send_query(
 | 
				
			||||||
                       std::move(block),
 | 
					      ton::lite_api::liteServer_getBlockHeader(std::move(block), 0xffff),
 | 
				
			||||||
                       0xffff),
 | 
					      promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockHeader>&& hdr) {
 | 
				
			||||||
                     promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockHeader>&& hdr) {
 | 
					        auto blk_id = ton::create_block_id(hdr->id_);
 | 
				
			||||||
                       auto blk_id = ton::create_block_id(hdr->id_);
 | 
					        auto R = vm::std_boc_deserialize(std::move(hdr->header_proof_));
 | 
				
			||||||
                       auto R = vm::std_boc_deserialize(std::move(hdr->header_proof_));
 | 
					        tonlib_api::blocks_header header;
 | 
				
			||||||
                       tonlib_api::blocks_header header;
 | 
					        if (R.is_error()) {
 | 
				
			||||||
                       if (R.is_error()) {
 | 
					          LOG(WARNING) << "R.is_error() ";
 | 
				
			||||||
                            LOG(WARNING) << "R.is_error() ";
 | 
					        } else {
 | 
				
			||||||
                       } else {
 | 
					          auto root = R.move_as_ok();
 | 
				
			||||||
                          auto root = R.move_as_ok();
 | 
					          try {
 | 
				
			||||||
                          try {
 | 
					            ton::RootHash vhash{root->get_hash().bits()};
 | 
				
			||||||
                            ton::RootHash vhash{root->get_hash().bits()};
 | 
					            auto virt_root = vm::MerkleProof::virtualize(root, 1);
 | 
				
			||||||
                            auto virt_root = vm::MerkleProof::virtualize(root, 1);
 | 
					            if (virt_root.is_null()) {
 | 
				
			||||||
                            if (virt_root.is_null()) {
 | 
					              LOG(WARNING) << "virt root is null";
 | 
				
			||||||
                              LOG(WARNING) << "virt root is null";
 | 
					            } else {
 | 
				
			||||||
                            } else {
 | 
					              std::vector<ton::BlockIdExt> prev;
 | 
				
			||||||
                              std::vector<ton::BlockIdExt> prev;
 | 
					              ton::BlockIdExt mc_blkid;
 | 
				
			||||||
                              ton::BlockIdExt mc_blkid;
 | 
					              bool after_split;
 | 
				
			||||||
                              bool after_split;
 | 
					              auto res = block::unpack_block_prev_blk_ext(virt_root, blk_id, prev, mc_blkid, after_split);
 | 
				
			||||||
                              auto res = block::unpack_block_prev_blk_ext(virt_root, blk_id, prev, mc_blkid, after_split);
 | 
					              if (res.is_error()) {
 | 
				
			||||||
                              if (res.is_error()) {
 | 
					                LOG(WARNING) << "res.is_error() ";
 | 
				
			||||||
                                LOG(WARNING) << "res.is_error() ";
 | 
					              } else {
 | 
				
			||||||
                              } else {
 | 
					                block::gen::Block::Record blk;
 | 
				
			||||||
                                block::gen::Block::Record blk;
 | 
					                block::gen::BlockInfo::Record info;
 | 
				
			||||||
                                block::gen::BlockInfo::Record info;
 | 
					                if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info))) {
 | 
				
			||||||
                                if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info))) {
 | 
					                  LOG(WARNING) << "unpack failed";
 | 
				
			||||||
                                  LOG(WARNING) << "unpack failed";
 | 
					                } else {
 | 
				
			||||||
                                } else {
 | 
					                  header.id_ = to_tonlib_api(blk_id);
 | 
				
			||||||
                                  header.id_ = to_tonlib_api(blk_id);
 | 
					                  header.global_id_ = blk.global_id;
 | 
				
			||||||
                                  header.global_id_ = blk.global_id;
 | 
					                  header.version_ = info.version;
 | 
				
			||||||
                                  header.version_ = info.version;
 | 
					                  header.flags_ = info.flags;
 | 
				
			||||||
                                  header.flags_ = info.flags;
 | 
					                  header.after_merge_ = info.after_merge;
 | 
				
			||||||
                                  header.after_merge_ = info.after_merge;
 | 
					                  header.after_split_ = info.after_split;
 | 
				
			||||||
                                  header.after_split_ = info.after_split;
 | 
					                  header.before_split_ = info.before_split;
 | 
				
			||||||
                                  header.before_split_ = info.before_split;
 | 
					                  header.want_merge_ = info.want_merge;
 | 
				
			||||||
                                  header.want_merge_ = info.want_merge;
 | 
					                  header.want_split_ = info.want_split;
 | 
				
			||||||
                                  header.want_split_ = info.want_split;
 | 
					                  header.validator_list_hash_short_ = info.gen_validator_list_hash_short;
 | 
				
			||||||
                                  header.validator_list_hash_short_ = info.gen_validator_list_hash_short;
 | 
					                  header.catchain_seqno_ = info.gen_catchain_seqno;
 | 
				
			||||||
                                  header.catchain_seqno_ = info.gen_catchain_seqno;
 | 
					                  header.min_ref_mc_seqno_ = info.min_ref_mc_seqno;
 | 
				
			||||||
                                  header.min_ref_mc_seqno_ = info.min_ref_mc_seqno;
 | 
					                  header.start_lt_ = info.start_lt;
 | 
				
			||||||
                                  header.start_lt_ = info.start_lt;
 | 
					                  header.end_lt_ = info.end_lt;
 | 
				
			||||||
                                  header.end_lt_ = info.end_lt;
 | 
					                  header.gen_utime_ = info.gen_utime;
 | 
				
			||||||
                                  header.gen_utime_ = info.gen_utime;
 | 
					                  header.is_key_block_ = info.key_block;
 | 
				
			||||||
                                  header.is_key_block_ = info.key_block;
 | 
					                  header.vert_seqno_ = info.vert_seq_no;
 | 
				
			||||||
                                  header.vert_seqno_ = info.vert_seq_no;
 | 
					                  if (!info.not_master) {
 | 
				
			||||||
                                  if(!info.not_master) {
 | 
					                    header.prev_key_block_seqno_ = info.prev_key_block_seqno;
 | 
				
			||||||
                                   header.prev_key_block_seqno_ = info.prev_key_block_seqno;
 | 
					                  }
 | 
				
			||||||
                                  }
 | 
					                  for (auto id : prev) {
 | 
				
			||||||
                                  for (auto id : prev) {
 | 
					                    header.prev_blocks_.push_back(to_tonlib_api(id));
 | 
				
			||||||
                                    header.prev_blocks_.push_back(to_tonlib_api(id));
 | 
					                  }
 | 
				
			||||||
                                  }
 | 
					                  //if(info.before_split) {
 | 
				
			||||||
                                  //if(info.before_split) {
 | 
					                  //} else {
 | 
				
			||||||
                                  //} else {
 | 
					                  //}
 | 
				
			||||||
                                  //}
 | 
					                  return tonlib_api::make_object<tonlib_api::blocks_header>(std::move(header));
 | 
				
			||||||
                                  return tonlib_api::make_object<tonlib_api::blocks_header>(std::move(header));
 | 
					                }
 | 
				
			||||||
                                }
 | 
					              }
 | 
				
			||||||
                              }
 | 
					            }
 | 
				
			||||||
                            }
 | 
					          } catch (vm::VmError& err) {
 | 
				
			||||||
                          } catch (vm::VmError& err) {
 | 
					            auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :");
 | 
				
			||||||
                           auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :");
 | 
					            LOG(ERROR) << std::move(E);
 | 
				
			||||||
                           LOG(ERROR) << std::move(E);
 | 
					          } catch (vm::VmVirtError& err) {
 | 
				
			||||||
                          } catch (vm::VmVirtError& err) {
 | 
					            auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :");
 | 
				
			||||||
                           auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :");
 | 
					            LOG(ERROR) << std::move(E);
 | 
				
			||||||
                           LOG(ERROR) << std::move(E);
 | 
					          } catch (...) {
 | 
				
			||||||
                          } catch (...) {
 | 
					            LOG(WARNING) << "exception catched ";
 | 
				
			||||||
                            LOG(WARNING) << "exception catched ";
 | 
					          }
 | 
				
			||||||
                          }
 | 
					        }
 | 
				
			||||||
                       }
 | 
					        return tonlib_api::make_object<tonlib_api::blocks_header>(std::move(header));
 | 
				
			||||||
                       return tonlib_api::make_object<tonlib_api::blocks_header>(std::move(header));
 | 
					      }));
 | 
				
			||||||
                     }));
 | 
					 | 
				
			||||||
  return td::Status::OK();
 | 
					  return td::Status::OK();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4890,15 +4867,17 @@ void TonlibClient::load_libs_from_disk() {
 | 
				
			||||||
  if (r_dict.is_error()) {
 | 
					  if (r_dict.is_error()) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  libraries = vm::Dictionary(vm::load_cell_slice(vm::CellBuilder().append_cellslice(vm::load_cell_slice(
 | 
					  libraries = vm::Dictionary(
 | 
				
			||||||
                                                                   r_dict.move_as_ok())).finalize()), 256);
 | 
					      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++;
 | 
					  // int n = 0; for (auto&& lr : libraries) n++;
 | 
				
			||||||
  LOG(DEBUG) << "loaded libraries from disk cache";
 | 
					  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
 | 
					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())
 | 
					  kv_->set("tonlib.libcache", vm::std_boc_serialize(vm::CellBuilder().append_cellslice(libraries.get_root()).finalize())
 | 
				
			||||||
                                                        .finalize()).move_as_ok().as_slice());
 | 
					                                  .move_as_ok()
 | 
				
			||||||
 | 
					                                  .as_slice());
 | 
				
			||||||
  // int n = 0; for (auto&& lr : libraries) n++;
 | 
					  // int n = 0; for (auto&& lr : libraries) n++;
 | 
				
			||||||
  LOG(DEBUG) << "stored libraries to disk cache";
 | 
					  LOG(DEBUG) << "stored libraries to disk cache";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@
 | 
				
			||||||
#include "tonlib/TonlibClient.h"
 | 
					#include "tonlib/TonlibClient.h"
 | 
				
			||||||
#include "tonlib/TonlibCallback.h"
 | 
					#include "tonlib/TonlibCallback.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tonlib/ExtClientRaw.h"
 | 
					#include "tonlib/ExtClientLazy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "smc-envelope/ManualDns.h"
 | 
					#include "smc-envelope/ManualDns.h"
 | 
				
			||||||
#include "smc-envelope/PaymentChannel.h"
 | 
					#include "smc-envelope/PaymentChannel.h"
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,6 @@
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
#include "git.h"
 | 
					#include "git.h"
 | 
				
			||||||
#include "ExtClientMulti.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
using tonlib_api::make_object;
 | 
					using tonlib_api::make_object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,7 +223,7 @@ class TonlibCli : public td::actor::Actor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (options_.use_callbacks_for_network) {
 | 
					    if (options_.use_callbacks_for_network) {
 | 
				
			||||||
      auto config = tonlib::Config::parse(options_.config).move_as_ok();
 | 
					      auto config = tonlib::Config::parse(options_.config).move_as_ok();
 | 
				
			||||||
      class Callback : public tonlib::ExtClientRaw::Callback {
 | 
					      class Callback : public tonlib::ExtClientLazy::Callback {
 | 
				
			||||||
       public:
 | 
					       public:
 | 
				
			||||||
        explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
 | 
					        explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -232,28 +231,15 @@ class TonlibCli : public td::actor::Actor {
 | 
				
			||||||
       private:
 | 
					       private:
 | 
				
			||||||
        td::actor::ActorShared<> parent_;
 | 
					        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_++;
 | 
					      ref_cnt_++;
 | 
				
			||||||
 | 
					      raw_client_ = tonlib::ExtClientLazy::create(config.lite_servers,
 | 
				
			||||||
 | 
					                                                  td::make_unique<Callback>(td::actor::actor_shared()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto config = !options_.config.empty()
 | 
					    auto config = !options_.config.empty()
 | 
				
			||||||
                      ? make_object<tonlib_api::config>(options_.config, options_.name,
 | 
					                  ? make_object<tonlib_api::config>(options_.config, options_.name,
 | 
				
			||||||
                                                        options_.use_callbacks_for_network, options_.ignore_cache)
 | 
					                                                    options_.use_callbacks_for_network, options_.ignore_cache)
 | 
				
			||||||
                      : nullptr;
 | 
					                  : nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
 | 
					    tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
 | 
				
			||||||
    if (options_.in_memory) {
 | 
					    if (options_.in_memory) {
 | 
				
			||||||
| 
						 | 
					@ -1544,9 +1530,8 @@ class TonlibCli : public td::actor::Actor {
 | 
				
			||||||
          auto update = tonlib_api::move_object_as<tonlib_api::updateSendLiteServerQuery>(std::move(result));
 | 
					          auto update = tonlib_api::move_object_as<tonlib_api::updateSendLiteServerQuery>(std::move(result));
 | 
				
			||||||
          CHECK(!raw_client_.empty());
 | 
					          CHECK(!raw_client_.empty());
 | 
				
			||||||
          snd_bytes_ += update->data_.size();
 | 
					          snd_bytes_ += update->data_.size();
 | 
				
			||||||
          ton::ShardIdFull shard(update->workchain_, update->shard_);
 | 
					          send_closure(raw_client_, &tonlib::ExtClientLazy::send_query, "query", td::BufferSlice(update->data_),
 | 
				
			||||||
          send_closure(raw_client_, &tonlib::ExtClientRaw::send_query, "query", td::BufferSlice(update->data_), shard,
 | 
					                       ton::ShardIdFull(update->workchain_, update->shard_), td::Timestamp::in(5),
 | 
				
			||||||
                       td::Timestamp::in(5),
 | 
					 | 
				
			||||||
                       [actor_id = actor_id(this), id = update->id_](td::Result<td::BufferSlice> res) {
 | 
					                       [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));
 | 
					                         send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res));
 | 
				
			||||||
                       });
 | 
					                       });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue