From 1da94e62ad64f370aae13f3c254dc78e8fc695b9 Mon Sep 17 00:00:00 2001 From: EmelyanenkoK Date: Wed, 9 Oct 2024 13:53:46 +0300 Subject: [PATCH 1/3] Send only first block candidate optimistically (#1260) * Broadcast only the first block candidate * Fix sending block broadcast --------- Co-authored-by: SpyCheese --- create-hardfork/create-hardfork.cpp | 2 +- test/test-ton-collator.cpp | 2 +- validator-session/validator-session-types.h | 6 ++ validator-session/validator-session.cpp | 26 ++++-- validator-session/validator-session.h | 9 +- validator-session/validator-session.hpp | 2 +- validator/fabric.h | 2 +- validator/full-node.cpp | 17 ++-- validator/full-node.h | 1 + validator/full-node.hpp | 2 +- validator/impl/accept-block.cpp | 13 +-- validator/impl/accept-block.hpp | 4 +- validator/impl/fabric.cpp | 8 +- validator/interfaces/validator-manager.h | 4 +- validator/manager-disk.cpp | 5 ++ validator/manager-disk.hpp | 4 +- validator/manager-hardfork.hpp | 6 +- validator/manager.cpp | 10 ++- validator/manager.hpp | 4 +- validator/validator-group.cpp | 96 ++++++++++++++------- validator/validator-group.hpp | 21 +++-- validator/validator.h | 2 +- 22 files changed, 164 insertions(+), 82 deletions(-) diff --git a/create-hardfork/create-hardfork.cpp b/create-hardfork/create-hardfork.cpp index 3110b1a8..501ce3b9 100644 --- a/create-hardfork/create-hardfork.cpp +++ b/create-hardfork/create-hardfork.cpp @@ -249,7 +249,7 @@ class HardforkCreator : public td::actor::Actor { void send_block_candidate(ton::BlockIdExt block_id, ton::CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::BufferSlice data) override { } - void send_broadcast(ton::BlockBroadcast broadcast, bool custom_overlays_only) override { + void send_broadcast(ton::BlockBroadcast broadcast, int mode) override { } void download_block(ton::BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) override { diff --git a/test/test-ton-collator.cpp b/test/test-ton-collator.cpp index 60476cf8..7c13870e 100644 --- a/test/test-ton-collator.cpp +++ b/test/test-ton-collator.cpp @@ -350,7 +350,7 @@ class TestNode : public td::actor::Actor { void send_block_candidate(ton::BlockIdExt block_id, ton::CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::BufferSlice data) override { } - void send_broadcast(ton::BlockBroadcast broadcast, bool custom_overlays_only) override { + void send_broadcast(ton::BlockBroadcast broadcast, int mode) override { } void download_block(ton::BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) override { diff --git a/validator-session/validator-session-types.h b/validator-session/validator-session-types.h index 78a9b246..7147bf2d 100644 --- a/validator-session/validator-session-types.h +++ b/validator-session/validator-session-types.h @@ -178,6 +178,12 @@ struct EndValidatorGroupStats { std::vector nodes; }; +struct BlockSourceInfo { + td::uint32 round, first_block_round; + PublicKey source; + td::int32 source_priority; +}; + } // namespace validatorsession } // namespace ton diff --git a/validator-session/validator-session.cpp b/validator-session/validator-session.cpp index 33b78e84..3a913990 100644 --- a/validator-session/validator-session.cpp +++ b/validator-session/validator-session.cpp @@ -553,7 +553,9 @@ void ValidatorSessionImpl::check_generate_slot() { LOG(WARNING) << print_id << ": failed to generate block candidate: " << R.move_as_error(); } }); - callback_->on_generate_slot(cur_round_, std::move(P)); + callback_->on_generate_slot( + BlockSourceInfo{cur_round_, first_block_round_, description().get_source_public_key(local_idx()), priority}, + std::move(P)); } else { alarm_timestamp().relax(t); } @@ -631,8 +633,10 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) { }); pending_approve_.insert(block_id); - callback_->on_candidate(cur_round_, description().get_source_public_key(block->get_src_idx()), B->root_hash_, - B->data_.clone(), B->collated_data_.clone(), std::move(P)); + callback_->on_candidate( + BlockSourceInfo{cur_round_, first_block_round_, description().get_source_public_key(block->get_src_idx()), + description().get_node_priority(block->get_src_idx(), cur_round_)}, + B->root_hash_, B->data_.clone(), B->collated_data_.clone(), std::move(P)); } else if (T.is_in_past()) { if (!active_requests_.count(block_id)) { auto v = virtual_state_->get_block_approvers(description(), block_id); @@ -905,15 +909,19 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) { stats.rounds.pop_back(); } + BlockSourceInfo source_info{cur_round_, first_block_round_, + description().get_source_public_key(block->get_src_idx()), + description().get_node_priority(block->get_src_idx(), cur_round_)}; if (it == blocks_.end()) { - callback_->on_block_committed(cur_round_, description().get_source_public_key(block->get_src_idx()), - block->get_root_hash(), block->get_file_hash(), td::BufferSlice(), - std::move(export_sigs), std::move(export_approve_sigs), std::move(stats)); + callback_->on_block_committed(std::move(source_info), block->get_root_hash(), block->get_file_hash(), + td::BufferSlice(), std::move(export_sigs), std::move(export_approve_sigs), + std::move(stats)); } else { - callback_->on_block_committed(cur_round_, description().get_source_public_key(block->get_src_idx()), - block->get_root_hash(), block->get_file_hash(), it->second->data_.clone(), - std::move(export_sigs), std::move(export_approve_sigs), std::move(stats)); + callback_->on_block_committed(std::move(source_info), block->get_root_hash(), block->get_file_hash(), + it->second->data_.clone(), std::move(export_sigs), std::move(export_approve_sigs), + std::move(stats)); } + first_block_round_ = cur_round_ + 1; } cur_round_++; if (have_block) { diff --git a/validator-session/validator-session.h b/validator-session/validator-session.h index e60330b0..b099d65e 100644 --- a/validator-session/validator-session.h +++ b/validator-session/validator-session.h @@ -85,11 +85,10 @@ class ValidatorSession : public td::actor::Actor { class Callback { public: - virtual void on_candidate(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash, - td::BufferSlice data, td::BufferSlice collated_data, - td::Promise promise) = 0; - virtual void on_generate_slot(td::uint32 round, td::Promise promise) = 0; - virtual void on_block_committed(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash, + virtual void on_candidate(BlockSourceInfo source_info, ValidatorSessionRootHash root_hash, td::BufferSlice data, + td::BufferSlice collated_data, td::Promise promise) = 0; + virtual void on_generate_slot(BlockSourceInfo source_info, td::Promise promise) = 0; + virtual void on_block_committed(BlockSourceInfo source_info, ValidatorSessionRootHash root_hash, ValidatorSessionFileHash file_hash, td::BufferSlice data, std::vector> signatures, std::vector> approve_signatures, diff --git a/validator-session/validator-session.hpp b/validator-session/validator-session.hpp index 39f196d8..690346f7 100644 --- a/validator-session/validator-session.hpp +++ b/validator-session/validator-session.hpp @@ -53,7 +53,7 @@ class ValidatorSessionImpl : public ValidatorSession { const ValidatorSessionState *real_state_ = nullptr; const ValidatorSessionState *virtual_state_ = nullptr; - td::uint32 cur_round_ = 0; + td::uint32 cur_round_ = 0, first_block_round_ = 0; td::Timestamp round_started_at_ = td::Timestamp::never(); td::Timestamp round_debug_at_ = td::Timestamp::never(); std::set pending_approve_; diff --git a/validator/fabric.h b/validator/fabric.h index 47418047..2c39aceb 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -56,7 +56,7 @@ void run_check_external_message(td::Ref message, td::actor::ActorId< void run_accept_block_query(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::Ref signatures, - td::Ref approve_signatures, bool send_broadcast, + td::Ref approve_signatures, int send_broadcast_mode, td::actor::ActorId manager, td::Promise promise); void run_fake_accept_block_query(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::actor::ActorId manager, diff --git a/validator/full-node.cpp b/validator/full-node.cpp index a72be3ff..bb6da2c8 100644 --- a/validator/full-node.cpp +++ b/validator/full-node.cpp @@ -261,21 +261,22 @@ void FullNodeImpl::send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_se } } -void FullNodeImpl::send_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) { - send_block_broadcast_to_custom_overlays(broadcast); - if (custom_overlays_only) { - return; +void FullNodeImpl::send_broadcast(BlockBroadcast broadcast, int mode) { + if (mode & broadcast_mode_custom) { + send_block_broadcast_to_custom_overlays(broadcast); } auto shard = get_shard(ShardIdFull{masterchainId}); if (shard.empty()) { VLOG(FULL_NODE_WARNING) << "dropping OUT broadcast to unknown shard"; return; } - if (broadcast.block_id.is_masterchain() && !private_block_overlays_.empty()) { + if (!private_block_overlays_.empty() && (mode & broadcast_mode_private_block)) { td::actor::send_closure(private_block_overlays_.begin()->second, &FullNodePrivateBlockOverlay::send_broadcast, broadcast.clone()); } - td::actor::send_closure(shard, &FullNodeShard::send_broadcast, std::move(broadcast)); + if (mode & broadcast_mode_public) { + td::actor::send_closure(shard, &FullNodeShard::send_broadcast, std::move(broadcast)); + } } void FullNodeImpl::download_block(BlockIdExt id, td::uint32 priority, td::Timestamp timeout, @@ -496,8 +497,8 @@ void FullNodeImpl::start_up() { td::actor::send_closure(id_, &FullNodeImpl::send_block_candidate, block_id, cc_seqno, validator_set_hash, std::move(data)); } - void send_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) override { - td::actor::send_closure(id_, &FullNodeImpl::send_broadcast, std::move(broadcast), custom_overlays_only); + void send_broadcast(BlockBroadcast broadcast, int mode) override { + td::actor::send_closure(id_, &FullNodeImpl::send_broadcast, std::move(broadcast), mode); } void download_block(BlockIdExt id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) override { diff --git a/validator/full-node.h b/validator/full-node.h index c3719f67..621cdac0 100644 --- a/validator/full-node.h +++ b/validator/full-node.h @@ -99,6 +99,7 @@ class FullNode : public td::actor::Actor { static constexpr td::uint64 max_state_size() { return 4ull << 30; } + enum { broadcast_mode_public = 1, broadcast_mode_private_block = 2, broadcast_mode_custom = 4 }; static td::actor::ActorOwn create(ton::PublicKeyHash local_id, adnl::AdnlNodeIdShort adnl_id, FileHash zero_state_file_hash, FullNodeConfig config, diff --git a/validator/full-node.hpp b/validator/full-node.hpp index 3dfa17fd..584be5ee 100644 --- a/validator/full-node.hpp +++ b/validator/full-node.hpp @@ -68,7 +68,7 @@ class FullNodeImpl : public FullNode { void send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_seqnp, td::BufferSlice data); void send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::BufferSlice data); - void send_broadcast(BlockBroadcast broadcast, bool custom_overlays_only); + void send_broadcast(BlockBroadcast broadcast, int mode); void download_block(BlockIdExt id, td::uint32 priority, td::Timestamp timeout, td::Promise promise); void download_zero_state(BlockIdExt id, td::uint32 priority, td::Timestamp timeout, td::Promise promise); diff --git a/validator/impl/accept-block.cpp b/validator/impl/accept-block.cpp index cfdeb052..a9dd7fe2 100644 --- a/validator/impl/accept-block.cpp +++ b/validator/impl/accept-block.cpp @@ -41,7 +41,7 @@ using namespace std::literals::string_literals; AcceptBlockQuery::AcceptBlockQuery(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::Ref signatures, - td::Ref approve_signatures, bool send_broadcast, + td::Ref approve_signatures, int send_broadcast_mode, td::actor::ActorId manager, td::Promise promise) : id_(id) , data_(std::move(data)) @@ -51,7 +51,7 @@ AcceptBlockQuery::AcceptBlockQuery(BlockIdExt id, td::Ref data, std:: , approve_signatures_(std::move(approve_signatures)) , is_fake_(false) , is_fork_(false) - , send_broadcast_(send_broadcast) + , send_broadcast_mode_(send_broadcast_mode) , manager_(manager) , promise_(std::move(promise)) , perf_timer_("acceptblock", 0.1, [manager](double duration) { @@ -72,7 +72,6 @@ AcceptBlockQuery::AcceptBlockQuery(AcceptBlockQuery::IsFake fake, BlockIdExt id, , validator_set_(std::move(validator_set)) , is_fake_(true) , is_fork_(false) - , send_broadcast_(false) , manager_(manager) , promise_(std::move(promise)) , perf_timer_("acceptblock", 0.1, [manager](double duration) { @@ -90,7 +89,6 @@ AcceptBlockQuery::AcceptBlockQuery(ForceFork ffork, BlockIdExt id, td::Refdata(); b.block_id = id_; @@ -947,8 +949,7 @@ void AcceptBlockQuery::applied() { } // do not wait for answer - td::actor::send_closure_later(manager_, &ValidatorManager::send_block_broadcast, std::move(b), - /* custom_overlays_only = */ !send_broadcast_); + td::actor::send_closure_later(manager_, &ValidatorManager::send_block_broadcast, std::move(b), send_broadcast_mode_); finish_query(); } diff --git a/validator/impl/accept-block.hpp b/validator/impl/accept-block.hpp index 95b5f281..d1c0baa6 100644 --- a/validator/impl/accept-block.hpp +++ b/validator/impl/accept-block.hpp @@ -50,7 +50,7 @@ class AcceptBlockQuery : public td::actor::Actor { struct ForceFork {}; AcceptBlockQuery(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::Ref signatures, - td::Ref approve_signatures, bool send_broadcast, + td::Ref approve_signatures, int send_broadcast_mode, td::actor::ActorId manager, td::Promise promise); AcceptBlockQuery(IsFake fake, BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::actor::ActorId manager, @@ -99,7 +99,7 @@ class AcceptBlockQuery : public td::actor::Actor { Ref approve_signatures_; bool is_fake_; bool is_fork_; - bool send_broadcast_; + int send_broadcast_mode_{0}; 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 36fa052a..65b92262 100644 --- a/validator/impl/fabric.cpp +++ b/validator/impl/fabric.cpp @@ -131,11 +131,11 @@ td::Result> create_ihr_message(td::BufferSlice data) { void run_accept_block_query(BlockIdExt id, td::Ref data, std::vector prev, td::Ref validator_set, td::Ref signatures, - td::Ref approve_signatures, bool send_broadcast, + td::Ref approve_signatures, int send_broadcast_mode, td::actor::ActorId manager, td::Promise promise) { - td::actor::create_actor(PSTRING() << "accept" << id.id.to_str(), id, std::move(data), prev, - std::move(validator_set), std::move(signatures), - std::move(approve_signatures), send_broadcast, manager, std::move(promise)) + td::actor::create_actor( + PSTRING() << "accept" << id.id.to_str(), id, std::move(data), prev, std::move(validator_set), + std::move(signatures), std::move(approve_signatures), send_broadcast_mode, manager, std::move(promise)) .release(); } diff --git a/validator/interfaces/validator-manager.h b/validator/interfaces/validator-manager.h index b6016bc2..ce0c27e1 100644 --- a/validator/interfaces/validator-manager.h +++ b/validator/interfaces/validator-manager.h @@ -105,6 +105,8 @@ class ValidatorManager : public ValidatorManagerInterface { virtual void set_block_candidate(BlockIdExt id, BlockCandidate candidate, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::Promise promise) = 0; + virtual void send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, + td::BufferSlice data) = 0; virtual void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority, td::Timestamp timeout, td::Promise> promise) = 0; @@ -144,7 +146,7 @@ class ValidatorManager : public ValidatorManagerInterface { virtual void send_external_message(td::Ref message) = 0; virtual void send_ihr_message(td::Ref message) = 0; virtual void send_top_shard_block_description(td::Ref desc) = 0; - virtual void send_block_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) = 0; + virtual void send_block_broadcast(BlockBroadcast broadcast, int mode) = 0; virtual void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise promise) = 0; virtual void get_shard_client_state(bool from_db, td::Promise promise) = 0; diff --git a/validator/manager-disk.cpp b/validator/manager-disk.cpp index 3418608d..62fdc4b4 100644 --- a/validator/manager-disk.cpp +++ b/validator/manager-disk.cpp @@ -785,6 +785,11 @@ void ValidatorManagerImpl::set_block_candidate(BlockIdExt id, BlockCandidate can td::actor::send_closure(db_, &Db::store_block_candidate, std::move(candidate), std::move(promise)); } +void ValidatorManagerImpl::send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, + td::uint32 validator_set_hash, td::BufferSlice data) { + callback_->send_block_candidate(id, cc_seqno, validator_set_hash, std::move(data)); +} + void ValidatorManagerImpl::write_handle(BlockHandle handle, td::Promise promise) { td::actor::send_closure(db_, &Db::store_block_handle, std::move(handle), std::move(promise)); } diff --git a/validator/manager-disk.hpp b/validator/manager-disk.hpp index e15def2a..5287a387 100644 --- a/validator/manager-disk.hpp +++ b/validator/manager-disk.hpp @@ -185,6 +185,8 @@ class ValidatorManagerImpl : public ValidatorManager { void set_block_candidate(BlockIdExt id, BlockCandidate candidate, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::Promise promise) override; + void send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, + td::BufferSlice data) override; void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority, td::Timestamp timeout, td::Promise> promise) override; @@ -259,7 +261,7 @@ class ValidatorManagerImpl : public ValidatorManager { new_ihr_message(message->serialize()); } void send_top_shard_block_description(td::Ref desc) override; - void send_block_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) override { + void send_block_broadcast(BlockBroadcast broadcast, int mode) override { } void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise promise) override; diff --git a/validator/manager-hardfork.hpp b/validator/manager-hardfork.hpp index a43d4a70..2e703faf 100644 --- a/validator/manager-hardfork.hpp +++ b/validator/manager-hardfork.hpp @@ -226,6 +226,10 @@ class ValidatorManagerImpl : public ValidatorManager { td::uint32 validator_set_hash, td::Promise promise) override { promise.set_value(td::Unit()); } + void send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, + td::BufferSlice data) { + callback_->send_block_candidate(id, cc_seqno, validator_set_hash, std::move(data)); + } void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority, td::Timestamp timeout, td::Promise> promise) override; @@ -326,7 +330,7 @@ class ValidatorManagerImpl : public ValidatorManager { void send_top_shard_block_description(td::Ref desc) override { UNREACHABLE(); } - void send_block_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) override { + void send_block_broadcast(BlockBroadcast broadcast, int mode) override { } void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise promise) override { diff --git a/validator/manager.cpp b/validator/manager.cpp index 03c4f795..67cd60a7 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -1284,11 +1284,15 @@ void ValidatorManagerImpl::set_block_candidate(BlockIdExt id, BlockCandidate can } if (!id.is_masterchain()) { add_cached_block_candidate(ReceivedBlock{id, candidate.data.clone()}); - callback_->send_block_candidate(id, cc_seqno, validator_set_hash, candidate.data.clone()); } td::actor::send_closure(db_, &Db::store_block_candidate, std::move(candidate), std::move(promise)); } +void ValidatorManagerImpl::send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, + td::uint32 validator_set_hash, td::BufferSlice data) { + callback_->send_block_candidate(id, cc_seqno, validator_set_hash, std::move(data)); +} + void ValidatorManagerImpl::write_handle(BlockHandle handle, td::Promise promise) { auto P = td::PromiseCreator::lambda( [SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result R) mutable { @@ -1616,8 +1620,8 @@ void ValidatorManagerImpl::send_top_shard_block_description(td::Refsend_broadcast(std::move(broadcast), custom_overlays_only); +void ValidatorManagerImpl::send_block_broadcast(BlockBroadcast broadcast, int mode) { + callback_->send_broadcast(std::move(broadcast), mode); } void ValidatorManagerImpl::start_up() { diff --git a/validator/manager.hpp b/validator/manager.hpp index 28949837..7410f75f 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -434,6 +434,8 @@ class ValidatorManagerImpl : public ValidatorManager { void set_block_candidate(BlockIdExt id, BlockCandidate candidate, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::Promise promise) override; + void send_block_candidate_broadcast(BlockIdExt id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, + td::BufferSlice data) override; void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority, td::Timestamp timeout, td::Promise> promise) override; @@ -498,7 +500,7 @@ class ValidatorManagerImpl : public ValidatorManager { void send_external_message(td::Ref message) override; void send_ihr_message(td::Ref message) override; void send_top_shard_block_description(td::Ref desc) override; - void send_block_broadcast(BlockBroadcast broadcast, bool custom_overlays_only) override; + void send_block_broadcast(BlockBroadcast broadcast, int mode) override; void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise promise) override; void get_shard_client_state(bool from_db, td::Promise promise) override; diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index 2f43b3b9..1c6a9d0e 100644 --- a/validator/validator-group.cpp +++ b/validator/validator-group.cpp @@ -18,6 +18,7 @@ */ #include "validator-group.hpp" #include "fabric.h" +#include "full-node-master.hpp" #include "ton/ton-io.hpp" #include "td/utils/overloaded.h" #include "common/delay.h" @@ -27,8 +28,14 @@ namespace ton { namespace validator { +static bool need_send_candidate_broadcast(const validatorsession::BlockSourceInfo &source_info, bool is_masterchain) { + return source_info.first_block_round == source_info.round && source_info.source_priority == 0 && !is_masterchain; +} + void ValidatorGroup::generate_block_candidate( - td::uint32 round_id, td::Promise promise) { + validatorsession::BlockSourceInfo source_info, + td::Promise promise) { + td::uint32 round_id = source_info.round; if (round_id > last_known_round_id_) { last_known_round_id_ = round_id; } @@ -53,12 +60,15 @@ void ValidatorGroup::generate_block_candidate( run_collate_query( shard_, min_masterchain_block_id_, prev_block_ids_, Ed25519_PublicKey{local_id_full_.ed25519_value().raw()}, validator_set_, opts_->get_collator_options(), manager_, td::Timestamp::in(10.0), - [SelfId = actor_id(this), cache = cached_collated_block_](td::Result R) { - td::actor::send_closure(SelfId, &ValidatorGroup::generated_block_candidate, std::move(cache), std::move(R)); + [SelfId = actor_id(this), cache = cached_collated_block_, source_info](td::Result R) mutable { + td::actor::send_closure(SelfId, &ValidatorGroup::generated_block_candidate, std::move(source_info), + std::move(cache), std::move(R)); }, cancellation_token_source_.get_cancellation_token(), /* mode = */ 0); } -void ValidatorGroup::generated_block_candidate(std::shared_ptr cache, td::Result R) { +void ValidatorGroup::generated_block_candidate(validatorsession::BlockSourceInfo source_info, + std::shared_ptr cache, + td::Result R) { if (R.is_error()) { for (auto &p : cache->promises) { p.set_error(R.error().clone()); @@ -69,6 +79,9 @@ void ValidatorGroup::generated_block_candidate(std::shared_ptrresult = std::move(candidate); for (auto &p : cache->promises) { p.set_value(cache->result.value().clone()); @@ -77,8 +90,9 @@ void ValidatorGroup::generated_block_candidate(std::shared_ptrpromises.clear(); } -void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidate block, +void ValidatorGroup::validate_block_candidate(validatorsession::BlockSourceInfo source_info, BlockCandidate block, td::Promise> promise) { + td::uint32 round_id = source_info.round; if (round_id > last_known_round_id_) { last_known_round_id_ = round_id; } @@ -97,7 +111,8 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat return; } - auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), round_id, block = block.clone(), + auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), source_info, block = block.clone(), manager = manager_, + validator_set = validator_set_, promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { auto S = R.move_as_error(); @@ -105,19 +120,22 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat LOG(ERROR) << "failed to validate candidate: " << S; } delay_action( - [SelfId, round_id, block = std::move(block), promise = std::move(promise)]() mutable { - td::actor::send_closure(SelfId, &ValidatorGroup::validate_block_candidate, round_id, std::move(block), - std::move(promise)); + [SelfId, source_info, block = std::move(block), promise = std::move(promise)]() mutable { + td::actor::send_closure(SelfId, &ValidatorGroup::validate_block_candidate, std::move(source_info), + std::move(block), std::move(promise)); }, td::Timestamp::in(0.1)); } else { auto v = R.move_as_ok(); v.visit(td::overloaded( [&](UnixTime ts) { - td::actor::send_closure(SelfId, &ValidatorGroup::update_approve_cache, block_to_cache_key(block), - ts); + td::actor::send_closure(SelfId, &ValidatorGroup::update_approve_cache, block_to_cache_key(block), ts); td::actor::send_closure(SelfId, &ValidatorGroup::add_available_block_candidate, block.pubkey.as_bits256(), block.id, block.collated_file_hash); + if (need_send_candidate_broadcast(source_info, block.id.is_masterchain())) { + td::actor::send_closure(SelfId, &ValidatorGroup::send_block_candidate_broadcast, block.id, + block.data.clone()); + } promise.set_value({ts, false}); }, [&](CandidateReject reject) { @@ -140,13 +158,14 @@ void ValidatorGroup::update_approve_cache(CacheKey key, UnixTime value) { approved_candidates_cache_[key] = value; } -void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block_data, +void ValidatorGroup::accept_block_candidate(validatorsession::BlockSourceInfo source_info, td::BufferSlice block_data, RootHash root_hash, FileHash file_hash, std::vector signatures, std::vector approve_signatures, validatorsession::ValidatorSessionStats stats, td::Promise promise) { stats.cc_seqno = validator_set_->get_catchain_seqno(); + td::uint32 round_id = source_info.round; if (round_id >= last_known_round_id_) { last_known_round_id_ = round_id + 1; } @@ -165,7 +184,21 @@ 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{}; - bool send_broadcast = src == local_id_; + + // Creator of the block sends broadcast to public overlays + // Creator of the block sends broadcast to private block overlay unless candidate broadcast was sent + // Any node sends broadcast to custom overlays unless candidate broadcast was sent + int send_broadcast_mode = 0; + bool sent_candidate = sent_candidate_broadcasts_.contains(block->block_id()); + if (source_info.source.compute_short_id() == local_id_) { + send_broadcast_mode |= fullnode::FullNode::broadcast_mode_public; + if (!sent_candidate) { + send_broadcast_mode |= fullnode::FullNode::broadcast_mode_private_block; + } + } + if (!sent_candidate) { + send_broadcast_mode |= fullnode::FullNode::broadcast_mode_custom; + } auto P = td::PromiseCreator::lambda([=, SelfId = actor_id(this), block_id = next_block_id, prev = prev_block_ids_, promise = std::move(promise)](td::Result R) mutable { @@ -176,7 +209,7 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s } 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), send_broadcast, + std::move(prev), std::move(sig_set), std::move(approve_sig_set), send_broadcast_mode, std::move(promise)); } else { promise.set_value(R.move_as_ok()); @@ -184,7 +217,8 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s }); run_accept_block_query(next_block_id, std::move(block), prev_block_ids_, validator_set_, std::move(sig_set), - std::move(approve_sig_set), send_broadcast, manager_, std::move(P)); + std::move(approve_sig_set), send_broadcast_mode, manager_, + std::move(P)); prev_block_ids_ = std::vector{next_block_id}; cached_collated_block_ = nullptr; approved_candidates_cache_.clear(); @@ -193,14 +227,14 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s void ValidatorGroup::retry_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::Ref approve_sig_set, int send_broadcast_mode, td::Promise promise) { auto P = td::PromiseCreator::lambda( [=, SelfId = actor_id(this), 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), send_broadcast, + std::move(prev), std::move(sig_set), std::move(approve_sig_set), send_broadcast_mode, std::move(promise)); } else { promise.set_value(R.move_as_ok()); @@ -208,7 +242,7 @@ void ValidatorGroup::retry_accept_block_query(BlockIdExt block_id, td::Ref ValidatorGroup::ma public: Callback(td::actor::ActorId id) : id_(id) { } - void on_candidate(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash, - td::BufferSlice data, td::BufferSlice collated_data, + void on_candidate(validatorsession::BlockSourceInfo source_info, + validatorsession::ValidatorSessionRootHash root_hash, td::BufferSlice data, + td::BufferSlice collated_data, td::Promise promise) override { auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result> R) mutable { @@ -266,18 +301,19 @@ std::unique_ptr ValidatorGroup::ma } }); - BlockCandidate candidate{Ed25519_PublicKey{source.ed25519_value().raw()}, + BlockCandidate candidate{Ed25519_PublicKey{source_info.source.ed25519_value().raw()}, BlockIdExt{0, 0, 0, root_hash, sha256_bits256(data.as_slice())}, sha256_bits256(collated_data.as_slice()), data.clone(), collated_data.clone()}; - td::actor::send_closure(id_, &ValidatorGroup::validate_block_candidate, round, std::move(candidate), - std::move(P)); + td::actor::send_closure(id_, &ValidatorGroup::validate_block_candidate, std::move(source_info), + std::move(candidate), std::move(P)); } - void on_generate_slot(td::uint32 round, + void on_generate_slot(validatorsession::BlockSourceInfo source_info, td::Promise promise) override { - td::actor::send_closure(id_, &ValidatorGroup::generate_block_candidate, round, std::move(promise)); + td::actor::send_closure(id_, &ValidatorGroup::generate_block_candidate, std::move(source_info), + std::move(promise)); } - void on_block_committed(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash, + void on_block_committed(validatorsession::BlockSourceInfo source_info, validatorsession::ValidatorSessionRootHash root_hash, validatorsession::ValidatorSessionFileHash file_hash, td::BufferSlice data, std::vector> signatures, std::vector> approve_signatures, @@ -291,9 +327,9 @@ std::unique_ptr ValidatorGroup::ma approve_sigs.emplace_back(BlockSignature{sig.first.bits256_value(), std::move(sig.second)}); } auto P = td::PromiseCreator::lambda([](td::Result) {}); - td::actor::send_closure(id_, &ValidatorGroup::accept_block_candidate, round, source.compute_short_id(), - std::move(data), root_hash, file_hash, std::move(sigs), std::move(approve_sigs), - std::move(stats), std::move(P)); + td::actor::send_closure(id_, &ValidatorGroup::accept_block_candidate, std::move(source_info), std::move(data), + root_hash, file_hash, std::move(sigs), std::move(approve_sigs), std::move(stats), + std::move(P)); } void on_block_skipped(td::uint32 round) override { td::actor::send_closure(id_, &ValidatorGroup::skip_round, round); @@ -379,7 +415,7 @@ 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), false, std::move(p.promise)); + std::move(p.approve_sigs), 0, 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 35d574ac..db55614f 100644 --- a/validator/validator-group.hpp +++ b/validator/validator-group.hpp @@ -34,18 +34,18 @@ class ValidatorManager; class ValidatorGroup : public td::actor::Actor { public: - void generate_block_candidate(td::uint32 round_id, + void generate_block_candidate(validatorsession::BlockSourceInfo source_info, td::Promise promise); - void validate_block_candidate(td::uint32 round_id, BlockCandidate block, + void validate_block_candidate(validatorsession::BlockSourceInfo source_info, BlockCandidate block, td::Promise> promise); - void accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block, RootHash root_hash, + void accept_block_candidate(validatorsession::BlockSourceInfo source_info, td::BufferSlice block, RootHash root_hash, FileHash file_hash, std::vector signatures, 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, - bool send_broadcast, td::Promise promise); + int send_broadcast_mode, td::Promise promise); void get_approved_candidate(PublicKey source, RootHash root_hash, FileHash file_hash, FileHash collated_data_file_hash, td::Promise promise); BlockIdExt create_next_block_id(RootHash root_hash, FileHash file_hash) const; @@ -140,7 +140,8 @@ class ValidatorGroup : public td::actor::Actor { std::shared_ptr cached_collated_block_; td::CancellationTokenSource cancellation_token_source_; - void generated_block_candidate(std::shared_ptr cache, td::Result R); + void generated_block_candidate(validatorsession::BlockSourceInfo source_info, + std::shared_ptr cache, td::Result R); using CacheKey = std::tuple; std::map approved_candidates_cache_; @@ -161,6 +162,16 @@ class ValidatorGroup : public td::actor::Actor { void add_available_block_candidate(td::Bits256 source, BlockIdExt id, FileHash collated_data_hash) { available_block_candidates_.emplace(source, id, collated_data_hash); } + + std::set sent_candidate_broadcasts_; + + void send_block_candidate_broadcast(BlockIdExt id, td::BufferSlice data) { + if (sent_candidate_broadcasts_.insert(id).second) { + td::actor::send_closure(manager_, &ValidatorManager::send_block_candidate_broadcast, id, + validator_set_->get_catchain_seqno(), validator_set_->get_validator_set_hash(), + std::move(data)); + } + } }; } // namespace validator diff --git a/validator/validator.h b/validator/validator.h index 45e617f9..9dbaa185 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -174,7 +174,7 @@ class ValidatorManagerInterface : public td::actor::Actor { virtual void send_shard_block_info(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) = 0; virtual void send_block_candidate(BlockIdExt block_id, CatchainSeqno cc_seqno, td::uint32 validator_set_hash, td::BufferSlice data) = 0; - virtual void send_broadcast(BlockBroadcast broadcast, bool custom_overlays_only = false) = 0; + virtual void send_broadcast(BlockBroadcast broadcast, int mode) = 0; virtual void download_block(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) = 0; virtual void download_zero_state(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, From b69214b6af61eb7f1e0ab246ed98846d653b50e0 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Wed, 9 Oct 2024 13:55:59 +0300 Subject: [PATCH 2/3] Validator patch: state download, adnl stats (#1257) * Persistent state download improvements 1) Don't start over on restart 2) Download shards one at a time to reduce RAM usage 3) More logs * Remove old peers from adnl stats --- adnl/adnl-local-id.cpp | 27 ++++++----- adnl/adnl-local-id.h | 18 +++++-- adnl/adnl-peer-table.cpp | 6 +-- adnl/adnl-peer-table.hpp | 2 +- adnl/adnl-peer.cpp | 18 +++++-- adnl/adnl-peer.h | 4 +- adnl/adnl-peer.hpp | 4 +- adnl/adnl.h | 2 +- tl/generate/scheme/ton_api.tl | 2 +- tl/generate/scheme/ton_api.tlo | Bin 97708 -> 97736 bytes .../validator-engine-console-query.cpp | 20 +++++++- .../validator-engine-console-query.h | 8 +++- validator-engine/validator-engine.cpp | 2 +- validator/downloaders/download-state.cpp | 14 +++++- validator/manager-init.cpp | 2 +- validator/net/download-state.cpp | 28 +++++++---- validator/net/download-state.hpp | 1 + validator/shard-client.cpp | 44 +++++++++--------- validator/shard-client.hpp | 9 +--- 19 files changed, 135 insertions(+), 76 deletions(-) diff --git a/adnl/adnl-local-id.cpp b/adnl/adnl-local-id.cpp index d72fc7bc..e0c62de7 100644 --- a/adnl/adnl-local-id.cpp +++ b/adnl/adnl-local-id.cpp @@ -306,7 +306,7 @@ void AdnlLocalId::update_packet(AdnlPacket packet, bool update_id, bool sign, td } } -void AdnlLocalId::get_stats(td::Promise> promise) { +void AdnlLocalId::get_stats(bool all, td::Promise> promise) { auto stats = create_tl_object(); stats->short_id_ = short_id_.bits256_value(); for (auto &[ip, x] : inbound_rate_limiter_) { @@ -317,7 +317,7 @@ void AdnlLocalId::get_stats(td::Promisepackets_recent_ = packet_stats_prev_.tl(); - stats->packets_total_ = packet_stats_total_.tl(); + stats->packets_total_ = packet_stats_total_.tl(all); stats->packets_total_->ts_start_ = (double)Adnl::adnl_start_time(); stats->packets_total_->ts_end_ = td::Clocks::system(); promise.set_result(std::move(stats)); @@ -325,14 +325,14 @@ void AdnlLocalId::get_stats(td::Promise AdnlLocalId::PacketStats::tl() const { +tl_object_ptr AdnlLocalId::PacketStats::tl(bool all) const { + double threshold = all ? -1.0 : td::Clocks::system() - 600.0; auto obj = create_tl_object(); obj->ts_start_ = ts_start; obj->ts_end_ = ts_end; for (const auto &[ip, packets] : decrypted_packets) { - obj->decrypted_packets_.push_back(create_tl_object( - ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets)); + if (packets.last_packet_ts >= threshold) { + obj->decrypted_packets_.push_back(create_tl_object( + ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets.packets)); + } } for (const auto &[ip, packets] : dropped_packets) { - obj->dropped_packets_.push_back(create_tl_object( - ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets)); + if (packets.last_packet_ts >= threshold) { + obj->dropped_packets_.push_back(create_tl_object( + ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets.packets)); + } } return obj; } diff --git a/adnl/adnl-local-id.h b/adnl/adnl-local-id.h index be9d79d2..fa7f7f74 100644 --- a/adnl/adnl-local-id.h +++ b/adnl/adnl-local-id.h @@ -78,7 +78,7 @@ class AdnlLocalId : public td::actor::Actor { void update_packet(AdnlPacket packet, bool update_id, bool sign, td::int32 update_addr_list_if, td::int32 update_priority_addr_list_if, td::Promise promise); - void get_stats(td::Promise> promise); + void get_stats(bool all, td::Promise> promise); td::uint32 get_mode() { return mode_; @@ -111,10 +111,20 @@ class AdnlLocalId : public td::actor::Actor { std::map inbound_rate_limiter_; struct PacketStats { double ts_start = 0.0, ts_end = 0.0; - std::map decrypted_packets; - std::map dropped_packets; - tl_object_ptr tl() const; + struct Counter { + td::uint64 packets = 0; + double last_packet_ts = 0.0; + + void inc() { + ++packets; + last_packet_ts = td::Clocks::system(); + } + }; + std::map decrypted_packets; + std::map dropped_packets; + + tl_object_ptr tl(bool all = true) const; } packet_stats_cur_, packet_stats_prev_, packet_stats_total_; void add_decrypted_packet_stats(td::IPAddress addr); void add_dropped_packet_stats(td::IPAddress addr); diff --git a/adnl/adnl-peer-table.cpp b/adnl/adnl-peer-table.cpp index d885623a..b8aab567 100644 --- a/adnl/adnl-peer-table.cpp +++ b/adnl/adnl-peer-table.cpp @@ -385,7 +385,7 @@ void AdnlPeerTableImpl::get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_ td::actor::send_closure(it->second, &AdnlPeer::get_conn_ip_str, l_id, std::move(promise)); } -void AdnlPeerTableImpl::get_stats(td::Promise> promise) { +void AdnlPeerTableImpl::get_stats(bool all, td::Promise> promise) { class Cb : public td::actor::Actor { public: explicit Cb(td::Promise> promise) : promise_(std::move(promise)) { @@ -440,7 +440,7 @@ void AdnlPeerTableImpl::get_stats(td::Promise for (auto &[id, local_id] : local_ids_) { td::actor::send_closure(callback, &Cb::inc_pending); - td::actor::send_closure(local_id.local_id, &AdnlLocalId::get_stats, + td::actor::send_closure(local_id.local_id, &AdnlLocalId::get_stats, all, [id = id, callback](td::Result> R) { if (R.is_error()) { VLOG(ADNL_NOTICE) @@ -454,7 +454,7 @@ void AdnlPeerTableImpl::get_stats(td::Promise for (auto &[id, peer] : peers_) { td::actor::send_closure(callback, &Cb::inc_pending); td::actor::send_closure( - peer, &AdnlPeer::get_stats, + peer, &AdnlPeer::get_stats, all, [id = id, callback](td::Result>> R) { if (R.is_error()) { VLOG(ADNL_NOTICE) << "failed to get stats for peer " << id << " : " << R.move_as_error(); diff --git a/adnl/adnl-peer-table.hpp b/adnl/adnl-peer-table.hpp index 12f64fcb..9ad61b65 100644 --- a/adnl/adnl-peer-table.hpp +++ b/adnl/adnl-peer-table.hpp @@ -108,7 +108,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable { td::Promise, AdnlAddress>> promise) override; void get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_id, td::Promise promise) override; - void get_stats(td::Promise> promise) override; + void get_stats(bool all, td::Promise> promise) override; struct PrintId {}; PrintId print_id() const { diff --git a/adnl/adnl-peer.cpp b/adnl/adnl-peer.cpp index 2b0077a8..7f5c6039 100644 --- a/adnl/adnl-peer.cpp +++ b/adnl/adnl-peer.cpp @@ -808,7 +808,15 @@ void AdnlPeerPairImpl::get_conn_ip_str(td::Promise promise) { promise.set_value("undefined"); } -void AdnlPeerPairImpl::get_stats(td::Promise> promise) { +void AdnlPeerPairImpl::get_stats(bool all, td::Promise> promise) { + if (!all) { + double threshold = td::Clocks::system() - 600.0; + if (last_in_packet_ts_ < threshold && last_out_packet_ts_ < threshold) { + promise.set_value(nullptr); + return; + } + } + auto stats = create_tl_object(); stats->local_id_ = local_id_.bits256_value(); stats->peer_id_ = peer_id_short_.bits256_value(); @@ -993,7 +1001,7 @@ void AdnlPeerImpl::update_addr_list(AdnlNodeIdShort local_id, td::uint32 local_m td::actor::send_closure(it->second, &AdnlPeerPair::update_addr_list, std::move(addr_list)); } -void AdnlPeerImpl::get_stats(td::Promise>> promise) { +void AdnlPeerImpl::get_stats(bool all, td::Promise>> promise) { class Cb : public td::actor::Actor { public: explicit Cb(td::Promise>> promise) @@ -1001,7 +1009,9 @@ void AdnlPeerImpl::get_stats(td::Promise peer_pair) { - result_.push_back(std::move(peer_pair)); + if (peer_pair) { + result_.push_back(std::move(peer_pair)); + } dec_pending(); } @@ -1027,7 +1037,7 @@ void AdnlPeerImpl::get_stats(td::Promise> R) { if (R.is_error()) { diff --git a/adnl/adnl-peer.h b/adnl/adnl-peer.h index b7d6adc0..1215f71d 100644 --- a/adnl/adnl-peer.h +++ b/adnl/adnl-peer.h @@ -59,7 +59,7 @@ class AdnlPeerPair : public td::actor::Actor { virtual void update_peer_id(AdnlNodeIdFull id) = 0; virtual void update_addr_list(AdnlAddressList addr_list) = 0; virtual void get_conn_ip_str(td::Promise promise) = 0; - virtual void get_stats(td::Promise> promise) = 0; + virtual void get_stats(bool all, td::Promise> promise) = 0; static td::actor::ActorOwn create(td::actor::ActorId network_manager, td::actor::ActorId peer_table, td::uint32 local_mode, @@ -101,7 +101,7 @@ class AdnlPeer : public td::actor::Actor { td::actor::ActorId local_actor, AdnlAddressList addr_list) = 0; virtual void update_dht_node(td::actor::ActorId dht_node) = 0; virtual void get_conn_ip_str(AdnlNodeIdShort l_id, td::Promise promise) = 0; - virtual void get_stats(td::Promise>> promise) = 0; + virtual void get_stats(bool all, td::Promise>> promise) = 0; }; } // namespace adnl diff --git a/adnl/adnl-peer.hpp b/adnl/adnl-peer.hpp index d25a24cf..7db2e2a1 100644 --- a/adnl/adnl-peer.hpp +++ b/adnl/adnl-peer.hpp @@ -90,7 +90,7 @@ class AdnlPeerPairImpl : public AdnlPeerPair { void update_peer_id(AdnlNodeIdFull id) override; void get_conn_ip_str(td::Promise promise) override; - void get_stats(td::Promise> promise) override; + void get_stats(bool all, td::Promise> promise) override; void got_data_from_db(td::Result R); void got_data_from_static_nodes(td::Result R); @@ -302,7 +302,7 @@ class AdnlPeerImpl : public AdnlPeer { AdnlAddressList addr_list) override; void update_dht_node(td::actor::ActorId dht_node) override; void get_conn_ip_str(AdnlNodeIdShort l_id, td::Promise promise) override; - void get_stats(td::Promise>> promise) override; + void get_stats(bool all, td::Promise>> promise) override; //void check_signature(td::BufferSlice data, td::BufferSlice signature, td::Promise promise) override; AdnlPeerImpl(td::actor::ActorId network_manager, td::actor::ActorId peer_table, diff --git a/adnl/adnl.h b/adnl/adnl.h index a276e0c2..b49581a9 100644 --- a/adnl/adnl.h +++ b/adnl/adnl.h @@ -121,7 +121,7 @@ class Adnl : public AdnlSenderInterface { virtual void create_tunnel(AdnlNodeIdShort dst, td::uint32 size, td::Promise, AdnlAddress>> promise) = 0; - virtual void get_stats(td::Promise> promise) = 0; + virtual void get_stats(bool all, td::Promise> promise) = 0; static td::actor::ActorOwn create(std::string db, td::actor::ActorId keyring); diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 4172bc39..9ef47d95 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -764,7 +764,7 @@ engine.validator.setStateSerializerEnabled enabled:Bool = engine.validator.Succe engine.validator.setCollatorOptionsJson json:string = engine.validator.Success; engine.validator.getCollatorOptionsJson = engine.validator.JsonConfig; -engine.validator.getAdnlStats = adnl.Stats; +engine.validator.getAdnlStats all:Bool = adnl.Stats; engine.validator.getActorTextStats = engine.validator.TextStats; ---types--- diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 70a993632c8ecbe04072d787eb979e1dc479d569..bc46d1b16c9b737a44a09b3a2d363dc13ebf2847 100644 GIT binary patch delta 50 zcmV-20L}lb`vu7R1%R{x&`t&8-k*~lm$6R)6qo5v0TT=X0000R=HDp;VQg%Zz&ISY I2u}f|E+}OaMF0Q* delta 37 tcmX@{n{~}^)`l&N7yMYm6;uw(PA?2(6q)|gk5PDXPn67d6Mx1jdH^c64k`cu diff --git a/validator-engine-console/validator-engine-console-query.cpp b/validator-engine-console/validator-engine-console-query.cpp index 2a0d44f7..ff4e6e04 100644 --- a/validator-engine-console/validator-engine-console-query.cpp +++ b/validator-engine-console/validator-engine-console-query.cpp @@ -1306,13 +1306,21 @@ td::Status GetCollatorOptionsJsonQuery::receive(td::BufferSlice data) { td::Status GetAdnlStatsJsonQuery::run() { TRY_RESULT_ASSIGN(file_name_, tokenizer_.get_token()); + if (!tokenizer_.endl()) { + TRY_RESULT(s, tokenizer_.get_token()); + if (s == "all") { + all_ = true; + } else { + return td::Status::Error(PSTRING() << "unexpected token " << s); + } + } TRY_STATUS(tokenizer_.check_endl()); return td::Status::OK(); } td::Status GetAdnlStatsJsonQuery::send() { auto b = - ton::create_serialize_tl_object(); + ton::create_serialize_tl_object(all_); td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); return td::Status::OK(); } @@ -1327,13 +1335,21 @@ td::Status GetAdnlStatsJsonQuery::receive(td::BufferSlice data) { } td::Status GetAdnlStatsQuery::run() { + if (!tokenizer_.endl()) { + TRY_RESULT(s, tokenizer_.get_token()); + if (s == "all") { + all_ = true; + } else { + return td::Status::Error(PSTRING() << "unexpected token " << s); + } + } TRY_STATUS(tokenizer_.check_endl()); return td::Status::OK(); } td::Status GetAdnlStatsQuery::send() { auto b = - ton::create_serialize_tl_object(); + ton::create_serialize_tl_object(all_); td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); return td::Status::OK(); } diff --git a/validator-engine-console/validator-engine-console-query.h b/validator-engine-console/validator-engine-console-query.h index c3c02150..0e21c9c2 100644 --- a/validator-engine-console/validator-engine-console-query.h +++ b/validator-engine-console/validator-engine-console-query.h @@ -1327,7 +1327,8 @@ class GetAdnlStatsJsonQuery : public Query { return "getadnlstatsjson"; } static std::string get_help() { - return "getadnlstatsjson \tsave adnl stats to "; + return "getadnlstatsjson [all]\tsave adnl stats to . all - returns all peers (default - only " + "peers with traffic in the last 10 minutes)"; } std::string name() const override { return get_name(); @@ -1335,6 +1336,7 @@ class GetAdnlStatsJsonQuery : public Query { private: std::string file_name_; + bool all_ = false; }; class GetAdnlStatsQuery : public Query { @@ -1349,7 +1351,8 @@ class GetAdnlStatsQuery : public Query { return "getadnlstats"; } static std::string get_help() { - return "getadnlstats\tdisplay adnl stats"; + return "getadnlstats [all]\tdisplay adnl stats. all - returns all peers (default - only peers with traffic in the " + "last 10 minutes)"; } std::string name() const override { return get_name(); @@ -1357,4 +1360,5 @@ class GetAdnlStatsQuery : public Query { private: std::string file_name_; + bool all_ = false; }; diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index a2ca6a24..8b35b2b1 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -3913,7 +3913,7 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getAdnlSt return; } td::actor::send_closure( - adnl_, &ton::adnl::Adnl::get_stats, + adnl_, &ton::adnl::Adnl::get_stats, query.all_, [promise = std::move(promise)](td::Result> R) mutable { if (R.is_ok()) { promise.set_value(ton::serialize_tl_object(R.move_as_ok(), true)); diff --git a/validator/downloaders/download-state.cpp b/validator/downloaders/download-state.cpp index ccce8f77..32978ea5 100644 --- a/validator/downloaders/download-state.cpp +++ b/validator/downloaders/download-state.cpp @@ -50,7 +50,16 @@ void DownloadShardState::start_up() { void DownloadShardState::got_block_handle(BlockHandle handle) { handle_ = std::move(handle); - download_state(); + if (handle_->received_state()) { + LOG(WARNING) << "shard state " << block_id_.to_str() << " already stored in db"; + td::actor::send_closure(manager_, &ValidatorManagerInterface::get_shard_state_from_db, handle_, + [SelfId = actor_id(this)](td::Result> R) { + R.ensure(); + td::actor::send_closure(SelfId, &DownloadShardState::written_shard_state, R.move_as_ok()); + }); + } else { + download_state(); + } } void DownloadShardState::retry() { @@ -165,6 +174,7 @@ void DownloadShardState::downloaded_shard_state(td::BufferSlice data) { } void DownloadShardState::checked_shard_state() { + LOG(WARNING) << "checked shard state " << block_id_.to_str(); auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { R.ensure(); td::actor::send_closure(SelfId, &DownloadShardState::written_shard_state_file); @@ -179,6 +189,7 @@ void DownloadShardState::checked_shard_state() { } void DownloadShardState::written_shard_state_file() { + LOG(WARNING) << "written shard state file " << block_id_.to_str(); auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result> R) { R.ensure(); td::actor::send_closure(SelfId, &DownloadShardState::written_shard_state, R.move_as_ok()); @@ -207,6 +218,7 @@ void DownloadShardState::written_shard_state(td::Ref state) { } void DownloadShardState::written_block_handle() { + LOG(WARNING) << "finished downloading and storing shard state " << block_id_.to_str(); finish_query(); } diff --git a/validator/manager-init.cpp b/validator/manager-init.cpp index aa110380..64a0a547 100644 --- a/validator/manager-init.cpp +++ b/validator/manager-init.cpp @@ -227,7 +227,7 @@ void ValidatorManagerMasterchainReiniter::choose_masterchain_state() { } if (!p || ValidatorManager::is_persistent_state(h->unix_time(), p->unix_time())) { auto ttl = ValidatorManager::persistent_state_ttl(h->unix_time()); - double time_to_download = 3600 * 3; + double time_to_download = 3600 * 8; if (ttl > td::Clocks::system() + time_to_download) { handle = h; break; diff --git a/validator/net/download-state.cpp b/validator/net/download-state.cpp index 2740ce41..2b373ef3 100644 --- a/validator/net/download-state.cpp +++ b/validator/net/download-state.cpp @@ -52,12 +52,7 @@ DownloadState::DownloadState(BlockIdExt block_id, BlockIdExt masterchain_block_i void DownloadState::abort_query(td::Status reason) { if (promise_) { - if (reason.code() == ErrorCode::notready || reason.code() == ErrorCode::timeout) { - VLOG(FULL_NODE_DEBUG) << "failed to download state " << block_id_ << " from " << download_from_ << ": " << reason; - } else { - VLOG(FULL_NODE_NOTICE) << "failed to download state " << block_id_ << " from " << download_from_ << ": " - << reason; - } + LOG(WARNING) << "failed to download state " << block_id_.to_str() << " from " << download_from_ << ": " << reason; promise_.set_error(std::move(reason)); } stop(); @@ -77,6 +72,19 @@ void DownloadState::finish_query() { void DownloadState::start_up() { alarm_timestamp() = timeout_; + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_persistent_state, block_id_, + masterchain_block_id_, + [SelfId = actor_id(this), block_id = block_id_](td::Result R) { + if (R.is_error()) { + td::actor::send_closure(SelfId, &DownloadState::get_block_handle); + } else { + LOG(WARNING) << "got block state from disk: " << block_id.to_str(); + td::actor::send_closure(SelfId, &DownloadState::got_block_state, R.move_as_ok()); + } + }); +} + +void DownloadState::get_block_handle() { auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { if (R.is_error()) { td::actor::send_closure(SelfId, &DownloadState::abort_query, R.move_as_error()); @@ -115,7 +123,7 @@ void DownloadState::got_block_handle(BlockHandle handle) { void DownloadState::got_node_to_download(adnl::AdnlNodeIdShort node) { download_from_ = node; - LOG(INFO) << "downloading state " << block_id_.to_str() << " from " << download_from_; + LOG(WARNING) << "downloading state " << block_id_.to_str() << " from " << download_from_; auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) mutable { if (R.is_error()) { @@ -192,8 +200,8 @@ void DownloadState::got_block_state_part(td::BufferSlice data, td::uint32 reques double elapsed = prev_logged_timer_.elapsed(); if (elapsed > 10.0) { prev_logged_timer_ = td::Timer(); - LOG(INFO) << "downloading state " << block_id_.to_str() << ": total=" << sum_ << " (" - << td::format::as_size((td::uint64)(double(sum_ - prev_logged_sum_) / elapsed)) << "/s)"; + LOG(WARNING) << "downloading state " << block_id_.to_str() << ": " << td::format::as_size(sum_) << " (" + << td::format::as_size((td::uint64)(double(sum_ - prev_logged_sum_) / elapsed)) << "/s)"; prev_logged_sum_ = sum_; } @@ -234,7 +242,7 @@ void DownloadState::got_block_state_part(td::BufferSlice data, td::uint32 reques void DownloadState::got_block_state(td::BufferSlice data) { state_ = std::move(data); - LOG(INFO) << "finished downloading state " << block_id_.to_str() << ": total=" << sum_; + LOG(WARNING) << "finished downloading state " << block_id_.to_str() << ": " << td::format::as_size(state_.size()); finish_query(); } diff --git a/validator/net/download-state.hpp b/validator/net/download-state.hpp index 7db1327f..19c44beb 100644 --- a/validator/net/download-state.hpp +++ b/validator/net/download-state.hpp @@ -43,6 +43,7 @@ class DownloadState : public td::actor::Actor { void finish_query(); void start_up() override; + void get_block_handle(); void got_block_handle(BlockHandle handle); void got_node_to_download(adnl::AdnlNodeIdShort node); void got_block_state_description(td::BufferSlice data_description); diff --git a/validator/shard-client.cpp b/validator/shard-client.cpp index 62a762a5..24dd77e8 100644 --- a/validator/shard-client.cpp +++ b/validator/shard-client.cpp @@ -79,30 +79,30 @@ void ShardClient::got_init_state_from_db(td::Ref state) { void ShardClient::start_up_init_mode() { build_shard_overlays(); - - auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { - R.ensure(); - td::actor::send_closure(SelfId, &ShardClient::applied_all_shards); - }); - - td::MultiPromise mp; - auto ig = mp.init_guard(); - ig.add_promise(std::move(P)); - - auto vec = masterchain_state_->get_shards(); - for (auto &shard : vec) { - if (opts_->need_monitor(shard->shard())) { - auto P = td::PromiseCreator::lambda([promise = ig.get_promise()](td::Result> R) mutable { - R.ensure(); - promise.set_value(td::Unit()); - }); - - td::actor::create_actor("downloadstate", shard->top_block_id(), - masterchain_block_handle_->id(), 2, manager_, - td::Timestamp::in(3600 * 3), std::move(P)) - .release(); + std::vector shards; + for (const auto& s : masterchain_state_->get_shards()) { + if (opts_->need_monitor(s->shard())) { + shards.push_back(s->top_block_id()); } } + download_shard_states(masterchain_block_handle_->id(), std::move(shards), 0); +} + +void ShardClient::download_shard_states(BlockIdExt masterchain_block_id, std::vector shards, size_t idx) { + if (idx >= shards.size()) { + LOG(WARNING) << "downloaded all shard states"; + applied_all_shards(); + return; + } + BlockIdExt block_id = shards[idx]; + td::actor::create_actor( + "downloadstate", block_id, masterchain_block_handle_->id(), 2, manager_, td::Timestamp::in(3600 * 5), + [=, SelfId = actor_id(this), shards = std::move(shards)](td::Result> R) { + R.ensure(); + td::actor::send_closure(SelfId, &ShardClient::download_shard_states, masterchain_block_id, std::move(shards), + idx + 1); + }) + .release(); } void ShardClient::applied_all_shards() { diff --git a/validator/shard-client.hpp b/validator/shard-client.hpp index 455b67e7..c1676deb 100644 --- a/validator/shard-client.hpp +++ b/validator/shard-client.hpp @@ -68,19 +68,12 @@ class ShardClient : public td::actor::Actor { void start_up() override; void start_up_init_mode(); - void start_up_init_mode_finished(); + void download_shard_states(BlockIdExt masterchain_block_id, std::vector shards, size_t idx); void start(); void got_state_from_db(BlockIdExt masterchain_block_id); void got_init_handle_from_db(BlockHandle handle); void got_init_state_from_db(td::Ref state); - void im_download_shard_state(BlockIdExt block_id, td::Promise promise); - void im_downloaded_zero_state(BlockIdExt block_id, td::BufferSlice data, td::Promise promise); - void im_downloaded_proof_link(BlockIdExt block_id, td::BufferSlice data, td::Promise promise); - void im_checked_proof_link(BlockIdExt block_id, td::Promise promise); - void im_downloaded_shard_state(BlockIdExt block_id, td::Promise promise); - void im_got_shard_handle(BlockHandle handle, td::Promise promise); - void new_masterchain_block_id(BlockIdExt masterchain_block_id); void got_masterchain_block_handle(BlockHandle handle); void download_masterchain_state(); From fd1735f6ecc1b69a1a2ca8a3a4a621142f8cb559 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirsanov Date: Wed, 9 Oct 2024 16:03:58 +0300 Subject: [PATCH 3/3] [FunC] Fix a bug with << operator to zero value (#1262) --- crypto/func/auto-tests/tests/bit-operators.fc | 53 +++++++++++++++++++ crypto/func/builtins.cpp | 4 +- crypto/func/func.h | 2 +- 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 crypto/func/auto-tests/tests/bit-operators.fc diff --git a/crypto/func/auto-tests/tests/bit-operators.fc b/crypto/func/auto-tests/tests/bit-operators.fc new file mode 100644 index 00000000..3cc5b522 --- /dev/null +++ b/crypto/func/auto-tests/tests/bit-operators.fc @@ -0,0 +1,53 @@ + +int lshift() { + return (1 << 0) == 1; +} + +int rshift() { + return (1 >> 0) == 1; +} + +int lshift_var(int i) { + return (1 << i) == 1; +} + +int rshift_var(int i) { + return (1 >> i) == 1; +} + +int main(int x) { + if (x == 0) { + return lshift(); + } elseif (x == 1) { + return rshift(); + } elseif (x == 2) { + return lshift_var(0); + } elseif (x == 3) { + return rshift_var(0); + } elseif (x == 4) { + return lshift_var(1); + } else { + return rshift_var(1); + } +} + +int is_claimed(int index) method_id(11) { + int claim_bit_index = index % 256; + int mask = 1 << claim_bit_index; + return (255 & mask) == mask; +} + + +{- + method_id | in | out +TESTCASE | 0 | 0 | -1 +TESTCASE | 0 | 1 | -1 +TESTCASE | 0 | 2 | -1 +TESTCASE | 0 | 3 | -1 +TESTCASE | 0 | 4 | 0 +TESTCASE | 0 | 5 | 0 +TESTCASE | 11 | 0 | -1 +TESTCASE | 11 | 1 | -1 +TESTCASE | 11 | 256 | -1 +TESTCASE | 11 | 8 | 0 +-} diff --git a/crypto/func/builtins.cpp b/crypto/func/builtins.cpp index 9de673fd..cf3adf41 100644 --- a/crypto/func/builtins.cpp +++ b/crypto/func/builtins.cpp @@ -264,7 +264,7 @@ int emulate_lshift(int a, int b) { } int t = ((b & VarDescr::_NonZero) ? VarDescr::_Even : 0); t |= b & VarDescr::_Finite; - return emulate_mul(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | VarDescr::_Even | t); + return emulate_mul(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | t); } int emulate_div(int a, int b) { @@ -310,7 +310,7 @@ int emulate_rshift(int a, int b) { } int t = ((b & VarDescr::_NonZero) ? VarDescr::_Even : 0); t |= b & VarDescr::_Finite; - return emulate_div(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | VarDescr::_Even | t); + return emulate_div(a, VarDescr::_Int | VarDescr::_Pos | VarDescr::_NonZero | t); } int emulate_mod(int a, int b, int round_mode = -1) { diff --git a/crypto/func/func.h b/crypto/func/func.h index 2b95bcbc..e2476911 100644 --- a/crypto/func/func.h +++ b/crypto/func/func.h @@ -45,7 +45,7 @@ extern std::string generated_from; constexpr int optimize_depth = 20; -const std::string func_version{"0.4.4"}; +const std::string func_version{"0.4.5"}; enum Keyword { _Eof = -1,