From 996c23e506bdb930bc8517f6c6bb91809a89b051 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Mon, 18 Jul 2022 18:35:06 +0300 Subject: [PATCH] Shardchain validation without monitoring shardchains --- create-hardfork/create-hardfork.cpp | 4 +- overlay/overlay-manager.cpp | 9 +++ overlay/overlay-manager.h | 2 + overlay/overlay.cpp | 16 ++++- overlay/overlay.hpp | 7 ++ overlay/overlays.h | 2 + test/test-ton-collator.cpp | 4 +- validator-engine/validator-engine.cpp | 7 +- validator-engine/validator-engine.hpp | 4 ++ validator/fabric.h | 4 ++ validator/full-node-shard.cpp | 92 +++++++++++++++++++-------- validator/full-node-shard.h | 4 +- validator/full-node-shard.hpp | 6 +- validator/full-node.cpp | 24 +++---- validator/full-node.hpp | 2 +- validator/impl/accept-block.cpp | 31 +++++++++ validator/impl/accept-block.hpp | 6 ++ validator/impl/fabric.cpp | 11 ++++ validator/manager.cpp | 4 +- validator/validator-group.cpp | 49 ++++++-------- validator/validator-group.hpp | 6 +- validator/validator.h | 4 +- 22 files changed, 210 insertions(+), 88 deletions(-) diff --git a/create-hardfork/create-hardfork.cpp b/create-hardfork/create-hardfork.cpp index 15533768..849a31b1 100644 --- a/create-hardfork/create-hardfork.cpp +++ b/create-hardfork/create-hardfork.cpp @@ -236,9 +236,7 @@ class HardforkCreator : public td::actor::Actor { td::actor::send_closure(id_, &ton::validator::ValidatorManager::sync_complete, td::PromiseCreator::lambda([](td::Unit) {})); } - void add_shard(ton::ShardIdFull) override { - } - void del_shard(ton::ShardIdFull) override { + void subscribe_to_shard(ton::ShardIdFull) override { } void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { } diff --git a/overlay/overlay-manager.cpp b/overlay/overlay-manager.cpp index 41750b4f..2eac5a0c 100644 --- a/overlay/overlay-manager.cpp +++ b/overlay/overlay-manager.cpp @@ -98,6 +98,15 @@ void OverlayManager::create_public_overlay(adnl::AdnlNodeIdShort local_id, Overl std::move(callback), std::move(rules), scope)); } +void OverlayManager::create_public_overlay_no_subscribe(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, + OverlayPrivacyRules rules, td::string scope) { + CHECK(!dht_node_.empty()); + auto id = overlay_id.compute_short_id(); + register_overlay(local_id, id, + Overlay::create(keyring_, adnl_, actor_id(this), dht_node_, local_id, std::move(overlay_id), nullptr, + std::move(rules), scope)); +} + void OverlayManager::create_private_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, std::vector nodes, std::unique_ptr callback, OverlayPrivacyRules rules) { diff --git a/overlay/overlay-manager.h b/overlay/overlay-manager.h index d9739bf3..b03261e8 100644 --- a/overlay/overlay-manager.h +++ b/overlay/overlay-manager.h @@ -52,6 +52,8 @@ class OverlayManager : public Overlays { void create_public_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, std::unique_ptr callback, OverlayPrivacyRules rules, td::string scope) override; + void create_public_overlay_no_subscribe(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, + OverlayPrivacyRules rules, td::string scope) override; void create_private_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, std::vector nodes, std::unique_ptr callback, OverlayPrivacyRules rules) override; diff --git a/overlay/overlay.cpp b/overlay/overlay.cpp index 3c707e60..a6d0bc89 100644 --- a/overlay/overlay.cpp +++ b/overlay/overlay.cpp @@ -149,6 +149,9 @@ void OverlayImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice data, if (R.is_error()) { // allow custom query to be here + if (!subscribed()) { + return; + } callback_->receive_query(src, overlay_id_, std::move(data), std::move(promise)); return; } @@ -225,6 +228,9 @@ void OverlayImpl::receive_message(adnl::AdnlNodeIdShort src, td::BufferSlice dat } auto X = fetch_tl_object(data.clone(), true); if (X.is_error()) { + if (!subscribed()) { + return; + } VLOG(OVERLAY_DEBUG) << this << ": received custom message"; callback_->receive_message(src, overlay_id_, std::move(data)); return; @@ -268,7 +274,7 @@ void OverlayImpl::alarm() { } if (public_) { - if (peers_.size() > 0) { + if (peers_.size() > 0 && subscribed()) { auto P = get_random_peer(); if (P) { send_random_peers(P->get_id(), {}); @@ -336,7 +342,7 @@ void OverlayImpl::receive_dht_nodes(td::Result res, bool dummy) { } void OverlayImpl::update_dht_nodes(OverlayNode node) { - if (!public_) { + if (!public_ || !subscribed()) { return; } @@ -497,6 +503,9 @@ void OverlayImpl::send_new_fec_broadcast_part(PublicKeyHash local_id, Overlay::B } void OverlayImpl::deliver_broadcast(PublicKeyHash source, td::BufferSlice data) { + if (!subscribed()) { + return; + } callback_->receive_broadcast(source, overlay_id_, std::move(data)); } @@ -569,6 +578,9 @@ void OverlayImpl::set_privacy_rules(OverlayPrivacyRules rules) { } void OverlayImpl::check_broadcast(PublicKeyHash src, td::BufferSlice data, td::Promise promise) { + if (!subscribed()) { + return; + } callback_->check_broadcast(src, overlay_id_, std::move(data), std::move(promise)); } diff --git a/overlay/overlay.hpp b/overlay/overlay.hpp index 1d5f9861..ddcb0267 100644 --- a/overlay/overlay.hpp +++ b/overlay/overlay.hpp @@ -251,8 +251,15 @@ class OverlayImpl : public Overlay { } private: + bool subscribed() const { + return (bool)callback_; + } + template void process_query(adnl::AdnlNodeIdShort src, T &query, td::Promise promise) { + if (!subscribed()) { + return; + } callback_->receive_query(src, overlay_id_, serialize_tl_object(&query, true), std::move(promise)); } diff --git a/overlay/overlays.h b/overlay/overlays.h index 45316254..6781b6c3 100644 --- a/overlay/overlays.h +++ b/overlay/overlays.h @@ -194,6 +194,8 @@ class Overlays : public td::actor::Actor { virtual void create_public_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, std::unique_ptr callback, OverlayPrivacyRules rules, td::string scope) = 0; + virtual void create_public_overlay_no_subscribe(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, + OverlayPrivacyRules rules, td::string scope) = 0; virtual void create_private_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdFull overlay_id, std::vector nodes, std::unique_ptr callback, OverlayPrivacyRules rules) = 0; diff --git a/test/test-ton-collator.cpp b/test/test-ton-collator.cpp index 9ed5c781..1e46bc7d 100644 --- a/test/test-ton-collator.cpp +++ b/test/test-ton-collator.cpp @@ -323,9 +323,7 @@ class TestNode : public td::actor::Actor { td::actor::send_closure(id_, &ton::validator::ValidatorManager::sync_complete, td::PromiseCreator::lambda([](td::Unit) {})); } - void add_shard(ton::ShardIdFull) override { - } - void del_shard(ton::ShardIdFull) override { + void subscribe_to_shard(ton::ShardIdFull) override { } void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override { } diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index 2e158e07..11345524 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -1300,10 +1300,10 @@ td::Status ValidatorEngine::load_global_config() { validator_options_ = ton::validator::ValidatorManagerOptions::create(zero_state, init_block); validator_options_.write().set_shard_check_function( - [](ton::ShardIdFull shard, ton::CatchainSeqno cc_seqno, + [masterchain_only = masterchain_only_](ton::ShardIdFull shard, ton::CatchainSeqno cc_seqno, ton::validator::ValidatorManagerOptions::ShardCheckMode mode) -> bool { if (mode == ton::validator::ValidatorManagerOptions::ShardCheckMode::m_monitor) { - return true; + return shard.is_masterchain() || !masterchain_only; } CHECK(mode == ton::validator::ValidatorManagerOptions::ShardCheckMode::m_validate); return true; @@ -3648,6 +3648,9 @@ int main(int argc, char *argv[]) { }); return td::Status::OK(); }); + p.add_option('M', "masterchain-only", "don't track shardchains", [&]() { + acts.push_back([&x]() { td::actor::send_closure(x, &ValidatorEngine::set_masterchain_only); }); + }); td::uint32 threads = 7; p.add_checked_option( 't', "threads", PSTRING() << "number of threads (default=" << threads << ")", [&](td::Slice fname) { diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index beb24237..0a7f8e26 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -202,6 +202,7 @@ class ValidatorEngine : public td::actor::Actor { bool started_ = false; ton::BlockSeqno truncate_seqno_{0}; std::string session_logs_file_; + bool masterchain_only_ = false; std::set unsafe_catchains_; std::map> unsafe_catchain_rotations_; @@ -253,6 +254,9 @@ class ValidatorEngine : public td::actor::Actor { void add_key_to_set(ton::PublicKey key) { keys_[key.compute_short_id()] = key; } + void set_masterchain_only() { + masterchain_only_ = true; + } void start_up() override; ValidatorEngine() { } diff --git a/validator/fabric.h b/validator/fabric.h index 158ea7e0..6f06dcc9 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -59,6 +59,10 @@ void run_fake_accept_block_query(BlockIdExt id, td::Ref data, std::ve td::Promise promise); void run_hardfork_accept_block_query(BlockIdExt id, td::Ref data, td::actor::ActorId manager, td::Promise promise); +void run_broadcast_only_accept_block_query(BlockIdExt id, td::Ref data, std::vector prev, + td::Ref validator_set, td::Ref signatures, + td::Ref approve_signatures, + td::actor::ActorId manager, td::Promise promise); void run_apply_block_query(BlockIdExt id, td::Ref block, BlockIdExt masterchain_block_id, td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise); diff --git a/validator/full-node-shard.cpp b/validator/full-node-shard.cpp index 1094c896..8e579f3c 100644 --- a/validator/full-node-shard.cpp +++ b/validator/full-node-shard.cpp @@ -69,31 +69,41 @@ void Neighbour::update_roundtrip(double t) { } void FullNodeShardImpl::create_overlay() { - class Callback : public overlay::Overlays::Callback { - public: - void receive_message(adnl::AdnlNodeIdShort src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override { - // just ignore - } - void receive_query(adnl::AdnlNodeIdShort src, overlay::OverlayIdShort overlay_id, td::BufferSlice data, - td::Promise promise) override { - td::actor::send_closure(node_, &FullNodeShardImpl::receive_query, src, std::move(data), std::move(promise)); - } - void receive_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override { - td::actor::send_closure(node_, &FullNodeShardImpl::receive_broadcast, src, std::move(data)); - } - void check_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data, - td::Promise promise) override { - td::actor::send_closure(node_, &FullNodeShardImpl::check_broadcast, src, std::move(data), std::move(promise)); - } - Callback(td::actor::ActorId node) : node_(node) { - } + if (subscribed_) { + class Callback : public overlay::Overlays::Callback { + public: + void receive_message(adnl::AdnlNodeIdShort src, overlay::OverlayIdShort overlay_id, + td::BufferSlice data) override { + // just ignore + } + void receive_query(adnl::AdnlNodeIdShort src, overlay::OverlayIdShort overlay_id, td::BufferSlice data, + td::Promise promise) override { + td::actor::send_closure(node_, &FullNodeShardImpl::receive_query, src, std::move(data), std::move(promise)); + } + void receive_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data) override { + td::actor::send_closure(node_, &FullNodeShardImpl::receive_broadcast, src, std::move(data)); + } + void check_broadcast(PublicKeyHash src, overlay::OverlayIdShort overlay_id, td::BufferSlice data, + td::Promise promise) override { + td::actor::send_closure(node_, &FullNodeShardImpl::check_broadcast, src, std::move(data), std::move(promise)); + } + Callback(td::actor::ActorId node) : node_(node) { + } - private: - td::actor::ActorId node_; - }; + private: + td::actor::ActorId node_; + }; - 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() << ", \"workchain_id\": " << get_workchain() << " }"); + 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() + << ", \"workchain_id\": " << get_workchain() << " }"); + } else { + td::actor::send_closure(overlays_, &overlay::Overlays::create_public_overlay_no_subscribe, adnl_id_, + overlay_id_full_.clone(), rules_, + PSTRING() << "{ \"type\": \"shard\", \"shard_id\": " << get_shard() + << ", \"workchain_id\": " << get_workchain() << " }"); + } td::actor::send_closure(rldp_, &rldp::Rldp::add_id, adnl_id_); if (cert_) { @@ -119,6 +129,15 @@ void FullNodeShardImpl::update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promis create_overlay(); } +void FullNodeShardImpl::subscribe_to_shard() { + if (subscribed_ || !client_.empty()) { + return; + } + td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_); + subscribed_ = true; + create_overlay(); +} + void FullNodeShardImpl::try_get_next_block(td::Timestamp timeout, td::Promise promise) { if (timeout.is_in_past()) { promise.set_error(td::Status::Error(ErrorCode::timeout, "timeout")); @@ -576,8 +595,14 @@ void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_ex } void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_newShardBlockBroadcast &query) { + auto block_id = create_block_id(query.block_->block_); + if (block_id.shard_full() != shard_) { + LOG(WARNING) << "dropping newShardBlockBroadcast: expected shard " << shard_.to_str() << ", got shard " + << block_id.shard_full().to_str(); + return; + } td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::new_shard_block, - create_block_id(query.block_->block_), query.block_->cc_seqno_, + block_id, query.block_->cc_seqno_, std::move(query.block_->data_)); } @@ -588,6 +613,11 @@ void FullNodeShardImpl::process_broadcast(PublicKeyHash src, ton_api::tonNode_bl } BlockIdExt block_id = create_block_id(query.id_); + if (block_id.shard_full() != shard_) { + LOG(WARNING) << "dropping blockBroadcast: expected shard " << shard_.to_str() << ", got shard " + << block_id.shard_full().to_str(); + return; + } BlockBroadcast B{block_id, std::move(signatures), static_cast(query.catchain_seqno_), @@ -817,6 +847,10 @@ void FullNodeShardImpl::start_up() { } } +void FullNodeShardImpl::tear_down() { + td::actor::send_closure(overlays_, &ton::overlay::Overlays::delete_overlay, adnl_id_, overlay_id_); +} + void FullNodeShardImpl::sign_new_certificate(PublicKeyHash sign_by) { if (sign_by.is_zero()) { return; @@ -1053,7 +1087,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) + td::actor::ActorId client, bool subscribe) : shard_(shard) , local_id_(local_id) , adnl_id_(adnl_id) @@ -1063,16 +1097,18 @@ FullNodeShardImpl::FullNodeShardImpl(ShardIdFull shard, PublicKeyHash local_id, , rldp_(rldp) , overlays_(overlays) , validator_manager_(validator_manager) - , client_(client) { + , client_(client) + , subscribed_(subscribe) { } td::actor::ActorOwn FullNodeShard::create( ShardIdFull shard, PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id, FileHash zero_state_file_hash, 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) { + td::actor::ActorId validator_manager, td::actor::ActorId client, + bool subscribe) { return td::actor::create_actor("tonnode", shard, local_id, adnl_id, zero_state_file_hash, keyring, - adnl, rldp, overlays, validator_manager, client); + adnl, rldp, overlays, validator_manager, client, subscribe); } } // namespace fullnode diff --git a/validator/full-node-shard.h b/validator/full-node-shard.h index c1712baf..e45e2325 100644 --- a/validator/full-node-shard.h +++ b/validator/full-node-shard.h @@ -36,6 +36,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 subscribe_to_shard() = 0; virtual void send_ihr_message(td::BufferSlice data) = 0; virtual void send_external_message(td::BufferSlice data) = 0; @@ -70,7 +71,8 @@ class FullNodeShard : public td::actor::Actor { ShardIdFull shard, PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id, FileHash zero_state_file_hash, 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); + td::actor::ActorId validator_manager, td::actor::ActorId client, + bool subscribe); }; } // namespace fullnode diff --git a/validator/full-node-shard.hpp b/validator/full-node-shard.hpp index a2dd5cc4..33705bc7 100644 --- a/validator/full-node-shard.hpp +++ b/validator/full-node-shard.hpp @@ -80,6 +80,7 @@ class FullNodeShardImpl : public FullNodeShard { void create_overlay(); void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise promise) override; + virtual void subscribe_to_shard() override; //td::Result fetch_block(td::BufferSlice data); void prevalidate_block(BlockIdExt block_id, td::BufferSlice data, td::BufferSlice proof, @@ -167,6 +168,7 @@ class FullNodeShardImpl : public FullNodeShard { void set_handle(BlockHandle handle, td::Promise promise) override; void start_up() override; + void tear_down() override; void alarm() override; void update_validators(std::vector public_key_hashes, PublicKeyHash local_hash) override; @@ -202,7 +204,7 @@ 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); + td::actor::ActorId client, bool subscribe); private: bool use_new_download() const { @@ -239,6 +241,8 @@ class FullNodeShardImpl : public FullNodeShard { td::Timestamp reload_neighbours_at_; td::Timestamp ping_neighbours_at_; adnl::AdnlNodeIdShort last_pinged_neighbour_ = adnl::AdnlNodeIdShort::zero(); + + bool subscribed_ = false; }; } // namespace fullnode diff --git a/validator/full-node.cpp b/validator/full-node.cpp index 6606f215..5712d3cf 100644 --- a/validator/full-node.cpp +++ b/validator/full-node.cpp @@ -120,14 +120,17 @@ void FullNodeImpl::initial_read_complete(BlockHandle top_handle) { td::actor::send_closure(it->second, &FullNodeShard::set_handle, top_handle, std::move(P)); } -void FullNodeImpl::add_shard(ShardIdFull shard) { +void FullNodeImpl::add_shard(ShardIdFull shard, bool subscribe) { while (true) { - if (shards_.count(shard) == 0) { + auto it = shards_.find(shard); + if (it == shards_.end()) { shards_.emplace(shard, FullNodeShard::create(shard, local_id_, adnl_id_, zero_state_file_hash_, keyring_, adnl_, - rldp_, overlays_, validator_manager_, client_)); + rldp_, overlays_, validator_manager_, client_, subscribe)); if (all_validators_.size() > 0) { td::actor::send_closure(shards_[shard], &FullNodeShard::update_validators, all_validators_, sign_cert_by_); } + } else if (subscribe) { + td::actor::send_closure(it->second, &FullNodeShard::subscribe_to_shard); } else { break; } @@ -148,7 +151,7 @@ void FullNodeImpl::sync_completed() { } void FullNodeImpl::send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) { - auto shard = get_shard(ShardIdFull{masterchainId}); + auto shard = get_shard(dst); if (shard.empty()) { VLOG(FULL_NODE_WARNING) << "dropping OUT ihr message to unknown shard"; return; @@ -166,7 +169,7 @@ void FullNodeImpl::send_ext_message(AccountIdPrefixFull dst, td::BufferSlice dat } void FullNodeImpl::send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) { - auto shard = get_shard(ShardIdFull{masterchainId, shardIdAll}); + auto shard = get_shard(block_id.shard_full()); if (shard.empty()) { VLOG(FULL_NODE_WARNING) << "dropping OUT shard block info message to unknown shard"; return; @@ -175,7 +178,7 @@ void FullNodeImpl::send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_s } void FullNodeImpl::send_broadcast(BlockBroadcast broadcast) { - auto shard = get_shard(ShardIdFull{masterchainId}); + auto shard = get_shard(broadcast.block_id.shard_full()); if (shard.empty()) { VLOG(FULL_NODE_WARNING) << "dropping OUT broadcast to unknown shard"; return; @@ -381,11 +384,8 @@ void FullNodeImpl::start_up() { void initial_read_complete(BlockHandle handle) override { td::actor::send_closure(id_, &FullNodeImpl::initial_read_complete, handle); } - void add_shard(ShardIdFull shard) override { - td::actor::send_closure(id_, &FullNodeImpl::add_shard, shard); - } - void del_shard(ShardIdFull shard) override { - td::actor::send_closure(id_, &FullNodeImpl::del_shard, shard); + void subscribe_to_shard(ShardIdFull shard) override { + td::actor::send_closure(id_, &FullNodeImpl::add_shard, shard, true); } void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) override { td::actor::send_closure(id_, &FullNodeImpl::send_ihr_message, dst, std::move(data)); @@ -465,7 +465,7 @@ FullNodeImpl::FullNodeImpl(PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id , validator_manager_(validator_manager) , client_(client) , db_root_(db_root) { - add_shard(ShardIdFull{masterchainId}); + add_shard(ShardIdFull{masterchainId}, true); } td::actor::ActorOwn FullNode::create(ton::PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id, diff --git a/validator/full-node.hpp b/validator/full-node.hpp index 6d57f4a8..f3ce9d05 100644 --- a/validator/full-node.hpp +++ b/validator/full-node.hpp @@ -52,7 +52,7 @@ class FullNodeImpl : public FullNode { void update_adnl_id(adnl::AdnlNodeIdShort adnl_id, td::Promise promise) override; - void add_shard(ShardIdFull shard); + void add_shard(ShardIdFull shard, bool subscribe = false); void del_shard(ShardIdFull shard); void sync_completed(); diff --git a/validator/impl/accept-block.cpp b/validator/impl/accept-block.cpp index a5c4d9a1..74adcd69 100644 --- a/validator/impl/accept-block.cpp +++ b/validator/impl/accept-block.cpp @@ -92,6 +92,28 @@ AcceptBlockQuery::AcceptBlockQuery(ForceFork ffork, BlockIdExt id, td::Ref data, std::vector prev, + td::Ref validator_set, td::Ref signatures, + td::Ref approve_signatures, + td::actor::ActorId manager, td::Promise promise) + : id_(id) + , data_(std::move(data)) + , prev_(std::move(prev)) + , validator_set_(std::move(validator_set)) + , signatures_(std::move(signatures)) + , approve_signatures_(std::move(approve_signatures)) + , is_fake_(false) + , is_fork_(false) + , send_broadcast_(true) + , broadcast_only_(false) + , manager_(manager) + , promise_(std::move(promise)) { + state_keep_old_hash_.clear(); + state_old_hash_.clear(); + state_hash_.clear(); + CHECK(prev_.size() > 0); +} + bool AcceptBlockQuery::precheck_header() { VLOG(VALIDATOR_DEBUG) << "precheck_header()"; // 0. sanity check @@ -384,6 +406,15 @@ void AcceptBlockQuery::start_up() { return; } + if (broadcast_only_) { + if (!create_new_proof()) { + fatal_error("cannot generate proof for block "s + id_.to_str()); + return; + } + applied(); + return; + } + td::actor::send_closure( manager_, &ValidatorManager::get_block_handle, id_, true, [SelfId = actor_id(this)](td::Result R) { check_send_error(SelfId, R) || diff --git a/validator/impl/accept-block.hpp b/validator/impl/accept-block.hpp index 0b8cf2c3..b45095b4 100644 --- a/validator/impl/accept-block.hpp +++ b/validator/impl/accept-block.hpp @@ -48,6 +48,7 @@ class AcceptBlockQuery : public td::actor::Actor { public: struct IsFake {}; struct ForceFork {}; + struct BroadcastOnly{}; AcceptBlockQuery(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::Ref signatures, td::Ref approve_signatures, bool send_broadcast, @@ -57,6 +58,10 @@ class AcceptBlockQuery : public td::actor::Actor { td::Promise promise); AcceptBlockQuery(ForceFork ffork, BlockIdExt id, td::Ref data, td::actor::ActorId manager, td::Promise promise); + AcceptBlockQuery(BroadcastOnly, BlockIdExt id, td::Ref data, std::vector prev, + td::Ref validator_set, td::Ref signatures, + td::Ref approve_signatures, td::actor::ActorId manager, + td::Promise promise); private: static constexpr td::uint32 priority() { @@ -98,6 +103,7 @@ class AcceptBlockQuery : public td::actor::Actor { bool is_fake_; bool is_fork_; bool send_broadcast_; + bool broadcast_only_{false}; bool ancestors_split_{false}, is_key_block_{false}; td::Timestamp timeout_ = td::Timestamp::in(600.0); td::actor::ActorId manager_; diff --git a/validator/impl/fabric.cpp b/validator/impl/fabric.cpp index 6958ad89..e86b9b90 100644 --- a/validator/impl/fabric.cpp +++ b/validator/impl/fabric.cpp @@ -151,6 +151,17 @@ void run_hardfork_accept_block_query(BlockIdExt id, td::Ref data, .release(); } +void run_broadcast_only_accept_block_query(BlockIdExt id, td::Ref data, std::vector prev, + td::Ref validator_set, td::Ref signatures, + td::Ref approve_signatures, + td::actor::ActorId manager, + td::Promise promise) { + td::actor::create_actor("broadcastaccept", AcceptBlockQuery::BroadcastOnly(), id, std::move(data), + prev, std::move(validator_set), std::move(signatures), + std::move(approve_signatures), manager, std::move(promise)) + .release(); +} + void run_apply_block_query(BlockIdExt id, td::Ref block, BlockIdExt masterchain_block_id, td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise) { diff --git a/validator/manager.cpp b/validator/manager.cpp index 182ba9c3..1d639291 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2367,7 +2367,7 @@ void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promiseadd_shard(shard); + callback_->subscribe_to_shard(shard); } void ValidatorManagerImpl::update_async_serializer_state(AsyncSerializerState state, td::Promise promise) { @@ -2396,7 +2396,7 @@ void ValidatorManagerImpl::get_archive_slice(td::uint64 archive_id, td::uint64 o } bool ValidatorManagerImpl::is_validator() { - return temp_keys_.size() > 0 || permanent_keys_.size() > 0; + return true; // temp_keys_.size() > 0 || permanent_keys_.size() > 0; } PublicKeyHash ValidatorManagerImpl::get_validator(ShardIdFull shard, td::Ref val_set) { diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index ab7f2062..9efda413 100644 --- a/validator/validator-group.cpp +++ b/validator/validator-group.cpp @@ -121,9 +121,15 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s td::actor::send_closure(manager_, &ValidatorManager::log_validator_session_stats, next_block_id, std::move(stats)); auto block = block_data.size() > 0 ? create_block(next_block_id, std::move(block_data)).move_as_ok() : td::Ref{}; + accept_block_query(next_block_id, std::move(block), std::move(prev_block_ids_), std::move(sig_set), + std::move(approve_sig_set), src == local_id_, std::move(promise)); + prev_block_ids_ = std::vector{next_block_id}; +} - auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), block_id = next_block_id, block, prev = prev_block_ids_, - sig_set, approve_sig_set, +void ValidatorGroup::accept_block_query(BlockIdExt block_id, td::Ref block, std::vector prev, + td::Ref sig_set, td::Ref approve_sig_set, + bool send_broadcast, td::Promise promise) { + auto P = td::PromiseCreator::lambda([=, SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { if (R.error().code() == ErrorCode::cancelled) { @@ -131,35 +137,22 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s return; } LOG_CHECK(R.error().code() == ErrorCode::timeout || R.error().code() == ErrorCode::notready) << R.move_as_error(); - td::actor::send_closure(SelfId, &ValidatorGroup::retry_accept_block_query, block_id, std::move(block), - std::move(prev), std::move(sig_set), std::move(approve_sig_set), std::move(promise)); + td::actor::send_closure(SelfId, &ValidatorGroup::accept_block_query, block_id, std::move(block), std::move(prev), + std::move(sig_set), std::move(approve_sig_set), false, std::move(promise)); } else { promise.set_value(R.move_as_ok()); } }); - run_accept_block_query(next_block_id, std::move(block), prev_block_ids_, validator_set_, std::move(sig_set), - std::move(approve_sig_set), src == local_id_, manager_, std::move(P)); - prev_block_ids_ = std::vector{next_block_id}; -} - -void ValidatorGroup::retry_accept_block_query(BlockIdExt block_id, td::Ref block, - std::vector prev, td::Ref sig_set, - td::Ref approve_sig_set, - td::Promise promise) { - auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), block_id, block, prev, sig_set, approve_sig_set, - promise = std::move(promise)](td::Result R) mutable { - if (R.is_error()) { - LOG_CHECK(R.error().code() == ErrorCode::timeout) << R.move_as_error(); - td::actor::send_closure(SelfId, &ValidatorGroup::retry_accept_block_query, block_id, std::move(block), - std::move(prev), std::move(sig_set), std::move(approve_sig_set), std::move(promise)); - } else { - promise.set_value(R.move_as_ok()); - } - }); - - run_accept_block_query(block_id, std::move(block), prev, validator_set_, std::move(sig_set), - std::move(approve_sig_set), false, manager_, std::move(P)); + if (shard_.is_masterchain() || lite_mode_) { + run_accept_block_query(block_id, std::move(block), std::move(prev), validator_set_, std::move(sig_set), + std::move(approve_sig_set), send_broadcast, manager_, std::move(P)); + } else if (send_broadcast) { + run_broadcast_only_accept_block_query(block_id, std::move(block), std::move(prev), validator_set_, + std::move(sig_set), std::move(approve_sig_set), manager_, std::move(P)); + } else { + promise.set_value(td::Unit()); + } } void ValidatorGroup::skip_round(td::uint32 round_id) { @@ -311,8 +304,8 @@ void ValidatorGroup::start(std::vector prev, BlockIdExt min_masterch auto block = p.block.size() > 0 ? create_block(next_block_id, std::move(p.block)).move_as_ok() : td::Ref{}; - retry_accept_block_query(next_block_id, std::move(block), prev_block_ids_, std::move(p.sigs), - std::move(p.approve_sigs), std::move(p.promise)); + accept_block_query(next_block_id, std::move(block), std::move(prev_block_ids_), std::move(p.sigs), + std::move(p.approve_sigs), false, std::move(p.promise)); prev_block_ids_ = std::vector{next_block_id}; } postponed_accept_.clear(); diff --git a/validator/validator-group.hpp b/validator/validator-group.hpp index 91d801cd..bd5e1043 100644 --- a/validator/validator-group.hpp +++ b/validator/validator-group.hpp @@ -39,9 +39,9 @@ class ValidatorGroup : public td::actor::Actor { std::vector approve_signatures, validatorsession::ValidatorSessionStats stats, td::Promise promise); void skip_round(td::uint32 round); - void retry_accept_block_query(BlockIdExt block_id, td::Ref block, std::vector prev, - td::Ref sigs, td::Ref approve_sigs, - td::Promise promise); + void accept_block_query(BlockIdExt block_id, td::Ref block, std::vector prev, + td::Ref sigs, td::Ref approve_sigs, + bool send_broadcast, td::Promise promise); void get_approved_candidate(PublicKey source, RootHash root_hash, FileHash file_hash, FileHash collated_data_file_hash, td::Promise promise); BlockId create_next_block_id_simple() const; diff --git a/validator/validator.h b/validator/validator.h index 09081f1e..132ff06e 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -111,8 +111,8 @@ class ValidatorManagerInterface : public td::actor::Actor { virtual ~Callback() = default; virtual void initial_read_complete(BlockHandle top_masterchain_blocks) = 0; - virtual void add_shard(ShardIdFull shard) = 0; - virtual void del_shard(ShardIdFull shard) = 0; + virtual void subscribe_to_shard(ShardIdFull shard) = 0; + //virtual void del_shard(ShardIdFull shard) = 0; virtual void send_ihr_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0; virtual void send_ext_message(AccountIdPrefixFull dst, td::BufferSlice data) = 0;