mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
changed validate broadcast logic, added new queries to
validator-engine-console
This commit is contained in:
parent
47814dca3d
commit
d8244eff53
24 changed files with 695 additions and 84 deletions
|
@ -87,6 +87,11 @@ target_include_directories(adnl-proxy PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_S
|
|||
target_link_libraries(adnl-proxy PUBLIC tdactor ton_crypto tl_api tdnet common
|
||||
tl-utils)
|
||||
|
||||
add_executable(adnl-pong adnl-pong.cpp)
|
||||
target_include_directories(adnl-pong PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnl-pong PUBLIC tdactor ton_crypto tl_api tdnet common
|
||||
tl-utils adnl dht)
|
||||
|
||||
add_library(adnltest STATIC ${ADNL_TEST_SOURCE})
|
||||
target_include_directories(adnltest PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(adnltest PUBLIC adnl )
|
||||
|
|
|
@ -283,11 +283,19 @@ void AdnlPeerTableImpl::start_up() {
|
|||
|
||||
void AdnlPeerTableImpl::write_new_addr_list_to_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id, AdnlDbItem node,
|
||||
td::Promise<td::Unit> promise) {
|
||||
if (db_.empty()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(db_, &AdnlDb::update, local_id, peer_id, std::move(node), std::move(promise));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::get_addr_list_from_db(AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
td::Promise<AdnlDbItem> promise) {
|
||||
if (db_.empty()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "db not inited"));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(db_, &AdnlDb::get, local_id, peer_id, std::move(promise));
|
||||
}
|
||||
|
||||
|
@ -295,7 +303,9 @@ AdnlPeerTableImpl::AdnlPeerTableImpl(std::string db_root, td::actor::ActorId<key
|
|||
keyring_ = keyring;
|
||||
static_nodes_manager_ = AdnlStaticNodesManager::create();
|
||||
|
||||
if (!db_root.empty()) {
|
||||
db_ = AdnlDb::create(db_root + "/adnl");
|
||||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::deliver(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) {
|
||||
|
|
195
adnl/adnl-pong.cpp
Normal file
195
adnl/adnl-pong.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
This file is part of TON Blockchain source code.
|
||||
|
||||
TON Blockchain is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
TON Blockchain is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program with the OpenSSL library.
|
||||
You must obey the GNU General Public License in all respects for all
|
||||
of the code used other than OpenSSL. If you modify file(s) with this
|
||||
exception, you may extend this exception to your version of the file(s),
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "td/net/UdpServer.h"
|
||||
#include "td/utils/port/signals.h"
|
||||
#include "td/utils/OptionsParser.h"
|
||||
#include "td/utils/FileLog.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/port/user.h"
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "common/checksum.h"
|
||||
#include "common/errorcode.h"
|
||||
#include "tl-utils/tl-utils.hpp"
|
||||
#include "auto/tl/ton_api_json.h"
|
||||
#include "adnl/adnl.h"
|
||||
#include <map>
|
||||
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace adnl {
|
||||
|
||||
class Callback : public adnl::Adnl::Callback {
|
||||
public:
|
||||
void receive_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
|
||||
}
|
||||
void receive_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
TRY_RESULT_PROMISE_PREFIX(promise, f, fetch_tl_object<ton_api::adnl_ping>(std::move(data), true),
|
||||
"adnl.ping expected");
|
||||
promise.set_value(create_serialize_tl_object<ton_api::adnl_pong>(f->value_));
|
||||
}
|
||||
|
||||
Callback() {
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
||||
std::atomic<bool> rotate_logs_flags{false};
|
||||
void force_rotate_logs(int sig) {
|
||||
rotate_logs_flags.store(true);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
SET_VERBOSITY_LEVEL(verbosity_INFO);
|
||||
|
||||
ton::PrivateKey pk;
|
||||
td::IPAddress addr;
|
||||
|
||||
td::set_default_failure_signal_handler().ensure();
|
||||
|
||||
std::unique_ptr<td::LogInterface> logger_;
|
||||
SCOPE_EXIT {
|
||||
td::log_interface = td::default_log_interface;
|
||||
};
|
||||
|
||||
std::string config = "/var/ton-work/etc/adnl-proxy.conf.json";
|
||||
|
||||
td::OptionsParser p;
|
||||
p.set_description("adnl pinger");
|
||||
p.add_option('v', "verbosity", "set verbosity level", [&](td::Slice arg) {
|
||||
int v = VERBOSITY_NAME(FATAL) + (td::to_integer<int>(arg));
|
||||
SET_VERBOSITY_LEVEL(v);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('h', "help", "prints_help", [&]() {
|
||||
char b[10240];
|
||||
td::StringBuilder sb(td::MutableSlice{b, 10000});
|
||||
sb << p;
|
||||
std::cout << sb.as_cslice().c_str();
|
||||
std::exit(2);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('d', "daemonize", "set SIGHUP", [&]() {
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
close(0);
|
||||
setsid();
|
||||
#endif
|
||||
td::set_signal_handler(td::SignalType::HangUp, force_rotate_logs).ensure();
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('l', "logname", "log to file", [&](td::Slice fname) {
|
||||
auto F = std::make_unique<td::FileLog>();
|
||||
TRY_STATUS(F->init(fname.str(), std::numeric_limits<td::uint64>::max(), true));
|
||||
logger_ = std::move(F);
|
||||
td::log_interface = logger_.get();
|
||||
return td::Status::OK();
|
||||
});
|
||||
td::uint32 threads = 7;
|
||||
p.add_option('t', "threads", PSTRING() << "number of threads (default=" << threads << ")", [&](td::Slice fname) {
|
||||
td::int32 v;
|
||||
try {
|
||||
v = std::stoi(fname.str());
|
||||
} catch (...) {
|
||||
return td::Status::Error(ton::ErrorCode::error, "bad value for --threads: not a number");
|
||||
}
|
||||
if (v < 1 || v > 256) {
|
||||
return td::Status::Error(ton::ErrorCode::error, "bad value for --threads: should be in range [1..256]");
|
||||
}
|
||||
threads = v;
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('u', "user", "change user", [&](td::Slice user) { return td::change_user(user); });
|
||||
p.add_option('k', "key", "private key", [&](td::Slice key) {
|
||||
TRY_RESULT_ASSIGN(pk, ton::PrivateKey::import(key));
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('a', "addr", "ip:port of instance", [&](td::Slice key) {
|
||||
TRY_STATUS(addr.init_host_port(key.str()));
|
||||
return td::Status::OK();
|
||||
});
|
||||
|
||||
p.run(argc, argv).ensure();
|
||||
|
||||
if (pk.empty()) {
|
||||
LOG(FATAL) << "no --key given";
|
||||
}
|
||||
if (!addr.is_valid()) {
|
||||
LOG(FATAL) << "no --addr given";
|
||||
}
|
||||
|
||||
td::actor::Scheduler scheduler({threads});
|
||||
|
||||
td::actor::ActorOwn<ton::keyring::Keyring> keyring;
|
||||
td::actor::ActorOwn<ton::adnl::Adnl> adnl;
|
||||
td::actor::ActorOwn<ton::adnl::AdnlNetworkManager> network_manager;
|
||||
|
||||
auto pub = pk.compute_public_key();
|
||||
|
||||
scheduler.run_in_context([&]() {
|
||||
keyring = ton::keyring::Keyring::create("");
|
||||
td::actor::send_closure(keyring, &ton::keyring::Keyring::add_key, std::move(pk), true, [](td::Unit) {});
|
||||
|
||||
adnl = ton::adnl::Adnl::create("", keyring.get());
|
||||
|
||||
network_manager = ton::adnl::AdnlNetworkManager::create(static_cast<td::uint16>(addr.get_port()));
|
||||
|
||||
td::actor::send_closure(network_manager, &ton::adnl::AdnlNetworkManager::add_self_addr, addr, 0);
|
||||
|
||||
auto tladdr = ton::create_tl_object<ton::ton_api::adnl_address_udp>(addr.get_ipv4(), addr.get_port());
|
||||
auto addr_vec = std::vector<ton::tl_object_ptr<ton::ton_api::adnl_Address>>();
|
||||
addr_vec.push_back(std::move(tladdr));
|
||||
auto tladdrlist = ton::create_tl_object<ton::ton_api::adnl_addressList>(
|
||||
std::move(addr_vec), ton::adnl::Adnl::adnl_start_time(), ton::adnl::Adnl::adnl_start_time(), 0, 2000000000);
|
||||
auto addrlist = ton::adnl::AdnlAddressList::create(tladdrlist).move_as_ok();
|
||||
|
||||
td::actor::send_closure(adnl, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, std::move(addrlist));
|
||||
td::actor::send_closure(adnl, &ton::adnl::Adnl::subscribe, ton::adnl::AdnlNodeIdShort{pub.compute_short_id()},
|
||||
ton::adnl::Adnl::int_to_bytestring(ton::ton_api::adnl_ping::ID),
|
||||
std::make_unique<ton::adnl::Callback>());
|
||||
});
|
||||
|
||||
while (scheduler.run(1)) {
|
||||
if (rotate_logs_flags.exchange(false)) {
|
||||
if (td::log_interface) {
|
||||
td::log_interface->rotate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,7 +67,7 @@ td::Result<std::unique_ptr<Config>> Config::extract_from_key_block(Ref<vm::Cell>
|
|||
tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra) && mc_extra.key_block && mc_extra.config.not_null())) {
|
||||
return td::Status::Error(-400, "cannot unpack extra header of key block to extract configuration");
|
||||
}
|
||||
return block::Config::unpack_config(std::move(mc_extra.config));
|
||||
return block::Config::unpack_config(std::move(mc_extra.config), mode);
|
||||
}
|
||||
|
||||
td::Result<std::unique_ptr<Config>> Config::extract_from_state(Ref<vm::Cell> mc_state_root, int mode) {
|
||||
|
@ -1482,6 +1482,7 @@ std::vector<ton::ValidatorDescr> Config::compute_validator_set(ton::ShardIdFull
|
|||
std::vector<ton::ValidatorDescr> Config::compute_validator_set(ton::ShardIdFull shard, ton::UnixTime time,
|
||||
ton::CatchainSeqno cc_seqno) const {
|
||||
if (!cur_validators_) {
|
||||
LOG(DEBUG) << "failed to compute validator set: cur_validators_ is empty";
|
||||
return {};
|
||||
} else {
|
||||
return compute_validator_set(shard, *cur_validators_, time, cc_seqno);
|
||||
|
|
|
@ -498,6 +498,14 @@ engine.adnlProxy.config ports:(vector engine.adnlProxy.port) = engine.adnlProxy.
|
|||
|
||||
---types---
|
||||
|
||||
adnl.pong value:long = adnl.Pong;
|
||||
|
||||
---functions---
|
||||
|
||||
adnl.ping value:long = adnl.Pong;
|
||||
|
||||
---types---
|
||||
|
||||
engine.validator.keyHash key_hash:int256 = engine.validator.KeyHash;
|
||||
engine.validator.signature signature:bytes = engine.validator.Signature;
|
||||
|
||||
|
@ -513,6 +521,9 @@ engine.validator.jsonConfig data:string = engine.validator.JsonConfig;
|
|||
|
||||
engine.validator.electionBid election_date:int perm_key:int256 adnl_addr:int256 to_send_payload:bytes = engine.validator.ElectionBid;
|
||||
|
||||
engine.validator.dhtServerStatus id:int256 status:int = engine.validator.DhtServerStatus;
|
||||
engine.validator.dhtServersStatus servers:(vector engine.validator.dhtServerStatus) = engine.validator.DhtServersStatus;
|
||||
|
||||
---functions---
|
||||
|
||||
engine.validator.getTime = engine.validator.Time;
|
||||
|
@ -550,4 +561,6 @@ engine.validator.setVerbosity verbosity:int = engine.validator.Success;
|
|||
|
||||
engine.validator.createElectionBid election_date:int election_addr:string wallet:string = engine.validator.ElectionBid;
|
||||
|
||||
engine.validator.checkDhtServers id:int256 = engine.validator.DhtServersStatus;
|
||||
|
||||
engine.validator.controlQuery data:bytes = Object;
|
||||
|
|
Binary file not shown.
|
@ -655,3 +655,23 @@ td::Status CreateElectionBidQuery::receive(td::BufferSlice data) {
|
|||
TRY_STATUS(td::write_file(fname_, f->to_send_payload_.as_slice()));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status CheckDhtServersQuery::run() {
|
||||
TRY_RESULT_ASSIGN(id_, tokenizer_.get_token<ton::PublicKeyHash>());
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status CheckDhtServersQuery::send() {
|
||||
auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_checkDhtServers>(id_.tl());
|
||||
td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise());
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status CheckDhtServersQuery::receive(td::BufferSlice data) {
|
||||
TRY_RESULT_PREFIX(f, ton::fetch_tl_object<ton::ton_api::engine_validator_dhtServersStatus>(data.as_slice(), true),
|
||||
"received incorrect answer: ");
|
||||
for (auto &s : f->servers_) {
|
||||
td::TerminalIO::out() << "id=" << s->id_ << " status=" << (s->status_ ? "SUCCESS" : "FAIL") << "\n";
|
||||
}
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
|
|
@ -821,3 +821,24 @@ class CreateElectionBidQuery : public Query {
|
|||
std::string fname_;
|
||||
};
|
||||
|
||||
class CheckDhtServersQuery : public Query {
|
||||
public:
|
||||
CheckDhtServersQuery(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 "checkdht";
|
||||
}
|
||||
static std::string get_help() {
|
||||
return "checkdht <adnlid>\tchecks, which root DHT servers are accessible from this ADNL addr";
|
||||
}
|
||||
std::string name() const override {
|
||||
return get_name();
|
||||
}
|
||||
|
||||
private:
|
||||
ton::PublicKeyHash id_;
|
||||
};
|
||||
|
|
|
@ -130,6 +130,7 @@ void ValidatorEngineConsole::run() {
|
|||
add_query_runner(std::make_unique<QueryRunnerImpl<AddNetworkAddressQuery>>());
|
||||
add_query_runner(std::make_unique<QueryRunnerImpl<AddNetworkProxyAddressQuery>>());
|
||||
add_query_runner(std::make_unique<QueryRunnerImpl<CreateElectionBidQuery>>());
|
||||
add_query_runner(std::make_unique<QueryRunnerImpl<CheckDhtServersQuery>>());
|
||||
}
|
||||
|
||||
bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) {
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
|
||||
#include "memprof/memprof.h"
|
||||
|
||||
#include "dht/dht.hpp"
|
||||
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
@ -749,6 +751,65 @@ class ValidatorElectionBidCreator : public td::actor::Actor {
|
|||
td::BufferSlice result_;
|
||||
};
|
||||
|
||||
class CheckDhtServerStatusQuery : public td::actor::Actor {
|
||||
public:
|
||||
void start_up() override {
|
||||
auto &n = dht_config_->nodes();
|
||||
|
||||
result_.resize(n.size(), false);
|
||||
|
||||
pending_ = n.size();
|
||||
for (td::uint32 i = 0; i < n.size(); i++) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), idx = i](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &CheckDhtServerStatusQuery::got_result, idx, R.is_ok());
|
||||
});
|
||||
|
||||
auto &E = n.list().at(i);
|
||||
|
||||
td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_peer, local_id_, E.adnl_id(), E.addr_list());
|
||||
td::actor::send_closure(adnl_, &ton::adnl::Adnl::send_query, local_id_, E.adnl_id().compute_short_id(), "ping",
|
||||
std::move(P), td::Timestamp::in(1.0),
|
||||
ton::create_serialize_tl_object<ton::ton_api::dht_getSignedAddressList>());
|
||||
}
|
||||
}
|
||||
|
||||
void got_result(td::uint32 idx, bool result) {
|
||||
result_[idx] = result;
|
||||
CHECK(pending_ > 0);
|
||||
if (!--pending_) {
|
||||
finish_query();
|
||||
}
|
||||
}
|
||||
|
||||
void finish_query() {
|
||||
std::vector<ton::tl_object_ptr<ton::ton_api::engine_validator_dhtServerStatus>> vec;
|
||||
auto &n = dht_config_->nodes();
|
||||
for (td::uint32 i = 0; i < n.size(); i++) {
|
||||
auto &E = n.list().at(i);
|
||||
vec.push_back(ton::create_tl_object<ton::ton_api::engine_validator_dhtServerStatus>(
|
||||
E.adnl_id().compute_short_id().bits256_value(), result_[i] ? 1 : 0));
|
||||
}
|
||||
promise_.set_value(
|
||||
ton::create_serialize_tl_object<ton::ton_api::engine_validator_dhtServersStatus>(std::move(vec)));
|
||||
stop();
|
||||
}
|
||||
|
||||
CheckDhtServerStatusQuery(std::shared_ptr<ton::dht::DhtGlobalConfig> dht_config, ton::adnl::AdnlNodeIdShort local_id,
|
||||
td::actor::ActorId<ton::adnl::Adnl> adnl, td::Promise<td::BufferSlice> promise)
|
||||
: dht_config_(std::move(dht_config)), local_id_(local_id), adnl_(adnl), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<ton::dht::DhtGlobalConfig> dht_config_;
|
||||
|
||||
std::vector<bool> result_;
|
||||
td::uint32 pending_;
|
||||
|
||||
ton::adnl::AdnlNodeIdShort local_id_;
|
||||
td::actor::ActorId<ton::adnl::Adnl> adnl_;
|
||||
td::Promise<td::BufferSlice> promise_;
|
||||
};
|
||||
|
||||
void ValidatorEngine::set_local_config(std::string str) {
|
||||
local_config_ = str;
|
||||
}
|
||||
|
@ -2535,6 +2596,31 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_createEle
|
|||
.release();
|
||||
}
|
||||
|
||||
void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_checkDhtServers &query, td::BufferSlice data,
|
||||
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise) {
|
||||
if (!(perm & ValidatorEnginePermissions::vep_default)) {
|
||||
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized")));
|
||||
return;
|
||||
}
|
||||
if (keyring_.empty()) {
|
||||
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "keyring not started")));
|
||||
return;
|
||||
}
|
||||
if (!dht_config_) {
|
||||
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "no dht config")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (config_.adnl_ids.count(ton::PublicKeyHash{query.id_}) == 0) {
|
||||
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "no dht config")));
|
||||
return;
|
||||
}
|
||||
|
||||
td::actor::create_actor<CheckDhtServerStatusQuery>("pinger", dht_config_, ton::adnl::AdnlNodeIdShort{query.id_},
|
||||
adnl_.get(), std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src,
|
||||
ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) {
|
||||
|
|
|
@ -347,6 +347,8 @@ class ValidatorEngine : public td::actor::Actor {
|
|||
td::uint32 perm, td::Promise<td::BufferSlice> promise);
|
||||
void run_control_query(ton::ton_api::engine_validator_createElectionBid &query, td::BufferSlice data,
|
||||
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
|
||||
void run_control_query(ton::ton_api::engine_validator_checkDhtServers &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) {
|
||||
|
|
|
@ -9,6 +9,7 @@ set(TON_VALIDATOR_SOURCE
|
|||
block.cpp
|
||||
check-proof.cpp
|
||||
collator.cpp
|
||||
config.cpp
|
||||
external-message.cpp
|
||||
fabric.cpp
|
||||
ihr-message.cpp
|
||||
|
@ -27,6 +28,7 @@ set(TON_VALIDATOR_SOURCE
|
|||
collate-query-impl.h
|
||||
collator-impl.h
|
||||
collator.h
|
||||
config.hpp
|
||||
external-message.hpp
|
||||
ihr-message.hpp
|
||||
liteserver.hpp
|
||||
|
|
58
validator/impl/config.cpp
Normal file
58
validator/impl/config.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
|
||||
#include "config.hpp"
|
||||
#include "block/block-parse.h"
|
||||
#include "block/block-auto.h"
|
||||
#include "vm/boc.h"
|
||||
#include "vm/cells/MerkleProof.h"
|
||||
#include "validator-set.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
td::Ref<ValidatorSet> ConfigHolderQ::get_total_validator_set(int next) const {
|
||||
if (!config_) {
|
||||
LOG(ERROR) << "MasterchainStateQ::get_total_validator_set() : no config";
|
||||
return {};
|
||||
}
|
||||
auto nodes = config_->compute_total_validator_set(next);
|
||||
if (nodes.empty()) {
|
||||
return {};
|
||||
}
|
||||
return Ref<ValidatorSetQ>{true, 0, ton::ShardIdFull{}, std::move(nodes)};
|
||||
}
|
||||
|
||||
td::Ref<ValidatorSet> ConfigHolderQ::get_validator_set(ShardIdFull shard, UnixTime utime,
|
||||
CatchainSeqno cc_seqno) const {
|
||||
if (!config_) {
|
||||
LOG(ERROR) << "MasterchainStateQ::get_validator_set() : no config";
|
||||
return {};
|
||||
}
|
||||
auto nodes = config_->compute_validator_set(shard, utime, cc_seqno);
|
||||
if (nodes.empty()) {
|
||||
return {};
|
||||
}
|
||||
return Ref<ValidatorSetQ>{true, cc_seqno, shard, std::move(nodes)};
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
50
validator/impl/config.hpp
Normal file
50
validator/impl/config.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "validator/interfaces/config.h"
|
||||
|
||||
namespace ton {
|
||||
namespace validator {
|
||||
using td::Ref;
|
||||
|
||||
class ConfigHolderQ : public ConfigHolder {
|
||||
std::shared_ptr<block::Config> config_;
|
||||
std::shared_ptr<vm::StaticBagOfCellsDb> boc_;
|
||||
|
||||
public:
|
||||
ConfigHolderQ() = default;
|
||||
ConfigHolderQ(std::shared_ptr<block::Config> config, std::shared_ptr<vm::StaticBagOfCellsDb> boc)
|
||||
: config_(std::move(config)), boc_(std::move(boc)) {
|
||||
}
|
||||
ConfigHolderQ(std::shared_ptr<block::Config> config) : config_(std::move(config)) {
|
||||
}
|
||||
const block::Config *get_config() const {
|
||||
return config_.get();
|
||||
}
|
||||
ConfigHolderQ *make_copy() const override {
|
||||
return new ConfigHolderQ(*this);
|
||||
}
|
||||
// if necessary, add more public methods providing interface to config_->...()
|
||||
td::Ref<ValidatorSet> get_total_validator_set(int next) const override; // next = -1 -> prev, next = 0 -> cur
|
||||
td::Ref<ValidatorSet> get_validator_set(ShardIdFull shard, UnixTime utime, CatchainSeqno seqno) const override;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
|
@ -43,10 +43,10 @@ td::Result<Ref<ProofLink>> ProofQ::export_as_proof_link() const {
|
|||
}
|
||||
|
||||
td::Result<BlockSeqno> ProofLinkQ::prev_key_mc_seqno() const {
|
||||
if (!id_.is_masterchain()) {
|
||||
return td::Status::Error(
|
||||
-668, "cannot compute previous key masterchain block from ProofLink of non-masterchain block "s + id_.to_str());
|
||||
}
|
||||
//if (!id_.is_masterchain()) {
|
||||
// return td::Status::Error(
|
||||
// -668, "cannot compute previous key masterchain block from ProofLink of non-masterchain block "s + id_.to_str());
|
||||
//}
|
||||
TRY_RESULT(pair, get_virtual_root(true));
|
||||
try {
|
||||
block::gen::Block::Record blk;
|
||||
|
@ -68,8 +68,7 @@ td::Result<td::Ref<ConfigHolder>> ProofLinkQ::get_key_block_config() const {
|
|||
}
|
||||
TRY_RESULT(pair, get_virtual_root(true));
|
||||
try {
|
||||
TRY_RESULT(cfg, block::Config::extract_from_key_block(
|
||||
std::move(pair.first), block::Config::needValidatorSet | block::Config::needWorkchainInfo));
|
||||
TRY_RESULT(cfg, block::Config::extract_from_key_block(std::move(pair.first), block::Config::needValidatorSet));
|
||||
return td::make_ref<ConfigHolderQ>(std::move(cfg), std::move(pair.second));
|
||||
} catch (vm::VmVirtError &) {
|
||||
return td::Status::Error(-668,
|
||||
|
@ -77,6 +76,26 @@ td::Result<td::Ref<ConfigHolder>> ProofLinkQ::get_key_block_config() const {
|
|||
}
|
||||
}
|
||||
|
||||
td::Result<ProofLink::BasicHeaderInfo> ProofLinkQ::get_basic_header_info() const {
|
||||
BasicHeaderInfo res;
|
||||
TRY_RESULT(pair, get_virtual_root(true));
|
||||
try {
|
||||
block::gen::Block::Record blk;
|
||||
block::gen::BlockInfo::Record info;
|
||||
if (!(tlb::unpack_cell(std::move(pair.first), blk) && tlb::unpack_cell(blk.info, info) && !info.version)) {
|
||||
return td::Status::Error(-668,
|
||||
"cannot unpack block header in the Merkle proof for masterchain block "s + id_.to_str());
|
||||
}
|
||||
res.cc_seqno = info.gen_catchain_seqno;
|
||||
res.utime = info.gen_utime;
|
||||
res.validator_set_hash = info.gen_validator_list_hash_short;
|
||||
res.prev_key_mc_seqno = info.prev_key_block_seqno;
|
||||
return res;
|
||||
} catch (vm::VmVirtError &) {
|
||||
return td::Status::Error(-668, "virtualization error in masterchain block proof for "s + id_.to_str());
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> ProofLinkQ::get_virtual_root(
|
||||
bool lazy) const {
|
||||
if (data_.empty()) {
|
||||
|
@ -127,17 +146,5 @@ td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> Pr
|
|||
return std::make_pair(std::move(virt_root), std::move(boc));
|
||||
}
|
||||
|
||||
td::Ref<ValidatorSet> ConfigHolderQ::get_total_validator_set(int next) const {
|
||||
if (!config_) {
|
||||
LOG(ERROR) << "MasterchainStateQ::get_total_validator_set() : no config";
|
||||
return {};
|
||||
}
|
||||
auto nodes = config_->compute_total_validator_set(next);
|
||||
if (nodes.empty()) {
|
||||
return {};
|
||||
}
|
||||
return Ref<ValidatorSetQ>{true, 0, ton::ShardIdFull{}, std::move(nodes)};
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
} // namespace ton
|
||||
|
|
|
@ -22,32 +22,12 @@
|
|||
#include "block/block-db.h"
|
||||
#include "block/mc-config.h"
|
||||
#include "vm/db/StaticBagOfCellsDb.h"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace ton {
|
||||
namespace validator {
|
||||
using td::Ref;
|
||||
|
||||
class ConfigHolderQ : public ConfigHolder {
|
||||
std::shared_ptr<block::Config> config_;
|
||||
std::shared_ptr<vm::StaticBagOfCellsDb> boc_;
|
||||
|
||||
public:
|
||||
ConfigHolderQ() = default;
|
||||
ConfigHolderQ(std::shared_ptr<block::Config> config, std::shared_ptr<vm::StaticBagOfCellsDb> boc)
|
||||
: config_(std::move(config)), boc_(std::move(boc)) {
|
||||
}
|
||||
ConfigHolderQ(std::shared_ptr<block::Config> config) : config_(std::move(config)) {
|
||||
}
|
||||
const block::Config *get_config() const {
|
||||
return config_.get();
|
||||
}
|
||||
ConfigHolderQ *make_copy() const override {
|
||||
return new ConfigHolderQ(*this);
|
||||
}
|
||||
// if necessary, add more public methods providing interface to config_->...()
|
||||
td::Ref<ValidatorSet> get_total_validator_set(int next) const override; // next = -1 -> prev, next = 0 -> cur
|
||||
};
|
||||
|
||||
class ProofLinkQ : virtual public ProofLink {
|
||||
protected:
|
||||
BlockIdExt id_;
|
||||
|
@ -67,6 +47,7 @@ class ProofLinkQ : virtual public ProofLink {
|
|||
}
|
||||
td::Result<BlockSeqno> prev_key_mc_seqno() const override;
|
||||
td::Result<td::Ref<ConfigHolder>> get_key_block_config() const override;
|
||||
td::Result<BasicHeaderInfo> get_basic_header_info() const override;
|
||||
|
||||
protected:
|
||||
td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> get_virtual_root(
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "interfaces/shard.h"
|
||||
#include "vm/db/StaticBagOfCellsDb.h"
|
||||
#include "block/mc-config.h"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -138,6 +139,13 @@ class MasterchainStateQ : public MasterchainState, public ShardStateQ {
|
|||
std::shared_ptr<block::ConfigInfo> get_config() const {
|
||||
return config_;
|
||||
}
|
||||
td::Result<td::Ref<ConfigHolder>> get_key_block_config() const override {
|
||||
if (!config_) {
|
||||
return td::Status::Error(ErrorCode::notready, "config not found");
|
||||
} else {
|
||||
return td::make_ref<ConfigHolderQ>(config_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ZeroStateIdExt zerostate_id_;
|
||||
|
|
|
@ -665,9 +665,7 @@ bool ValidateQuery::try_unpack_mc_state() {
|
|||
}
|
||||
config_ = res.move_as_ok();
|
||||
CHECK(config_);
|
||||
if (mc_seqno_) {
|
||||
config_->set_block_id_ext(mc_blkid_);
|
||||
}
|
||||
old_shard_conf_ = std::make_unique<block::ShardConfig>(*config_);
|
||||
if (!is_masterchain()) {
|
||||
new_shard_conf_ = std::make_unique<block::ShardConfig>(*config_);
|
||||
|
@ -684,6 +682,11 @@ bool ValidateQuery::try_unpack_mc_state() {
|
|||
} else {
|
||||
prev_key_block_seqno_ = 0;
|
||||
}
|
||||
if (prev_key_seqno_ != prev_key_block_seqno_) {
|
||||
return reject_query(PSTRING() << "previous key block seqno value in candidate block header is " << prev_key_seqno_
|
||||
<< " while the correct value corresponding to reference masterchain state "
|
||||
<< mc_blkid_.to_str() << " is " << prev_key_block_seqno_);
|
||||
}
|
||||
auto limits = config_->get_block_limits(is_masterchain());
|
||||
if (limits.is_error()) {
|
||||
return fatal_error(limits.move_as_error());
|
||||
|
@ -5002,7 +5005,7 @@ bool ValidateQuery::check_mc_state_extra() {
|
|||
} else if (!new_extra.r1.last_key_block->prefetch_ulong(1)) {
|
||||
return reject_query("last_key_block:(Maybe ExtBlkRef) changed in the new state, but it became a nothing$0");
|
||||
} else {
|
||||
auto& cs = new_extra.r1.last_key_block.write();
|
||||
vm::CellSlice cs = *new_extra.r1.last_key_block;
|
||||
BlockIdExt blkid;
|
||||
LogicalTime lt;
|
||||
CHECK(cs.fetch_ulong(1) == 1 && block::tlb::t_ExtBlkRef.unpack(cs, blkid, <));
|
||||
|
@ -5017,6 +5020,20 @@ bool ValidateQuery::check_mc_state_extra() {
|
|||
", but it is not a key block");
|
||||
}
|
||||
}
|
||||
if (new_extra.r1.last_key_block->prefetch_ulong(1)) {
|
||||
auto& cs = new_extra.r1.last_key_block.write();
|
||||
BlockIdExt blkid;
|
||||
LogicalTime lt;
|
||||
CHECK(cs.fetch_ulong(1) == 1 && block::tlb::t_ExtBlkRef.unpack(cs, blkid, <));
|
||||
if (blkid != prev_key_block_) {
|
||||
return reject_query("new masterchain state declares previous key block to be "s + blkid.to_str() +
|
||||
" but the value computed from previous masterchain state is " + prev_key_block_.to_str());
|
||||
}
|
||||
} else if (prev_key_block_seqno_ > 0) {
|
||||
return reject_query(PSTRING() << "new masterchain state declares no previous key block, but the block header "
|
||||
"announces previous key block seqno "
|
||||
<< prev_key_block_seqno_);
|
||||
}
|
||||
// global_balance:CurrencyCollection
|
||||
block::CurrencyCollection global_balance, old_global_balance;
|
||||
if (!global_balance.validate_unpack(new_extra.global_balance)) {
|
||||
|
|
|
@ -34,6 +34,7 @@ class ConfigHolder : public td::CntObject {
|
|||
virtual ~ConfigHolder() = default;
|
||||
|
||||
virtual td::Ref<ValidatorSet> get_total_validator_set(int next) const = 0; // next = -1 -> prev, next = 0 -> cur
|
||||
virtual td::Ref<ValidatorSet> get_validator_set(ShardIdFull shard, UnixTime utime, CatchainSeqno seqno) const = 0;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -27,11 +27,18 @@ namespace validator {
|
|||
|
||||
class ProofLink : public td::CntObject {
|
||||
public:
|
||||
struct BasicHeaderInfo {
|
||||
UnixTime utime;
|
||||
CatchainSeqno cc_seqno;
|
||||
td::uint32 validator_set_hash;
|
||||
BlockSeqno prev_key_mc_seqno;
|
||||
};
|
||||
virtual ~ProofLink() = default;
|
||||
virtual BlockIdExt block_id() const = 0;
|
||||
virtual td::BufferSlice data() const = 0;
|
||||
virtual td::Result<BlockSeqno> prev_key_mc_seqno() const = 0;
|
||||
virtual td::Result<td::Ref<ConfigHolder>> get_key_block_config() const = 0;
|
||||
virtual td::Result<BasicHeaderInfo> get_basic_header_info() const = 0;
|
||||
};
|
||||
|
||||
class Proof : virtual public ProofLink {
|
||||
|
|
|
@ -79,6 +79,7 @@ class MasterchainState : virtual public ShardState {
|
|||
virtual bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid,
|
||||
ton::LogicalTime* end_lt = nullptr) const = 0;
|
||||
virtual bool check_old_mc_block_id(const ton::BlockIdExt& blkid, bool strict = false) const = 0;
|
||||
virtual td::Result<td::Ref<ConfigHolder>> get_key_block_config() const = 0;
|
||||
virtual td::Status prepare() {
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
|
|
@ -1908,12 +1908,14 @@ void ValidatorManagerImpl::send_peek_key_block_request() {
|
|||
}
|
||||
|
||||
void ValidatorManagerImpl::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) {
|
||||
std::vector<std::pair<std::string, std::string>> vec;
|
||||
vec.emplace_back("unixtime", td::to_string(static_cast<UnixTime>(td::Clocks::system())));
|
||||
if (!last_masterchain_block_handle_) {
|
||||
promise.set_value(std::vector<std::pair<std::string, std::string>>());
|
||||
promise.set_value(std::move(vec));
|
||||
return;
|
||||
}
|
||||
std::vector<std::pair<std::string, std::string>> vec;
|
||||
vec.emplace_back("masterchainblock", last_masterchain_block_id_.to_str());
|
||||
vec.emplace_back("masterchainblocktime", td::to_string(last_masterchain_block_handle_->unix_time()));
|
||||
vec.emplace_back("gcmasterchainblock", gc_masterchain_handle_->id().to_str());
|
||||
vec.emplace_back("keymasterchainblock", last_key_block_handle_->id().to_str());
|
||||
vec.emplace_back("knownkeymasterchainblock", last_known_key_block_handle_->id().to_str());
|
||||
|
|
|
@ -69,33 +69,150 @@ void ValidateBroadcast::start_up() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto val_set = last_masterchain_state_->get_validator_set(broadcast_.block_id.shard_full());
|
||||
if (val_set.not_null() && val_set->get_catchain_seqno() == broadcast_.catchain_seqno &&
|
||||
val_set->get_validator_set_hash() == broadcast_.validator_set_hash) {
|
||||
if (broadcast_.block_id.is_masterchain()) {
|
||||
auto R = create_proof(broadcast_.block_id, broadcast_.proof.clone());
|
||||
if (R.is_error()) {
|
||||
abort_query(R.move_as_error_prefix("bad proof: "));
|
||||
return;
|
||||
}
|
||||
proof_ = R.move_as_ok();
|
||||
auto hR = proof_->get_basic_header_info();
|
||||
if (hR.is_error()) {
|
||||
abort_query(hR.move_as_error_prefix("bad proof: "));
|
||||
return;
|
||||
}
|
||||
header_info_ = hR.move_as_ok();
|
||||
} else {
|
||||
auto R = create_proof_link(broadcast_.block_id, broadcast_.proof.clone());
|
||||
if (R.is_error()) {
|
||||
abort_query(R.move_as_error_prefix("bad proof link: "));
|
||||
return;
|
||||
}
|
||||
proof_link_ = R.move_as_ok();
|
||||
auto hR = proof_link_->get_basic_header_info();
|
||||
if (hR.is_error()) {
|
||||
abort_query(hR.move_as_error_prefix("bad proof link: "));
|
||||
return;
|
||||
}
|
||||
header_info_ = hR.move_as_ok();
|
||||
}
|
||||
|
||||
BlockSeqno key_block_seqno = header_info_.prev_key_mc_seqno;
|
||||
exact_key_block_handle_ = key_block_seqno <= last_known_masterchain_block_handle_->id().seqno();
|
||||
if (key_block_seqno < last_known_masterchain_block_handle_->id().seqno()) {
|
||||
if (key_block_seqno < last_masterchain_state_->get_seqno()) {
|
||||
BlockIdExt block_id;
|
||||
if (!last_masterchain_state_->get_old_mc_block_id(key_block_seqno, block_id)) {
|
||||
abort_query(td::Status::Error(ErrorCode::error, "too old reference key block"));
|
||||
return;
|
||||
}
|
||||
got_key_block_id(block_id);
|
||||
} else if (key_block_seqno == last_masterchain_state_->get_seqno()) {
|
||||
got_key_block_handle(last_masterchain_block_handle_);
|
||||
} else {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockIdExt> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
|
||||
R.move_as_error_prefix("cannot find reference key block id: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_id, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_by_seqno_from_db,
|
||||
AccountIdPrefixFull{masterchainId, 0}, key_block_seqno, std::move(P));
|
||||
}
|
||||
} else {
|
||||
got_key_block_handle(last_known_masterchain_block_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateBroadcast::got_key_block_id(BlockIdExt block_id) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
|
||||
R.move_as_error_prefix("cannot find reference key block handle: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_handle, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidateBroadcast::got_key_block_handle(BlockHandle handle) {
|
||||
if (handle->id().seqno() == 0) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
|
||||
R.move_as_error_prefix("failed to get zero state: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::got_zero_state, td::Ref<MasterchainState>{R.move_as_ok()});
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, handle, std::move(P));
|
||||
} else {
|
||||
if (!handle->inited_proof() && !handle->inited_proof_link()) {
|
||||
abort_query(td::Status::Error(ErrorCode::notready, "reference key block proof not received"));
|
||||
return;
|
||||
}
|
||||
if (!handle->is_key_block()) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "reference key block is not key"));
|
||||
return;
|
||||
}
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ProofLink>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
|
||||
R.move_as_error_prefix("cannot get reference key block proof: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_proof_link, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_proof_link_from_db, handle, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateBroadcast::got_key_block_proof_link(td::Ref<ProofLink> key_proof_link) {
|
||||
key_proof_link_ = key_proof_link;
|
||||
auto confR = key_proof_link->get_key_block_config();
|
||||
if (confR.is_error()) {
|
||||
abort_query(confR.move_as_error_prefix("failed to extract config from key proof: "));
|
||||
return;
|
||||
}
|
||||
check_signatures_common(confR.move_as_ok());
|
||||
}
|
||||
|
||||
void ValidateBroadcast::got_zero_state(td::Ref<MasterchainState> state) {
|
||||
zero_state_ = state;
|
||||
auto confR = state->get_key_block_config();
|
||||
if (confR.is_error()) {
|
||||
abort_query(confR.move_as_error_prefix("failed to extract config from zero state: "));
|
||||
return;
|
||||
}
|
||||
check_signatures_common(confR.move_as_ok());
|
||||
}
|
||||
|
||||
void ValidateBroadcast::check_signatures_common(td::Ref<ConfigHolder> conf) {
|
||||
auto val_set = conf->get_validator_set(broadcast_.block_id.shard_full(), header_info_.utime, header_info_.cc_seqno);
|
||||
if (val_set.is_null()) {
|
||||
abort_query(td::Status::Error(ErrorCode::notready, "failed to compute validator set"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (val_set->get_validator_set_hash() != header_info_.validator_set_hash) {
|
||||
if (!exact_key_block_handle_) {
|
||||
abort_query(td::Status::Error(ErrorCode::notready, "too new block, don't know recent enough key block"));
|
||||
return;
|
||||
} else {
|
||||
abort_query(td::Status::Error(ErrorCode::notready, "bad validator set hash"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto S = val_set->check_signatures(broadcast_.block_id.root_hash, broadcast_.block_id.file_hash, sig_set_);
|
||||
if (S.is_ok()) {
|
||||
checked_signatures();
|
||||
return;
|
||||
} else {
|
||||
abort_query(S.move_as_error_prefix("failed signature check: "));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
val_set = last_masterchain_state_->get_next_validator_set(broadcast_.block_id.shard_full());
|
||||
if (val_set.not_null() && val_set->get_catchain_seqno() == broadcast_.catchain_seqno &&
|
||||
val_set->get_validator_set_hash() == broadcast_.validator_set_hash) {
|
||||
auto S = val_set->check_signatures(broadcast_.block_id.root_hash, broadcast_.block_id.file_hash, sig_set_);
|
||||
if (S.is_ok()) {
|
||||
checked_signatures();
|
||||
return;
|
||||
} else {
|
||||
abort_query(S.move_as_error_prefix("failed signature check: "));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad signature set"));
|
||||
}
|
||||
|
||||
void ValidateBroadcast::checked_signatures() {
|
||||
|
@ -142,13 +259,7 @@ void ValidateBroadcast::written_block_data() {
|
|||
checked_proof();
|
||||
return;
|
||||
}
|
||||
auto proofR = create_proof(broadcast_.block_id, broadcast_.proof.clone());
|
||||
if (proofR.is_error()) {
|
||||
abort_query(proofR.move_as_error_prefix("bad proof: "));
|
||||
return;
|
||||
}
|
||||
proof_ = proofR.move_as_ok();
|
||||
if (handle_->id().id.seqno == last_masterchain_block_handle_->id().id.seqno + 1) {
|
||||
if (exact_key_block_handle_) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error_prefix("db error: "));
|
||||
|
@ -156,7 +267,12 @@ void ValidateBroadcast::written_block_data() {
|
|||
td::actor::send_closure(SelfId, &ValidateBroadcast::checked_proof);
|
||||
}
|
||||
});
|
||||
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P));
|
||||
if (!key_proof_link_.is_null()) {
|
||||
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P), key_proof_link_);
|
||||
} else {
|
||||
CHECK(!zero_state_.not_null());
|
||||
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P), zero_state_);
|
||||
}
|
||||
} else {
|
||||
checked_proof();
|
||||
}
|
||||
|
@ -165,12 +281,6 @@ void ValidateBroadcast::written_block_data() {
|
|||
checked_proof();
|
||||
return;
|
||||
}
|
||||
auto proofR = create_proof_link(broadcast_.block_id, broadcast_.proof.clone());
|
||||
if (proofR.is_error()) {
|
||||
abort_query(proofR.move_as_error());
|
||||
return;
|
||||
}
|
||||
proof_link_ = proofR.move_as_ok();
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error_prefix("db error: "));
|
||||
|
@ -183,7 +293,10 @@ void ValidateBroadcast::written_block_data() {
|
|||
}
|
||||
|
||||
void ValidateBroadcast::checked_proof() {
|
||||
if (handle_->inited_proof()) {
|
||||
if (handle_->inited_proof() && handle_->is_key_block()) {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::update_last_known_key_block, handle_, false);
|
||||
}
|
||||
if (handle_->inited_proof() && handle_->id().seqno() - last_masterchain_block_handle_->id().seqno() <= 16) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error());
|
||||
|
|
|
@ -31,7 +31,8 @@ class ValidateBroadcast : public td::actor::Actor {
|
|||
BlockHandle last_masterchain_block_handle_;
|
||||
td::Ref<MasterchainState> last_masterchain_state_;
|
||||
BlockHandle last_known_masterchain_block_handle_;
|
||||
td::Ref<Proof> last_known_masterchain_block_proof_;
|
||||
|
||||
ProofLink::BasicHeaderInfo header_info_;
|
||||
|
||||
td::actor::ActorId<ValidatorManager> manager_;
|
||||
td::Timestamp timeout_;
|
||||
|
@ -45,6 +46,10 @@ class ValidateBroadcast : public td::actor::Actor {
|
|||
|
||||
td::PerfWarningTimer perf_timer_{"validatebroadcast", 0.1};
|
||||
|
||||
bool exact_key_block_handle_;
|
||||
td::Ref<ProofLink> key_proof_link_;
|
||||
td::Ref<MasterchainState> zero_state_;
|
||||
|
||||
public:
|
||||
ValidateBroadcast(BlockBroadcast broadcast, BlockHandle last_masterchain_block_handle,
|
||||
td::Ref<MasterchainState> last_masterchain_state, BlockHandle last_known_masterchain_block_handle,
|
||||
|
@ -59,6 +64,11 @@ class ValidateBroadcast : public td::actor::Actor {
|
|||
}
|
||||
|
||||
void start_up() override;
|
||||
void got_key_block_id(BlockIdExt block_id);
|
||||
void got_key_block_handle(BlockHandle block_handle);
|
||||
void got_key_block_proof_link(td::Ref<ProofLink> proof_link);
|
||||
void got_zero_state(td::Ref<MasterchainState> state);
|
||||
void check_signatures_common(td::Ref<ConfigHolder> conf);
|
||||
void checked_signatures();
|
||||
void got_block_handle(BlockHandle handle);
|
||||
void written_block_data();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue