diff --git a/create-hardfork/create-hardfork.cpp b/create-hardfork/create-hardfork.cpp index a24b7fc1..3fb57f41 100644 --- a/create-hardfork/create-hardfork.cpp +++ b/create-hardfork/create-hardfork.cpp @@ -237,7 +237,8 @@ class HardforkCreator : public td::actor::Actor { td::PromiseCreator::lambda([](td::Unit) {})); } void update_shard_configuration(td::Ref state, - std::set shards_to_monitor) override { + std::set shards_to_monitor, + std::set temporary_shards) override { } void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { } diff --git a/dht-server/dht-server.cpp b/dht-server/dht-server.cpp index d1f43953..3bd65cc6 100644 --- a/dht-server/dht-server.cpp +++ b/dht-server/dht-server.cpp @@ -57,7 +57,7 @@ Config::Config() { 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(config.out_port_); if (!out_port) { out_port = 3278; diff --git a/dht-server/dht-server.hpp b/dht-server/dht-server.hpp index 724e7bbf..724232fa 100644 --- a/dht-server/dht-server.hpp +++ b/dht-server/dht-server.hpp @@ -94,7 +94,7 @@ struct Config { ton::tl_object_ptr tl() const; 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 { diff --git a/overlay/overlay.cpp b/overlay/overlay.cpp index ff86d837..8e35e2a2 100644 --- a/overlay/overlay.cpp +++ b/overlay/overlay.cpp @@ -235,12 +235,12 @@ void OverlayImpl::receive_message(adnl::AdnlNodeIdShort src, td::BufferSlice dat auto X = fetch_tl_object(data.clone(), true); if (X.is_error()) { auto Y = fetch_tl_object(data.clone(), true); - if (Y.is_ok()) { + if (Y.is_ok() && public_) { VLOG(OVERLAY_DEBUG) << this << ": received removePeer message from " << src; if (peers_.exists(src)) { del_peer(src); - callback_->on_remove_peer(src); } + callback_->on_remove_peer(src); return; } } diff --git a/test/test-ton-collator.cpp b/test/test-ton-collator.cpp index d9ec82e5..8ef469b5 100644 --- a/test/test-ton-collator.cpp +++ b/test/test-ton-collator.cpp @@ -324,7 +324,8 @@ class TestNode : public td::actor::Actor { td::PromiseCreator::lambda([](td::Unit) {})); } void update_shard_configuration(td::Ref state, - std::set shards_to_monitor) override { + std::set shards_to_monitor, + std::set temporary_shards) override { } void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { } diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 733c034a..39cfb5ee 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -407,6 +407,7 @@ tonNode.dataFull id:tonNode.blockIdExt proof:bytes block:bytes is_link:Bool = to tonNode.dataFullEmpty = tonNode.DataFull; tonNode.capabilities version:int capabilities:long = tonNode.Capabilities; +tonNode.capabilitiesV2 version:int capabilities:long have_state:Bool = tonNode.Capabilities; 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.getCapabilities = tonNode.Capabilities; +tonNode.getCapabilitiesV2 = tonNode.Capabilities; 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) 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) validators:(vector engine.validator) collators:(vector engine.collator) fullnode:int256 fullnodeslaves:(vector engine.validator.fullNodeSlave) diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index c62bf28e..413fbd87 100644 Binary files a/tl/generate/scheme/ton_api.tlo and b/tl/generate/scheme/ton_api.tlo differ diff --git a/ton/ton-tl.hpp b/ton/ton-tl.hpp index f6bda4d9..5df54ec6 100644 --- a/ton/ton-tl.hpp +++ b/ton/ton-tl.hpp @@ -62,12 +62,12 @@ inline tl_object_ptr create_tl_shard_id(const ShardIdF return create_tl_object(s.workchain, s.shard); } -inline tl_object_ptr unpack_engine_validator_config( +inline tl_object_ptr unpack_engine_validator_config( tl_object_ptr config) { - tl_object_ptr res; + tl_object_ptr res; ton_api::downcast_call(*config, td::overloaded( [&](ton_api::engine_validator_config &c) { - res = create_tl_object( + res = create_tl_object( c.out_port_, std::move(c.addrs_), std::move(c.adnl_), std::move(c.dht_), std::move(c.validators_), std::vector>(), c.fullnode_, @@ -75,8 +75,8 @@ inline tl_object_ptr unpack_engine_validato std::move(c.liteservers_), std::move(c.control_), std::vector>(), std::move(c.gc_)); }, - [&](ton_api::engine_validator_config_v2 &c) { - res = std::make_unique(std::move(c)); + [&](ton_api::engine_validator_configV2 &c) { + res = std::make_unique(std::move(c)); })); return res; } diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index 65fb0e8f..c0f85d03 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -75,7 +75,7 @@ Config::Config() { 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(); out_port = static_cast(config.out_port_); if (!out_port) { @@ -263,7 +263,7 @@ ton::tl_object_ptr Config::tl() const { 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)); } else { - return ton::create_tl_object( + return ton::create_tl_object( 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)); diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index 47d612b7..b5d770a4 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -140,7 +140,7 @@ struct Config { ton::tl_object_ptr tl() const; 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 { diff --git a/validator/full-node-shard.cpp b/validator/full-node-shard.cpp index fea4916d..4bd7bf36 100644 --- a/validator/full-node-shard.cpp +++ b/validator/full-node-shard.cpp @@ -46,11 +46,25 @@ namespace validator { namespace fullnode { +static const td::uint32 PROTO_CAPABILITIES_V2 = 2; + Neighbour Neighbour::zero = Neighbour{adnl::AdnlNodeIdShort::zero()}; -void Neighbour::update_proto_version(const ton_api::tonNode_capabilities &q) { - proto_version = q.version_; - capabilities = q.capabilities_; +void Neighbour::update_proto_version(ton_api::tonNode_Capabilities &q) { + ton_api::downcast_call(q, td::overloaded( + [&](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) { @@ -97,7 +111,7 @@ void FullNodeShardImpl::create_overlay() { td::actor::ActorId node_; }; - if (active_) { + if (is_active()) { td::actor::send_closure(overlays_, &overlay::Overlays::create_public_overlay, adnl_id_, overlay_id_full_.clone(), std::make_unique(actor_id(this)), rules_, PSTRING() << "{ \"type\": \"shard\", \"shard_id\": " << get_shard() @@ -137,13 +151,16 @@ void FullNodeShardImpl::update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promis create_overlay(); } -void FullNodeShardImpl::set_active(bool active) { - if (active_ == active || shard_.is_masterchain()) { +void FullNodeShardImpl::set_mode(FullNodeShardMode mode) { + if (shard_.is_masterchain()) { return; } - td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_); - active_ = active; - create_overlay(); + bool was_active = is_active(); + mode_ = mode; + 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 promise) { @@ -562,6 +579,12 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod promise.set_value(create_serialize_tl_object(proto_version(), proto_capabilities())); } +void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilitiesV2 &query, + td::Promise promise) { + promise.set_value(create_serialize_tl_object(proto_version(), proto_capabilities(), + mode_ == FullNodeShardMode::active)); +} + void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query, td::Promise promise) { 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, td::Promise promise) { - if (!active_) { + if (!is_active()) { promise.set_error(td::Status::Error("shard is inactive")); return; } @@ -671,7 +694,7 @@ void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_bl } void FullNodeShardImpl::receive_broadcast(PublicKeyHash src, td::BufferSlice broadcast) { - if (!active_) { + if (!is_active()) { return; } auto B = fetch_tl_object(std::move(broadcast), true); @@ -801,7 +824,7 @@ void FullNodeShardImpl::download_block_proof_link(BlockIdExt block_id, td::uint3 td::Promise promise) { auto &b = choose_neighbour(); td::actor::create_actor("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))) .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, td::Promise> promise) { auto &b = choose_neighbour(); - td::actor::create_actor("next", block_id, 16, adnl_id_, overlay_id_, adnl::AdnlNodeIdShort::zero(), + td::actor::create_actor("next", block_id, 16, adnl_id_, overlay_id_, b.adnl_id, 1, timeout, validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) .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, td::Promise promise) { - auto &b = choose_neighbour(); + auto &b = choose_neighbour(true); td::actor::create_actor( - "archive", masterchain_seqno, std::move(tmp_dir), adnl_id_, overlay_id_, adnl::AdnlNodeIdShort::zero(), timeout, - validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) + "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), true)) .release(); } @@ -828,9 +851,9 @@ void FullNodeShardImpl::download_out_msg_queue_proof(BlockIdExt block_id, ShardI td::Promise> promise) { // TODO: maybe more complex download (like other requests here) // TODO: estimate max size - auto &b = choose_neighbour(); + auto &b = choose_neighbour(true); auto P = td::PromiseCreator::lambda( - [=, promise = create_neighbour_promise(b, std::move(promise))](td::Result R) mutable { + [=, promise = create_neighbour_promise(b, std::move(promise), true)](td::Result R) mutable { if (R.is_error()) { promise.set_result(R.move_as_error()); return; @@ -1026,11 +1049,21 @@ void FullNodeShardImpl::got_neighbours(std::vector vec) { continue; } 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 b = adnl::AdnlNodeIdShort::zero(); td::uint32 cnt = 0; double u = 0; for (auto &n : neighbours_) { + if (neighbours_with_state <= min_neighbours_with_state() && n.second.has_state) { + continue; + } if (n.second.unreliability > u) { u = n.second.unreliability; a = n.first; @@ -1054,34 +1087,47 @@ void FullNodeShardImpl::got_neighbours(std::vector vec) { } } -const Neighbour &FullNodeShardImpl::choose_neighbour() const { +const Neighbour &FullNodeShardImpl::choose_neighbour(bool require_state) const { if (neighbours_.size() == 0) { return Neighbour::zero; } - const Neighbour *best = nullptr; - td::uint32 sum = 0; + for (int attempt = 0; attempt < (require_state ? 2 : 1); ++attempt) { + const Neighbour *best = nullptr; + td::uint32 sum = 0; - for (auto &x : neighbours_) { - td::uint32 unr = static_cast(x.second.unreliability); + for (auto &x : neighbours_) { + if (require_state) { + if (attempt == 0 && !x.second.has_state) { + continue; + } + if (attempt == 1 && x.second.has_state_known) { + continue; + } + } + auto unr = static_cast(x.second.unreliability); - if (x.second.proto_version < proto_version()) { - unr += 4; - } else if (x.second.proto_version == proto_version() && x.second.capabilities < proto_capabilities()) { - unr += 2; - } + if (x.second.proto_version < proto_version()) { + unr += 4; + } else if (x.second.proto_version == proto_version() && x.second.capabilities < proto_capabilities()) { + unr += 2; + } - auto f = static_cast(fail_unreliability()); + auto f = static_cast(fail_unreliability()); - if (unr <= f) { - auto w = 1 << (f - unr); - sum += w; - if (td::Random::fast(0, sum - 1) <= w - 1) { - best = &x.second; + if (unr <= f) { + auto w = 1 << (f - unr); + sum += w; + if (td::Random::fast(0, sum - 1) <= w - 1) { + 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) { @@ -1100,11 +1146,11 @@ void FullNodeShardImpl::got_neighbour_capabilities(adnl::AdnlNodeIdShort adnl_id if (it == neighbours_.end()) { return; } - auto F = fetch_tl_object(std::move(data), true); + auto F = fetch_tl_object(std::move(data), true); if (F.is_error()) { it->second.query_failed(); } else { - it->second.update_proto_version(*F.move_as_ok().get()); + it->second.update_proto_version(*F.ok()); it->second.query_success(t); } } @@ -1133,7 +1179,12 @@ void FullNodeShardImpl::ping_neighbours() { td::Time::now() - start_time, R.move_as_ok()); } }); - auto q = create_serialize_tl_object(); + td::BufferSlice q; + if (it->second.capabilities >= PROTO_CAPABILITIES_V2) { + q = create_serialize_tl_object(); + } else { + q = create_serialize_tl_object(); + } 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)); @@ -1148,7 +1199,7 @@ FullNodeShardImpl::FullNodeShardImpl(ShardIdFull shard, PublicKeyHash local_id, td::actor::ActorId adnl, td::actor::ActorId rldp, td::actor::ActorId overlays, td::actor::ActorId validator_manager, - td::actor::ActorId client, bool active) + td::actor::ActorId client, FullNodeShardMode mode) : shard_(shard) , local_id_(local_id) , adnl_id_(adnl_id) @@ -1159,7 +1210,7 @@ FullNodeShardImpl::FullNodeShardImpl(ShardIdFull shard, PublicKeyHash local_id, , overlays_(overlays) , validator_manager_(validator_manager) , client_(client) - , active_(shard.is_masterchain() || active) { + , mode_(shard.is_masterchain() ? FullNodeShardMode::active : mode) { } td::actor::ActorOwn FullNodeShard::create( @@ -1167,9 +1218,9 @@ td::actor::ActorOwn FullNodeShard::create( td::actor::ActorId keyring, td::actor::ActorId adnl, td::actor::ActorId rldp, td::actor::ActorId overlays, td::actor::ActorId validator_manager, td::actor::ActorId client, - bool active) { + FullNodeShardMode mode) { return td::actor::create_actor("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 diff --git a/validator/full-node-shard.h b/validator/full-node-shard.h index 7da46af1..e24873aa 100644 --- a/validator/full-node-shard.h +++ b/validator/full-node-shard.h @@ -28,6 +28,13 @@ namespace validator { 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 { public: virtual ~FullNodeShard() = default; @@ -36,7 +43,7 @@ class FullNodeShard : public td::actor::Actor { virtual ShardIdFull get_shard_full() const = 0; virtual void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise 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_external_message(td::BufferSlice data) = 0; @@ -74,7 +81,7 @@ class FullNodeShard : public td::actor::Actor { td::actor::ActorId keyring, td::actor::ActorId adnl, td::actor::ActorId rldp, td::actor::ActorId overlays, td::actor::ActorId validator_manager, td::actor::ActorId client, - bool active = true); + FullNodeShardMode mode = FullNodeShardMode::active); }; } // namespace fullnode diff --git a/validator/full-node-shard.hpp b/validator/full-node-shard.hpp index a9b76181..cd7c20a9 100644 --- a/validator/full-node-shard.hpp +++ b/validator/full-node-shard.hpp @@ -36,10 +36,12 @@ struct Neighbour { double roundtrip_relax_at = 0; double roundtrip_weight = 0; double unreliability = 0; + bool has_state_known = false; + bool has_state = false; 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_failed(); void update_roundtrip(double t); @@ -66,11 +68,14 @@ class FullNodeShardImpl : public FullNodeShard { return 2; } static constexpr td::uint64 proto_capabilities() { - return 1; + return 2; } static constexpr td::uint32 max_neighbours() { return 16; } + static constexpr td::uint32 min_neighbours_with_state() { + return 10; + } static constexpr double stop_unreliability() { return 5.0; } @@ -80,11 +85,8 @@ class FullNodeShardImpl : public FullNodeShard { void create_overlay(); void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise promise) override; - void set_active(bool active) override; + void set_mode(FullNodeShardMode mode) override; - //td::Result fetch_block(td::BufferSlice data); - void prevalidate_block(BlockIdExt block_id, td::BufferSlice data, td::BufferSlice proof, - td::Promise promise); void try_get_next_block(td::Timestamp timestamp, td::Promise promise); void got_next_block(td::Result block); void get_next_block(); @@ -129,6 +131,8 @@ class FullNodeShardImpl : public FullNodeShard { td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilities &query, td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getCapabilitiesV2 &query, + td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveInfo &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_getArchiveSlice &query, @@ -189,14 +193,16 @@ class FullNodeShardImpl : public FullNodeShard { void got_neighbours(std::vector res); 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); - const Neighbour &choose_neighbour() const; + const Neighbour &choose_neighbour(bool require_state = false) const; template - td::Promise create_neighbour_promise(const Neighbour &x, td::Promise p) { - return td::PromiseCreator::lambda([id = x.adnl_id, SelfId = actor_id(this), p = std::move(p), - ts = td::Time::now()](td::Result R) mutable { + td::Promise create_neighbour_promise(const Neighbour &x, td::Promise p, bool require_state = false) { + return td::PromiseCreator::lambda([id = x.adnl_id, SelfId = actor_id(this), p = std::move(p), ts = td::Time::now(), + ignore_error = require_state && !x.has_state_known](td::Result R) mutable { 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 { 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, td::actor::ActorId rldp, td::actor::ActorId overlays, td::actor::ActorId validator_manager, - td::actor::ActorId client, bool active = true); + td::actor::ActorId client, FullNodeShardMode mode = FullNodeShardMode::active); private: bool use_new_download() const { return false; } + bool is_active() const { + return mode_ != FullNodeShardMode::inactive; + } + ShardIdFull shard_; BlockHandle handle_; td::Promise promise_; @@ -247,7 +257,7 @@ class FullNodeShardImpl : public FullNodeShard { td::Timestamp ping_neighbours_at_; adnl::AdnlNodeIdShort last_pinged_neighbour_ = adnl::AdnlNodeIdShort::zero(); - bool active_ = false; + FullNodeShardMode mode_; }; } // namespace fullnode diff --git a/validator/full-node.cpp b/validator/full-node.cpp index e4a2cf57..6792f969 100644 --- a/validator/full-node.cpp +++ b/validator/full-node.cpp @@ -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)); } -void FullNodeImpl::update_shard_configuration(td::Ref state, - std::set shards_to_monitor) { +void FullNodeImpl::update_shard_configuration(td::Ref state, std::set shards_to_monitor, + std::set temporary_shards) { + CHECK(shards_to_monitor.count(ShardIdFull(masterchainId))); std::map new_shards; - std::set new_active; + std::map new_active; new_shards[ShardIdFull(masterchainId)] = state->get_block_id(); std::set workchains; - auto set_active = [&](ShardIdFull shard) { - while (new_active.insert(shard).second && shard.pfx_len() > 0) { + auto set_active = [&](ShardIdFull shard, FullNodeShardMode mode) { + while (new_active.emplace(shard, mode).second && shard.pfx_len() > 0) { shard = shard_parent(shard); } }; @@ -155,20 +156,24 @@ void FullNodeImpl::update_shard_configuration(td::Ref state, } } 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) { - if (info.active == active) { + auto info_set_mode = [&](ShardIdFull shard, ShardInfo& info, FullNodeShardMode mode) { + if (info.mode == mode) { return; } if (info.actor.empty()) { - add_shard_actor(shard, active); + add_shard_actor(shard, mode); return; } - info.active = active; - td::actor::send_closure(info.actor, &FullNodeShard::set_active, active); - info.delete_at = active ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); + info.mode = mode; + td::actor::send_closure(info.actor, &FullNodeShard::set_mode, mode); + info.delete_at = + mode != FullNodeShardMode::inactive ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); }; for (auto shard : new_shards) { @@ -180,16 +185,17 @@ void FullNodeImpl::update_shard_configuration(td::Ref state, ShardIdFull shard = p.first; ShardInfo &info = p.second; 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) { - info_set_active(shard, shards_[shard], true); + for (const auto& s : new_active) { + info_set_mode(s.first, shards_[s.first], s.second); } auto it = shards_.begin(); 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.delete_at = td::Timestamp::never(); } @@ -201,15 +207,15 @@ void FullNodeImpl::update_shard_configuration(td::Ref state, } } -void FullNodeImpl::add_shard_actor(ShardIdFull shard, bool active) { +void FullNodeImpl::add_shard_actor(ShardIdFull shard, FullNodeShardMode mode) { ShardInfo &info = shards_[shard]; if (!info.actor.empty()) { return; } info.actor = FullNodeShard::create(shard, local_id_, adnl_id_, zero_state_file_hash_, keyring_, adnl_, rldp_, - overlays_, validator_manager_, client_, active); - info.active = active; - info.delete_at = active ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); + overlays_, validator_manager_, client_, mode); + info.mode = mode; + info.delete_at = mode != FullNodeShardMode::inactive ? td::Timestamp::never() : td::Timestamp::in(INACTIVE_SHARD_TTL); if (all_validators_.size() > 0) { td::actor::send_closure(info.actor, &FullNodeShard::update_validators, all_validators_, sign_cert_by_); } @@ -350,9 +356,9 @@ td::actor::ActorId FullNodeImpl::get_shard(ShardIdFull shard, boo auto it = shards_.find(s); if (it != shards_.end() && it->second.exists) { 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); } return it->second.actor.get(); @@ -365,9 +371,9 @@ td::actor::ActorId FullNodeImpl::get_shard(ShardIdFull shard, boo } auto &info = shards_[shard]; 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); } return info.actor.get(); @@ -488,9 +494,10 @@ void FullNodeImpl::start_up() { void initial_read_complete(BlockHandle handle) override { td::actor::send_closure(id_, &FullNodeImpl::initial_read_complete, handle); } - void update_shard_configuration(td::Ref state, std::set shards_to_monitor) override { + void update_shard_configuration(td::Ref state, std::set shards_to_monitor, + std::set temporary_shards) override { 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 { 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) , db_root_(db_root) , started_promise_(std::move(started_promise)) { - add_shard_actor(ShardIdFull{masterchainId}, true); + add_shard_actor(ShardIdFull{masterchainId}, FullNodeShardMode::active); } td::actor::ActorOwn FullNode::create( diff --git a/validator/full-node.hpp b/validator/full-node.hpp index 2f825458..fbe60d1b 100644 --- a/validator/full-node.hpp +++ b/validator/full-node.hpp @@ -52,7 +52,8 @@ class FullNodeImpl : public FullNode { void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise promise) override; - void update_shard_configuration(td::Ref state, std::set shards_to_monitor); + void update_shard_configuration(td::Ref state, std::set shards_to_monitor, + std::set temporary_shards); void sync_completed(); @@ -91,7 +92,7 @@ class FullNodeImpl : public FullNode { td::Promise started_promise); private: - void add_shard_actor(ShardIdFull shard, bool active); + void add_shard_actor(ShardIdFull shard, FullNodeShardMode mode); PublicKeyHash local_id_; adnl::AdnlNodeIdShort adnl_id_; @@ -103,7 +104,7 @@ class FullNodeImpl : public FullNode { struct ShardInfo { bool exists = false; td::actor::ActorOwn actor; - bool active = false; + FullNodeShardMode mode = FullNodeShardMode::inactive; td::Timestamp delete_at = td::Timestamp::never(); }; std::map shards_; diff --git a/validator/manager.cpp b/validator/manager.cpp index 04edefdc..7e7e1e84 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2453,8 +2453,7 @@ void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promise state, std::set 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)); + callback_->update_shard_configuration(std::move(state), std::move(shards_to_monitor), extra_active_shards_); } void ValidatorManagerImpl::update_async_serializer_state(AsyncSerializerState state, td::Promise promise) { diff --git a/validator/validator.h b/validator/validator.h index 545c8a81..0595949f 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -110,7 +110,8 @@ class ValidatorManagerInterface : public td::actor::Actor { virtual void initial_read_complete(BlockHandle top_masterchain_blocks) = 0; virtual void update_shard_configuration(td::Ref state, - std::set shards_to_monitor) = 0; + std::set shards_to_monitor, + std::set temporary_shards) = 0; virtual void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0; virtual void send_ext_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0;