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

Improved neighbor choosing in full-node-shard

This commit is contained in:
SpyCheese 2022-08-12 12:10:46 +03:00
parent 662435462e
commit 910398da92
17 changed files with 185 additions and 105 deletions

View file

@ -237,7 +237,8 @@ class HardforkCreator : public td::actor::Actor {
td::PromiseCreator::lambda([](td::Unit) {})); td::PromiseCreator::lambda([](td::Unit) {}));
} }
void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state, void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state,
std::set<ton::ShardIdFull> shards_to_monitor) override { std::set<ton::ShardIdFull> shards_to_monitor,
std::set<ton::ShardIdFull> temporary_shards) override {
} }
void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override {
} }

View file

@ -57,7 +57,7 @@ Config::Config() {
out_port = 3278; out_port = 3278;
} }
Config::Config(const ton::ton_api::engine_validator_config_v2 &config) { Config::Config(const ton::ton_api::engine_validator_configV2 &config) {
out_port = static_cast<td::uint16>(config.out_port_); out_port = static_cast<td::uint16>(config.out_port_);
if (!out_port) { if (!out_port) {
out_port = 3278; out_port = 3278;

View file

@ -94,7 +94,7 @@ struct Config {
ton::tl_object_ptr<ton::ton_api::engine_validator_Config> tl() const; ton::tl_object_ptr<ton::ton_api::engine_validator_Config> tl() const;
Config(); Config();
Config(const ton::ton_api::engine_validator_config_v2 &config); Config(const ton::ton_api::engine_validator_configV2 &config);
}; };
class DhtServer : public td::actor::Actor { class DhtServer : public td::actor::Actor {

View file

@ -235,12 +235,12 @@ void OverlayImpl::receive_message(adnl::AdnlNodeIdShort src, td::BufferSlice dat
auto X = fetch_tl_object<ton_api::overlay_Broadcast>(data.clone(), true); auto X = fetch_tl_object<ton_api::overlay_Broadcast>(data.clone(), true);
if (X.is_error()) { if (X.is_error()) {
auto Y = fetch_tl_object<ton_api::overlay_message_removePeer>(data.clone(), true); auto Y = fetch_tl_object<ton_api::overlay_message_removePeer>(data.clone(), true);
if (Y.is_ok()) { if (Y.is_ok() && public_) {
VLOG(OVERLAY_DEBUG) << this << ": received removePeer message from " << src; VLOG(OVERLAY_DEBUG) << this << ": received removePeer message from " << src;
if (peers_.exists(src)) { if (peers_.exists(src)) {
del_peer(src); del_peer(src);
callback_->on_remove_peer(src);
} }
callback_->on_remove_peer(src);
return; return;
} }
} }

View file

@ -324,7 +324,8 @@ class TestNode : public td::actor::Actor {
td::PromiseCreator::lambda([](td::Unit) {})); td::PromiseCreator::lambda([](td::Unit) {}));
} }
void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state, void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state,
std::set<ton::ShardIdFull> shards_to_monitor) override { std::set<ton::ShardIdFull> shards_to_monitor,
std::set<ton::ShardIdFull> temporary_shards) override {
} }
void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override {
} }

View file

@ -407,6 +407,7 @@ tonNode.dataFull id:tonNode.blockIdExt proof:bytes block:bytes is_link:Bool = to
tonNode.dataFullEmpty = tonNode.DataFull; tonNode.dataFullEmpty = tonNode.DataFull;
tonNode.capabilities version:int capabilities:long = tonNode.Capabilities; tonNode.capabilities version:int capabilities:long = tonNode.Capabilities;
tonNode.capabilitiesV2 version:int capabilities:long have_state:Bool = tonNode.Capabilities;
tonNode.success = tonNode.Success; tonNode.success = tonNode.Success;
@ -450,6 +451,7 @@ tonNode.getArchiveSlice archive_id:long offset:long max_size:int = tonNode.Data;
tonNode.getOutMsgQueueProof block_id:tonNode.blockIdExt dst_workchain:int dst_shard:long = tonNode.OutMsgQueueProof; tonNode.getOutMsgQueueProof block_id:tonNode.blockIdExt dst_workchain:int dst_shard:long = tonNode.OutMsgQueueProof;
tonNode.getCapabilities = tonNode.Capabilities; tonNode.getCapabilities = tonNode.Capabilities;
tonNode.getCapabilitiesV2 = tonNode.Capabilities;
tonNode.slave.sendExtMessage message:tonNode.externalMessage = tonNode.Success; tonNode.slave.sendExtMessage message:tonNode.externalMessage = tonNode.Success;
@ -598,7 +600,7 @@ engine.validator.config out_port:int addrs:(vector engine.Addr) adnl:(vector eng
liteservers:(vector engine.liteServer) control:(vector engine.controlInterface) liteservers:(vector engine.liteServer) control:(vector engine.controlInterface)
gc:engine.gc = engine.validator.Config; gc:engine.gc = engine.validator.Config;
engine.validator.config_v2 out_port:int addrs:(vector engine.Addr) adnl:(vector engine.adnl) engine.validator.configV2 out_port:int addrs:(vector engine.Addr) adnl:(vector engine.adnl)
dht:(vector engine.dht) dht:(vector engine.dht)
validators:(vector engine.validator) collators:(vector engine.collator) validators:(vector engine.validator) collators:(vector engine.collator)
fullnode:int256 fullnodeslaves:(vector engine.validator.fullNodeSlave) fullnode:int256 fullnodeslaves:(vector engine.validator.fullNodeSlave)

Binary file not shown.

View file

@ -62,12 +62,12 @@ inline tl_object_ptr<ton_api::tonNode_shardId> create_tl_shard_id(const ShardIdF
return create_tl_object<ton_api::tonNode_shardId>(s.workchain, s.shard); 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( inline tl_object_ptr<ton_api::engine_validator_configV2> unpack_engine_validator_config(
tl_object_ptr<ton_api::engine_validator_Config> config) { tl_object_ptr<ton_api::engine_validator_Config> config) {
tl_object_ptr<ton_api::engine_validator_config_v2> res; tl_object_ptr<ton_api::engine_validator_configV2> res;
ton_api::downcast_call(*config, td::overloaded( ton_api::downcast_call(*config, td::overloaded(
[&](ton_api::engine_validator_config &c) { [&](ton_api::engine_validator_config &c) {
res = create_tl_object<ton_api::engine_validator_config_v2>( res = create_tl_object<ton_api::engine_validator_configV2>(
c.out_port_, std::move(c.addrs_), std::move(c.adnl_), std::move(c.dht_), c.out_port_, std::move(c.addrs_), std::move(c.adnl_), std::move(c.dht_),
std::move(c.validators_), std::move(c.validators_),
std::vector<tl_object_ptr<ton_api::engine_collator>>(), c.fullnode_, std::vector<tl_object_ptr<ton_api::engine_collator>>(), c.fullnode_,
@ -75,8 +75,8 @@ inline tl_object_ptr<ton_api::engine_validator_config_v2> unpack_engine_validato
std::move(c.liteservers_), std::move(c.control_), std::move(c.liteservers_), std::move(c.control_),
std::vector<tl_object_ptr<ton_api::tonNode_shardId>>(), std::move(c.gc_)); std::vector<tl_object_ptr<ton_api::tonNode_shardId>>(), std::move(c.gc_));
}, },
[&](ton_api::engine_validator_config_v2 &c) { [&](ton_api::engine_validator_configV2 &c) {
res = std::make_unique<ton_api::engine_validator_config_v2>(std::move(c)); res = std::make_unique<ton_api::engine_validator_configV2>(std::move(c));
})); }));
return res; return res;
} }

View file

@ -75,7 +75,7 @@ Config::Config() {
full_node = ton::PublicKeyHash::zero(); full_node = ton::PublicKeyHash::zero();
} }
Config::Config(const ton::ton_api::engine_validator_config_v2 &config) { Config::Config(const ton::ton_api::engine_validator_configV2 &config) {
full_node = ton::PublicKeyHash::zero(); full_node = ton::PublicKeyHash::zero();
out_port = static_cast<td::uint16>(config.out_port_); out_port = static_cast<td::uint16>(config.out_port_);
if (!out_port) { if (!out_port) {
@ -263,7 +263,7 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_Config> Config::tl() const {
full_node.tl(), std::move(full_node_slaves_vec), std::move(full_node_masters_vec), std::move(liteserver_vec), full_node.tl(), std::move(full_node_slaves_vec), std::move(full_node_masters_vec), std::move(liteserver_vec),
std::move(control_vec), std::move(gc_vec)); std::move(control_vec), std::move(gc_vec));
} else { } else {
return ton::create_tl_object<ton::ton_api::engine_validator_config_v2>( return ton::create_tl_object<ton::ton_api::engine_validator_configV2>(
out_port, std::move(addrs_vec), std::move(adnl_vec), std::move(dht_vec), std::move(val_vec), std::move(col_vec), 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), 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)); std::move(control_vec), std::move(shards_vec), std::move(gc_vec));

View file

@ -140,7 +140,7 @@ struct Config {
ton::tl_object_ptr<ton::ton_api::engine_validator_Config> tl() const; ton::tl_object_ptr<ton::ton_api::engine_validator_Config> tl() const;
Config(); Config();
Config(const ton::ton_api::engine_validator_config_v2 &config); Config(const ton::ton_api::engine_validator_configV2 &config);
}; };
class ValidatorEngine : public td::actor::Actor { class ValidatorEngine : public td::actor::Actor {

View file

@ -46,11 +46,25 @@ namespace validator {
namespace fullnode { namespace fullnode {
static const td::uint32 PROTO_CAPABILITIES_V2 = 2;
Neighbour Neighbour::zero = Neighbour{adnl::AdnlNodeIdShort::zero()}; Neighbour Neighbour::zero = Neighbour{adnl::AdnlNodeIdShort::zero()};
void Neighbour::update_proto_version(const ton_api::tonNode_capabilities &q) { void Neighbour::update_proto_version(ton_api::tonNode_Capabilities &q) {
proto_version = q.version_; ton_api::downcast_call(q, td::overloaded(
capabilities = q.capabilities_; [&](ton_api::tonNode_capabilities &x) {
proto_version = x.version_;
capabilities = x.capabilities_;
if (capabilities < PROTO_CAPABILITIES_V2) {
has_state_known = has_state = true;
}
},
[&](ton_api::tonNode_capabilitiesV2 &x) {
proto_version = x.version_;
capabilities = x.capabilities_;
has_state_known = true;
has_state = x.have_state_;
}));
} }
void Neighbour::query_success(double t) { void Neighbour::query_success(double t) {
@ -97,7 +111,7 @@ void FullNodeShardImpl::create_overlay() {
td::actor::ActorId<FullNodeShardImpl> node_; td::actor::ActorId<FullNodeShardImpl> node_;
}; };
if (active_) { if (is_active()) {
td::actor::send_closure(overlays_, &overlay::Overlays::create_public_overlay, adnl_id_, overlay_id_full_.clone(), td::actor::send_closure(overlays_, &overlay::Overlays::create_public_overlay, adnl_id_, overlay_id_full_.clone(),
std::make_unique<Callback>(actor_id(this)), rules_, std::make_unique<Callback>(actor_id(this)), rules_,
PSTRING() << "{ \"type\": \"shard\", \"shard_id\": " << get_shard() PSTRING() << "{ \"type\": \"shard\", \"shard_id\": " << get_shard()
@ -137,13 +151,16 @@ void FullNodeShardImpl::update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promis
create_overlay(); create_overlay();
} }
void FullNodeShardImpl::set_active(bool active) { void FullNodeShardImpl::set_mode(FullNodeShardMode mode) {
if (active_ == active || shard_.is_masterchain()) { if (shard_.is_masterchain()) {
return; return;
} }
td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_); bool was_active = is_active();
active_ = active; mode_ = mode;
create_overlay(); if (was_active != is_active()) {
td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_);
create_overlay();
}
} }
void FullNodeShardImpl::try_get_next_block(td::Timestamp timeout, td::Promise<ReceivedBlock> promise) { void FullNodeShardImpl::try_get_next_block(td::Timestamp timeout, td::Promise<ReceivedBlock> promise) {
@ -562,6 +579,12 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod
promise.set_value(create_serialize_tl_object<ton_api::tonNode_capabilities>(proto_version(), proto_capabilities())); promise.set_value(create_serialize_tl_object<ton_api::tonNode_capabilities>(proto_version(), proto_capabilities()));
} }
void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilitiesV2 &query,
td::Promise<td::BufferSlice> promise) {
promise.set_value(create_serialize_tl_object<ton_api::tonNode_capabilitiesV2>(proto_version(), proto_capabilities(),
mode_ == FullNodeShardMode::active));
}
void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query, void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query,
td::Promise<td::BufferSlice> promise) { td::Promise<td::BufferSlice> promise) {
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(
@ -609,7 +632,7 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod
void FullNodeShardImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice query, void FullNodeShardImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice query,
td::Promise<td::BufferSlice> promise) { td::Promise<td::BufferSlice> promise) {
if (!active_) { if (!is_active()) {
promise.set_error(td::Status::Error("shard is inactive")); promise.set_error(td::Status::Error("shard is inactive"));
return; return;
} }
@ -671,7 +694,7 @@ void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_bl
} }
void FullNodeShardImpl::receive_broadcast(PublicKeyHash src, td::BufferSlice broadcast) { void FullNodeShardImpl::receive_broadcast(PublicKeyHash src, td::BufferSlice broadcast) {
if (!active_) { if (!is_active()) {
return; return;
} }
auto B = fetch_tl_object<ton_api::tonNode_Broadcast>(std::move(broadcast), true); auto B = fetch_tl_object<ton_api::tonNode_Broadcast>(std::move(broadcast), true);
@ -801,7 +824,7 @@ void FullNodeShardImpl::download_block_proof_link(BlockIdExt block_id, td::uint3
td::Promise<td::BufferSlice> promise) { td::Promise<td::BufferSlice> promise) {
auto &b = choose_neighbour(); auto &b = choose_neighbour();
td::actor::create_actor<DownloadProof>("downloadproofreq", block_id, true, false, adnl_id_, overlay_id_, td::actor::create_actor<DownloadProof>("downloadproofreq", block_id, true, false, adnl_id_, overlay_id_,
adnl::AdnlNodeIdShort::zero(), priority, timeout, validator_manager_, rldp_, b.adnl_id, priority, timeout, validator_manager_, rldp_,
overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise)))
.release(); .release();
} }
@ -809,7 +832,7 @@ void FullNodeShardImpl::download_block_proof_link(BlockIdExt block_id, td::uint3
void FullNodeShardImpl::get_next_key_blocks(BlockIdExt block_id, td::Timestamp timeout, void FullNodeShardImpl::get_next_key_blocks(BlockIdExt block_id, td::Timestamp timeout,
td::Promise<std::vector<BlockIdExt>> promise) { td::Promise<std::vector<BlockIdExt>> promise) {
auto &b = choose_neighbour(); auto &b = choose_neighbour();
td::actor::create_actor<GetNextKeyBlocks>("next", block_id, 16, adnl_id_, overlay_id_, adnl::AdnlNodeIdShort::zero(), td::actor::create_actor<GetNextKeyBlocks>("next", block_id, 16, adnl_id_, overlay_id_, b.adnl_id,
1, timeout, validator_manager_, rldp_, overlays_, adnl_, client_, 1, timeout, validator_manager_, rldp_, overlays_, adnl_, client_,
create_neighbour_promise(b, std::move(promise))) create_neighbour_promise(b, std::move(promise)))
.release(); .release();
@ -817,10 +840,10 @@ void FullNodeShardImpl::get_next_key_blocks(BlockIdExt block_id, td::Timestamp t
void FullNodeShardImpl::download_archive(BlockSeqno masterchain_seqno, std::string tmp_dir, td::Timestamp timeout, void FullNodeShardImpl::download_archive(BlockSeqno masterchain_seqno, std::string tmp_dir, td::Timestamp timeout,
td::Promise<std::string> promise) { td::Promise<std::string> promise) {
auto &b = choose_neighbour(); auto &b = choose_neighbour(true);
td::actor::create_actor<DownloadArchiveSlice>( td::actor::create_actor<DownloadArchiveSlice>(
"archive", masterchain_seqno, std::move(tmp_dir), adnl_id_, overlay_id_, adnl::AdnlNodeIdShort::zero(), timeout, "archive", masterchain_seqno, std::move(tmp_dir), adnl_id_, overlay_id_, b.adnl_id, timeout,
validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise), true))
.release(); .release();
} }
@ -828,9 +851,9 @@ void FullNodeShardImpl::download_out_msg_queue_proof(BlockIdExt block_id, ShardI
td::Promise<td::Ref<OutMsgQueueProof>> promise) { td::Promise<td::Ref<OutMsgQueueProof>> promise) {
// TODO: maybe more complex download (like other requests here) // TODO: maybe more complex download (like other requests here)
// TODO: estimate max size // TODO: estimate max size
auto &b = choose_neighbour(); auto &b = choose_neighbour(true);
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda(
[=, promise = create_neighbour_promise(b, std::move(promise))](td::Result<td::BufferSlice> R) mutable { [=, promise = create_neighbour_promise(b, std::move(promise), true)](td::Result<td::BufferSlice> R) mutable {
if (R.is_error()) { if (R.is_error()) {
promise.set_result(R.move_as_error()); promise.set_result(R.move_as_error());
return; return;
@ -1026,11 +1049,21 @@ void FullNodeShardImpl::got_neighbours(std::vector<adnl::AdnlNodeIdShort> vec) {
continue; continue;
} }
if (neighbours_.size() == max_neighbours()) { if (neighbours_.size() == max_neighbours()) {
td::uint32 neighbours_with_state = 0;
for (const auto &n : neighbours_) {
if (n.second.has_state) {
++neighbours_with_state;
}
}
adnl::AdnlNodeIdShort a = adnl::AdnlNodeIdShort::zero(); adnl::AdnlNodeIdShort a = adnl::AdnlNodeIdShort::zero();
adnl::AdnlNodeIdShort b = adnl::AdnlNodeIdShort::zero(); adnl::AdnlNodeIdShort b = adnl::AdnlNodeIdShort::zero();
td::uint32 cnt = 0; td::uint32 cnt = 0;
double u = 0; double u = 0;
for (auto &n : neighbours_) { for (auto &n : neighbours_) {
if (neighbours_with_state <= min_neighbours_with_state() && n.second.has_state) {
continue;
}
if (n.second.unreliability > u) { if (n.second.unreliability > u) {
u = n.second.unreliability; u = n.second.unreliability;
a = n.first; a = n.first;
@ -1054,34 +1087,47 @@ void FullNodeShardImpl::got_neighbours(std::vector<adnl::AdnlNodeIdShort> vec) {
} }
} }
const Neighbour &FullNodeShardImpl::choose_neighbour() const { const Neighbour &FullNodeShardImpl::choose_neighbour(bool require_state) const {
if (neighbours_.size() == 0) { if (neighbours_.size() == 0) {
return Neighbour::zero; return Neighbour::zero;
} }
const Neighbour *best = nullptr; for (int attempt = 0; attempt < (require_state ? 2 : 1); ++attempt) {
td::uint32 sum = 0; const Neighbour *best = nullptr;
td::uint32 sum = 0;
for (auto &x : neighbours_) { for (auto &x : neighbours_) {
td::uint32 unr = static_cast<td::uint32>(x.second.unreliability); if (require_state) {
if (attempt == 0 && !x.second.has_state) {
continue;
}
if (attempt == 1 && x.second.has_state_known) {
continue;
}
}
auto unr = static_cast<td::uint32>(x.second.unreliability);
if (x.second.proto_version < proto_version()) { if (x.second.proto_version < proto_version()) {
unr += 4; unr += 4;
} else if (x.second.proto_version == proto_version() && x.second.capabilities < proto_capabilities()) { } else if (x.second.proto_version == proto_version() && x.second.capabilities < proto_capabilities()) {
unr += 2; unr += 2;
} }
auto f = static_cast<td::uint32>(fail_unreliability()); auto f = static_cast<td::uint32>(fail_unreliability());
if (unr <= f) { if (unr <= f) {
auto w = 1 << (f - unr); auto w = 1 << (f - unr);
sum += w; sum += w;
if (td::Random::fast(0, sum - 1) <= w - 1) { if (td::Random::fast(0, sum - 1) <= w - 1) {
best = &x.second; best = &x.second;
}
} }
} }
if (best) {
return *best;
}
} }
return best ? *best : Neighbour::zero; return Neighbour::zero;
} }
void FullNodeShardImpl::update_neighbour_stats(adnl::AdnlNodeIdShort adnl_id, double t, bool success) { void FullNodeShardImpl::update_neighbour_stats(adnl::AdnlNodeIdShort adnl_id, double t, bool success) {
@ -1100,11 +1146,11 @@ void FullNodeShardImpl::got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id
if (it == neighbours_.end()) { if (it == neighbours_.end()) {
return; return;
} }
auto F = fetch_tl_object<ton_api::tonNode_capabilities>(std::move(data), true); auto F = fetch_tl_object<ton_api::tonNode_Capabilities>(std::move(data), true);
if (F.is_error()) { if (F.is_error()) {
it->second.query_failed(); it->second.query_failed();
} else { } else {
it->second.update_proto_version(*F.move_as_ok().get()); it->second.update_proto_version(*F.ok());
it->second.query_success(t); it->second.query_success(t);
} }
} }
@ -1133,7 +1179,12 @@ void FullNodeShardImpl::ping_neighbours() {
td::Time::now() - start_time, R.move_as_ok()); td::Time::now() - start_time, R.move_as_ok());
} }
}); });
auto q = create_serialize_tl_object<ton_api::tonNode_getCapabilities>(); td::BufferSlice q;
if (it->second.capabilities >= PROTO_CAPABILITIES_V2) {
q = create_serialize_tl_object<ton_api::tonNode_getCapabilitiesV2>();
} else {
q = create_serialize_tl_object<ton_api::tonNode_getCapabilities>();
}
td::actor::send_closure(overlays_, &overlay::Overlays::send_query, it->first, adnl_id_, overlay_id_, td::actor::send_closure(overlays_, &overlay::Overlays::send_query, it->first, adnl_id_, overlay_id_,
"get_prepare_block", std::move(P), td::Timestamp::in(1.0), std::move(q)); "get_prepare_block", std::move(P), td::Timestamp::in(1.0), std::move(q));
@ -1148,7 +1199,7 @@ FullNodeShardImpl::FullNodeShardImpl(ShardIdFull shard, PublicKeyHash local_id,
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,
td::actor::ActorId<overlay::Overlays> overlays, td::actor::ActorId<overlay::Overlays> overlays,
td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<ValidatorManagerInterface> validator_manager,
td::actor::ActorId<adnl::AdnlExtClient> client, bool active) td::actor::ActorId<adnl::AdnlExtClient> client, FullNodeShardMode mode)
: shard_(shard) : shard_(shard)
, local_id_(local_id) , local_id_(local_id)
, adnl_id_(adnl_id) , adnl_id_(adnl_id)
@ -1159,7 +1210,7 @@ FullNodeShardImpl::FullNodeShardImpl(ShardIdFull shard, PublicKeyHash local_id,
, overlays_(overlays) , overlays_(overlays)
, validator_manager_(validator_manager) , validator_manager_(validator_manager)
, client_(client) , client_(client)
, active_(shard.is_masterchain() || active) { , mode_(shard.is_masterchain() ? FullNodeShardMode::active : mode) {
} }
td::actor::ActorOwn<FullNodeShard> FullNodeShard::create( td::actor::ActorOwn<FullNodeShard> FullNodeShard::create(
@ -1167,9 +1218,9 @@ td::actor::ActorOwn<FullNodeShard> FullNodeShard::create(
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays, td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays,
td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<adnl::AdnlExtClient> client, td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<adnl::AdnlExtClient> client,
bool active) { FullNodeShardMode mode) {
return td::actor::create_actor<FullNodeShardImpl>("tonnode", shard, local_id, adnl_id, zero_state_file_hash, keyring, return td::actor::create_actor<FullNodeShardImpl>("tonnode", shard, local_id, adnl_id, zero_state_file_hash, keyring,
adnl, rldp, overlays, validator_manager, client, active); adnl, rldp, overlays, validator_manager, client, mode);
} }
} // namespace fullnode } // namespace fullnode

View file

@ -28,6 +28,13 @@ namespace validator {
namespace fullnode { namespace fullnode {
enum FullNodeShardMode {
active, // Node can answer queries about the shard
active_temp, // Like 'active', but queries about shard state are not allowed (only blocks)
inactive // Node is not a part of the overlay (overlay is_external)
};
class FullNodeShard : public td::actor::Actor { class FullNodeShard : public td::actor::Actor {
public: public:
virtual ~FullNodeShard() = default; virtual ~FullNodeShard() = default;
@ -36,7 +43,7 @@ class FullNodeShard : public td::actor::Actor {
virtual ShardIdFull get_shard_full() const = 0; virtual ShardIdFull get_shard_full() const = 0;
virtual void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) = 0; virtual void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) = 0;
virtual void set_active(bool active) = 0; virtual void set_mode(FullNodeShardMode mode) = 0;
virtual void send_ihr_message(td::BufferSlice data) = 0; virtual void send_ihr_message(td::BufferSlice data) = 0;
virtual void send_external_message(td::BufferSlice data) = 0; virtual void send_external_message(td::BufferSlice data) = 0;
@ -74,7 +81,7 @@ class FullNodeShard : public td::actor::Actor {
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays, td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays,
td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<adnl::AdnlExtClient> client, td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<adnl::AdnlExtClient> client,
bool active = true); FullNodeShardMode mode = FullNodeShardMode::active);
}; };
} // namespace fullnode } // namespace fullnode

View file

@ -36,10 +36,12 @@ struct Neighbour {
double roundtrip_relax_at = 0; double roundtrip_relax_at = 0;
double roundtrip_weight = 0; double roundtrip_weight = 0;
double unreliability = 0; double unreliability = 0;
bool has_state_known = false;
bool has_state = false;
Neighbour(adnl::AdnlNodeIdShort adnl_id) : adnl_id(std::move(adnl_id)) { Neighbour(adnl::AdnlNodeIdShort adnl_id) : adnl_id(std::move(adnl_id)) {
} }
void update_proto_version(const ton_api::tonNode_capabilities &q); void update_proto_version(ton_api::tonNode_Capabilities &q);
void query_success(double t); void query_success(double t);
void query_failed(); void query_failed();
void update_roundtrip(double t); void update_roundtrip(double t);
@ -66,11 +68,14 @@ class FullNodeShardImpl : public FullNodeShard {
return 2; return 2;
} }
static constexpr td::uint64 proto_capabilities() { static constexpr td::uint64 proto_capabilities() {
return 1; return 2;
} }
static constexpr td::uint32 max_neighbours() { static constexpr td::uint32 max_neighbours() {
return 16; return 16;
} }
static constexpr td::uint32 min_neighbours_with_state() {
return 10;
}
static constexpr double stop_unreliability() { static constexpr double stop_unreliability() {
return 5.0; return 5.0;
} }
@ -80,11 +85,8 @@ class FullNodeShardImpl : public FullNodeShard {
void create_overlay(); void create_overlay();
void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) override; void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) override;
void set_active(bool active) override; void set_mode(FullNodeShardMode mode) override;
//td::Result<Block> fetch_block(td::BufferSlice data);
void prevalidate_block(BlockIdExt block_id, td::BufferSlice data, td::BufferSlice proof,
td::Promise<ReceivedBlock> promise);
void try_get_next_block(td::Timestamp timestamp, td::Promise<ReceivedBlock> promise); void try_get_next_block(td::Timestamp timestamp, td::Promise<ReceivedBlock> promise);
void got_next_block(td::Result<BlockHandle> block); void got_next_block(td::Result<BlockHandle> block);
void get_next_block(); void get_next_block();
@ -129,6 +131,8 @@ class FullNodeShardImpl : public FullNodeShard {
td::Promise<td::BufferSlice> promise); td::Promise<td::BufferSlice> promise);
void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilities &query, void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilities &query,
td::Promise<td::BufferSlice> promise); td::Promise<td::BufferSlice> promise);
void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilitiesV2 &query,
td::Promise<td::BufferSlice> promise);
void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query, void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query,
td::Promise<td::BufferSlice> promise); td::Promise<td::BufferSlice> promise);
void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveSlice &query, void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveSlice &query,
@ -189,14 +193,16 @@ class FullNodeShardImpl : public FullNodeShard {
void got_neighbours(std::vector<adnl::AdnlNodeIdShort> res); void got_neighbours(std::vector<adnl::AdnlNodeIdShort> res);
void update_neighbour_stats(adnl::AdnlNodeIdShort adnl_id, double t, bool success); void update_neighbour_stats(adnl::AdnlNodeIdShort adnl_id, double t, bool success);
void got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id, double t, td::BufferSlice data); void got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id, double t, td::BufferSlice data);
const Neighbour &choose_neighbour() const; const Neighbour &choose_neighbour(bool require_state = false) const;
template <typename T> template <typename T>
td::Promise<T> create_neighbour_promise(const Neighbour &x, td::Promise<T> p) { td::Promise<T> create_neighbour_promise(const Neighbour &x, td::Promise<T> p, bool require_state = false) {
return td::PromiseCreator::lambda([id = x.adnl_id, SelfId = actor_id(this), p = std::move(p), return td::PromiseCreator::lambda([id = x.adnl_id, SelfId = actor_id(this), p = std::move(p), ts = td::Time::now(),
ts = td::Time::now()](td::Result<T> R) mutable { ignore_error = require_state && !x.has_state_known](td::Result<T> R) mutable {
if (R.is_error() && R.error().code() != ErrorCode::notready && R.error().code() != ErrorCode::cancelled) { if (R.is_error() && R.error().code() != ErrorCode::notready && R.error().code() != ErrorCode::cancelled) {
td::actor::send_closure(SelfId, &FullNodeShardImpl::update_neighbour_stats, id, td::Time::now() - ts, false); if (!ignore_error) {
td::actor::send_closure(SelfId, &FullNodeShardImpl::update_neighbour_stats, id, td::Time::now() - ts, false);
}
} else { } else {
td::actor::send_closure(SelfId, &FullNodeShardImpl::update_neighbour_stats, id, td::Time::now() - ts, true); td::actor::send_closure(SelfId, &FullNodeShardImpl::update_neighbour_stats, id, td::Time::now() - ts, true);
} }
@ -209,13 +215,17 @@ class FullNodeShardImpl : public FullNodeShard {
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,
td::actor::ActorId<overlay::Overlays> overlays, td::actor::ActorId<overlay::Overlays> overlays,
td::actor::ActorId<ValidatorManagerInterface> validator_manager, td::actor::ActorId<ValidatorManagerInterface> validator_manager,
td::actor::ActorId<adnl::AdnlExtClient> client, bool active = true); td::actor::ActorId<adnl::AdnlExtClient> client, FullNodeShardMode mode = FullNodeShardMode::active);
private: private:
bool use_new_download() const { bool use_new_download() const {
return false; return false;
} }
bool is_active() const {
return mode_ != FullNodeShardMode::inactive;
}
ShardIdFull shard_; ShardIdFull shard_;
BlockHandle handle_; BlockHandle handle_;
td::Promise<td::Unit> promise_; td::Promise<td::Unit> promise_;
@ -247,7 +257,7 @@ class FullNodeShardImpl : public FullNodeShard {
td::Timestamp ping_neighbours_at_; td::Timestamp ping_neighbours_at_;
adnl::AdnlNodeIdShort last_pinged_neighbour_ = adnl::AdnlNodeIdShort::zero(); adnl::AdnlNodeIdShort last_pinged_neighbour_ = adnl::AdnlNodeIdShort::zero();
bool active_ = false; FullNodeShardMode mode_;
}; };
} // namespace fullnode } // namespace fullnode

View file

@ -132,14 +132,15 @@ void FullNodeImpl::initial_read_complete(BlockHandle top_handle) {
td::actor::send_closure(it->second.actor, &FullNodeShard::set_handle, top_handle, std::move(P)); td::actor::send_closure(it->second.actor, &FullNodeShard::set_handle, top_handle, std::move(P));
} }
void FullNodeImpl::update_shard_configuration(td::Ref<MasterchainState> state, void FullNodeImpl::update_shard_configuration(td::Ref<MasterchainState> state, std::set<ShardIdFull> shards_to_monitor,
std::set<ShardIdFull> shards_to_monitor) { std::set<ShardIdFull> temporary_shards) {
CHECK(shards_to_monitor.count(ShardIdFull(masterchainId)));
std::map<ShardIdFull, BlockIdExt> new_shards; std::map<ShardIdFull, BlockIdExt> new_shards;
std::set<ShardIdFull> new_active; std::map<ShardIdFull, FullNodeShardMode> new_active;
new_shards[ShardIdFull(masterchainId)] = state->get_block_id(); new_shards[ShardIdFull(masterchainId)] = state->get_block_id();
std::set<WorkchainId> workchains; std::set<WorkchainId> workchains;
auto set_active = [&](ShardIdFull shard) { auto set_active = [&](ShardIdFull shard, FullNodeShardMode mode) {
while (new_active.insert(shard).second && shard.pfx_len() > 0) { while (new_active.emplace(shard, mode).second && shard.pfx_len() > 0) {
shard = shard_parent(shard); shard = shard_parent(shard);
} }
}; };
@ -155,20 +156,24 @@ void FullNodeImpl::update_shard_configuration(td::Ref<MasterchainState> state,
} }
} }
for (ShardIdFull shard : shards_to_monitor) { for (ShardIdFull shard : shards_to_monitor) {
set_active(shard); set_active(shard, FullNodeShardMode::active);
}
for (ShardIdFull shard : temporary_shards) {
set_active(shard, FullNodeShardMode::active_temp);
} }
auto info_set_active = [&](ShardIdFull shard, ShardInfo& info, bool active) { auto info_set_mode = [&](ShardIdFull shard, ShardInfo& info, FullNodeShardMode mode) {
if (info.active == active) { if (info.mode == mode) {
return; return;
} }
if (info.actor.empty()) { if (info.actor.empty()) {
add_shard_actor(shard, active); add_shard_actor(shard, mode);
return; return;
} }
info.active = active; info.mode = mode;
td::actor::send_closure(info.actor, &FullNodeShard::set_active, active); td::actor::send_closure(info.actor, &FullNodeShard::set_mode, mode);
info.delete_at = active ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); info.delete_at =
mode != FullNodeShardMode::inactive ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL);
}; };
for (auto shard : new_shards) { for (auto shard : new_shards) {
@ -180,16 +185,17 @@ void FullNodeImpl::update_shard_configuration(td::Ref<MasterchainState> state,
ShardIdFull shard = p.first; ShardIdFull shard = p.first;
ShardInfo &info = p.second; ShardInfo &info = p.second;
info.exists = new_shards.count(shard); info.exists = new_shards.count(shard);
info_set_active(shard, info, new_active.count(shard)); auto it = new_active.find(shard);
info_set_mode(shard, info, it == new_active.end() ? FullNodeShardMode::inactive : it->second);
} }
for (ShardIdFull shard : new_active) { for (const auto& s : new_active) {
info_set_active(shard, shards_[shard], true); info_set_mode(s.first, shards_[s.first], s.second);
} }
auto it = shards_.begin(); auto it = shards_.begin();
while (it != shards_.end()) { while (it != shards_.end()) {
if (!it->second.active && it->second.delete_at && it->second.delete_at.is_in_past()) { if (it->second.mode == FullNodeShardMode::inactive && it->second.delete_at && it->second.delete_at.is_in_past()) {
it->second.actor.reset(); it->second.actor.reset();
it->second.delete_at = td::Timestamp::never(); it->second.delete_at = td::Timestamp::never();
} }
@ -201,15 +207,15 @@ void FullNodeImpl::update_shard_configuration(td::Ref<MasterchainState> state,
} }
} }
void FullNodeImpl::add_shard_actor(ShardIdFull shard, bool active) { void FullNodeImpl::add_shard_actor(ShardIdFull shard, FullNodeShardMode mode) {
ShardInfo &info = shards_[shard]; ShardInfo &info = shards_[shard];
if (!info.actor.empty()) { if (!info.actor.empty()) {
return; return;
} }
info.actor = FullNodeShard::create(shard, local_id_, adnl_id_, zero_state_file_hash_, keyring_, adnl_, rldp_, info.actor = FullNodeShard::create(shard, local_id_, adnl_id_, zero_state_file_hash_, keyring_, adnl_, rldp_,
overlays_, validator_manager_, client_, active); overlays_, validator_manager_, client_, mode);
info.active = active; info.mode = mode;
info.delete_at = active ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); info.delete_at = mode != FullNodeShardMode::inactive ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL);
if (all_validators_.size() > 0) { if (all_validators_.size() > 0) {
td::actor::send_closure(info.actor, &FullNodeShard::update_validators, all_validators_, sign_cert_by_); td::actor::send_closure(info.actor, &FullNodeShard::update_validators, all_validators_, sign_cert_by_);
} }
@ -350,9 +356,9 @@ td::actor::ActorId<FullNodeShard> FullNodeImpl::get_shard(ShardIdFull shard, boo
auto it = shards_.find(s); auto it = shards_.find(s);
if (it != shards_.end() && it->second.exists) { if (it != shards_.end() && it->second.exists) {
if (it->second.actor.empty()) { if (it->second.actor.empty()) {
add_shard_actor(s, false); add_shard_actor(s, FullNodeShardMode::inactive);
} }
if (!it->second.active) { if (it->second.mode == FullNodeShardMode::inactive) {
it->second.delete_at = td::Timestamp::in(INACTIVE_SHARD_TTL); it->second.delete_at = td::Timestamp::in(INACTIVE_SHARD_TTL);
} }
return it->second.actor.get(); return it->second.actor.get();
@ -365,9 +371,9 @@ td::actor::ActorId<FullNodeShard> FullNodeImpl::get_shard(ShardIdFull shard, boo
} }
auto &info = shards_[shard]; auto &info = shards_[shard];
if (info.actor.empty()) { if (info.actor.empty()) {
add_shard_actor(shard, false); add_shard_actor(shard, FullNodeShardMode::inactive);
} }
if (!info.active) { if (info.mode == FullNodeShardMode::inactive) {
info.delete_at = td::Timestamp::in(INACTIVE_SHARD_TTL); info.delete_at = td::Timestamp::in(INACTIVE_SHARD_TTL);
} }
return info.actor.get(); return info.actor.get();
@ -488,9 +494,10 @@ void FullNodeImpl::start_up() {
void initial_read_complete(BlockHandle handle) override { void initial_read_complete(BlockHandle handle) override {
td::actor::send_closure(id_, &FullNodeImpl::initial_read_complete, handle); td::actor::send_closure(id_, &FullNodeImpl::initial_read_complete, handle);
} }
void update_shard_configuration(td::Ref<MasterchainState> state, std::set<ShardIdFull> shards_to_monitor) override { void update_shard_configuration(td::Ref<MasterchainState> state, std::set<ShardIdFull> shards_to_monitor,
std::set<ShardIdFull> temporary_shards) override {
td::actor::send_closure(id_, &FullNodeImpl::update_shard_configuration, std::move(state), td::actor::send_closure(id_, &FullNodeImpl::update_shard_configuration, std::move(state),
std::move(shards_to_monitor)); std::move(shards_to_monitor), std::move(temporary_shards));
} }
void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) override { void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) override {
td::actor::send_closure(id_, &FullNodeImpl::send_ihr_message, dst, std::move(data)); td::actor::send_closure(id_, &FullNodeImpl::send_ihr_message, dst, std::move(data));
@ -576,7 +583,7 @@ FullNodeImpl::FullNodeImpl(PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id
, client_(client) , client_(client)
, db_root_(db_root) , db_root_(db_root)
, started_promise_(std::move(started_promise)) { , started_promise_(std::move(started_promise)) {
add_shard_actor(ShardIdFull{masterchainId}, true); add_shard_actor(ShardIdFull{masterchainId}, FullNodeShardMode::active);
} }
td::actor::ActorOwn<FullNode> FullNode::create( td::actor::ActorOwn<FullNode> FullNode::create(

View file

@ -52,7 +52,8 @@ class FullNodeImpl : public FullNode {
void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) override; void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise<td::Unit> promise) override;
void update_shard_configuration(td::Ref<MasterchainState> state, std::set<ShardIdFull> shards_to_monitor); void update_shard_configuration(td::Ref<MasterchainState> state, std::set<ShardIdFull> shards_to_monitor,
std::set<ShardIdFull> temporary_shards);
void sync_completed(); void sync_completed();
@ -91,7 +92,7 @@ class FullNodeImpl : public FullNode {
td::Promise<td::Unit> started_promise); td::Promise<td::Unit> started_promise);
private: private:
void add_shard_actor(ShardIdFull shard, bool active); void add_shard_actor(ShardIdFull shard, FullNodeShardMode mode);
PublicKeyHash local_id_; PublicKeyHash local_id_;
adnl::AdnlNodeIdShort adnl_id_; adnl::AdnlNodeIdShort adnl_id_;
@ -103,7 +104,7 @@ class FullNodeImpl : public FullNode {
struct ShardInfo { struct ShardInfo {
bool exists = false; bool exists = false;
td::actor::ActorOwn<FullNodeShard> actor; td::actor::ActorOwn<FullNodeShard> actor;
bool active = false; FullNodeShardMode mode = FullNodeShardMode::inactive;
td::Timestamp delete_at = td::Timestamp::never(); td::Timestamp delete_at = td::Timestamp::never();
}; };
std::map<ShardIdFull, ShardInfo> shards_; std::map<ShardIdFull, ShardInfo> shards_;

View file

@ -2453,8 +2453,7 @@ void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promise<Bloc
void ValidatorManagerImpl::update_shard_configuration(td::Ref<MasterchainState> state, void ValidatorManagerImpl::update_shard_configuration(td::Ref<MasterchainState> state,
std::set<ShardIdFull> shards_to_monitor) { std::set<ShardIdFull> shards_to_monitor) {
shards_to_monitor_ = shards_to_monitor; shards_to_monitor_ = shards_to_monitor;
shards_to_monitor.insert(extra_active_shards_.begin(), extra_active_shards_.end()); callback_->update_shard_configuration(std::move(state), std::move(shards_to_monitor), extra_active_shards_);
callback_->update_shard_configuration(std::move(state), std::move(shards_to_monitor));
} }
void ValidatorManagerImpl::update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) { void ValidatorManagerImpl::update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) {

View file

@ -110,7 +110,8 @@ class ValidatorManagerInterface : public td::actor::Actor {
virtual void initial_read_complete(BlockHandle top_masterchain_blocks) = 0; virtual void initial_read_complete(BlockHandle top_masterchain_blocks) = 0;
virtual void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state, virtual void update_shard_configuration(td::Ref<ton::validator::MasterchainState> state,
std::set<ShardIdFull> shards_to_monitor) = 0; std::set<ShardIdFull> shards_to_monitor,
std::set<ShardIdFull> temporary_shards) = 0;
virtual void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0; virtual void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0;
virtual void send_ext_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0; virtual void send_ext_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0;