mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
More detailed validator session stats
This commit is contained in:
parent
b3e6819f3f
commit
417c3bb640
6 changed files with 118 additions and 47 deletions
|
@ -724,6 +724,10 @@ http.server.config dhs:(vector http.server.dnsEntry) local_hosts:(vector http.se
|
||||||
|
|
||||||
---types---
|
---types---
|
||||||
|
|
||||||
validatorSession.stats id:tonNode.blockId round_id:int total_validators:int total_weight:long signatures:int
|
validatorSession.statsProducer id:int256 block_status:int block_timestamp:long = validatorSession.StatsProducer;
|
||||||
signatures_weight:long approve_signatures:int approve_signatures_weight:long
|
|
||||||
creator:int256 producers:(vector int256) = validatorSession.Stats;
|
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
|
||||||
|
signatures:int signatures_weight:long approve_signatures:int approve_signatures_weight:long
|
||||||
|
first_round:int rounds:(vector validatorSession.statsRound) = validatorSession.Stats;
|
||||||
|
|
Binary file not shown.
|
@ -64,16 +64,30 @@ struct ValidatorSessionNode {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ValidatorSessionStats {
|
struct ValidatorSessionStats {
|
||||||
td::uint32 round;
|
enum { status_none = 0, status_received = 1, status_rejected = 2, status_approved = 3 };
|
||||||
td::uint32 total_validators;
|
|
||||||
ValidatorWeight total_weight;
|
|
||||||
td::uint32 signatures;
|
|
||||||
ValidatorWeight signatures_weight;
|
|
||||||
td::uint32 approve_signatures;
|
|
||||||
ValidatorWeight approve_signatures_weight;
|
|
||||||
|
|
||||||
PublicKeyHash creator;
|
struct Producer {
|
||||||
std::vector<PublicKeyHash> producers;
|
PublicKeyHash id = PublicKeyHash::zero();
|
||||||
|
int block_status = status_none;
|
||||||
|
td::uint64 block_timestamp = 0;
|
||||||
|
};
|
||||||
|
struct Round {
|
||||||
|
td::uint64 timestamp = 0;
|
||||||
|
std::vector<Producer> producers;
|
||||||
|
};
|
||||||
|
|
||||||
|
td::uint32 first_round;
|
||||||
|
std::vector<Round> rounds;
|
||||||
|
|
||||||
|
td::uint64 timestamp = 0;
|
||||||
|
PublicKeyHash self = PublicKeyHash::zero();
|
||||||
|
PublicKeyHash creator = PublicKeyHash::zero();
|
||||||
|
td::uint32 total_validators = 0;
|
||||||
|
ValidatorWeight total_weight = 0;
|
||||||
|
td::uint32 signatures = 0;
|
||||||
|
ValidatorWeight signatures_weight = 0;
|
||||||
|
td::uint32 approve_signatures = 0;
|
||||||
|
ValidatorWeight approve_signatures_weight = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validatorsession
|
} // namespace validatorsession
|
||||||
|
|
|
@ -260,6 +260,7 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
|
||||||
CHECK(!pending_reject_.count(block_id));
|
CHECK(!pending_reject_.count(block_id));
|
||||||
CHECK(!rejected_.count(block_id));
|
CHECK(!rejected_.count(block_id));
|
||||||
|
|
||||||
|
stats_set_candidate_status(cur_round_, src, ValidatorSessionStats::status_received);
|
||||||
auto v = virtual_state_->choose_blocks_to_approve(description(), local_idx());
|
auto v = virtual_state_->choose_blocks_to_approve(description(), local_idx());
|
||||||
for (auto &b : v) {
|
for (auto &b : v) {
|
||||||
if (b && SentBlock::get_block_id(b) == block_id) {
|
if (b && SentBlock::get_block_id(b) == block_id) {
|
||||||
|
@ -331,7 +332,8 @@ void ValidatorSessionImpl::process_query(PublicKeyHash src, td::BufferSlice data
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::candidate_decision_fail(td::uint32 round, ValidatorSessionCandidateId hash,
|
void ValidatorSessionImpl::candidate_decision_fail(td::uint32 round, ValidatorSessionCandidateId hash,
|
||||||
std::string result, td::BufferSlice proof) {
|
std::string result, td::uint32 src, td::BufferSlice proof) {
|
||||||
|
stats_set_candidate_status(round, description().get_source_id(src), ValidatorSessionStats::status_rejected);
|
||||||
if (round != cur_round_) {
|
if (round != cur_round_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +347,8 @@ void ValidatorSessionImpl::candidate_decision_fail(td::uint32 round, ValidatorSe
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::candidate_decision_ok(td::uint32 round, ValidatorSessionCandidateId hash, RootHash root_hash,
|
void ValidatorSessionImpl::candidate_decision_ok(td::uint32 round, ValidatorSessionCandidateId hash, RootHash root_hash,
|
||||||
FileHash file_hash, td::uint32 ok_from) {
|
FileHash file_hash, td::uint32 src, td::uint32 ok_from) {
|
||||||
|
stats_set_candidate_status(round, description().get_source_id(src), ValidatorSessionStats::status_approved);
|
||||||
if (round != cur_round_) {
|
if (round != cur_round_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -512,6 +515,7 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
|
||||||
|
|
||||||
auto P = td::PromiseCreator::lambda([round = cur_round_, hash = block_id, root_hash = block->get_root_hash(),
|
auto P = td::PromiseCreator::lambda([round = cur_round_, hash = block_id, root_hash = block->get_root_hash(),
|
||||||
file_hash = block->get_file_hash(), timer = std::move(timer),
|
file_hash = block->get_file_hash(), timer = std::move(timer),
|
||||||
|
src = block->get_src_idx(),
|
||||||
SelfId = actor_id(this)](td::Result<CandidateDecision> res) {
|
SelfId = actor_id(this)](td::Result<CandidateDecision> res) {
|
||||||
if (res.is_error()) {
|
if (res.is_error()) {
|
||||||
LOG(ERROR) << "round " << round << " failed to validate candidate " << hash << ": " << res.move_as_error();
|
LOG(ERROR) << "round " << round << " failed to validate candidate " << hash << ": " << res.move_as_error();
|
||||||
|
@ -521,10 +525,10 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
|
||||||
auto R = res.move_as_ok();
|
auto R = res.move_as_ok();
|
||||||
if (R.is_ok()) {
|
if (R.is_ok()) {
|
||||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::candidate_decision_ok, round, hash, root_hash,
|
td::actor::send_closure(SelfId, &ValidatorSessionImpl::candidate_decision_ok, round, hash, root_hash,
|
||||||
file_hash, R.ok_from());
|
file_hash, src, R.ok_from());
|
||||||
} else {
|
} else {
|
||||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::candidate_decision_fail, round, hash, R.reason(),
|
td::actor::send_closure(SelfId, &ValidatorSessionImpl::candidate_decision_fail, round, hash, R.reason(),
|
||||||
R.proof());
|
src, R.proof());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pending_approve_.insert(block_id);
|
pending_approve_.insert(block_id);
|
||||||
|
@ -770,41 +774,36 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = blocks_[0].find(SentBlock::get_block_id(block));
|
auto it = blocks_[0].find(SentBlock::get_block_id(block));
|
||||||
if (!block) {
|
bool have_block = (bool)block;
|
||||||
|
if (!have_block) {
|
||||||
callback_->on_block_skipped(cur_round_);
|
callback_->on_block_skipped(cur_round_);
|
||||||
} else {
|
} else {
|
||||||
ValidatorSessionStats stats;
|
cur_stats_.timestamp = (td::uint64)td::Clocks::system();
|
||||||
stats.round = cur_round_;
|
cur_stats_.total_validators = description().get_total_nodes();
|
||||||
stats.total_validators = description().get_total_nodes();
|
cur_stats_.total_weight = description().get_total_weight();
|
||||||
stats.total_weight = description().get_total_weight();
|
cur_stats_.signatures = (td::uint32)export_sigs.size();
|
||||||
stats.signatures = (td::uint32)export_sigs.size();
|
cur_stats_.signatures_weight = signatures_weight;
|
||||||
stats.signatures_weight = signatures_weight;
|
cur_stats_.approve_signatures = (td::uint32)export_approve_sigs.size();
|
||||||
stats.approve_signatures = (td::uint32)export_approve_sigs.size();
|
cur_stats_.approve_signatures_weight = approve_signatures_weight;
|
||||||
stats.approve_signatures_weight = approve_signatures_weight;
|
cur_stats_.creator = description().get_source_id(block->get_src_idx());
|
||||||
stats.creator = description().get_source_id(block->get_src_idx());
|
cur_stats_.self = description().get_source_id(local_idx());
|
||||||
stats.producers.resize(description().get_max_priority() + 1, PublicKeyHash::zero());
|
|
||||||
for (td::uint32 i = 0; i < description().get_total_nodes(); i++) {
|
|
||||||
td::int32 priority = description().get_node_priority(i, cur_round_);
|
|
||||||
if (priority >= 0) {
|
|
||||||
CHECK((size_t)priority < stats.producers.size());
|
|
||||||
stats.producers[priority] = description().get_source_id(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (!stats.producers.empty() && stats.producers.back().is_zero()) {
|
|
||||||
stats.producers.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it == blocks_[0].end()) {
|
if (it == blocks_[0].end()) {
|
||||||
callback_->on_block_committed(cur_round_, description().get_source_public_key(block->get_src_idx()),
|
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(),
|
block->get_root_hash(), block->get_file_hash(), td::BufferSlice(),
|
||||||
std::move(export_sigs), std::move(export_approve_sigs), std::move(stats));
|
std::move(export_sigs), std::move(export_approve_sigs), std::move(cur_stats_));
|
||||||
} else {
|
} else {
|
||||||
callback_->on_block_committed(cur_round_, description().get_source_public_key(block->get_src_idx()),
|
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(),
|
block->get_root_hash(), block->get_file_hash(), it->second->data_.clone(),
|
||||||
std::move(export_sigs), std::move(export_approve_sigs), std::move(stats));
|
std::move(export_sigs), std::move(export_approve_sigs), std::move(cur_stats_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur_round_++;
|
cur_round_++;
|
||||||
|
if (have_block) {
|
||||||
|
stats_init();
|
||||||
|
} else {
|
||||||
|
stats_add_round();
|
||||||
|
}
|
||||||
for (size_t i = 0; i < blocks_.size() - 1; i++) {
|
for (size_t i = 0; i < blocks_.size() - 1; i++) {
|
||||||
blocks_[i] = std::move(blocks_[i + 1]);
|
blocks_[i] = std::move(blocks_[i + 1]);
|
||||||
}
|
}
|
||||||
|
@ -895,6 +894,47 @@ void ValidatorSessionImpl::start_up() {
|
||||||
|
|
||||||
check_all();
|
check_all();
|
||||||
td::actor::send_closure(rldp_, &rldp::Rldp::add_id, description().get_source_adnl_id(local_idx()));
|
td::actor::send_closure(rldp_, &rldp::Rldp::add_id, description().get_source_adnl_id(local_idx()));
|
||||||
|
|
||||||
|
stats_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidatorSessionImpl::stats_init() {
|
||||||
|
cur_stats_ = ValidatorSessionStats();
|
||||||
|
cur_stats_.first_round = cur_round_;
|
||||||
|
stats_add_round();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidatorSessionImpl::stats_add_round() {
|
||||||
|
cur_stats_.rounds.emplace_back();
|
||||||
|
auto& round = cur_stats_.rounds.back();
|
||||||
|
round.timestamp = (td::uint64)td::Clocks::system();
|
||||||
|
round.producers.resize(description().get_max_priority() + 1);
|
||||||
|
for (td::uint32 i = 0; i < description().get_total_nodes(); i++) {
|
||||||
|
td::int32 priority = description().get_node_priority(i, cur_round_);
|
||||||
|
if (priority >= 0) {
|
||||||
|
CHECK((size_t)priority < round.producers.size());
|
||||||
|
round.producers[priority].id = description().get_source_id(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!round.producers.empty() && round.producers.back().id.is_zero()) {
|
||||||
|
round.producers.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidatorSessionImpl::stats_set_candidate_status(td::uint32 round, PublicKeyHash src, int status) {
|
||||||
|
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 it = std::find_if(stats_round.producers.begin(), stats_round.producers.end(),
|
||||||
|
[&](const ValidatorSessionStats::Producer& p) { return p.id == src; });
|
||||||
|
if (it == stats_round.producers.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (it->block_status == ValidatorSessionStats::status_none) {
|
||||||
|
it->block_timestamp = (td::uint64)td::Clocks::system();
|
||||||
|
}
|
||||||
|
it->block_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
td::actor::ActorOwn<ValidatorSession> ValidatorSession::create(
|
td::actor::ActorOwn<ValidatorSession> ValidatorSession::create(
|
||||||
|
|
|
@ -154,6 +154,11 @@ class ValidatorSessionImpl : public ValidatorSession {
|
||||||
bool catchain_started_ = false;
|
bool catchain_started_ = false;
|
||||||
bool allow_unsafe_self_blocks_resync_;
|
bool allow_unsafe_self_blocks_resync_;
|
||||||
|
|
||||||
|
ValidatorSessionStats cur_stats_;
|
||||||
|
void stats_init();
|
||||||
|
void stats_add_round();
|
||||||
|
void stats_set_candidate_status(td::uint32 round, PublicKeyHash src, int status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
|
ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
|
||||||
std::vector<ValidatorSessionNode> nodes, std::unique_ptr<Callback> callback,
|
std::vector<ValidatorSessionNode> nodes, std::unique_ptr<Callback> callback,
|
||||||
|
@ -177,9 +182,9 @@ class ValidatorSessionImpl : public ValidatorSession {
|
||||||
void try_sign();
|
void try_sign();
|
||||||
|
|
||||||
void candidate_decision_fail(td::uint32 round, ValidatorSessionCandidateId hash, std::string result,
|
void candidate_decision_fail(td::uint32 round, ValidatorSessionCandidateId hash, std::string result,
|
||||||
td::BufferSlice proof);
|
td::uint32 src, td::BufferSlice proof);
|
||||||
void candidate_decision_ok(td::uint32 round, ValidatorSessionCandidateId hash, RootHash root_hash, FileHash file_hash,
|
void candidate_decision_ok(td::uint32 round, ValidatorSessionCandidateId hash, RootHash root_hash, FileHash file_hash,
|
||||||
td::uint32 ok_from);
|
td::uint32 src, td::uint32 ok_from);
|
||||||
void candidate_approved_signed(td::uint32 round, ValidatorSessionCandidateId hash, td::uint32 ok_from,
|
void candidate_approved_signed(td::uint32 round, ValidatorSessionCandidateId hash, td::uint32 ok_from,
|
||||||
td::BufferSlice signature);
|
td::BufferSlice signature);
|
||||||
|
|
||||||
|
|
|
@ -2523,14 +2523,22 @@ void ValidatorManagerImpl::log_validator_session_stats(BlockIdExt block_id,
|
||||||
if (fname.empty()) {
|
if (fname.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<td::Bits256> producers;
|
|
||||||
for (const PublicKeyHash& id : stats.producers) {
|
std::vector<tl_object_ptr<ton_api::validatorSession_statsRound>> rounds;
|
||||||
producers.push_back(id.bits256_value());
|
for (const auto& round : stats.rounds) {
|
||||||
|
std::vector<tl_object_ptr<ton_api::validatorSession_statsProducer>> producers;
|
||||||
|
for (const auto& producer : round.producers) {
|
||||||
|
producers.push_back(create_tl_object<ton_api::validatorSession_statsProducer>(
|
||||||
|
producer.id.bits256_value(), producer.block_status, producer.block_timestamp));
|
||||||
|
}
|
||||||
|
rounds.push_back(create_tl_object<ton_api::validatorSession_statsRound>(round.timestamp, std::move(producers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto obj = create_tl_object<ton_api::validatorSession_stats>(
|
auto obj = create_tl_object<ton_api::validatorSession_stats>(
|
||||||
create_tl_block_id_simple(block_id.id), stats.round, stats.total_validators, stats.total_weight,
|
create_tl_block_id_simple(block_id.id), stats.timestamp, stats.self.bits256_value(),
|
||||||
stats.signatures, stats.signatures_weight, stats.approve_signatures, stats.approve_signatures_weight,
|
stats.creator.bits256_value(), stats.total_validators, stats.total_weight, stats.signatures,
|
||||||
stats.creator.bits256_value(), std::move(producers));
|
stats.signatures_weight, stats.approve_signatures, stats.approve_signatures_weight, stats.first_round,
|
||||||
|
std::move(rounds));
|
||||||
std::string s = td::json_encode<std::string>(td::ToJson(*obj.get()), false);
|
std::string s = td::json_encode<std::string>(td::ToJson(*obj.get()), false);
|
||||||
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return c == '\n' || c == '\r'; }), s.end());
|
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return c == '\n' || c == '\r'; }), s.end());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue