1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-15 04:32:21 +00:00

Update validator config format; partial liteservers and their support in liteclient

This commit is contained in:
SpyCheese 2022-08-08 12:21:15 +03:00
parent a792565afa
commit 51e6885f2c
12 changed files with 657 additions and 363 deletions

View file

@ -38,6 +38,9 @@
#include "td/utils/TsFileLog.h" #include "td/utils/TsFileLog.h"
#include "td/utils/Random.h" #include "td/utils/Random.h"
#include "ton/ton-tl.hpp"
#include "tl/tl_json.h"
#include "memprof/memprof.h" #include "memprof/memprof.h"
#if TD_DARWIN || TD_LINUX #if TD_DARWIN || TD_LINUX
@ -54,7 +57,7 @@ Config::Config() {
out_port = 3278; out_port = 3278;
} }
Config::Config(ton::ton_api::engine_validator_config &config) { Config::Config(const ton::ton_api::engine_validator_config_v2 &config) {
out_port = static_cast<td::uint16>(config.out_port_); out_port = static_cast<td::uint16>(config.out_port_);
if (!out_port) { if (!out_port) {
out_port = 3278; out_port = 3278;
@ -121,7 +124,7 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
} }
} }
ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const { ton::tl_object_ptr<ton::ton_api::engine_validator_Config> Config::tl() const {
std::vector<ton::tl_object_ptr<ton::ton_api::engine_Addr>> addrs_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_Addr>> addrs_vec;
for (auto &x : addrs) { for (auto &x : addrs) {
if (x.second.proxy) { if (x.second.proxy) {
@ -146,7 +149,7 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
dht_vec.push_back(ton::create_tl_object<ton::ton_api::engine_dht>(x.tl())); dht_vec.push_back(ton::create_tl_object<ton::ton_api::engine_dht>(x.tl()));
} }
std::vector<ton::tl_object_ptr<ton::ton_api::engine_Validator>> val_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator>> val_vec;
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeSlave>> full_node_slaves_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeSlave>> full_node_slaves_vec;
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeMaster>> full_node_masters_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeMaster>> full_node_masters_vec;
@ -597,14 +600,14 @@ void DhtServer::load_config(td::Promise<td::Unit> promise) {
} }
auto conf_json = conf_json_R.move_as_ok(); auto conf_json = conf_json_R.move_as_ok();
ton::ton_api::engine_validator_config conf; ton::tl_object_ptr<ton::ton_api::engine_validator_Config> conf;
auto S = ton::ton_api::from_json(conf, conf_json.get_object()); auto S = td::from_json(conf, std::move(conf_json));
if (S.is_error()) { if (S.is_error()) {
promise.set_error(S.move_as_error_prefix("json does not fit TL scheme")); promise.set_error(S.move_as_error_prefix("json does not fit TL scheme"));
return; return;
} }
config_ = Config{conf}; config_ = Config{*ton::unpack_engine_validator_config(std::move(conf))};
td::MultiPromise mp; td::MultiPromise mp;
auto ig = mp.init_guard(); auto ig = mp.init_guard();

View file

@ -91,10 +91,10 @@ struct Config {
td::Result<bool> config_del_control_process(td::int32 port, ton::PublicKeyHash id); td::Result<bool> config_del_control_process(td::int32 port, ton::PublicKeyHash id);
td::Result<bool> config_del_gc(ton::PublicKeyHash key); td::Result<bool> config_del_gc(ton::PublicKeyHash key);
ton::tl_object_ptr<ton::ton_api::engine_validator_config> tl() const; ton::tl_object_ptr<ton::ton_api::engine_validator_Config> tl() const;
Config(); Config();
Config(ton::ton_api::engine_validator_config &config); Config(const ton::ton_api::engine_validator_config_v2 &config);
}; };
class DhtServer : public td::actor::Actor { class DhtServer : public td::actor::Actor {

View file

@ -41,8 +41,6 @@
#include "td/utils/crypto.h" #include "td/utils/crypto.h"
#include "td/utils/overloaded.h" #include "td/utils/overloaded.h"
#include "td/utils/port/signals.h" #include "td/utils/port/signals.h"
#include "td/utils/port/stacktrace.h"
#include "td/utils/port/StdStreams.h"
#include "td/utils/port/FileFd.h" #include "td/utils/port/FileFd.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include "ton/lite-tl.hpp" #include "ton/lite-tl.hpp"
@ -59,17 +57,14 @@
#include "vm/cp0.h" #include "vm/cp0.h"
#include "vm/memo.h" #include "vm/memo.h"
#include "ton/ton-shard.h" #include "ton/ton-shard.h"
#include "openssl/rand.hpp"
#include "crypto/vm/utils.h" #include "crypto/vm/utils.h"
#include "crypto/common/util.h" #include "crypto/common/util.h"
#include "common/checksum.h" #include "common/checksum.h"
#if TD_DARWIN || TD_LINUX #if TD_DARWIN || TD_LINUX
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#endif #endif
#include <iostream> #include <iostream>
#include <sstream>
#include "git.h" #include "git.h"
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
@ -77,22 +72,27 @@ using td::Ref;
int verbosity; int verbosity;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> TestNode::make_callback() { int TestNode::LiteServer::max_common_prefix(ton::ShardIdFull shard) const {
class Callback : public ton::adnl::AdnlExtClient::Callback { if (shard.is_masterchain()) {
public: return 0;
void on_ready() override {
td::actor::send_closure(id_, &TestNode::conn_ready);
} }
void on_stop_ready() override { if (is_full) {
td::actor::send_closure(id_, &TestNode::conn_closed); return shard.pfx_len();
} }
Callback(td::actor::ActorId<TestNode> id) : id_(std::move(id)) { int res = -1;
for (const ton::ShardIdFull &our_shard : shards) {
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;
} }
private: bool TestNode::LiteServer::supports_shard(ton::ShardIdFull shard) const {
td::actor::ActorId<TestNode> id_; return is_full || shard.is_masterchain() ||
}; std::any_of(shards.begin(), shards.end(),
return std::make_unique<Callback>(actor_id(this)); [&](const ton::ShardIdFull& our_shard) { return ton::shard_is_ancestor(shard, our_shard); });
} }
void TestNode::run() { void TestNode::run() {
@ -110,19 +110,22 @@ void TestNode::run() {
io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique<Cb>(actor_id(this))); io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique<Cb>(actor_id(this)));
td::actor::send_closure(io_, &td::TerminalIO::set_log_interface); td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
if (remote_public_key_.empty()) { if (!single_remote_public_key_.empty()) { // Use single provided liteserver
LiteServer s;
s.addr = single_remote_addr_;
s.public_key = single_remote_public_key_;
single_liteserver_idx_ = 0;
servers_.push_back(std::move(s));
run_init_queries();
return;
}
auto G = td::read_file(global_config_).move_as_ok(); auto G = td::read_file(global_config_).move_as_ok();
auto gc_j = td::json_decode(G.as_slice()).move_as_ok(); auto gc_j = td::json_decode(G.as_slice()).move_as_ok();
ton::ton_api::liteclient_config_global gc; ton::ton_api::liteclient_config_global gc;
ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); ton::ton_api::from_json(gc, gc_j.get_object()).ensure();
CHECK(gc.liteservers_.size() > 0); CHECK(gc.liteservers_.size() > 0);
auto idx = liteserver_idx_ >= 0 ? liteserver_idx_
: td::Random::fast(0, static_cast<td::uint32>(gc.liteservers_.size() - 1));
CHECK(idx >= 0 && static_cast<td::uint32>(idx) <= gc.liteservers_.size());
auto& cli = gc.liteservers_[idx];
remote_addr_.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure();
remote_public_key_ = ton::PublicKey{cli->id_};
td::TerminalIO::out() << "using liteserver " << idx << " with addr " << remote_addr_ << "\n";
if (gc.validator_ && gc.validator_->zero_state_) { if (gc.validator_ && gc.validator_->zero_state_) {
zstate_id_.workchain = gc.validator_->zero_state_->workchain_; zstate_id_.workchain = gc.validator_->zero_state_->workchain_;
if (zstate_id_.workchain != ton::workchainInvalid) { if (zstate_id_.workchain != ton::workchainInvalid) {
@ -131,10 +134,34 @@ void TestNode::run() {
td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n"; td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n";
} }
} }
for (auto& server : gc.liteservers_) {
LiteServer s;
ton::ton_api::downcast_call(*server,
td::overloaded(
[&](ton::ton_api::liteserver_desc& obj) {
s.addr.init_host_port(td::IPAddress::ipv4_to_str(obj.ip_), obj.port_).ensure();
s.public_key = ton::PublicKey{obj.id_};
},
[&](ton::ton_api::liteserver_descV2& obj) {
s.addr.init_host_port(td::IPAddress::ipv4_to_str(obj.ip_), obj.port_).ensure();
s.public_key = ton::PublicKey{obj.id_};
s.is_full = false;
for (const auto& shard : obj.shards_) {
s.shards.emplace_back(shard->workchain_, shard->shard_);
CHECK(s.shards.back().is_valid_ext());
}
}));
servers_.push_back(std::move(s));
} }
client_ = if (single_liteserver_idx_ != -1) { // Use single liteserver from config
ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_, make_callback()); CHECK(single_liteserver_idx_ >= 0 && (size_t)single_liteserver_idx_ < gc.liteservers_.size());
td::TerminalIO::out() << "using liteserver " << single_liteserver_idx_ << " with addr "
<< servers_[single_liteserver_idx_].addr << "\n";
}
run_init_queries();
} }
void TestNode::got_result(td::Result<td::BufferSlice> R, td::Promise<td::BufferSlice> promise) { void TestNode::got_result(td::Result<td::BufferSlice> R, td::Promise<td::BufferSlice> promise) {
@ -179,23 +206,156 @@ void TestNode::after_got_result(bool ok) {
} }
} }
bool TestNode::envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) { bool TestNode::envelope_send_query_to_any(td::BufferSlice query, td::Promise<td::BufferSlice> promise) {
return envelope_send_query_to_shard(ton::ShardIdFull(ton::masterchainId), std::move(query), std::move(promise));
}
bool TestNode::envelope_send_query_to_account(ton::AccountIdPrefixFull prefix, td::BufferSlice query,
td::Promise<td::BufferSlice> promise) {
if (single_liteserver_idx_ >= 0) {
return envelope_send_query_to_server(single_liteserver_idx_, std::move(query), std::move(promise));
}
// TODO: maybe use current shard configuration?
int max_prefix_len = -1;
for (const LiteServer &server : servers_) {
max_prefix_len = std::max(max_prefix_len, server.max_common_prefix(prefix.as_leaf_shard()));
}
max_prefix_len = std::min(max_prefix_len, ton::max_shard_pfx_len);
if (max_prefix_len == -1) {
running_queries_++; running_queries_++;
if (!ready_ || client_.empty()) { got_result(td::Status::Error("failed to select a suitable server"), std::move(promise));
got_result(td::Status::Error("failed to send query to server: not ready"), std::move(promise));
return false; return false;
} }
ton::ShardIdFull shard = shard_prefix(prefix.as_leaf_shard(), max_prefix_len);
return envelope_send_query_to_shard(shard, std::move(query), std::move(promise));
}
bool TestNode::envelope_send_query_to_shard(ton::ShardIdFull shard, td::BufferSlice query,
td::Promise<td::BufferSlice> promise) {
if (single_liteserver_idx_ >= 0) {
return envelope_send_query_to_server(single_liteserver_idx_, std::move(query), std::move(promise));
}
if (shard.is_masterchain() && mc_server_idx_ != -1) {
return envelope_send_query_to_server(mc_server_idx_, std::move(query), std::move(promise));
}
auto it = shard_server_idx_cached_.find(shard);
if (it != shard_server_idx_cached_.end()) {
return envelope_send_query_to_server(it->second, std::move(query), std::move(promise));
}
int server_idx = -1;
int random_idx = -1;
int cnt = 0;
bool selected_full = false;
for (int i = 0; i < (int)servers_.size(); ++i) {
const LiteServer &server = servers_[i];
if (!server.supports_shard(shard)) {
continue;
}
if (server.is_full && !selected_full) {
selected_full = true;
server_idx = -1;
cnt = 0;
}
if (!server.is_full && selected_full) {
continue;
}
if (!server.client.empty()) {
server_idx = i;
}
if (td::Random::fast(0, cnt) == 0) {
random_idx = i;
}
++cnt;
}
if (server_idx == -1) {
server_idx = random_idx;
}
if (server_idx == -1) {
running_queries_++;
got_result(td::Status::Error("failed to select a suitable server"), std::move(promise));
return false;
}
shard_server_idx_cached_[shard] = server_idx;
if (shard.is_masterchain()) {
mc_server_idx_ = server_idx;
}
return envelope_send_query_to_server(server_idx, std::move(query), std::move(promise));
}
bool TestNode::envelope_send_query_to_server(td::int32 server_idx, td::BufferSlice query,
td::Promise<td::BufferSlice> promise) {
running_queries_++;
LiteServer &server = servers_.at(server_idx);
if (server.client.empty()) {
start_client(server_idx);
}
CHECK(!server.client.empty());
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(
[SelfId = actor_id(this), promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable { [SelfId = actor_id(this), promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
td::actor::send_closure(SelfId, &TestNode::got_result, std::move(R), std::move(promise)); td::actor::send_closure(SelfId, &TestNode::got_result, std::move(R), std::move(promise));
}); });
td::BufferSlice b = td::BufferSlice b =
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(query)), true); ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(query)), true);
td::actor::send_closure(client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), if (server.client_ready) {
td::actor::send_closure(server.client, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b),
td::Timestamp::in(10.0), std::move(P)); td::Timestamp::in(10.0), std::move(P));
} else {
server.wait_client_ready.push_back(
[client = server.client.get(), b = std::move(b), P = std::move(P)](td::Result<td::Unit> R) mutable {
if (R.is_ok()) {
td::actor::send_closure(client, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b),
td::Timestamp::in(10.0), std::move(P));
} else {
P.set_error(R.move_as_error_prefix("failed to connect: "));
}
});
}
return true; return true;
} }
void TestNode::start_client(int server_idx) {
LiteServer &server = servers_[server_idx];
CHECK(server.client.empty());
class Callback : public ton::adnl::AdnlExtClient::Callback {
public:
void on_ready() override {
td::actor::send_closure(id_, &TestNode::conn_ready, server_idx_);
}
void on_stop_ready() override {
td::actor::send_closure(id_, &TestNode::conn_closed, server_idx_);
}
Callback(td::actor::ActorId<TestNode> id, int server_idx) : id_(std::move(id)), server_idx_(server_idx) {
}
private:
td::actor::ActorId<TestNode> id_;
int server_idx_;
};
server.client_ready = false;
server.wait_client_ready.clear();
LOG(INFO) << "Connecting to " << server.addr << " (liteserver #" << server_idx << ")";
server.client = ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{server.public_key}, server.addr,
std::make_unique<Callback>(actor_id(this), server_idx));
}
void TestNode::conn_ready(int server_idx) {
LiteServer &server = servers_[server_idx];
LOG(INFO) << "Connection to " << server.addr << " (liteserver #" << server_idx << ") is ready";
server.client_ready = true;
for (auto &p : server.wait_client_ready) {
p.set_result(td::Unit());
}
server.wait_client_ready.clear();
}
void TestNode::conn_closed(int server_idx) {
LiteServer &server = servers_[server_idx];
LOG(INFO) << "Connection to " << server.addr << " (liteserver #" << server_idx << ") closed";
server.client_ready = false;
server.wait_client_ready.clear();
}
td::Promise<td::Unit> TestNode::trivial_promise() { td::Promise<td::Unit> TestNode::trivial_promise() {
return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result<td::Unit> res) { return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result<td::Unit> res) {
if (res.is_error()) { if (res.is_error()) {
@ -310,7 +470,7 @@ bool TestNode::dump_cached_cell(td::Slice hash_pfx, td::Slice type_name) {
bool TestNode::get_server_time() { bool TestNode::get_server_time() {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getTime>(), true); auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getTime>(), true);
return envelope_send_query(std::move(b), [&, Self = actor_id(this)](td::Result<td::BufferSlice> res) -> void { return envelope_send_query_to_any(std::move(b), [&, Self = actor_id(this)](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot get server time"; LOG(ERROR) << "cannot get server time";
return; return;
@ -319,9 +479,10 @@ bool TestNode::get_server_time() {
if (F.is_error()) { if (F.is_error()) {
LOG(ERROR) << "cannot parse answer to liteServer.getTime"; LOG(ERROR) << "cannot parse answer to liteServer.getTime";
} else { } else {
server_time_ = F.move_as_ok()->now_; mc_server_time_ = F.move_as_ok()->now_;
server_time_got_at_ = now(); mc_server_time_got_at_ = now();
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_
<< ")";
} }
} }
}); });
@ -329,13 +490,13 @@ bool TestNode::get_server_time() {
bool TestNode::get_server_version(int mode) { bool TestNode::get_server_version(int mode) {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getVersion>(), true); auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getVersion>(), true);
return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> res) { return envelope_send_query_to_any(std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> res) {
td::actor::send_closure_later(Self, &TestNode::got_server_version, std::move(res), mode); td::actor::send_closure_later(Self, &TestNode::got_server_version, std::move(res), mode);
}); });
}; };
void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) { void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
server_ok_ = false; mc_server_ok_ = false;
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot get server version and time (server too old?)"; LOG(ERROR) << "cannot get server version and time (server too old?)";
} else { } else {
@ -344,11 +505,11 @@ void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
LOG(ERROR) << "cannot parse answer to liteServer.getVersion"; LOG(ERROR) << "cannot parse answer to liteServer.getVersion";
} else { } else {
auto a = F.move_as_ok(); auto a = F.move_as_ok();
set_server_version(a->version_, a->capabilities_); set_mc_server_version(a->version_, a->capabilities_);
set_server_time(a->now_); set_mc_server_time(a->now_);
} }
} }
if (!server_ok_) { if (!mc_server_ok_) {
LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff) LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff)
<< " with capabilities " << min_ls_capabilities << " required), some queries are unavailable"; << " with capabilities " << min_ls_capabilities << " required), some queries are unavailable";
} }
@ -357,27 +518,27 @@ void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
} }
} }
void TestNode::set_server_version(td::int32 version, td::int64 capabilities) { void TestNode::set_mc_server_version(td::int32 version, td::int64 capabilities) {
if (server_version_ != version || server_capabilities_ != capabilities) { if (mc_server_version_ != version || mc_server_capabilities_ != capabilities) {
server_version_ = version; mc_server_version_ = version;
server_capabilities_ = capabilities; mc_server_capabilities_ = capabilities;
LOG(WARNING) << "server version is " << (server_version_ >> 8) << "." << (server_version_ & 0xff) LOG(WARNING) << "server version is " << (mc_server_version_ >> 8) << "." << (mc_server_version_ & 0xff)
<< ", capabilities " << server_capabilities_; << ", capabilities " << mc_server_capabilities_;
} }
server_ok_ = (server_version_ >= min_ls_version) && !(~server_capabilities_ & min_ls_capabilities); mc_server_ok_ = (mc_server_version_ >= min_ls_version) && !(~mc_server_capabilities_ & min_ls_capabilities);
} }
void TestNode::set_server_time(int server_utime) { void TestNode::set_mc_server_time(int server_utime) {
server_time_ = server_utime; mc_server_time_ = server_utime;
server_time_got_at_ = now(); mc_server_time_got_at_ = now();
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")"; LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_ << ")";
} }
bool TestNode::get_server_mc_block_id() { bool TestNode::get_server_mc_block_id() {
int mode = (server_capabilities_ & 2) ? 0 : -1; int mode = (mc_server_capabilities_ & 2) ? 0 : -1;
if (mode < 0) { if (mode < 0) {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfo>(), true); auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfo>(), true);
return envelope_send_query(std::move(b), [Self = actor_id(this)](td::Result<td::BufferSlice> res) -> void { return envelope_send_query_to_any(std::move(b), [Self = actor_id(this)](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot get masterchain info from server"; LOG(ERROR) << "cannot get masterchain info from server";
return; return;
@ -397,7 +558,8 @@ bool TestNode::get_server_mc_block_id() {
} else { } else {
auto b = auto b =
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfoExt>(mode), true); ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfoExt>(mode), true);
return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> res) -> void { return envelope_send_query_to_any(
std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot get extended masterchain info from server"; LOG(ERROR) << "cannot get extended masterchain info from server";
return; return;
@ -448,8 +610,8 @@ void TestNode::got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt
void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version, void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version,
long long capabilities, int last_utime, int server_now) { long long capabilities, int last_utime, int server_now) {
set_server_version(version, capabilities); set_mc_server_version(version, capabilities);
set_server_time(server_now); set_mc_server_time(server_now);
if (last_utime > server_now) { if (last_utime > server_now) {
LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime
<< " (" << last_utime - server_now << " seconds in the future)"; << " (" << last_utime - server_now << " seconds in the future)";
@ -457,10 +619,10 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI
LOG(WARNING) << "server appears to be out of sync: its newest masterchain block is " << blkid.to_str() LOG(WARNING) << "server appears to be out of sync: its newest masterchain block is " << blkid.to_str()
<< " created at " << last_utime << " (" << server_now - last_utime << " created at " << last_utime << " (" << server_now - last_utime
<< " seconds ago according to the server's clock)"; << " seconds ago according to the server's clock)";
} else if (last_utime < server_time_got_at_ - 60) { } else if (last_utime < mc_server_time_got_at_ - 60) {
LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain " LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain "
"block known to server is " "block known to server is "
<< blkid.to_str() << " created at " << last_utime << " (" << server_now - server_time_got_at_ << blkid.to_str() << " created at " << last_utime << " (" << server_now - mc_server_time_got_at_
<< " seconds ago according to the local clock)"; << " seconds ago according to the local clock)";
} }
got_server_mc_block_id(blkid, zstateid, last_utime); got_server_mc_block_id(blkid, zstateid, last_utime);
@ -469,7 +631,8 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI
bool TestNode::request_block(ton::BlockIdExt blkid) { bool TestNode::request_block(ton::BlockIdExt blkid) {
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getBlock>(ton::create_tl_lite_block_id(blkid)), true); ton::create_tl_object<ton::lite_api::liteServer_getBlock>(ton::create_tl_lite_block_id(blkid)), true);
return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) -> void { return envelope_send_query_to_shard(
blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server"; LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server";
return; return;
@ -494,7 +657,8 @@ bool TestNode::request_block(ton::BlockIdExt blkid) {
bool TestNode::request_state(ton::BlockIdExt blkid) { bool TestNode::request_state(ton::BlockIdExt blkid) {
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getState>(ton::create_tl_lite_block_id(blkid)), true); ton::create_tl_object<ton::lite_api::liteServer_getState>(ton::create_tl_lite_block_id(blkid)), true);
return envelope_send_query(std::move(b), [Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) -> void { return envelope_send_query_to_shard(
blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server"; LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server";
return; return;
@ -1149,8 +1313,18 @@ td::Status TestNode::send_ext_msg_from_filename(std::string filename) {
LOG(ERROR) << "failed to read file `" << filename << "`: " << err.to_string(); LOG(ERROR) << "failed to read file `" << filename << "`: " << err.to_string();
return err; return err;
} }
if (ready_ && !client_.empty()) {
LOG(ERROR) << "sending query from file " << filename; LOG(ERROR) << "sending query from file " << filename;
TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(F.ok().as_slice()), "invalid boc: ");
block::gen::CommonMsgInfo::Record_ext_in_msg_info info;
if (!tlb::unpack_cell_inexact(root, info)) {
return td::Status::Error("failed to unpack external message header");
}
auto dest_prefix = block::tlb::t_MsgAddressInt.get_prefix(info.dest);
if (!dest_prefix.is_valid()) {
return td::Status::Error("destination of the message is invalid");
}
auto P = td::PromiseCreator::lambda([](td::Result<td::BufferSlice> R) { auto P = td::PromiseCreator::lambda([](td::Result<td::BufferSlice> R) {
if (R.is_error()) { if (R.is_error()) {
return; return;
@ -1165,11 +1339,8 @@ td::Status TestNode::send_ext_msg_from_filename(std::string filename) {
}); });
auto b = auto b =
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_sendMessage>(F.move_as_ok()), true); ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_sendMessage>(F.move_as_ok()), true);
return envelope_send_query(std::move(b), std::move(P)) ? td::Status::OK() return envelope_send_query_to_account(dest_prefix, std::move(b), std::move(P)) ? td::Status::OK()
: td::Status::Error("cannot send query to server"); : td::Status::Error("cannot send query to server");
} else {
return td::Status::Error("server connection not ready");
}
} }
bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid,
@ -1177,9 +1348,6 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress
if (!ref_blkid.is_valid()) { if (!ref_blkid.is_valid()) {
return set_error("must obtain last block information before making other queries"); return set_error("must obtain last block information before making other queries");
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
if (addr_ext) { if (addr_ext) {
return get_special_smc_addr(addr_ext, [this, ref_blkid, filename, mode](td::Result<ton::StdSmcAddress> res) { return get_special_smc_addr(addr_ext, [this, ref_blkid, filename, mode](td::Result<ton::StdSmcAddress> res) {
if (res.is_error()) { if (res.is_error()) {
@ -1193,10 +1361,12 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>( auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>(
ton::create_tl_lite_block_id(ref_blkid), std::move(a)), ton::create_tl_lite_block_id(ref_blkid), std::move(a)),
true); true);
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to "
<< ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode; << ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode;
return envelope_send_query( return envelope_send_query_to_account(
std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result<td::BufferSlice> R) { account_prefix, std::move(b),
[Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result<td::BufferSlice> R) {
if (R.is_error()) { if (R.is_error()) {
return; return;
} }
@ -1275,18 +1445,17 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
if (!ref_blkid.is_valid()) { if (!ref_blkid.is_valid()) {
return set_error("must obtain last block information before making other queries"); return set_error("must obtain last block information before making other queries");
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr); auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr);
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
if (!mode) { if (!mode) {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>( auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>(
ton::create_tl_lite_block_id(ref_blkid), std::move(a)), ton::create_tl_lite_block_id(ref_blkid), std::move(a)),
true); true);
LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to "
<< ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters"; << ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters";
return envelope_send_query( return envelope_send_query_to_account(
std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params), account_prefix, std::move(b),
[Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params),
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable { promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
if (R.is_error()) { if (R.is_error()) {
promise.set_error(R.move_as_error()); promise.set_error(R.move_as_error());
@ -1327,8 +1496,9 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
LOG(INFO) << "requesting remote get-method execution for " << workchain << ":" << addr.to_hex() LOG(INFO) << "requesting remote get-method execution for " << workchain << ":" << addr.to_hex()
<< " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with " << " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with "
<< params.size() << " parameters"; << params.size() << " parameters";
return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, return envelope_send_query_to_account(
params = std::move(params), account_prefix, std::move(b),
[Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, params = std::move(params),
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable { promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
if (R.is_error()) { if (R.is_error()) {
promise.set_error(R.move_as_error()); promise.set_error(R.move_as_error());
@ -1340,11 +1510,11 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
promise.set_error(td::Status::Error("cannot parse answer to liteServer.runSmcMethod")); promise.set_error(td::Status::Error("cannot parse answer to liteServer.runSmcMethod"));
} else { } else {
auto f = F.move_as_ok(); auto f = F.move_as_ok();
td::actor::send_closure_later(Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_), td::actor::send_closure_later(
ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_),
std::move(f->proof_), std::move(f->state_proof_), workchain, addr, method_name, ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), std::move(f->proof_),
std::move(params), std::move(f->init_c7_), std::move(f->lib_extras_), std::move(f->state_proof_), workchain, addr, method_name, std::move(params), std::move(f->init_c7_),
std::move(f->result_), f->exit_code_, std::move(promise)); std::move(f->lib_extras_), std::move(f->result_), f->exit_code_, std::move(promise));
} }
}); });
} }
@ -1577,7 +1747,7 @@ void TestNode::send_compute_complaint_price_query(ton::StdSmcAddress elector_add
params.emplace_back(td::make_refint(refs)); params.emplace_back(td::make_refint(refs));
params.emplace_back(td::make_refint(expires_in)); params.emplace_back(td::make_refint(expires_in));
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(
[this, expires_in, bits, refs, chash, filename](td::Result<std::vector<vm::StackEntry>> R) { [expires_in, bits, refs, chash, filename](td::Result<std::vector<vm::StackEntry>> R) {
if (R.is_error()) { if (R.is_error()) {
LOG(ERROR) << R.move_as_error(); LOG(ERROR) << R.move_as_error();
return; return;
@ -1639,10 +1809,6 @@ bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress
return set_error("domain name too long"); return set_error("domain name too long");
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
if (workchain == ton::workchainInvalid) { if (workchain == ton::workchainInvalid) {
if (dns_root_queried_) { if (dns_root_queried_) {
workchain = ton::masterchainId; workchain = ton::masterchainId;
@ -1843,17 +2009,16 @@ bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workc
if (!ton::shard_contains(blkid.shard_full(), ton::extract_addr_prefix(workchain, addr))) { if (!ton::shard_contains(blkid.shard_full(), ton::extract_addr_prefix(workchain, addr))) {
return set_error("the shard of this block cannot contain this account"); return set_error("the shard of this block cannot contain this account");
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr); auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr);
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getOneTransaction>( auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getOneTransaction>(
ton::create_tl_lite_block_id(blkid), std::move(a), lt), ton::create_tl_lite_block_id(blkid), std::move(a), lt),
true); true);
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
LOG(INFO) << "requesting transaction " << lt << " of " << workchain << ":" << addr.to_hex() << " from block " LOG(INFO) << "requesting transaction " << lt << " of " << workchain << ":" << addr.to_hex() << " from block "
<< blkid.to_str(); << blkid.to_str();
return envelope_send_query( return envelope_send_query_to_account(
std::move(b), [Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result<td::BufferSlice> R) -> void { account_prefix, std::move(b),
[Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result<td::BufferSlice> R) -> void {
if (R.is_error()) { if (R.is_error()) {
return; return;
} }
@ -1870,16 +2035,15 @@ bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workc
bool TestNode::get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt, bool TestNode::get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::LogicalTime lt,
ton::Bits256 hash, unsigned count, bool dump) { ton::Bits256 hash, unsigned count, bool dump) {
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr); auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr);
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getTransactions>(count, std::move(a), lt, hash), true); ton::create_tl_object<ton::lite_api::liteServer_getTransactions>(count, std::move(a), lt, hash), true);
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
LOG(INFO) << "requesting " << count << " last transactions from " << lt << ":" << hash.to_hex() << " of " << workchain LOG(INFO) << "requesting " << count << " last transactions from " << lt << ":" << hash.to_hex() << " of " << workchain
<< ":" << addr.to_hex(); << ":" << addr.to_hex();
return envelope_send_query( return envelope_send_query_to_account(
std::move(b), [Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result<td::BufferSlice> R) { account_prefix, std::move(b),
[Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result<td::BufferSlice> R) {
if (R.is_error()) { if (R.is_error()) {
return; return;
} }
@ -2236,10 +2400,10 @@ void TestNode::got_one_transaction(ton::BlockIdExt req_blkid, ton::BlockIdExt bl
<< " but received data has " << root->get_hash().bits().to_hex(256); << " but received data has " << root->get_hash().bits().to_hex(256);
return; return;
} }
} catch (vm::VmError err) { } catch (vm::VmError &err) {
LOG(ERROR) << "error while traversing block transaction proof : " << err.get_msg(); LOG(ERROR) << "error while traversing block transaction proof : " << err.get_msg();
return; return;
} catch (vm::VmVirtError err) { } catch (vm::VmVirtError &err) {
LOG(ERROR) << "virtualization error while traversing block transaction proof : " << err.get_msg(); LOG(ERROR) << "virtualization error while traversing block transaction proof : " << err.get_msg();
return; return;
} }
@ -2418,16 +2582,14 @@ void TestNode::got_last_transactions(std::vector<ton::BlockIdExt> blkids, td::Bu
bool TestNode::get_block_transactions(ton::BlockIdExt blkid, int mode, unsigned count, ton::Bits256 acc_addr, bool TestNode::get_block_transactions(ton::BlockIdExt blkid, int mode, unsigned count, ton::Bits256 acc_addr,
ton::LogicalTime lt) { ton::LogicalTime lt) {
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
auto a = ton::create_tl_object<ton::lite_api::liteServer_transactionId3>(acc_addr, lt); auto a = ton::create_tl_object<ton::lite_api::liteServer_transactionId3>(acc_addr, lt);
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_listBlockTransactions>( auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_listBlockTransactions>(
ton::create_tl_lite_block_id(blkid), mode, count, std::move(a), false, false), ton::create_tl_lite_block_id(blkid), mode, count, std::move(a), false, false),
true); true);
LOG(INFO) << "requesting " << count << " transactions from block " << blkid.to_str() << " starting from account " LOG(INFO) << "requesting " << count << " transactions from block " << blkid.to_str() << " starting from account "
<< acc_addr.to_hex() << " lt " << lt; << acc_addr.to_hex() << " lt " << lt;
return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> R) { return envelope_send_query_to_shard(
blkid.shard_full(), std::move(b), [Self = actor_id(this), mode](td::Result<td::BufferSlice> R) {
if (R.is_error()) { if (R.is_error()) {
return; return;
} }
@ -2469,13 +2631,11 @@ bool TestNode::get_all_shards(std::string filename, bool use_last, ton::BlockIdE
if (!blkid.is_masterchain()) { if (!blkid.is_masterchain()) {
return set_error("only masterchain blocks contain shard configuration"); return set_error("only masterchain blocks contain shard configuration");
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getAllShardsInfo>(ton::create_tl_lite_block_id(blkid)), true); ton::create_tl_object<ton::lite_api::liteServer_getAllShardsInfo>(ton::create_tl_lite_block_id(blkid)), true);
LOG(INFO) << "requesting recent shard configuration"; LOG(INFO) << "requesting recent shard configuration";
return envelope_send_query(std::move(b), [Self = actor_id(this), filename](td::Result<td::BufferSlice> R) -> void { return envelope_send_query_to_any(
std::move(b), [Self = actor_id(this), filename](td::Result<td::BufferSlice> R) -> void {
if (R.is_error()) { if (R.is_error()) {
return; return;
} }
@ -2484,8 +2644,8 @@ bool TestNode::get_all_shards(std::string filename, bool use_last, ton::BlockIdE
LOG(ERROR) << "cannot parse answer to liteServer.getAllShardsInfo"; LOG(ERROR) << "cannot parse answer to liteServer.getAllShardsInfo";
} else { } else {
auto f = F.move_as_ok(); auto f = F.move_as_ok();
td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_), std::move(f->proof_), td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_),
std::move(f->data_), filename); std::move(f->proof_), std::move(f->data_), filename);
} }
}); });
} }
@ -2551,9 +2711,6 @@ bool TestNode::parse_get_config_params(ton::BlockIdExt blkid, int mode, std::str
params.push_back(x); params.push_back(x);
} }
} }
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
if (!blkid.is_masterchain_ext()) { if (!blkid.is_masterchain_ext()) {
return set_error("only masterchain blocks contain configuration"); return set_error("only masterchain blocks contain configuration");
} }
@ -2572,10 +2729,6 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, td::Promise<std::unique_
bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise<ConfigInfo> promise, int mode, bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise<ConfigInfo> promise, int mode,
std::string filename, std::vector<int> params) { std::string filename, std::vector<int> params) {
if (!(ready_ && !client_.empty())) {
promise.set_error(td::Status::Error("server connection not ready"));
return false;
}
if (!blkid.is_masterchain_ext()) { if (!blkid.is_masterchain_ext()) {
promise.set_error(td::Status::Error("masterchain reference block expected")); promise.set_error(td::Status::Error("masterchain reference block expected"));
return false; return false;
@ -2593,7 +2746,8 @@ bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise<ConfigIn
true); true);
LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block " LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block "
<< blkid.to_str(); << blkid.to_str();
return envelope_send_query(std::move(b), [Self = actor_id(this), mode, filename, blkid, params = std::move(params), return envelope_send_query_to_any(
std::move(b), [Self = actor_id(this), mode, filename, blkid, params = std::move(params),
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable { promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params), td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params),
std::move(R), std::move(promise)); std::move(R), std::move(promise));
@ -2785,8 +2939,8 @@ bool TestNode::get_block(ton::BlockIdExt blkid, bool dump) {
LOG(INFO) << "got block download request for " << blkid.to_str(); LOG(INFO) << "got block download request for " << blkid.to_str();
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getBlock>(ton::create_tl_lite_block_id(blkid)), true); ton::create_tl_object<ton::lite_api::liteServer_getBlock>(ton::create_tl_lite_block_id(blkid)), true);
return envelope_send_query( return envelope_send_query_to_shard(
std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void { blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot obtain block " << blkid.to_str() LOG(ERROR) << "cannot obtain block " << blkid.to_str()
<< " from server : " << res.move_as_error().to_string(); << " from server : " << res.move_as_error().to_string();
@ -2814,8 +2968,8 @@ bool TestNode::get_state(ton::BlockIdExt blkid, bool dump) {
LOG(INFO) << "got state download request for " << blkid.to_str(); LOG(INFO) << "got state download request for " << blkid.to_str();
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getState>(ton::create_tl_lite_block_id(blkid)), true); ton::create_tl_object<ton::lite_api::liteServer_getState>(ton::create_tl_lite_block_id(blkid)), true);
return envelope_send_query( return envelope_send_query_to_shard(
std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void { blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot obtain state " << blkid.to_str() LOG(ERROR) << "cannot obtain state " << blkid.to_str()
<< " from server : " << res.move_as_error().to_string(); << " from server : " << res.move_as_error().to_string();
@ -2952,7 +3106,7 @@ void TestNode::got_state(ton::BlockIdExt blkid, ton::RootHash root_hash, ton::Fi
} }
bool TestNode::get_show_block_header(ton::BlockIdExt blkid, int mode) { bool TestNode::get_show_block_header(ton::BlockIdExt blkid, int mode) {
return get_block_header(blkid, mode, [this, blkid](td::Result<BlockHdrInfo> R) { return get_block_header(blkid, mode, [this](td::Result<BlockHdrInfo> R) {
if (R.is_error()) { if (R.is_error()) {
LOG(ERROR) << "unable to fetch block header: " << R.move_as_error(); LOG(ERROR) << "unable to fetch block header: " << R.move_as_error();
} else { } else {
@ -2967,8 +3121,9 @@ bool TestNode::get_block_header(ton::BlockIdExt blkid, int mode, td::Promise<Tes
LOG(INFO) << "got block header request for " << blkid.to_str() << " with mode " << mode; LOG(INFO) << "got block header request for " << blkid.to_str() << " with mode " << mode;
auto b = ton::serialize_tl_object( auto b = ton::serialize_tl_object(
ton::create_tl_object<ton::lite_api::liteServer_getBlockHeader>(ton::create_tl_lite_block_id(blkid), mode), true); ton::create_tl_object<ton::lite_api::liteServer_getBlockHeader>(ton::create_tl_lite_block_id(blkid), mode), true);
return envelope_send_query( return envelope_send_query_to_shard(
std::move(b), [this, blkid, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void { blkid.shard_full(), std::move(b),
[this, blkid, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void {
TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R),
PSLICE() << "cannot obtain block header for " << blkid.to_str() << " from server :"); PSLICE() << "cannot obtain block header for " << blkid.to_str() << " from server :");
got_block_header_raw(std::move(res), std::move(promise), blkid); got_block_header_raw(std::move(res), std::move(promise), blkid);
@ -2994,8 +3149,8 @@ bool TestNode::lookup_block(ton::ShardIdFull shard, int mode, td::uint64 arg,
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_lookupBlock>( auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_lookupBlock>(
mode, ton::create_tl_lite_block_id_simple(id), arg, (td::uint32)arg), mode, ton::create_tl_lite_block_id_simple(id), arg, (td::uint32)arg),
true); true);
return envelope_send_query( return envelope_send_query_to_shard(
std::move(b), [this, id, mode, arg, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void { shard, std::move(b), [this, id, mode, arg, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void {
TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R), TRY_RESULT_PROMISE_PREFIX(promise, res, std::move(R),
PSLICE() << "cannot look up block header for " << id.to_str() << " with mode " << mode PSLICE() << "cannot look up block header for " << id.to_str() << " with mode " << mode
<< " and argument " << arg << " from server :"); << " and argument " << arg << " from server :");
@ -3109,9 +3264,9 @@ void TestNode::got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int
return; return;
} }
show_block_header(blkid, std::move(virt_root), mode); show_block_header(blkid, std::move(virt_root), mode);
} catch (vm::VmError err) { } catch (vm::VmError &err) {
LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg();
} catch (vm::VmVirtError err) { } catch (vm::VmVirtError &err) {
LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg(); LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg();
} }
show_new_blkids(); show_new_blkids();
@ -3140,7 +3295,8 @@ bool TestNode::get_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mod
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getBlockProof>( ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getBlockProof>(
mode & 0xfff, ton::create_tl_lite_block_id(from), ton::create_tl_lite_block_id(to)), mode & 0xfff, ton::create_tl_lite_block_id(from), ton::create_tl_lite_block_id(to)),
true); true);
return envelope_send_query(std::move(b), [Self = actor_id(this), from, to, mode](td::Result<td::BufferSlice> res) { return envelope_send_query_to_any(
std::move(b), [Self = actor_id(this), from, to, mode](td::Result<td::BufferSlice> res) {
if (res.is_error()) { if (res.is_error()) {
LOG(ERROR) << "cannot obtain block proof for " << ((mode & 1) ? to.to_str() : "last masterchain block") LOG(ERROR) << "cannot obtain block proof for " << ((mode & 1) ? to.to_str() : "last masterchain block")
<< " starting from " << from.to_str() << " from server : " << res.move_as_error().to_string(); << " starting from " << from.to_str() << " from server : " << res.move_as_error().to_string();
@ -3201,9 +3357,6 @@ void TestNode::got_block_proof(ton::BlockIdExt from, ton::BlockIdExt to, int mod
bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after, bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_count, ton::Bits256 start_after,
ton::UnixTime min_utime) { ton::UnixTime min_utime) {
if (!(ready_ && !client_.empty())) {
return set_error("server connection not ready");
}
if (!blkid.is_masterchain_ext()) { if (!blkid.is_masterchain_ext()) {
return set_error("only masterchain blocks contain block creator statistics"); return set_error("only masterchain blocks contain block creator statistics");
} }
@ -3214,7 +3367,7 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_c
auto& os = *osp; auto& os = *osp;
return get_creator_stats( return get_creator_stats(
blkid, mode, req_count, start_after, min_utime, blkid, mode, req_count, start_after, min_utime,
[min_utime, &os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, [&os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt,
const block::DiscountedCounter& shard_cnt) -> bool { const block::DiscountedCounter& shard_cnt) -> bool {
os << key.to_hex() << " mc_cnt:" << mc_cnt << " shard_cnt:" << shard_cnt << std::endl; os << key.to_hex() << " mc_cnt:" << mc_cnt << " shard_cnt:" << shard_cnt << std::endl;
return true; return true;
@ -3244,10 +3397,6 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_c
bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton::UnixTime min_utime, bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton::UnixTime min_utime,
TestNode::creator_stats_func_t func, std::unique_ptr<TestNode::CreatorStatsRes> state, TestNode::creator_stats_func_t func, std::unique_ptr<TestNode::CreatorStatsRes> state,
td::Promise<std::unique_ptr<TestNode::CreatorStatsRes>> promise) { td::Promise<std::unique_ptr<TestNode::CreatorStatsRes>> promise) {
if (!(ready_ && !client_.empty())) {
promise.set_error(td::Status::Error("server connection not ready"));
return false;
}
if (!state) { if (!state) {
promise.set_error(td::Status::Error("null CreatorStatsRes")); promise.set_error(td::Status::Error("null CreatorStatsRes"));
return false; return false;
@ -3266,7 +3415,7 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, unsigned req_count, ton:
LOG(INFO) << "requesting up to " << req_count << " block creator stats records with respect to masterchain block " LOG(INFO) << "requesting up to " << req_count << " block creator stats records with respect to masterchain block "
<< blkid.to_str() << " starting from validator public key " << state->last_key.to_hex() << " created after " << blkid.to_str() << " starting from validator public key " << state->last_key.to_hex() << " created after "
<< min_utime << " (mode=" << state->mode << ")"; << min_utime << " (mode=" << state->mode << ")";
return envelope_send_query( return envelope_send_query_to_any(
std::move(b), [this, blkid, req_count, state = std::move(state), min_utime, func = std::move(func), std::move(b), [this, blkid, req_count, state = std::move(state), min_utime, func = std::move(func),
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable { promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
TRY_RESULT_PROMISE(promise, res, std::move(R)); TRY_RESULT_PROMISE(promise, res, std::move(R));
@ -3483,7 +3632,7 @@ bool TestNode::load_creator_stats(std::unique_ptr<TestNode::ValidatorLoadInfo> l
ton::UnixTime min_utime = info.valid_since - 1000; ton::UnixTime min_utime = info.valid_since - 1000;
return get_creator_stats( return get_creator_stats(
info.blk_id, 1000, min_utime, info.blk_id, 1000, min_utime,
[min_utime, &info](const td::Bits256& key, const block::DiscountedCounter& mc_cnt, [&info](const td::Bits256& key, const block::DiscountedCounter& mc_cnt,
const block::DiscountedCounter& shard_cnt) -> bool { const block::DiscountedCounter& shard_cnt) -> bool {
info.store_record(key, mc_cnt, shard_cnt); info.store_record(key, mc_cnt, shard_cnt);
return true; return true;
@ -3878,7 +4027,7 @@ td::Result<Ref<vm::Cell>> TestNode::ValidatorLoadInfo::build_proof(int idx, td::
block::gen::ValidatorDescr::Record_validator_addr rec2; block::gen::ValidatorDescr::Record_validator_addr rec2;
if (tlb::csr_unpack(entry, rec1)) { if (tlb::csr_unpack(entry, rec1)) {
pk = std::move(rec1.public_key); pk = std::move(rec1.public_key);
} else if (tlb::csr_unpack(std::move(entry), rec2)) { } else if (tlb::csr_unpack(entry, rec2)) {
pk = std::move(rec2.public_key); pk = std::move(rec2.public_key);
} else { } else {
return td::Status::Error("cannot unpack ValidatorDescr"); return td::Status::Error("cannot unpack ValidatorDescr");

View file

@ -45,22 +45,41 @@ class TestNode : public td::actor::Actor {
min_ls_version = 0x101, min_ls_version = 0x101,
min_ls_capabilities = 1 min_ls_capabilities = 1
}; // server version >= 1.1, capabilities at least +1 = build proof chains }; // server version >= 1.1, capabilities at least +1 = build proof chains
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client_;
td::actor::ActorOwn<td::TerminalIO> io_; td::actor::ActorOwn<td::TerminalIO> io_;
struct LiteServer {
td::IPAddress addr;
ton::PublicKey public_key;
bool is_full = true;
std::vector<ton::ShardIdFull> shards;
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client;
bool client_ready = false;
std::vector<td::Promise<td::Unit>> wait_client_ready;
int max_common_prefix(ton::ShardIdFull shard) const;
bool supports_shard(ton::ShardIdFull shard) const;
};
std::vector<LiteServer> servers_;
td::int32 single_liteserver_idx_ = -1;
td::IPAddress single_remote_addr_;
ton::PublicKey single_remote_public_key_;
std::map<ton::ShardIdFull, td::int32> shard_server_idx_cached_;
bool readline_enabled_ = true; bool readline_enabled_ = true;
bool server_ok_ = false;
td::int32 liteserver_idx_ = -1;
int print_limit_ = 1024; int print_limit_ = 1024;
bool ready_ = false;
bool inited_ = false;
std::string db_root_; std::string db_root_;
int server_time_ = 0; // mc_server is the server for queries to masterchain
int server_time_got_at_ = 0; int mc_server_idx_ = -1;
int server_version_ = 0; int mc_server_time_ = 0;
long long server_capabilities_ = 0; int mc_server_time_got_at_ = 0;
int mc_server_version_ = 0;
long long mc_server_capabilities_ = 0;
bool mc_server_ok_ = false;
ton::ZeroStateIdExt zstate_id_; ton::ZeroStateIdExt zstate_id_;
ton::BlockIdExt mc_last_id_; ton::BlockIdExt mc_last_id_;
@ -75,9 +94,6 @@ class TestNode : public td::actor::Actor {
const char *parse_ptr_, *parse_end_; const char *parse_ptr_, *parse_end_;
td::Status error_; td::Status error_;
td::IPAddress remote_addr_;
ton::PublicKey remote_public_key_;
std::vector<ton::BlockIdExt> known_blk_ids_; std::vector<ton::BlockIdExt> known_blk_ids_;
std::size_t shown_blk_ids_ = 0; std::size_t shown_blk_ids_ = 0;
@ -88,8 +104,6 @@ class TestNode : public td::actor::Actor {
std::map<td::Bits256, Ref<vm::Cell>> cell_cache_; std::map<td::Bits256, Ref<vm::Cell>> cell_cache_;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback();
using creator_stats_func_t = using creator_stats_func_t =
std::function<bool(const td::Bits256&, const block::DiscountedCounter&, const block::DiscountedCounter&)>; std::function<bool(const td::Bits256&, const block::DiscountedCounter&, const block::DiscountedCounter&)>;
@ -182,8 +196,8 @@ class TestNode : public td::actor::Actor {
void got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int created_at); void got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int created_at);
void got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version, void got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version,
long long capabilities, int last_utime, int server_now); long long capabilities, int last_utime, int server_now);
void set_server_version(td::int32 version, td::int64 capabilities); void set_mc_server_version(td::int32 version, td::int64 capabilities);
void set_server_time(int server_utime); void set_mc_server_time(int server_utime);
bool request_block(ton::BlockIdExt blkid); bool request_block(ton::BlockIdExt blkid);
bool request_state(ton::BlockIdExt blkid); bool request_state(ton::BlockIdExt blkid);
void got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data); void got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data);
@ -358,16 +372,6 @@ class TestNode : public td::actor::Actor {
static const tlb::TypenameLookup& get_tlb_dict(); static const tlb::TypenameLookup& get_tlb_dict();
public: public:
void conn_ready() {
LOG(ERROR) << "conn ready";
ready_ = true;
if (!inited_) {
run_init_queries();
}
}
void conn_closed() {
ready_ = false;
}
void set_global_config(std::string str) { void set_global_config(std::string str) {
global_config_ = str; global_config_ = str;
} }
@ -378,10 +382,10 @@ class TestNode : public td::actor::Actor {
readline_enabled_ = value; readline_enabled_ = value;
} }
void set_liteserver_idx(td::int32 idx) { void set_liteserver_idx(td::int32 idx) {
liteserver_idx_ = idx; single_liteserver_idx_ = idx;
} }
void set_remote_addr(td::IPAddress addr) { void set_remote_addr(td::IPAddress addr) {
remote_addr_ = addr; single_remote_addr_ = addr;
} }
void set_public_key(td::BufferSlice file_name) { void set_public_key(td::BufferSlice file_name) {
auto R = [&]() -> td::Result<ton::PublicKey> { auto R = [&]() -> td::Result<ton::PublicKey> {
@ -392,7 +396,7 @@ class TestNode : public td::actor::Actor {
if (R.is_error()) { if (R.is_error()) {
LOG(FATAL) << "bad server public key: " << R.move_as_error(); LOG(FATAL) << "bad server public key: " << R.move_as_error();
} }
remote_public_key_ = R.move_as_ok(); single_remote_public_key_ = R.move_as_ok();
} }
void decode_public_key(td::BufferSlice b64_key) { void decode_public_key(td::BufferSlice b64_key) {
auto R = [&]() -> td::Result<ton::PublicKey> { auto R = [&]() -> td::Result<ton::PublicKey> {
@ -404,7 +408,7 @@ class TestNode : public td::actor::Actor {
if (R.is_error()) { if (R.is_error()) {
LOG(FATAL) << "bad b64 server public key: " << R.move_as_error(); LOG(FATAL) << "bad b64 server public key: " << R.move_as_error();
} }
remote_public_key_ = R.move_as_ok(); single_remote_public_key_ = R.move_as_ok();
} }
void set_fail_timeout(td::Timestamp ts) { void set_fail_timeout(td::Timestamp ts) {
fail_timeout_ = ts; fail_timeout_ = ts;
@ -439,7 +443,18 @@ class TestNode : public td::actor::Actor {
void got_result(td::Result<td::BufferSlice> R, td::Promise<td::BufferSlice> promise); void got_result(td::Result<td::BufferSlice> R, td::Promise<td::BufferSlice> promise);
void after_got_result(bool ok); void after_got_result(bool ok);
bool envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise); bool envelope_send_query_to_any(td::BufferSlice query, td::Promise<td::BufferSlice> promise);
bool envelope_send_query_to_shard(ton::ShardIdFull shard, td::BufferSlice query,
td::Promise<td::BufferSlice> promise);
bool envelope_send_query_to_account(ton::AccountIdPrefixFull prefix, td::BufferSlice query,
td::Promise<td::BufferSlice> promise);
bool envelope_send_query_to_server(td::int32 server_idx, td::BufferSlice query, td::Promise<td::BufferSlice> promise);
void start_client(int server_idx);
void conn_ready(int server_idx);
void conn_closed(int server_idx);
void parse_line(td::BufferSlice data); void parse_line(td::BufferSlice data);
TestNode() { TestNode() {

View file

@ -364,6 +364,7 @@ tonNode.blockSignature who:int256 signature:bytes = tonNode.BlockSignature;
tonNode.blockId workchain:int shard:long seqno:int = tonNode.BlockId; tonNode.blockId workchain:int shard:long seqno:int = tonNode.BlockId;
tonNode.blockIdExt workchain:int shard:long seqno:int root_hash:int256 file_hash:int256 = tonNode.BlockIdExt; tonNode.blockIdExt workchain:int shard:long seqno:int root_hash:int256 file_hash:int256 = tonNode.BlockIdExt;
tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt; tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt;
tonNode.shardId workchain:int shard:long = tonNode.ShardId;
tonNode.blockDescriptionEmpty = tonNode.BlockDescription; tonNode.blockDescriptionEmpty = tonNode.BlockDescription;
tonNode.blockDescription id:tonNode.blockIdExt = tonNode.BlockDescription; tonNode.blockDescription id:tonNode.blockIdExt = tonNode.BlockDescription;
@ -568,7 +569,8 @@ validator.config.global zero_state:tonNode.blockIdExt init_block:tonNode.blockId
config.global adnl:adnl.config.global dht:dht.config.global validator:validator.config.global = config.Global; config.global adnl:adnl.config.global dht:dht.config.global validator:validator.config.global = config.Global;
liteserver.desc id:PublicKey ip:int port:int = liteserver.Desc; liteserver.desc id:PublicKey ip:int port:int = liteserver.Desc;
liteclient.config.global liteservers:(vector liteserver.desc) validator:validator.config.global = liteclient.config.Global; liteserver.descV2 id:PublicKey ip:int port:int shards:(vector tonNode.shardId) = liteserver.Desc;
liteclient.config.global liteservers:(vector liteserver.Desc) validator:validator.config.global = liteclient.config.Global;
engine.adnl id:int256 category:int = engine.Adnl; engine.adnl id:int256 category:int = engine.Adnl;
engine.addr ip:int port:int categories:(vector int) priority_categories:(vector int) = engine.Addr; engine.addr ip:int port:int categories:(vector int) priority_categories:(vector int) = engine.Addr;
@ -578,7 +580,7 @@ engine.dht id:int256 = engine.Dht;
engine.validatorTempKey key:int256 expire_at:int = engine.ValidatorTempKey; engine.validatorTempKey key:int256 expire_at:int = engine.ValidatorTempKey;
engine.validatorAdnlAddress id:int256 expire_at:int = engine.ValidatorAdnlAddress; engine.validatorAdnlAddress id:int256 expire_at:int = engine.ValidatorAdnlAddress;
engine.validator id:int256 temp_keys:(vector engine.validatorTempKey) adnl_addrs:(vector engine.validatorAdnlAddress) election_date:int expire_at:int = engine.Validator; engine.validator id:int256 temp_keys:(vector engine.validatorTempKey) adnl_addrs:(vector engine.validatorAdnlAddress) election_date:int expire_at:int = engine.Validator;
engine.collator adnl_id:int256 workchain:int shard:long = engine.Validator; engine.collator adnl_id:int256 shard:tonNode.shardId = engine.Collator;
engine.liteServer id:int256 port:int = engine.LiteServer; engine.liteServer id:int256 port:int = engine.LiteServer;
engine.controlProcess id:int256 permissions:int = engine.ControlProcess; engine.controlProcess id:int256 permissions:int = engine.ControlProcess;
engine.controlInterface id:int256 port:int allowed:(vector engine.controlProcess) = engine.ControlInterface; engine.controlInterface id:int256 port:int allowed:(vector engine.controlProcess) = engine.ControlInterface;
@ -594,6 +596,15 @@ engine.validator.config out_port:int addrs:(vector engine.Addr) adnl:(vector eng
liteservers:(vector engine.liteServer) control:(vector engine.controlInterface) liteservers:(vector engine.liteServer) control:(vector engine.controlInterface)
gc:engine.gc = engine.validator.Config; gc:engine.gc = engine.validator.Config;
engine.validator.config_v2 out_port:int addrs:(vector engine.Addr) adnl:(vector engine.adnl)
dht:(vector engine.dht)
validators:(vector engine.validator) collators:(vector engine.collator)
fullnode:int256 fullnodeslaves:(vector engine.validator.fullNodeSlave)
fullnodemasters:(vector engine.validator.fullNodeMaster)
liteservers:(vector engine.liteServer) control:(vector engine.controlInterface)
shards_to_monitor:(vector tonNode.shardId)
gc:engine.gc = engine.validator.Config;
---functions--- ---functions---
---types--- ---types---
@ -697,7 +708,8 @@ engine.validator.generateBlockCandidate block_id:tonNode.BlockId = db.Candidate;
engine.validator.getRequiredBlockCandidates = engine.validator.RequiredBlockCandidates; engine.validator.getRequiredBlockCandidates = engine.validator.RequiredBlockCandidates;
engine.validator.importBlockCandidate block:db.candidate = engine.validator.Success; engine.validator.importBlockCandidate block:db.candidate = engine.validator.Success;
engine.validator.addCollator adnl_id:int256 workchain:int shard:long = engine.validator.Success; engine.validator.addCollator adnl_id:int256 shard:tonNode.shardId = engine.validator.Success;
engine.validator.addShard shard:tonNode.shardId = engine.validator.Success;
---types--- ---types---

Binary file not shown.

View file

@ -19,7 +19,8 @@
#pragma once #pragma once
#include "ton-types.h" #include "ton-types.h"
#include "auto/tl/ton_api.h" #include "auto/tl/ton_api.hpp"
#include "td/utils/overloaded.h"
namespace ton { namespace ton {
@ -53,4 +54,31 @@ inline ZeroStateIdExt create_zero_state_id(tl_object_ptr<ton_api::tonNode_zeroSt
return ZeroStateIdExt{B->workchain_, B->root_hash_, B->file_hash_}; return ZeroStateIdExt{B->workchain_, B->root_hash_, B->file_hash_};
} }
inline ShardIdFull create_shard_id(const tl_object_ptr<ton_api::tonNode_shardId> &s) {
return ShardIdFull{s->workchain_, static_cast<td::uint64>(s->shard_)};
}
inline tl_object_ptr<ton_api::tonNode_shardId> create_tl_shard_id(const ShardIdFull &s) {
return create_tl_object<ton_api::tonNode_shardId>(s.workchain, s.shard);
}
inline tl_object_ptr<ton_api::engine_validator_config_v2> unpack_engine_validator_config(
tl_object_ptr<ton_api::engine_validator_Config> config) {
tl_object_ptr<ton_api::engine_validator_config_v2> res;
ton_api::downcast_call(*config, td::overloaded(
[&](ton_api::engine_validator_config &c) {
res = create_tl_object<ton_api::engine_validator_config_v2>(
c.out_port_, std::move(c.addrs_), std::move(c.adnl_), std::move(c.dht_),
std::move(c.validators_),
std::vector<tl_object_ptr<ton_api::engine_collator>>(), c.fullnode_,
std::move(c.fullnodeslaves_), std::move(c.fullnodemasters_),
std::move(c.liteservers_), std::move(c.control_),
std::vector<tl_object_ptr<ton_api::tonNode_shardId>>(), std::move(c.gc_));
},
[&](ton_api::engine_validator_config_v2 &c) {
res = std::make_unique<ton_api::engine_validator_config_v2>(std::move(c));
}));
return res;
}
} // namespace ton } // namespace ton

View file

@ -1101,7 +1101,7 @@ td::Status AddCollatorQuery::run() {
td::Status AddCollatorQuery::send() { td::Status AddCollatorQuery::send() {
auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_addCollator>( auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_addCollator>(
adnl_id_.tl(), wc_, shard_); adnl_id_.tl(), ton::create_tl_shard_id(ton::ShardIdFull(wc_, shard_)));
td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise());
return td::Status::OK(); return td::Status::OK();
} }
@ -1112,3 +1112,23 @@ td::Status AddCollatorQuery::receive(td::BufferSlice data) {
td::TerminalIO::out() << "successfully added collator\n"; td::TerminalIO::out() << "successfully added collator\n";
return td::Status::OK(); return td::Status::OK();
} }
td::Status AddShardQuery::run() {
TRY_RESULT_ASSIGN(wc_, tokenizer_.get_token<td::int32>());
TRY_RESULT_ASSIGN(shard_, tokenizer_.get_token<td::int64>());
return td::Status::OK();
}
td::Status AddShardQuery::send() {
auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_addShard>(
ton::create_tl_shard_id(ton::ShardIdFull(wc_, shard_)));
td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise());
return td::Status::OK();
}
td::Status AddShardQuery::receive(td::BufferSlice data) {
TRY_RESULT_PREFIX(f, ton::fetch_tl_object<ton::ton_api::engine_validator_success>(data.as_slice(), true),
"received incorrect answer: ");
td::TerminalIO::out() << "successfully added shard\n";
return td::Status::OK();
}

View file

@ -1187,3 +1187,26 @@ class AddCollatorQuery : public Query {
td::int32 wc_; td::int32 wc_;
td::int64 shard_; td::int64 shard_;
}; };
class AddShardQuery : public Query {
public:
AddShardQuery(td::actor::ActorId<ValidatorEngineConsole> console, Tokenizer tokenizer)
: Query(console, std::move(tokenizer)) {
}
td::Status run() override;
td::Status send() override;
td::Status receive(td::BufferSlice data) override;
static std::string get_name() {
return "addshard";
}
static std::string get_help() {
return "addshard <workchain> <shard>\tstart monitoring shard";
}
std::string name() const override {
return get_name();
}
private:
td::int32 wc_;
td::int64 shard_;
};

View file

@ -145,6 +145,7 @@ void ValidatorEngineConsole::run() {
add_query_runner(std::make_unique<QueryRunnerImpl<GetRequiredBlockCandidatesQuery>>()); add_query_runner(std::make_unique<QueryRunnerImpl<GetRequiredBlockCandidatesQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<ImportBlockCandidateQuery>>()); add_query_runner(std::make_unique<QueryRunnerImpl<ImportBlockCandidateQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<AddCollatorQuery>>()); add_query_runner(std::make_unique<QueryRunnerImpl<AddCollatorQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<AddShardQuery>>());
} }
bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) { bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) {

View file

@ -54,6 +54,7 @@
#include "td/utils/Random.h" #include "td/utils/Random.h"
#include "auto/tl/lite_api.h" #include "auto/tl/lite_api.h"
#include "tl/tl_json.h"
#include "memprof/memprof.h" #include "memprof/memprof.h"
@ -74,7 +75,7 @@ Config::Config() {
full_node = ton::PublicKeyHash::zero(); full_node = ton::PublicKeyHash::zero();
} }
Config::Config(ton::ton_api::engine_validator_config &config) { Config::Config(const ton::ton_api::engine_validator_config_v2 &config) {
full_node = ton::PublicKeyHash::zero(); full_node = ton::PublicKeyHash::zero();
out_port = static_cast<td::uint16>(config.out_port_); out_port = static_cast<td::uint16>(config.out_port_);
if (!out_port) { if (!out_port) {
@ -87,7 +88,7 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
std::vector<AdnlCategory> categories; std::vector<AdnlCategory> categories;
std::vector<AdnlCategory> priority_categories; std::vector<AdnlCategory> priority_categories;
ton::ton_api::downcast_call( ton::ton_api::downcast_call(
*addr.get(), *addr,
td::overloaded( td::overloaded(
[&](const ton::ton_api::engine_addr &obj) { [&](const ton::ton_api::engine_addr &obj) {
in_ip.init_ipv4_port(td::IPAddress::ipv4_to_str(obj.ip_), static_cast<td::uint16>(obj.port_)).ensure(); in_ip.init_ipv4_port(td::IPAddress::ipv4_to_str(obj.ip_), static_cast<td::uint16>(obj.port_)).ensure();
@ -125,24 +126,20 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
for (auto &dht : config.dht_) { for (auto &dht : config.dht_) {
config_add_dht_node(ton::PublicKeyHash{dht->id_}).ensure(); config_add_dht_node(ton::PublicKeyHash{dht->id_}).ensure();
} }
for (auto &v : config.validators_) { for (auto &val : config.validators_) {
ton::ton_api::downcast_call( auto key = ton::PublicKeyHash{val->id_};
*v, td::overloaded( config_add_validator_permanent_key(key, val->election_date_, val->expire_at_).ensure();
[&](ton::ton_api::engine_validator &val) { for (auto &temp : val->temp_keys_) {
auto key = ton::PublicKeyHash{val.id_};
config_add_validator_permanent_key(key, val.election_date_, val.expire_at_).ensure();
for (auto &temp : val.temp_keys_) {
config_add_validator_temp_key(key, ton::PublicKeyHash{temp->key_}, temp->expire_at_).ensure(); config_add_validator_temp_key(key, ton::PublicKeyHash{temp->key_}, temp->expire_at_).ensure();
} }
for (auto &adnl : val.adnl_addrs_) { for (auto &adnl : val->adnl_addrs_) {
config_add_validator_adnl_id(key, ton::PublicKeyHash{adnl->id_}, adnl->expire_at_).ensure(); config_add_validator_adnl_id(key, ton::PublicKeyHash{adnl->id_}, adnl->expire_at_).ensure();
} }
}, }
[&](ton::ton_api::engine_collator &col) { for (auto &col : config.collators_) {
auto key = ton::PublicKeyHash{col.adnl_id_}; auto key = ton::PublicKeyHash{col->adnl_id_};
ton::ShardIdFull shard(col.workchain_, col.shard_); ton::ShardIdFull shard = ton::create_shard_id(col->shard_);
config_add_collator(key, shard).ensure(); config_add_collator(key, shard).ensure();
}));
} }
config_add_full_node_adnl_id(ton::PublicKeyHash{config.fullnode_}).ensure(); config_add_full_node_adnl_id(ton::PublicKeyHash{config.fullnode_}).ensure();
@ -169,6 +166,10 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
} }
} }
for (auto &shard : config.shards_to_monitor_) {
config_add_shard(ton::create_shard_id(shard)).ensure();
}
if (config.gc_) { if (config.gc_) {
for (auto &gc : config.gc_->ids_) { for (auto &gc : config.gc_->ids_) {
config_add_gc(ton::PublicKeyHash{gc}).ensure(); config_add_gc(ton::PublicKeyHash{gc}).ensure();
@ -176,7 +177,7 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
} }
} }
ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const { ton::tl_object_ptr<ton::ton_api::engine_validator_config_v2> Config::tl() const {
std::vector<ton::tl_object_ptr<ton::ton_api::engine_Addr>> addrs_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_Addr>> addrs_vec;
for (auto &x : addrs) { for (auto &x : addrs) {
if (x.second.proxy) { if (x.second.proxy) {
@ -201,7 +202,7 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
dht_vec.push_back(ton::create_tl_object<ton::ton_api::engine_dht>(x.tl())); dht_vec.push_back(ton::create_tl_object<ton::ton_api::engine_dht>(x.tl()));
} }
std::vector<ton::tl_object_ptr<ton::ton_api::engine_Validator>> val_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator>> val_vec;
for (auto &val : validators) { for (auto &val : validators) {
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validatorTempKey>> temp_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validatorTempKey>> temp_vec;
for (auto &t : val.second.temp_keys) { for (auto &t : val.second.temp_keys) {
@ -214,9 +215,10 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
val_vec.push_back(ton::create_tl_object<ton::ton_api::engine_validator>( val_vec.push_back(ton::create_tl_object<ton::ton_api::engine_validator>(
val.first.tl(), std::move(temp_vec), std::move(adnl_val_vec), val.second.election_date, val.second.expire_at)); val.first.tl(), std::move(temp_vec), std::move(adnl_val_vec), val.second.election_date, val.second.expire_at));
} }
std::vector<ton::tl_object_ptr<ton::ton_api::engine_collator>> col_vec;
for (auto &col : collators) { for (auto &col : collators) {
val_vec.push_back(ton::create_tl_object<ton::ton_api::engine_collator>( col_vec.push_back(
col.adnl_id.tl(), col.shard.workchain, col.shard.shard)); ton::create_tl_object<ton::ton_api::engine_collator>(col.adnl_id.tl(), ton::create_tl_shard_id(col.shard)));
} }
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeSlave>> full_node_slaves_vec; std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_fullNodeSlave>> full_node_slaves_vec;
@ -245,14 +247,19 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
std::move(control_proc_vec))); std::move(control_proc_vec)));
} }
std::vector<ton::tl_object_ptr<ton::ton_api::tonNode_shardId>> shards_vec;
for (auto &shard : shards_to_monitor) {
shards_vec.push_back(ton::create_tl_shard_id(shard));
}
auto gc_vec = ton::create_tl_object<ton::ton_api::engine_gc>(std::vector<td::Bits256>{}); auto gc_vec = ton::create_tl_object<ton::ton_api::engine_gc>(std::vector<td::Bits256>{});
for (auto &id : gc) { for (auto &id : gc) {
gc_vec->ids_.push_back(id.tl()); gc_vec->ids_.push_back(id.tl());
} }
return ton::create_tl_object<ton::ton_api::engine_validator_config>( return ton::create_tl_object<ton::ton_api::engine_validator_config_v2>(
out_port, std::move(addrs_vec), std::move(adnl_vec), std::move(dht_vec), std::move(val_vec), full_node.tl(), out_port, std::move(addrs_vec), std::move(adnl_vec), std::move(dht_vec), std::move(val_vec), std::move(col_vec),
std::move(full_node_slaves_vec), std::move(full_node_masters_vec), std::move(liteserver_vec), full_node.tl(), std::move(full_node_slaves_vec), std::move(full_node_masters_vec), std::move(liteserver_vec),
std::move(control_vec), std::move(gc_vec)); std::move(control_vec), std::move(shards_vec), std::move(gc_vec));
} }
td::Result<bool> Config::config_add_network_addr(td::IPAddress in_ip, td::IPAddress out_ip, td::Result<bool> Config::config_add_network_addr(td::IPAddress in_ip, td::IPAddress out_ip,
@ -527,6 +534,17 @@ td::Result<bool> Config::config_add_control_process(ton::PublicKeyHash key, td::
} }
} }
td::Result<bool> Config::config_add_shard(ton::ShardIdFull shard) {
if (!shard.is_valid_ext()) {
return td::Status::Error(PSTRING() << "invalid shard " << shard.to_str());
}
if (std::find(shards_to_monitor.begin(), shards_to_monitor.end(), shard) != shards_to_monitor.end()) {
return false;
}
shards_to_monitor.push_back(shard);
return true;
}
td::Result<bool> Config::config_add_gc(ton::PublicKeyHash key) { td::Result<bool> Config::config_add_gc(ton::PublicKeyHash key) {
return gc.insert(key).second; return gc.insert(key).second;
} }
@ -1393,6 +1411,11 @@ void ValidatorEngine::init_validator_options() {
for (const auto& c : config_.collators) { for (const auto& c : config_.collators) {
shards.push_back(c.shard); shards.push_back(c.shard);
} }
for (const auto& s : config_.shards_to_monitor) {
shards.push_back(s);
}
std::sort(shards.begin(), shards.end());
shards.erase(std::unique(shards.begin(), shards.end()), shards.end());
validator_options_.write().set_shard_check_function( validator_options_.write().set_shard_check_function(
[shards = std::move(shards)](ton::ShardIdFull shard, ton::CatchainSeqno cc_seqno, [shards = std::move(shards)](ton::ShardIdFull shard, ton::CatchainSeqno cc_seqno,
ton::validator::ValidatorManagerOptions::ShardCheckMode mode) -> bool { ton::validator::ValidatorManagerOptions::ShardCheckMode mode) -> bool {
@ -1643,14 +1666,14 @@ void ValidatorEngine::load_config(td::Promise<td::Unit> promise) {
} }
auto conf_json = conf_json_R.move_as_ok(); auto conf_json = conf_json_R.move_as_ok();
ton::ton_api::engine_validator_config conf; ton::tl_object_ptr<ton::ton_api::engine_validator_Config> conf;
auto S = ton::ton_api::from_json(conf, conf_json.get_object()); auto S = td::from_json(conf, std::move(conf_json));
if (S.is_error()) { if (S.is_error()) {
promise.set_error(S.move_as_error_prefix("json does not fit TL scheme")); promise.set_error(S.move_as_error_prefix("json does not fit TL scheme"));
return; return;
} }
config_ = Config{conf}; config_ = Config{*ton::unpack_engine_validator_config(std::move(conf))};
td::MultiPromise mp; td::MultiPromise mp;
auto ig = mp.init_guard(); auto ig = mp.init_guard();
@ -3471,15 +3494,10 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_addCollat
} }
auto id = ton::PublicKeyHash{query.adnl_id_}; auto id = ton::PublicKeyHash{query.adnl_id_};
auto shard = ton::ShardIdFull(query.workchain_, query.shard_); auto shard = ton::create_shard_id(query.shard_);
if (!shard.is_valid_ext()) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "invalid shard")));
return;
}
auto R = config_.config_add_collator(id, shard); auto R = config_.config_add_collator(id, shard);
if (R.is_error()) { if (R.is_error()) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized"))); promise.set_value(create_control_query_error(R.move_as_error()));
return; return;
} }
if (!R.move_as_ok()) { if (!R.move_as_ok()) {
@ -3499,6 +3517,27 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_addCollat
}); });
} }
void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_addShard &query,
td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm,
td::Promise<td::BufferSlice> promise) {
if (!(perm & ValidatorEnginePermissions::vep_modify)) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized")));
return;
}
if (!started_) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "not started")));
return;
}
auto shard = ton::create_shard_id(query.shard_);
auto R = config_.config_add_shard(shard);
if (R.is_error()) {
promise.set_value(create_control_query_error(R.move_as_error()));
return;
}
promise.set_value(ton::serialize_tl_object(ton::create_tl_object<ton::ton_api::engine_validator_success>(), true));
}
void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src, void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src,
ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data,
td::Promise<td::BufferSlice> promise) { td::Promise<td::BufferSlice> promise) {
@ -3532,7 +3571,7 @@ void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNode
} }
auto f = F.move_as_ok(); auto f = F.move_as_ok();
ton::ton_api::downcast_call(*f.get(), [&](auto &obj) { ton::ton_api::downcast_call(*f, [&](auto &obj) {
run_control_query(obj, std::move(data), src.pubkey_hash(), it->second, std::move(promise)); run_control_query(obj, std::move(data), src.pubkey_hash(), it->second, std::move(promise));
}); });
} }
@ -3752,7 +3791,7 @@ int main(int argc, char *argv[]) {
}); });
return td::Status::OK(); return td::Status::OK();
}); });
p.add_option('M', "masterchain-only", "don't track shardchains", [&]() { p.add_option('M', "not-all-shards", "monitor only a necessary set of shards instead of all", [&]() {
acts.push_back([&x]() { td::actor::send_closure(x, &ValidatorEngine::set_masterchain_only); }); acts.push_back([&x]() { td::actor::send_closure(x, &ValidatorEngine::set_masterchain_only); });
}); });
td::uint32 threads = 7; td::uint32 threads = 7;

View file

@ -96,6 +96,7 @@ struct Config {
std::map<td::int32, ton::PublicKeyHash> liteservers; std::map<td::int32, ton::PublicKeyHash> liteservers;
std::map<td::int32, Control> controls; std::map<td::int32, Control> controls;
std::set<ton::PublicKeyHash> gc; std::set<ton::PublicKeyHash> gc;
std::vector<ton::ShardIdFull> shards_to_monitor;
void decref(ton::PublicKeyHash key); void decref(ton::PublicKeyHash key);
void incref(ton::PublicKeyHash key) { void incref(ton::PublicKeyHash key) {
@ -121,6 +122,7 @@ struct Config {
td::Result<bool> config_add_control_interface(ton::PublicKeyHash key, td::int32 port); td::Result<bool> config_add_control_interface(ton::PublicKeyHash key, td::int32 port);
td::Result<bool> config_add_control_process(ton::PublicKeyHash key, td::int32 port, ton::PublicKeyHash id, td::Result<bool> config_add_control_process(ton::PublicKeyHash key, td::int32 port, ton::PublicKeyHash id,
td::uint32 permissions); td::uint32 permissions);
td::Result<bool> config_add_shard(ton::ShardIdFull shard);
td::Result<bool> config_add_gc(ton::PublicKeyHash key); td::Result<bool> config_add_gc(ton::PublicKeyHash key);
td::Result<bool> config_del_network_addr(td::IPAddress addr, std::vector<AdnlCategory> cats, td::Result<bool> config_del_network_addr(td::IPAddress addr, std::vector<AdnlCategory> cats,
std::vector<AdnlCategory> prio_cats); std::vector<AdnlCategory> prio_cats);
@ -135,10 +137,10 @@ struct Config {
td::Result<bool> config_del_control_process(td::int32 port, ton::PublicKeyHash id); td::Result<bool> config_del_control_process(td::int32 port, ton::PublicKeyHash id);
td::Result<bool> config_del_gc(ton::PublicKeyHash key); td::Result<bool> config_del_gc(ton::PublicKeyHash key);
ton::tl_object_ptr<ton::ton_api::engine_validator_config> tl() const; ton::tl_object_ptr<ton::ton_api::engine_validator_config_v2> tl() const;
Config(); Config();
Config(ton::ton_api::engine_validator_config &config); Config(const ton::ton_api::engine_validator_config_v2 &config);
}; };
class ValidatorEngine : public td::actor::Actor { class ValidatorEngine : public td::actor::Actor {
@ -434,6 +436,8 @@ class ValidatorEngine : public td::actor::Actor {
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise); ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
void run_control_query(ton::ton_api::engine_validator_addCollator &query, td::BufferSlice data, void run_control_query(ton::ton_api::engine_validator_addCollator &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise); ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
void run_control_query(ton::ton_api::engine_validator_addShard &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
template <class T> template <class T>
void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm,
td::Promise<td::BufferSlice> promise) { td::Promise<td::BufferSlice> promise) {