From a68b5cbe627d4b68da68f05079e0cfc75aacd59f Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Tue, 16 Jan 2024 14:24:46 +0300 Subject: [PATCH] Improve validator session stats (#861) --- tl/generate/scheme/ton_api.tl | 5 +-- tl/generate/scheme/ton_api.tlo | Bin 86116 -> 86292 bytes validator-session/validator-session-types.h | 5 +++ validator-session/validator-session.cpp | 34 ++++++++++++++------ validator-session/validator-session.h | 1 + validator-session/validator-session.hpp | 4 ++- validator/manager.cpp | 11 ++++--- validator/validator-group.cpp | 16 ++++++++- 8 files changed, 58 insertions(+), 18 deletions(-) diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 346d9152..21e8318f 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -742,11 +742,12 @@ http.server.config dhs:(vector http.server.dnsEntry) local_hosts:(vector http.se ---types--- -validatorSession.statsProducer id:int256 block_status:int block_timestamp:long = validatorSession.StatsProducer; +validatorSession.statsProducer id:int256 candidate_id:int256 block_status:int block_timestamp:long comment:string = validatorSession.StatsProducer; validatorSession.statsRound timestamp:long producers:(vector validatorSession.statsProducer) = validatorSession.StatsRound; -validatorSession.stats id:tonNode.blockId timestamp:long self:int256 creator:int256 total_validators:int total_weight:long +validatorSession.stats success:Bool id:tonNode.blockIdExt timestamp:long self:int256 session_id:int256 cc_seqno:int + creator:int256 total_validators:int total_weight:long signatures:int signatures_weight:long approve_signatures:int approve_signatures_weight:long first_round:int rounds:(vector validatorSession.statsRound) = validatorSession.Stats; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 5b8e1c725e39ceff4097e4a654c796c9f84ff73e..9b74f1c3bbef41b10dba639833177fe7f6b6df74 100644 GIT binary patch delta 201 zcmaE|fOX0u)(s8@Ebn*lHBWXiFkm?$`9XJcg@M2&u+a1#CPoPfkmSu{LO%Qq3=GoG z?rX9amnJ8t78g%`U@kE^BTZ&{2P>n>^e;?|3e!968AT@NbO=q}^TDy crnj&%`b=J6%mESl!^+qJW^M0aW9;z)069x8RsaA1 diff --git a/validator-session/validator-session-types.h b/validator-session/validator-session-types.h index 57957478..bcbaa8f7 100644 --- a/validator-session/validator-session-types.h +++ b/validator-session/validator-session-types.h @@ -74,8 +74,10 @@ struct ValidatorSessionStats { struct Producer { PublicKeyHash id = PublicKeyHash::zero(); + ValidatorSessionCandidateId candidate_id = ValidatorSessionCandidateId::zero(); int block_status = status_none; td::uint64 block_timestamp = 0; + std::string comment; }; struct Round { td::uint64 timestamp = 0; @@ -85,6 +87,9 @@ struct ValidatorSessionStats { td::uint32 first_round; std::vector rounds; + bool success = false; + ValidatorSessionId session_id = ValidatorSessionId::zero(); + CatchainSeqno cc_seqno = 0; td::uint64 timestamp = 0; PublicKeyHash self = PublicKeyHash::zero(); PublicKeyHash creator = PublicKeyHash::zero(); diff --git a/validator-session/validator-session.cpp b/validator-session/validator-session.cpp index e08d8a7e..88de0fa5 100644 --- a/validator-session/validator-session.cpp +++ b/validator-session/validator-session.cpp @@ -288,7 +288,7 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice CHECK(!pending_reject_.count(block_id)); CHECK(!rejected_.count(block_id)); - stats_set_candidate_status(cur_round_, src, ValidatorSessionStats::status_received); + stats_set_candidate_status(cur_round_, src, block_id, ValidatorSessionStats::status_received); auto v = virtual_state_->choose_blocks_to_approve(description(), local_idx()); for (auto &b : v) { if (b && SentBlock::get_block_id(b) == block_id) { @@ -361,7 +361,8 @@ void ValidatorSessionImpl::process_query(PublicKeyHash src, td::BufferSlice data void ValidatorSessionImpl::candidate_decision_fail(td::uint32 round, ValidatorSessionCandidateId hash, std::string result, td::uint32 src, td::BufferSlice proof) { - stats_set_candidate_status(round, description().get_source_id(src), ValidatorSessionStats::status_rejected); + stats_set_candidate_status(round, description().get_source_id(src), hash, ValidatorSessionStats::status_rejected, + result); if (round != cur_round_) { return; } @@ -376,7 +377,8 @@ void ValidatorSessionImpl::candidate_decision_fail(td::uint32 round, ValidatorSe void ValidatorSessionImpl::candidate_decision_ok(td::uint32 round, ValidatorSessionCandidateId hash, RootHash root_hash, FileHash file_hash, td::uint32 src, td::uint32 ok_from) { - stats_set_candidate_status(round, description().get_source_id(src), ValidatorSessionStats::status_approved); + stats_set_candidate_status(round, description().get_source_id(src), hash, ValidatorSessionStats::status_approved, + PSTRING() << "ts=" << ok_from); if (round != cur_round_) { return; } @@ -812,15 +814,13 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) { if (!have_block) { callback_->on_block_skipped(cur_round_); } else { + cur_stats_.success = true; cur_stats_.timestamp = (td::uint64)td::Clocks::system(); - cur_stats_.total_validators = description().get_total_nodes(); - cur_stats_.total_weight = description().get_total_weight(); cur_stats_.signatures = (td::uint32)export_sigs.size(); cur_stats_.signatures_weight = signatures_weight; cur_stats_.approve_signatures = (td::uint32)export_approve_sigs.size(); cur_stats_.approve_signatures_weight = approve_signatures_weight; cur_stats_.creator = description().get_source_id(block->get_src_idx()); - cur_stats_.self = description().get_source_id(local_idx()); if (it == blocks_.end()) { callback_->on_block_committed(cur_round_, description().get_source_public_key(block->get_src_idx()), @@ -923,6 +923,12 @@ void ValidatorSessionImpl::destroy() { stop(); } +void ValidatorSessionImpl::get_current_stats(td::Promise promise) { + ValidatorSessionStats stats = cur_stats_; + stats.timestamp = (td::uint64)td::Clocks::system(); + promise.set_result(std::move(stats)); +} + void ValidatorSessionImpl::start_up() { CHECK(!rldp_.empty()); cur_round_ = 0; @@ -941,6 +947,10 @@ void ValidatorSessionImpl::start_up() { void ValidatorSessionImpl::stats_init() { cur_stats_ = ValidatorSessionStats(); cur_stats_.first_round = cur_round_; + cur_stats_.session_id = unique_hash_; + cur_stats_.total_validators = description().get_total_nodes(); + cur_stats_.total_weight = description().get_total_weight(); + cur_stats_.self = description().get_source_id(local_idx()); stats_add_round(); } @@ -961,20 +971,26 @@ void ValidatorSessionImpl::stats_add_round() { } } -void ValidatorSessionImpl::stats_set_candidate_status(td::uint32 round, PublicKeyHash src, int status) { +void ValidatorSessionImpl::stats_set_candidate_status(td::uint32 round, PublicKeyHash src, + ValidatorSessionCandidateId candidate_id, int status, + std::string comment) { if (round < cur_stats_.first_round || round - cur_stats_.first_round >= cur_stats_.rounds.size()) { return; } - auto& stats_round = cur_stats_.rounds[round - cur_stats_.first_round]; + auto &stats_round = cur_stats_.rounds[round - cur_stats_.first_round]; auto it = std::find_if(stats_round.producers.begin(), stats_round.producers.end(), - [&](const ValidatorSessionStats::Producer& p) { return p.id == src; }); + [&](const ValidatorSessionStats::Producer &p) { return p.id == src; }); if (it == stats_round.producers.end()) { return; } + it->candidate_id = candidate_id; if (it->block_status == ValidatorSessionStats::status_none) { it->block_timestamp = (td::uint64)td::Clocks::system(); } it->block_status = status; + if (!comment.empty()) { + it->comment = std::move(comment); + } } td::actor::ActorOwn ValidatorSession::create( diff --git a/validator-session/validator-session.h b/validator-session/validator-session.h index 376cac45..3f3b7ab9 100644 --- a/validator-session/validator-session.h +++ b/validator-session/validator-session.h @@ -91,6 +91,7 @@ class ValidatorSession : public td::actor::Actor { virtual void start() = 0; virtual void destroy() = 0; + virtual void get_current_stats(td::Promise promise) = 0; static td::actor::ActorOwn create( catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id, diff --git a/validator-session/validator-session.hpp b/validator-session/validator-session.hpp index 1717c99f..2dcbb46c 100644 --- a/validator-session/validator-session.hpp +++ b/validator-session/validator-session.hpp @@ -160,7 +160,8 @@ class ValidatorSessionImpl : public ValidatorSession { ValidatorSessionStats cur_stats_; void stats_init(); void stats_add_round(); - void stats_set_candidate_status(td::uint32 round, PublicKeyHash src, int status); + void stats_set_candidate_status(td::uint32 round, PublicKeyHash src, ValidatorSessionCandidateId candidate_id, + int status, std::string comment = ""); public: ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id, @@ -173,6 +174,7 @@ class ValidatorSessionImpl : public ValidatorSession { void start() override; void destroy() override; + void get_current_stats(td::Promise promise) override; void process_blocks(std::vector blocks); void finished_processing(); diff --git a/validator/manager.cpp b/validator/manager.cpp index dcda7b6e..21fa5887 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2640,18 +2640,19 @@ void ValidatorManagerImpl::log_validator_session_stats(BlockIdExt block_id, } std::vector> rounds; - for (const auto& round : stats.rounds) { + for (const auto &round : stats.rounds) { std::vector> producers; - for (const auto& producer : round.producers) { + for (const auto &producer : round.producers) { producers.push_back(create_tl_object( - producer.id.bits256_value(), producer.block_status, producer.block_timestamp)); + producer.id.bits256_value(), producer.candidate_id, producer.block_status, producer.block_timestamp, + producer.comment)); } rounds.push_back(create_tl_object(round.timestamp, std::move(producers))); } auto obj = create_tl_object( - create_tl_block_id_simple(block_id.id), stats.timestamp, stats.self.bits256_value(), - stats.creator.bits256_value(), stats.total_validators, stats.total_weight, stats.signatures, + stats.success, create_tl_block_id(block_id), stats.timestamp, stats.self.bits256_value(), stats.session_id, + stats.cc_seqno, stats.creator.bits256_value(), stats.total_validators, stats.total_weight, stats.signatures, stats.signatures_weight, stats.approve_signatures, stats.approve_signatures_weight, stats.first_round, std::move(rounds)); std::string s = td::json_encode(td::ToJson(*obj.get()), false); diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index 7baf0f05..51217bf9 100644 --- a/validator/validator-group.cpp +++ b/validator/validator-group.cpp @@ -136,7 +136,8 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s std::vector approve_signatures, validatorsession::ValidatorSessionStats stats, td::Promise promise) { - if (round_id >= last_known_round_id_) { + stats.cc_seqno = validator_set_->get_catchain_seqno(); + if (round_id >= last_known_round_id_) { last_known_round_id_ = round_id + 1; } auto sig_set = create_signature_set(std::move(signatures)); @@ -354,6 +355,19 @@ void ValidatorGroup::start(std::vector prev, BlockIdExt min_masterch void ValidatorGroup::destroy() { if (!session_.empty()) { + td::actor::send_closure(session_, &validatorsession::ValidatorSession::get_current_stats, + [manager = manager_, cc_seqno = validator_set_->get_catchain_seqno(), + block_id = create_next_block_id(RootHash::zero(), FileHash::zero())]( + td::Result R) { + if (R.is_error()) { + LOG(WARNING) << "Failed to get validator session stats: " << R.move_as_error(); + return; + } + auto stats = R.move_as_ok(); + stats.cc_seqno = cc_seqno; + td::actor::send_closure(manager, &ValidatorManager::log_validator_session_stats, block_id, + std::move(stats)); + }); auto ses = session_.release(); delay_action([ses]() mutable { td::actor::send_closure(ses, &validatorsession::ValidatorSession::destroy); }, td::Timestamp::in(10.0));