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/create-hardfork/create-hardfork.cpp b/create-hardfork/create-hardfork.cpp index 8956771d..42d2914a 100644 --- a/create-hardfork/create-hardfork.cpp +++ b/create-hardfork/create-hardfork.cpp @@ -248,7 +248,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/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, diff --git a/test/test-ton-collator.cpp b/test/test-ton-collator.cpp index c6aee54b..9e30836f 100644 --- a/test/test-ton-collator.cpp +++ b/test/test-ton-collator.cpp @@ -349,7 +349,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/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index f0b98c7a..05ea249c 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -803,7 +803,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; engine.validator.addCollator adnl_id:int256 shard:tonNode.shardId = engine.validator.Success; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index edde92ac..eaa9c416 100644 Binary files a/tl/generate/scheme/ton_api.tlo and b/tl/generate/scheme/ton_api.tlo differ diff --git a/validator-engine-console/validator-engine-console-query.cpp b/validator-engine-console/validator-engine-console-query.cpp index 37be3ff4..958692d5 100644 --- a/validator-engine-console/validator-engine-console-query.cpp +++ b/validator-engine-console/validator-engine-console-query.cpp @@ -1323,13 +1323,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(); } @@ -1344,13 +1352,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 0a1b9b30..5708fecd 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,6 +1360,7 @@ class GetAdnlStatsQuery : public Query { private: std::string file_name_; + bool all_ = false; }; class AddCollatorQuery : public Query { diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index 936ac0c3..3722dcd2 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -4085,7 +4085,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-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/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/fabric.h b/validator/fabric.h index 84de1da4..62906517 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -57,7 +57,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, bool apply, + td::Ref approve_signatures, int send_broadcast_mode, bool apply, 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 2cd578ab..0cd769e4 100644 --- a/validator/full-node.cpp +++ b/validator/full-node.cpp @@ -354,17 +354,16 @@ 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(broadcast.block_id.shard_full()); if (shard.empty()) { VLOG(FULL_NODE_WARNING) << "dropping OUT broadcast to unknown shard"; return; } - if (broadcast.block_id.is_masterchain()) { + if (mode & broadcast_mode_private_block) { if (!private_block_overlays_.empty()) { td::actor::send_closure(private_block_overlays_.begin()->second, &FullNodePrivateBlockOverlay::send_broadcast, broadcast.clone()); @@ -374,7 +373,9 @@ void FullNodeImpl::send_broadcast(BlockBroadcast broadcast, bool custom_overlays td::actor::send_closure(fast_sync_overlay, &FullNodeFastSyncOverlay::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, @@ -625,8 +626,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 8b47b947..627c0e55 100644 --- a/validator/full-node.h +++ b/validator/full-node.h @@ -106,6 +106,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 442a4db2..f6047ed5 100644 --- a/validator/full-node.hpp +++ b/validator/full-node.hpp @@ -69,7 +69,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 bada8cca..8af29a47 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, bool apply, + td::Ref approve_signatures, int send_broadcast_mode, bool apply, 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) , apply_(apply) , manager_(manager) , promise_(std::move(promise)) @@ -73,7 +73,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) { @@ -91,7 +90,6 @@ AcceptBlockQuery::AcceptBlockQuery(ForceFork ffork, BlockIdExt id, td::Refdata(); b.block_id = id_; @@ -956,8 +958,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 4d547e39..d8b763ba 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, bool apply, + td::Ref approve_signatures, int send_broadcast_mode, bool apply, 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 apply_ = true; bool ancestors_split_{false}, is_key_block_{false}; td::Timestamp timeout_ = td::Timestamp::in(600.0); diff --git a/validator/impl/fabric.cpp b/validator/impl/fabric.cpp index 16292c8c..db15b1ed 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, bool apply, + td::Ref approve_signatures, int send_broadcast_mode, bool apply, 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, apply, manager, std::move(promise)) + std::move(signatures), std::move(approve_signatures), send_broadcast_mode, apply, manager, std::move(promise)) .release(); } diff --git a/validator/interfaces/validator-manager.h b/validator/interfaces/validator-manager.h index 15965fc7..a728c93b 100644 --- a/validator/interfaces/validator-manager.h +++ b/validator/interfaces/validator-manager.h @@ -104,6 +104,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; @@ -143,7 +145,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 send_get_out_msg_queue_proof_request(ShardIdFull dst_shard, std::vector blocks, block::ImportedMsgQueueLimits limits, td::Promise>> promise) = 0; diff --git a/validator/manager-disk.cpp b/validator/manager-disk.cpp index 0a1ec14d..54238252 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 12b6c1e5..c54ccde5 100644 --- a/validator/manager-disk.hpp +++ b/validator/manager-disk.hpp @@ -189,6 +189,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; @@ -263,7 +265,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 send_get_out_msg_queue_proof_request(ShardIdFull dst_shard, std::vector blocks, block::ImportedMsgQueueLimits limits, diff --git a/validator/manager-hardfork.hpp b/validator/manager-hardfork.hpp index d75ffb81..daf83a19 100644 --- a/validator/manager-hardfork.hpp +++ b/validator/manager-hardfork.hpp @@ -231,6 +231,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; @@ -331,7 +335,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 send_get_out_msg_queue_proof_request(ShardIdFull dst_shard, std::vector blocks, block::ImportedMsgQueueLimits limits, diff --git a/validator/manager-init.cpp b/validator/manager-init.cpp index 39205f80..c2944b25 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/manager.cpp b/validator/manager.cpp index 7da001c9..f9726357 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -1428,11 +1428,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 { @@ -1761,8 +1765,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::send_get_out_msg_queue_proof_request( diff --git a/validator/manager.hpp b/validator/manager.hpp index 03e32225..b7e457e2 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -454,6 +454,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; @@ -518,7 +520,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 send_get_out_msg_queue_proof_request(ShardIdFull dst_shard, std::vector blocks, block::ImportedMsgQueueLimits limits, td::Promise>> promise) override; 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 d9cdcf7e..ac86cf37 100644 --- a/validator/shard-client.cpp +++ b/validator/shard-client.cpp @@ -74,29 +74,30 @@ void ShardClient::got_init_state_from_db(td::Ref state) { } void ShardClient::start_up_init_mode() { - auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { - R.ensure(); - td::actor::send_closure(SelfId, &ShardClient::apply_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(), masterchain_state_)) { - 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(), masterchain_state_)) { + 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 ea816192..7c2c978c 100644 --- a/validator/shard-client.hpp +++ b/validator/shard-client.hpp @@ -64,19 +64,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(); diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index 0c390760..118b9c11 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" @@ -30,8 +31,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,14 +60,16 @@ void ValidatorGroup::generate_block_candidate( cached_collated_block_->promises.push_back(promise.wrap([](BlockCandidate &&res) { return validatorsession::ValidatorSession::GeneratedCandidate{std::move(res), false}; })); - td::Promise P = [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)); + td::Promise P = [SelfId = actor_id(this), cache = cached_collated_block_, + source_info](td::Result R) { + td::actor::send_closure(SelfId, &ValidatorGroup::generated_block_candidate, source_info, std::move(cache), + std::move(R)); }; - collate_block(round_id, td::Timestamp::in(10.0), std::move(P)); + collate_block(source_info, td::Timestamp::in(10.0), std::move(P)); } -void ValidatorGroup::generated_block_candidate(std::shared_ptr cache, +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) { @@ -72,6 +81,9 @@ void ValidatorGroup::generated_block_candidate(std::shared_ptrresult = std::move(candidate); for (auto &p : cache->promises) { p.set_value(cache->result.value().clone()); @@ -80,8 +92,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; } @@ -100,7 +113,7 @@ 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(), promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { auto S = R.move_as_error(); @@ -108,19 +121,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) { @@ -142,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; } @@ -167,8 +184,23 @@ 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{}; + + // 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; + } 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)); + std::move(approve_sig_set), send_broadcast_mode, std::move(promise)); prev_block_ids_ = std::vector{next_block_id}; cached_collated_block_ = nullptr; approved_candidates_cache_.clear(); @@ -177,7 +209,7 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s 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, bool is_retry) { + int send_broadcast_mode, td::Promise promise, bool is_retry) { auto P = td::PromiseCreator::lambda([=, SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { @@ -187,7 +219,7 @@ void ValidatorGroup::accept_block_query(BlockIdExt block_id, td::Ref } LOG_CHECK(R.error().code() == ErrorCode::timeout || R.error().code() == ErrorCode::notready) << R.move_as_error(); 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), send_broadcast, + std::move(prev), std::move(sig_set), std::move(approve_sig_set), send_broadcast_mode, std::move(promise), true); } else { promise.set_value(R.move_as_ok()); @@ -195,7 +227,7 @@ void ValidatorGroup::accept_block_query(BlockIdExt block_id, td::Ref }); 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, monitoring_shard_, manager_, std::move(P)); + std::move(approve_sig_set), send_broadcast_mode, monitoring_shard_, manager_, std::move(P)); } void ValidatorGroup::skip_round(td::uint32 round_id) { @@ -231,8 +263,9 @@ std::unique_ptr 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 { @@ -247,18 +280,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, @@ -272,9 +306,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); @@ -363,7 +397,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{}; 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)); + std::move(p.approve_sigs), 0, std::move(p.promise)); prev_block_ids_ = std::vector{next_block_id}; } postponed_accept_.clear(); @@ -463,9 +497,9 @@ void ValidatorGroup::get_validator_group_info_for_litequery_cont( promise.set_result(std::move(result)); } -void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, - unsigned max_retries) { - if (round_id < last_known_round_id_) { +void ValidatorGroup::collate_block(validatorsession::BlockSourceInfo source_info, td::Timestamp timeout, + td::Promise promise, unsigned max_retries) { + if (source_info.round < last_known_round_id_) { promise.set_error(td::Status::Error("too old")); return; } @@ -528,7 +562,7 @@ void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, t LOG(WARNING) << "collate query for " << next_block_id.to_str() << ": " << R.error() << ", time=" << timer.elapsed() << "s, " << (retry ? "retrying" : "giving up"); if (retry) { - td::actor::send_closure(SelfId, &ValidatorGroup::collate_block, round_id, timeout, std::move(promise), + td::actor::send_closure(SelfId, &ValidatorGroup::collate_block, source_info, timeout, std::move(promise), max_retries - 1); } else { promise.set_result(td::Status::Error(ErrorCode::timeout, "timeout")); @@ -549,7 +583,7 @@ void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, t promise.set_error(R.move_as_error_prefix("rldp query failed: ")); return; } - td::actor::send_closure(SelfId, &ValidatorGroup::receive_collate_query_response, round_id, R.move_as_ok(), + td::actor::send_closure(SelfId, &ValidatorGroup::receive_collate_query_response, source_info, R.move_as_ok(), trusted_collator, std::move(promise)); }); LOG(INFO) << "sending collate query for " << next_block_id.to_str() << ": send to " << collator_adnl_id; @@ -560,24 +594,24 @@ void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, t std::move(P), timeout, std::move(query), max_answer_size); } -void ValidatorGroup::receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, bool trusted_collator, - td::Promise promise) { - if (round_id < last_known_round_id_) { +void ValidatorGroup::receive_collate_query_response(validatorsession::BlockSourceInfo source_info, td::BufferSlice data, + bool trusted_collator, td::Promise promise) { + if (source_info.round < last_known_round_id_) { promise.set_error(td::Status::Error("too old")); return; } TRY_RESULT_PROMISE(promise, f, fetch_tl_object(data, true)); td::Result res; ton_api::downcast_call(*f, td::overloaded( - [&](ton_api::collatorNode_generateBlockError &r) { - td::Status error = td::Status::Error(r.code_, r.message_); - res = error.move_as_error_prefix("collate query: "); - }, - [&](ton_api::collatorNode_generateBlockSuccess &r) { - res = CollatorNode::deserialize_candidate( - std::move(r.candidate_), - config_.max_block_size + config_.max_collated_data_size + 1024); - })); + [&](ton_api::collatorNode_generateBlockError &r) { + td::Status error = td::Status::Error(r.code_, r.message_); + res = error.move_as_error_prefix("collate query: "); + }, + [&](ton_api::collatorNode_generateBlockSuccess &r) { + res = CollatorNode::deserialize_candidate( + std::move(r.candidate_), + config_.max_block_size + config_.max_collated_data_size + 1024); + })); TRY_RESULT_PROMISE(promise, candidate, std::move(res)); if (candidate.pubkey.as_bits256() != local_id_full_.ed25519_value().raw()) { promise.set_error(td::Status::Error("collate query: block candidate source mismatch")); @@ -600,7 +634,7 @@ void ValidatorGroup::receive_collate_query_response(td::uint32 round_id, td::Buf } promise.set_result(std::move(candidate)); }); - validate_block_candidate(round_id, std::move(candidate), std::move(P)); + validate_block_candidate(source_info, std::move(candidate), std::move(P)); } } // namespace validator diff --git a/validator/validator-group.hpp b/validator/validator-group.hpp index c278c276..38fc9fb4 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 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, bool is_retry = false); + int send_broadcast_mode, td::Promise promise, bool is_retry = false); 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; @@ -97,10 +97,10 @@ class ValidatorGroup : public td::actor::Actor { private: std::unique_ptr make_validator_session_callback(); - void collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, - unsigned max_retries = 4); - void receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, bool trusted_collator, - td::Promise promise); + void collate_block(validatorsession::BlockSourceInfo source_info, td::Timestamp timeout, + td::Promise promise, unsigned max_retries = 4); + void receive_collate_query_response(validatorsession::BlockSourceInfo source_info, td::BufferSlice data, + bool trusted_collator, td::Promise promise); struct PostponedAccept { RootHash root_hash; @@ -150,7 +150,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_; @@ -171,6 +172,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 138b68b1..45807676 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -188,7 +188,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,