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:
parent
a792565afa
commit
51e6885f2c
12 changed files with 657 additions and 363 deletions
|
@ -38,6 +38,9 @@
|
|||
#include "td/utils/TsFileLog.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
#include "ton/ton-tl.hpp"
|
||||
#include "tl/tl_json.h"
|
||||
|
||||
#include "memprof/memprof.h"
|
||||
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
|
@ -54,7 +57,7 @@ Config::Config() {
|
|||
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_);
|
||||
if (!out_port) {
|
||||
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;
|
||||
for (auto &x : addrs) {
|
||||
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()));
|
||||
}
|
||||
|
||||
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_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();
|
||||
|
||||
ton::ton_api::engine_validator_config conf;
|
||||
auto S = ton::ton_api::from_json(conf, conf_json.get_object());
|
||||
ton::tl_object_ptr<ton::ton_api::engine_validator_Config> conf;
|
||||
auto S = td::from_json(conf, std::move(conf_json));
|
||||
if (S.is_error()) {
|
||||
promise.set_error(S.move_as_error_prefix("json does not fit TL scheme"));
|
||||
return;
|
||||
}
|
||||
|
||||
config_ = Config{conf};
|
||||
config_ = Config{*ton::unpack_engine_validator_config(std::move(conf))};
|
||||
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
|
|
|
@ -91,10 +91,10 @@ struct Config {
|
|||
td::Result<bool> config_del_control_process(td::int32 port, ton::PublicKeyHash id);
|
||||
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(ton::ton_api::engine_validator_config &config);
|
||||
Config(const ton::ton_api::engine_validator_config_v2 &config);
|
||||
};
|
||||
|
||||
class DhtServer : public td::actor::Actor {
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
#include "td/utils/crypto.h"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/utils/port/signals.h"
|
||||
#include "td/utils/port/stacktrace.h"
|
||||
#include "td/utils/port/StdStreams.h"
|
||||
#include "td/utils/port/FileFd.h"
|
||||
#include "terminal/terminal.h"
|
||||
#include "ton/lite-tl.hpp"
|
||||
|
@ -59,17 +57,14 @@
|
|||
#include "vm/cp0.h"
|
||||
#include "vm/memo.h"
|
||||
#include "ton/ton-shard.h"
|
||||
#include "openssl/rand.hpp"
|
||||
#include "crypto/vm/utils.h"
|
||||
#include "crypto/common/util.h"
|
||||
#include "common/checksum.h"
|
||||
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "git.h"
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
@ -77,22 +72,27 @@ using td::Ref;
|
|||
|
||||
int verbosity;
|
||||
|
||||
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> TestNode::make_callback() {
|
||||
class Callback : public ton::adnl::AdnlExtClient::Callback {
|
||||
public:
|
||||
void on_ready() override {
|
||||
td::actor::send_closure(id_, &TestNode::conn_ready);
|
||||
int TestNode::LiteServer::max_common_prefix(ton::ShardIdFull shard) const {
|
||||
if (shard.is_masterchain()) {
|
||||
return 0;
|
||||
}
|
||||
void on_stop_ready() override {
|
||||
td::actor::send_closure(id_, &TestNode::conn_closed);
|
||||
if (is_full) {
|
||||
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:
|
||||
td::actor::ActorId<TestNode> id_;
|
||||
};
|
||||
return std::make_unique<Callback>(actor_id(this));
|
||||
bool TestNode::LiteServer::supports_shard(ton::ShardIdFull shard) const {
|
||||
return is_full || shard.is_masterchain() ||
|
||||
std::any_of(shards.begin(), shards.end(),
|
||||
[&](const ton::ShardIdFull& our_shard) { return ton::shard_is_ancestor(shard, our_shard); });
|
||||
}
|
||||
|
||||
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)));
|
||||
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 gc_j = td::json_decode(G.as_slice()).move_as_ok();
|
||||
ton::ton_api::liteclient_config_global gc;
|
||||
ton::ton_api::from_json(gc, gc_j.get_object()).ensure();
|
||||
CHECK(gc.liteservers_.size() > 0);
|
||||
auto idx = liteserver_idx_ >= 0 ? liteserver_idx_
|
||||
: td::Random::fast(0, static_cast<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_) {
|
||||
zstate_id_.workchain = gc.validator_->zero_state_->workchain_;
|
||||
if (zstate_id_.workchain != ton::workchainInvalid) {
|
||||
|
@ -131,10 +134,34 @@ void TestNode::run() {
|
|||
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_ =
|
||||
ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_, make_callback());
|
||||
if (single_liteserver_idx_ != -1) { // Use single liteserver from config
|
||||
CHECK(single_liteserver_idx_ >= 0 && (size_t)single_liteserver_idx_ < gc.liteservers_.size());
|
||||
td::TerminalIO::out() << "using liteserver " << single_liteserver_idx_ << " with addr "
|
||||
<< servers_[single_liteserver_idx_].addr << "\n";
|
||||
}
|
||||
|
||||
run_init_queries();
|
||||
}
|
||||
|
||||
void TestNode::got_result(td::Result<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_++;
|
||||
if (!ready_ || client_.empty()) {
|
||||
got_result(td::Status::Error("failed to send query to server: not ready"), std::move(promise));
|
||||
got_result(td::Status::Error("failed to select a suitable server"), std::move(promise));
|
||||
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(
|
||||
[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::BufferSlice b =
|
||||
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));
|
||||
} 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;
|
||||
}
|
||||
|
||||
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() {
|
||||
return td::PromiseCreator::lambda([Self = actor_id(this)](td::Result<td::Unit> res) {
|
||||
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() {
|
||||
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()) {
|
||||
LOG(ERROR) << "cannot get server time";
|
||||
return;
|
||||
|
@ -319,9 +479,10 @@ bool TestNode::get_server_time() {
|
|||
if (F.is_error()) {
|
||||
LOG(ERROR) << "cannot parse answer to liteServer.getTime";
|
||||
} else {
|
||||
server_time_ = F.move_as_ok()->now_;
|
||||
server_time_got_at_ = now();
|
||||
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")";
|
||||
mc_server_time_ = F.move_as_ok()->now_;
|
||||
mc_server_time_got_at_ = now();
|
||||
LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_
|
||||
<< ")";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -329,13 +490,13 @@ bool TestNode::get_server_time() {
|
|||
|
||||
bool TestNode::get_server_version(int mode) {
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
|
||||
server_ok_ = false;
|
||||
mc_server_ok_ = false;
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << "cannot get server version and time (server too old?)";
|
||||
} else {
|
||||
|
@ -344,11 +505,11 @@ void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
|
|||
LOG(ERROR) << "cannot parse answer to liteServer.getVersion";
|
||||
} else {
|
||||
auto a = F.move_as_ok();
|
||||
set_server_version(a->version_, a->capabilities_);
|
||||
set_server_time(a->now_);
|
||||
set_mc_server_version(a->version_, a->capabilities_);
|
||||
set_mc_server_time(a->now_);
|
||||
}
|
||||
}
|
||||
if (!server_ok_) {
|
||||
if (!mc_server_ok_) {
|
||||
LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff)
|
||||
<< " with capabilities " << min_ls_capabilities << " required), some queries are unavailable";
|
||||
}
|
||||
|
@ -357,27 +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) {
|
||||
if (server_version_ != version || server_capabilities_ != capabilities) {
|
||||
server_version_ = version;
|
||||
server_capabilities_ = capabilities;
|
||||
LOG(WARNING) << "server version is " << (server_version_ >> 8) << "." << (server_version_ & 0xff)
|
||||
<< ", capabilities " << server_capabilities_;
|
||||
void TestNode::set_mc_server_version(td::int32 version, td::int64 capabilities) {
|
||||
if (mc_server_version_ != version || mc_server_capabilities_ != capabilities) {
|
||||
mc_server_version_ = version;
|
||||
mc_server_capabilities_ = capabilities;
|
||||
LOG(WARNING) << "server version is " << (mc_server_version_ >> 8) << "." << (mc_server_version_ & 0xff)
|
||||
<< ", capabilities " << mc_server_capabilities_;
|
||||
}
|
||||
server_ok_ = (server_version_ >= min_ls_version) && !(~server_capabilities_ & min_ls_capabilities);
|
||||
mc_server_ok_ = (mc_server_version_ >= min_ls_version) && !(~mc_server_capabilities_ & min_ls_capabilities);
|
||||
}
|
||||
|
||||
void TestNode::set_server_time(int server_utime) {
|
||||
server_time_ = server_utime;
|
||||
server_time_got_at_ = now();
|
||||
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")";
|
||||
void TestNode::set_mc_server_time(int server_utime) {
|
||||
mc_server_time_ = server_utime;
|
||||
mc_server_time_got_at_ = now();
|
||||
LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_ << ")";
|
||||
}
|
||||
|
||||
bool TestNode::get_server_mc_block_id() {
|
||||
int mode = (server_capabilities_ & 2) ? 0 : -1;
|
||||
int mode = (mc_server_capabilities_ & 2) ? 0 : -1;
|
||||
if (mode < 0) {
|
||||
auto b = ton::serialize_tl_object(ton::create_tl_object<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()) {
|
||||
LOG(ERROR) << "cannot get masterchain info from server";
|
||||
return;
|
||||
|
@ -397,7 +558,8 @@ bool TestNode::get_server_mc_block_id() {
|
|||
} else {
|
||||
auto b =
|
||||
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()) {
|
||||
LOG(ERROR) << "cannot get extended masterchain info from server";
|
||||
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,
|
||||
long long capabilities, int last_utime, int server_now) {
|
||||
set_server_version(version, capabilities);
|
||||
set_server_time(server_now);
|
||||
set_mc_server_version(version, capabilities);
|
||||
set_mc_server_time(server_now);
|
||||
if (last_utime > server_now) {
|
||||
LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime
|
||||
<< " (" << last_utime - server_now << " seconds in the future)";
|
||||
|
@ -457,10 +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()
|
||||
<< " created at " << last_utime << " (" << server_now - last_utime
|
||||
<< " seconds ago according to the server's clock)";
|
||||
} else if (last_utime < server_time_got_at_ - 60) {
|
||||
} else if (last_utime < mc_server_time_got_at_ - 60) {
|
||||
LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain "
|
||||
"block known to server is "
|
||||
<< blkid.to_str() << " created at " << last_utime << " (" << server_now - server_time_got_at_
|
||||
<< blkid.to_str() << " created at " << last_utime << " (" << server_now - mc_server_time_got_at_
|
||||
<< " seconds ago according to the local clock)";
|
||||
}
|
||||
got_server_mc_block_id(blkid, zstateid, last_utime);
|
||||
|
@ -469,7 +631,8 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI
|
|||
bool TestNode::request_block(ton::BlockIdExt blkid) {
|
||||
auto b = ton::serialize_tl_object(
|
||||
ton::create_tl_object<ton::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()) {
|
||||
LOG(ERROR) << "cannot obtain block " << blkid.to_str() << " from server";
|
||||
return;
|
||||
|
@ -494,7 +657,8 @@ bool TestNode::request_block(ton::BlockIdExt blkid) {
|
|||
bool TestNode::request_state(ton::BlockIdExt blkid) {
|
||||
auto b = ton::serialize_tl_object(
|
||||
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()) {
|
||||
LOG(ERROR) << "cannot obtain state " << blkid.to_str() << " from server";
|
||||
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();
|
||||
return err;
|
||||
}
|
||||
if (ready_ && !client_.empty()) {
|
||||
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) {
|
||||
if (R.is_error()) {
|
||||
return;
|
||||
|
@ -1165,11 +1339,8 @@ td::Status TestNode::send_ext_msg_from_filename(std::string filename) {
|
|||
});
|
||||
auto b =
|
||||
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");
|
||||
} else {
|
||||
return td::Status::Error("server connection not ready");
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
return set_error("must obtain last block information before making other queries");
|
||||
}
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
if (addr_ext) {
|
||||
return get_special_smc_addr(addr_ext, [this, ref_blkid, filename, mode](td::Result<ton::StdSmcAddress> res) {
|
||||
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>(
|
||||
ton::create_tl_lite_block_id(ref_blkid), std::move(a)),
|
||||
true);
|
||||
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
|
||||
LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to "
|
||||
<< ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode;
|
||||
return envelope_send_query(
|
||||
std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result<td::BufferSlice> R) {
|
||||
return envelope_send_query_to_account(
|
||||
account_prefix, std::move(b),
|
||||
[Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1275,18 +1445,17 @@ bool TestNode::start_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
|
|||
if (!ref_blkid.is_valid()) {
|
||||
return set_error("must obtain last block information before making other queries");
|
||||
}
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr);
|
||||
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
|
||||
if (!mode) {
|
||||
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>(
|
||||
ton::create_tl_lite_block_id(ref_blkid), std::move(a)),
|
||||
true);
|
||||
LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to "
|
||||
<< ref_blkid.to_str() << " to run method " << method_name << " with " << params.size() << " parameters";
|
||||
return envelope_send_query(
|
||||
std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params),
|
||||
return envelope_send_query_to_account(
|
||||
account_prefix, std::move(b),
|
||||
[Self = actor_id(this), workchain, addr, ref_blkid, method_name, params = std::move(params),
|
||||
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_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()
|
||||
<< " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with "
|
||||
<< params.size() << " parameters";
|
||||
return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode,
|
||||
params = std::move(params),
|
||||
return envelope_send_query_to_account(
|
||||
account_prefix, std::move(b),
|
||||
[Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, params = std::move(params),
|
||||
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_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"));
|
||||
} else {
|
||||
auto f = F.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_),
|
||||
ton::create_block_id(f->shardblk_), std::move(f->shard_proof_),
|
||||
std::move(f->proof_), std::move(f->state_proof_), workchain, addr, method_name,
|
||||
std::move(params), std::move(f->init_c7_), std::move(f->lib_extras_),
|
||||
std::move(f->result_), f->exit_code_, std::move(promise));
|
||||
td::actor::send_closure_later(
|
||||
Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_),
|
||||
ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), std::move(f->proof_),
|
||||
std::move(f->state_proof_), workchain, addr, method_name, std::move(params), std::move(f->init_c7_),
|
||||
std::move(f->lib_extras_), std::move(f->result_), f->exit_code_, std::move(promise));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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(expires_in));
|
||||
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()) {
|
||||
LOG(ERROR) << R.move_as_error();
|
||||
return;
|
||||
|
@ -1639,10 +1809,6 @@ bool TestNode::dns_resolve_start(ton::WorkchainId workchain, ton::StdSmcAddress
|
|||
return set_error("domain name too long");
|
||||
}
|
||||
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
|
||||
if (workchain == ton::workchainInvalid) {
|
||||
if (dns_root_queried_) {
|
||||
workchain = ton::masterchainId;
|
||||
|
@ -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))) {
|
||||
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 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),
|
||||
true);
|
||||
ton::AccountIdPrefixFull account_prefix(workchain, addr.bits().get_uint(64));
|
||||
LOG(INFO) << "requesting transaction " << lt << " of " << workchain << ":" << addr.to_hex() << " from block "
|
||||
<< blkid.to_str();
|
||||
return envelope_send_query(
|
||||
std::move(b), [Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result<td::BufferSlice> R) -> void {
|
||||
return envelope_send_query_to_account(
|
||||
account_prefix, std::move(b),
|
||||
[Self = actor_id(this), workchain, addr, lt, blkid, dump](td::Result<td::BufferSlice> R) -> void {
|
||||
if (R.is_error()) {
|
||||
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,
|
||||
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 b = ton::serialize_tl_object(
|
||||
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
|
||||
<< ":" << addr.to_hex();
|
||||
return envelope_send_query(
|
||||
std::move(b), [Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result<td::BufferSlice> R) {
|
||||
return envelope_send_query_to_account(
|
||||
account_prefix, std::move(b),
|
||||
[Self = actor_id(this), workchain, addr, lt, hash, count, dump](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
} catch (vm::VmError err) {
|
||||
} catch (vm::VmError &err) {
|
||||
LOG(ERROR) << "error while traversing block transaction proof : " << err.get_msg();
|
||||
return;
|
||||
} catch (vm::VmVirtError err) {
|
||||
} catch (vm::VmVirtError &err) {
|
||||
LOG(ERROR) << "virtualization error while traversing block transaction proof : " << err.get_msg();
|
||||
return;
|
||||
}
|
||||
|
@ -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,
|
||||
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 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),
|
||||
true);
|
||||
LOG(INFO) << "requesting " << count << " transactions from block " << blkid.to_str() << " starting from account "
|
||||
<< acc_addr.to_hex() << " lt " << lt;
|
||||
return envelope_send_query(std::move(b), [Self = actor_id(this), mode](td::Result<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()) {
|
||||
return;
|
||||
}
|
||||
|
@ -2469,13 +2631,11 @@ bool TestNode::get_all_shards(std::string filename, bool use_last, ton::BlockIdE
|
|||
if (!blkid.is_masterchain()) {
|
||||
return set_error("only masterchain blocks contain shard configuration");
|
||||
}
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
auto b = ton::serialize_tl_object(
|
||||
ton::create_tl_object<ton::lite_api::liteServer_getAllShardsInfo>(ton::create_tl_lite_block_id(blkid)), true);
|
||||
LOG(INFO) << "requesting recent shard configuration";
|
||||
return envelope_send_query(std::move(b), [Self = actor_id(this), filename](td::Result<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()) {
|
||||
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";
|
||||
} else {
|
||||
auto f = F.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_), std::move(f->proof_),
|
||||
std::move(f->data_), filename);
|
||||
td::actor::send_closure_later(Self, &TestNode::got_all_shards, ton::create_block_id(f->id_),
|
||||
std::move(f->proof_), std::move(f->data_), filename);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2551,9 +2711,6 @@ bool TestNode::parse_get_config_params(ton::BlockIdExt blkid, int mode, std::str
|
|||
params.push_back(x);
|
||||
}
|
||||
}
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
if (!blkid.is_masterchain_ext()) {
|
||||
return set_error("only masterchain blocks contain configuration");
|
||||
}
|
||||
|
@ -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,
|
||||
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()) {
|
||||
promise.set_error(td::Status::Error("masterchain reference block expected"));
|
||||
return false;
|
||||
|
@ -2593,7 +2746,8 @@ bool TestNode::get_config_params_ext(ton::BlockIdExt blkid, td::Promise<ConfigIn
|
|||
true);
|
||||
LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block "
|
||||
<< 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 {
|
||||
td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, mode, filename, std::move(params),
|
||||
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();
|
||||
auto b = ton::serialize_tl_object(
|
||||
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, dump](td::Result<td::BufferSlice> res) -> void {
|
||||
return envelope_send_query_to_shard(
|
||||
blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void {
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << "cannot obtain block " << blkid.to_str()
|
||||
<< " 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();
|
||||
auto b = ton::serialize_tl_object(
|
||||
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, dump](td::Result<td::BufferSlice> res) -> void {
|
||||
return envelope_send_query_to_shard(
|
||||
blkid.shard_full(), std::move(b), [Self = actor_id(this), blkid, dump](td::Result<td::BufferSlice> res) -> void {
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << "cannot obtain state " << blkid.to_str()
|
||||
<< " 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) {
|
||||
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()) {
|
||||
LOG(ERROR) << "unable to fetch block header: " << R.move_as_error();
|
||||
} 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;
|
||||
auto b = ton::serialize_tl_object(
|
||||
ton::create_tl_object<ton::lite_api::liteServer_getBlockHeader>(ton::create_tl_lite_block_id(blkid), mode), true);
|
||||
return envelope_send_query(
|
||||
std::move(b), [this, blkid, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void {
|
||||
return envelope_send_query_to_shard(
|
||||
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),
|
||||
PSLICE() << "cannot obtain block header for " << blkid.to_str() << " from server :");
|
||||
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>(
|
||||
mode, ton::create_tl_lite_block_id_simple(id), arg, (td::uint32)arg),
|
||||
true);
|
||||
return envelope_send_query(
|
||||
std::move(b), [this, id, mode, arg, promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable -> void {
|
||||
return envelope_send_query_to_shard(
|
||||
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),
|
||||
PSLICE() << "cannot look up block header for " << id.to_str() << " with mode " << mode
|
||||
<< " and argument " << arg << " from server :");
|
||||
|
@ -3109,9 +3264,9 @@ void TestNode::got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int
|
|||
return;
|
||||
}
|
||||
show_block_header(blkid, std::move(virt_root), mode);
|
||||
} catch (vm::VmError err) {
|
||||
} catch (vm::VmError &err) {
|
||||
LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg();
|
||||
} catch (vm::VmVirtError err) {
|
||||
} catch (vm::VmVirtError &err) {
|
||||
LOG(ERROR) << "error processing header for " << blkid.to_str() << " : " << err.get_msg();
|
||||
}
|
||||
show_new_blkids();
|
||||
|
@ -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>(
|
||||
mode & 0xfff, ton::create_tl_lite_block_id(from), ton::create_tl_lite_block_id(to)),
|
||||
true);
|
||||
return envelope_send_query(std::move(b), [Self = actor_id(this), from, to, mode](td::Result<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()) {
|
||||
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();
|
||||
|
@ -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,
|
||||
ton::UnixTime min_utime) {
|
||||
if (!(ready_ && !client_.empty())) {
|
||||
return set_error("server connection not ready");
|
||||
}
|
||||
if (!blkid.is_masterchain_ext()) {
|
||||
return set_error("only masterchain blocks contain block creator statistics");
|
||||
}
|
||||
|
@ -3214,7 +3367,7 @@ bool TestNode::get_creator_stats(ton::BlockIdExt blkid, int mode, unsigned req_c
|
|||
auto& os = *osp;
|
||||
return get_creator_stats(
|
||||
blkid, mode, req_count, start_after, min_utime,
|
||||
[min_utime, &os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt,
|
||||
[&os](const td::Bits256& key, const block::DiscountedCounter& mc_cnt,
|
||||
const block::DiscountedCounter& shard_cnt) -> bool {
|
||||
os << key.to_hex() << " mc_cnt:" << mc_cnt << " shard_cnt:" << shard_cnt << std::endl;
|
||||
return true;
|
||||
|
@ -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,
|
||||
TestNode::creator_stats_func_t func, std::unique_ptr<TestNode::CreatorStatsRes> state,
|
||||
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) {
|
||||
promise.set_error(td::Status::Error("null CreatorStatsRes"));
|
||||
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 "
|
||||
<< blkid.to_str() << " starting from validator public key " << state->last_key.to_hex() << " created after "
|
||||
<< min_utime << " (mode=" << state->mode << ")";
|
||||
return envelope_send_query(
|
||||
return envelope_send_query_to_any(
|
||||
std::move(b), [this, blkid, req_count, state = std::move(state), min_utime, func = std::move(func),
|
||||
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
|
||||
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;
|
||||
return get_creator_stats(
|
||||
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 {
|
||||
info.store_record(key, mc_cnt, shard_cnt);
|
||||
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;
|
||||
if (tlb::csr_unpack(entry, rec1)) {
|
||||
pk = std::move(rec1.public_key);
|
||||
} else if (tlb::csr_unpack(std::move(entry), rec2)) {
|
||||
} else if (tlb::csr_unpack(entry, rec2)) {
|
||||
pk = std::move(rec2.public_key);
|
||||
} else {
|
||||
return td::Status::Error("cannot unpack ValidatorDescr");
|
||||
|
|
|
@ -45,22 +45,41 @@ class TestNode : public td::actor::Actor {
|
|||
min_ls_version = 0x101,
|
||||
min_ls_capabilities = 1
|
||||
}; // server version >= 1.1, capabilities at least +1 = build proof chains
|
||||
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client_;
|
||||
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 server_ok_ = false;
|
||||
td::int32 liteserver_idx_ = -1;
|
||||
int print_limit_ = 1024;
|
||||
|
||||
bool ready_ = false;
|
||||
bool inited_ = false;
|
||||
std::string db_root_;
|
||||
|
||||
int server_time_ = 0;
|
||||
int server_time_got_at_ = 0;
|
||||
int server_version_ = 0;
|
||||
long long server_capabilities_ = 0;
|
||||
// mc_server is the server for queries to masterchain
|
||||
int mc_server_idx_ = -1;
|
||||
int mc_server_time_ = 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::BlockIdExt mc_last_id_;
|
||||
|
@ -75,9 +94,6 @@ class TestNode : public td::actor::Actor {
|
|||
const char *parse_ptr_, *parse_end_;
|
||||
td::Status error_;
|
||||
|
||||
td::IPAddress remote_addr_;
|
||||
ton::PublicKey remote_public_key_;
|
||||
|
||||
std::vector<ton::BlockIdExt> known_blk_ids_;
|
||||
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::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback();
|
||||
|
||||
using creator_stats_func_t =
|
||||
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_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version,
|
||||
long long capabilities, int last_utime, int server_now);
|
||||
void set_server_version(td::int32 version, td::int64 capabilities);
|
||||
void set_server_time(int server_utime);
|
||||
void set_mc_server_version(td::int32 version, td::int64 capabilities);
|
||||
void set_mc_server_time(int server_utime);
|
||||
bool request_block(ton::BlockIdExt blkid);
|
||||
bool request_state(ton::BlockIdExt blkid);
|
||||
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();
|
||||
|
||||
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) {
|
||||
global_config_ = str;
|
||||
}
|
||||
|
@ -378,10 +382,10 @@ class TestNode : public td::actor::Actor {
|
|||
readline_enabled_ = value;
|
||||
}
|
||||
void set_liteserver_idx(td::int32 idx) {
|
||||
liteserver_idx_ = idx;
|
||||
single_liteserver_idx_ = idx;
|
||||
}
|
||||
void set_remote_addr(td::IPAddress addr) {
|
||||
remote_addr_ = addr;
|
||||
single_remote_addr_ = addr;
|
||||
}
|
||||
void set_public_key(td::BufferSlice file_name) {
|
||||
auto R = [&]() -> td::Result<ton::PublicKey> {
|
||||
|
@ -392,7 +396,7 @@ class TestNode : public td::actor::Actor {
|
|||
if (R.is_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) {
|
||||
auto R = [&]() -> td::Result<ton::PublicKey> {
|
||||
|
@ -404,7 +408,7 @@ class TestNode : public td::actor::Actor {
|
|||
if (R.is_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) {
|
||||
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 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);
|
||||
|
||||
TestNode() {
|
||||
|
|
|
@ -364,6 +364,7 @@ tonNode.blockSignature who:int256 signature:bytes = tonNode.BlockSignature;
|
|||
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.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode.ZeroStateIdExt;
|
||||
tonNode.shardId workchain:int shard:long = tonNode.ShardId;
|
||||
|
||||
tonNode.blockDescriptionEmpty = 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;
|
||||
|
||||
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.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.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.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.controlProcess id:int256 permissions:int = engine.ControlProcess;
|
||||
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)
|
||||
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---
|
||||
---types---
|
||||
|
||||
|
@ -697,7 +708,8 @@ engine.validator.generateBlockCandidate block_id:tonNode.BlockId = db.Candidate;
|
|||
engine.validator.getRequiredBlockCandidates = engine.validator.RequiredBlockCandidates;
|
||||
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---
|
||||
|
||||
|
|
Binary file not shown.
|
@ -19,7 +19,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "ton-types.h"
|
||||
#include "auto/tl/ton_api.h"
|
||||
#include "auto/tl/ton_api.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
|
||||
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_};
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1101,7 +1101,7 @@ td::Status AddCollatorQuery::run() {
|
|||
|
||||
td::Status AddCollatorQuery::send() {
|
||||
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());
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
@ -1112,3 +1112,23 @@ td::Status AddCollatorQuery::receive(td::BufferSlice data) {
|
|||
td::TerminalIO::out() << "successfully added collator\n";
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -1187,3 +1187,26 @@ class AddCollatorQuery : public Query {
|
|||
td::int32 wc_;
|
||||
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_;
|
||||
};
|
||||
|
|
|
@ -145,6 +145,7 @@ void ValidatorEngineConsole::run() {
|
|||
add_query_runner(std::make_unique<QueryRunnerImpl<GetRequiredBlockCandidatesQuery>>());
|
||||
add_query_runner(std::make_unique<QueryRunnerImpl<ImportBlockCandidateQuery>>());
|
||||
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) {
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "td/utils/Random.h"
|
||||
|
||||
#include "auto/tl/lite_api.h"
|
||||
#include "tl/tl_json.h"
|
||||
|
||||
#include "memprof/memprof.h"
|
||||
|
||||
|
@ -74,7 +75,7 @@ Config::Config() {
|
|||
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();
|
||||
out_port = static_cast<td::uint16>(config.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> priority_categories;
|
||||
ton::ton_api::downcast_call(
|
||||
*addr.get(),
|
||||
*addr,
|
||||
td::overloaded(
|
||||
[&](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();
|
||||
|
@ -125,24 +126,20 @@ Config::Config(ton::ton_api::engine_validator_config &config) {
|
|||
for (auto &dht : config.dht_) {
|
||||
config_add_dht_node(ton::PublicKeyHash{dht->id_}).ensure();
|
||||
}
|
||||
for (auto &v : config.validators_) {
|
||||
ton::ton_api::downcast_call(
|
||||
*v, td::overloaded(
|
||||
[&](ton::ton_api::engine_validator &val) {
|
||||
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_) {
|
||||
for (auto &val : config.validators_) {
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
},
|
||||
[&](ton::ton_api::engine_collator &col) {
|
||||
auto key = ton::PublicKeyHash{col.adnl_id_};
|
||||
ton::ShardIdFull shard(col.workchain_, col.shard_);
|
||||
}
|
||||
for (auto &col : config.collators_) {
|
||||
auto key = ton::PublicKeyHash{col->adnl_id_};
|
||||
ton::ShardIdFull shard = ton::create_shard_id(col->shard_);
|
||||
config_add_collator(key, shard).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_) {
|
||||
for (auto &gc : config.gc_->ids_) {
|
||||
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;
|
||||
for (auto &x : addrs) {
|
||||
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()));
|
||||
}
|
||||
|
||||
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) {
|
||||
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validatorTempKey>> temp_vec;
|
||||
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.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) {
|
||||
val_vec.push_back(ton::create_tl_object<ton::ton_api::engine_collator>(
|
||||
col.adnl_id.tl(), col.shard.workchain, col.shard.shard));
|
||||
col_vec.push_back(
|
||||
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;
|
||||
|
@ -245,14 +247,19 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
|
|||
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>{});
|
||||
for (auto &id : gc) {
|
||||
gc_vec->ids_.push_back(id.tl());
|
||||
}
|
||||
return ton::create_tl_object<ton::ton_api::engine_validator_config>(
|
||||
out_port, std::move(addrs_vec), std::move(adnl_vec), std::move(dht_vec), std::move(val_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));
|
||||
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), std::move(col_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(shards_vec), std::move(gc_vec));
|
||||
}
|
||||
|
||||
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) {
|
||||
return gc.insert(key).second;
|
||||
}
|
||||
|
@ -1393,6 +1411,11 @@ void ValidatorEngine::init_validator_options() {
|
|||
for (const auto& c : config_.collators) {
|
||||
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(
|
||||
[shards = std::move(shards)](ton::ShardIdFull shard, ton::CatchainSeqno cc_seqno,
|
||||
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();
|
||||
|
||||
ton::ton_api::engine_validator_config conf;
|
||||
auto S = ton::ton_api::from_json(conf, conf_json.get_object());
|
||||
ton::tl_object_ptr<ton::ton_api::engine_validator_Config> conf;
|
||||
auto S = td::from_json(conf, std::move(conf_json));
|
||||
if (S.is_error()) {
|
||||
promise.set_error(S.move_as_error_prefix("json does not fit TL scheme"));
|
||||
return;
|
||||
}
|
||||
|
||||
config_ = Config{conf};
|
||||
config_ = Config{*ton::unpack_engine_validator_config(std::move(conf))};
|
||||
|
||||
td::MultiPromise mp;
|
||||
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 shard = ton::ShardIdFull(query.workchain_, query.shard_);
|
||||
if (!shard.is_valid_ext()) {
|
||||
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "invalid shard")));
|
||||
return;
|
||||
}
|
||||
|
||||
auto shard = ton::create_shard_id(query.shard_);
|
||||
auto R = config_.config_add_collator(id, shard);
|
||||
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;
|
||||
}
|
||||
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,
|
||||
ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
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();
|
||||
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
@ -3752,7 +3791,7 @@ int main(int argc, char *argv[]) {
|
|||
});
|
||||
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); });
|
||||
});
|
||||
td::uint32 threads = 7;
|
||||
|
|
|
@ -96,6 +96,7 @@ struct Config {
|
|||
std::map<td::int32, ton::PublicKeyHash> liteservers;
|
||||
std::map<td::int32, Control> controls;
|
||||
std::set<ton::PublicKeyHash> gc;
|
||||
std::vector<ton::ShardIdFull> shards_to_monitor;
|
||||
|
||||
void decref(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_process(ton::PublicKeyHash key, td::int32 port, ton::PublicKeyHash id,
|
||||
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_del_network_addr(td::IPAddress addr, std::vector<AdnlCategory> 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_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(ton::ton_api::engine_validator_config &config);
|
||||
Config(const ton::ton_api::engine_validator_config_v2 &config);
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
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>
|
||||
void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm,
|
||||
td::Promise<td::BufferSlice> promise) {
|
||||
|
|
Loading…
Reference in a new issue