1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-14 12:12:21 +00:00

Log validator session stats to file

This commit is contained in:
SpyCheese 2022-07-05 17:19:46 +03:00 committed by EmelyanenkoK
parent 17c561c4db
commit b3e6819f3f
17 changed files with 137 additions and 18 deletions

View file

@ -76,7 +76,8 @@ class TestNode : public td::actor::Actor {
void on_block_committed(td::uint32 round, ton::PublicKeyHash src,
ton::validatorsession::ValidatorSessionRootHash root_hash,
ton::validatorsession::ValidatorSessionFileHash file_hash, td::BufferSlice data,
std::vector<std::pair<ton::PublicKeyHash, td::BufferSlice>> signatures) override {
std::vector<std::pair<ton::PublicKeyHash, td::BufferSlice>> signatures,
ton::validatorsession::ValidatorSessionStats stats) override {
td::actor::send_closure(id_, &TestNode::on_block_committed, round, root_hash, std::move(data),
std::move(signatures));
}

View file

@ -721,3 +721,9 @@ http.server.host domains:(vector string) ip:int port:int adnl_id:adnl.id.short =
http.server.config dhs:(vector http.server.dnsEntry) local_hosts:(vector http.server.host) = http.server.Config;
---functions---
---types---
validatorSession.stats id:tonNode.blockId round_id:int total_validators:int total_weight:long signatures:int
signatures_weight:long approve_signatures:int approve_signatures_weight:long
creator:int256 producers:(vector int256) = validatorSession.Stats;

Binary file not shown.

View file

@ -1338,6 +1338,9 @@ td::Status ValidatorEngine::load_global_config() {
if (truncate_seqno_ > 0) {
validator_options_.write().truncate_db(truncate_seqno_);
}
if (!session_logs_file_.empty()) {
validator_options_.write().set_session_logs_file(session_logs_file_);
}
std::vector<ton::BlockIdExt> h;
for (auto &x : conf.validator_->hardforks_) {
@ -3466,7 +3469,11 @@ int main(int argc, char *argv[]) {
#endif
td::set_signal_handler(td::SignalType::HangUp, force_rotate_logs).ensure();
});
std::string session_logs_file;
p.add_option('l', "logname", "log to file", [&](td::Slice fname) {
if (session_logs_file.empty()) {
session_logs_file = fname.str() + ".session-stats";
}
logger_ = td::TsFileLog::create(fname.str()).move_as_ok();
td::log_interface = logger_.get();
});
@ -3503,6 +3510,9 @@ int main(int argc, char *argv[]) {
auto v = td::to_integer<ton::BlockSeqno>(fname);
acts.push_back([&x, v]() { td::actor::send_closure(x, &ValidatorEngine::set_truncate_seqno, v); });
});
p.add_option('\0', "session-logs", "file for validator session stats (default: {logname}.session-stats)",
[&](td::Slice fname) { session_logs_file = fname.str(); });
acts.push_back([&]() { td::actor::send_closure(x, &ValidatorEngine::set_session_logs_file, session_logs_file); });
p.add_checked_option(
'U', "unsafe-catchain-restore", "use SLOW and DANGEROUS catchain recover method", [&](td::Slice id) {
TRY_RESULT(seq, td::to_integer_safe<ton::CatchainSeqno>(id));

View file

@ -201,6 +201,7 @@ class ValidatorEngine : public td::actor::Actor {
bool started_keyring_ = false;
bool started_ = false;
ton::BlockSeqno truncate_seqno_{0};
std::string session_logs_file_;
std::set<ton::CatchainSeqno> unsafe_catchains_;
std::map<ton::BlockSeqno, std::pair<ton::CatchainSeqno, td::uint32>> unsafe_catchain_rotations_;
@ -243,6 +244,9 @@ class ValidatorEngine : public td::actor::Actor {
void set_truncate_seqno(ton::BlockSeqno seqno) {
truncate_seqno_ = seqno;
}
void set_session_logs_file(std::string f) {
session_logs_file_ = std::move(f);
}
void add_ip(td::IPAddress addr) {
addrs_.push_back(addr);
}
@ -250,7 +254,6 @@ class ValidatorEngine : public td::actor::Actor {
keys_[key.compute_short_id()] = key;
}
void start_up() override;
void got_result();
ValidatorEngine() {
}

View file

@ -63,6 +63,19 @@ struct ValidatorSessionNode {
ValidatorWeight weight;
};
struct ValidatorSessionStats {
td::uint32 round;
td::uint32 total_validators;
ValidatorWeight total_weight;
td::uint32 signatures;
ValidatorWeight signatures_weight;
td::uint32 approve_signatures;
ValidatorWeight approve_signatures_weight;
PublicKeyHash creator;
std::vector<PublicKeyHash> producers;
};
} // namespace validatorsession
} // namespace ton

View file

@ -746,36 +746,63 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) {
CHECK(approve_sigs);
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> export_sigs;
ValidatorWeight signatures_weight = 0;
CHECK(sigs->size() == description().get_total_nodes());
for (td::uint32 i = 0; i < description().get_total_nodes(); i++) {
auto sig = sigs->at(i);
if (sig) {
CHECK(description().is_persistent(sig));
export_sigs.emplace_back(description().get_source_id(i), sig->value().clone());
signatures_weight += description().get_node_weight(i);
}
}
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> export_approve_sigs;
ValidatorWeight approve_signatures_weight = 0;
CHECK(approve_sigs->size() == description().get_total_nodes());
for (td::uint32 i = 0; i < description().get_total_nodes(); i++) {
auto sig = approve_sigs->at(i);
if (sig) {
CHECK(description().is_persistent(sig));
export_approve_sigs.emplace_back(description().get_source_id(i), sig->value().clone());
approve_signatures_weight += description().get_node_weight(i);
}
}
auto it = blocks_[0].find(SentBlock::get_block_id(block));
if (!block) {
callback_->on_block_skipped(cur_round_);
} else if (it == blocks_[0].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));
} 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));
ValidatorSessionStats stats;
stats.round = cur_round_;
stats.total_validators = description().get_total_nodes();
stats.total_weight = description().get_total_weight();
stats.signatures = (td::uint32)export_sigs.size();
stats.signatures_weight = signatures_weight;
stats.approve_signatures = (td::uint32)export_approve_sigs.size();
stats.approve_signatures_weight = approve_signatures_weight;
stats.creator = description().get_source_id(block->get_src_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()) {
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));
} 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));
}
}
cur_round_++;
for (size_t i = 0; i < blocks_.size() - 1; i++) {

View file

@ -79,7 +79,8 @@ class ValidatorSession : public td::actor::Actor {
virtual void on_block_committed(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash,
ValidatorSessionFileHash file_hash, td::BufferSlice data,
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> signatures,
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> approve_signatures) = 0;
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> approve_signatures,
ValidatorSessionStats stats) = 0;
virtual void on_block_skipped(td::uint32 round) = 0;
virtual void get_approved_candidate(PublicKey source, ValidatorSessionRootHash root_hash,
ValidatorSessionFileHash file_hash,

View file

@ -28,6 +28,7 @@
#include "validator/validator.h"
#include "liteserver.h"
#include "crypto/vm/db/DynamicBagOfCellsDb.h"
#include "validator-session/validator-session-types.h"
namespace ton {
@ -166,6 +167,8 @@ class ValidatorManager : public ValidatorManagerInterface {
virtual void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) = 0;
virtual void log_validator_session_stats(BlockIdExt block_id, validatorsession::ValidatorSessionStats stats) = 0;
static bool is_persistent_state(UnixTime ts, UnixTime prev_ts) {
return ts / (1 << 17) != prev_ts / (1 << 17);
}

View file

@ -364,6 +364,9 @@ class ValidatorManagerImpl : public ValidatorManager {
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override {
UNREACHABLE();
}
void log_validator_session_stats(BlockIdExt block_id, validatorsession::ValidatorSessionStats stats) override {
UNREACHABLE();
}
private:
PublicKeyHash local_id_;

View file

@ -423,6 +423,9 @@ class ValidatorManagerImpl : public ValidatorManager {
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override {
UNREACHABLE();
}
void log_validator_session_stats(BlockIdExt block_id, validatorsession::ValidatorSessionStats stats) override {
UNREACHABLE();
}
private:
td::Ref<ValidatorManagerOptions> opts_;

View file

@ -26,6 +26,7 @@
#include "fabric.h"
#include "manager.h"
#include "validate-broadcast.hpp"
#include "ton/ton-tl.hpp"
#include "ton/ton-io.hpp"
#include "state-serializer.hpp"
#include "get-next-key-blocks.h"
@ -33,14 +34,19 @@
#include "auto/tl/lite_api.h"
#include "tl-utils/lite-utils.hpp"
#include "auto/tl/ton_api_json.h"
#include "tl/tl_json.h"
#include "td/utils/Random.h"
#include "td/utils/port/path.h"
#include "td/utils/JsonBuilder.h"
#include "common/delay.h"
#include "validator/stats-merger.h"
#include <fstream>
namespace ton {
namespace validator {
@ -2511,6 +2517,31 @@ void ValidatorManagerImpl::wait_shard_client_state(BlockSeqno seqno, td::Timesta
shard_client_waiters_[seqno].waiting_.emplace_back(timeout, 0, std::move(promise));
}
void ValidatorManagerImpl::log_validator_session_stats(BlockIdExt block_id,
validatorsession::ValidatorSessionStats stats) {
std::string fname = opts_->get_session_logs_file();
if (fname.empty()) {
return;
}
std::vector<td::Bits256> producers;
for (const PublicKeyHash& id : stats.producers) {
producers.push_back(id.bits256_value());
}
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,
stats.signatures, stats.signatures_weight, stats.approve_signatures, stats.approve_signatures_weight,
stats.creator.bits256_value(), std::move(producers));
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());
std::ofstream file;
file.open(fname, std::ios_base::app);
file << s << "\n";
file.close();
LOG(INFO) << "Writing validator session stats for " << block_id.id;
}
td::actor::ActorOwn<ValidatorManagerInterface> ValidatorManagerFactory::create(
td::Ref<ValidatorManagerOptions> opts, std::string db_root, td::actor::ActorId<keyring::Keyring> keyring,
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,

View file

@ -530,6 +530,8 @@ class ValidatorManagerImpl : public ValidatorManager {
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override;
void log_validator_session_stats(BlockIdExt block_id, validatorsession::ValidatorSessionStats stats) override;
private:
td::Timestamp resend_shard_blocks_at_;
td::Timestamp check_waiters_at_;

View file

@ -85,6 +85,7 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s
RootHash root_hash, FileHash file_hash,
std::vector<BlockSignature> signatures,
std::vector<BlockSignature> approve_signatures,
validatorsession::ValidatorSessionStats stats,
td::Promise<td::Unit> promise) {
if (round_id >= last_known_round_id_) {
last_known_round_id_ = round_id + 1;
@ -95,11 +96,12 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s
validator_set_->check_approve_signatures(root_hash, file_hash, approve_sig_set).ensure();
if (!started_) {
postoned_accept_.push_back(PostponedAccept{root_hash, file_hash, std::move(block_data), std::move(sig_set),
std::move(approve_sig_set), std::move(promise)});
postponed_accept_.push_back(PostponedAccept{root_hash, file_hash, std::move(block_data), std::move(sig_set),
std::move(approve_sig_set), std::move(stats), std::move(promise)});
return;
}
auto next_block_id = create_next_block_id(root_hash, file_hash);
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<BlockData>{};
@ -198,7 +200,8 @@ std::unique_ptr<validatorsession::ValidatorSession::Callback> ValidatorGroup::ma
void on_block_committed(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash,
validatorsession::ValidatorSessionFileHash file_hash, td::BufferSlice data,
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> signatures,
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> approve_signatures) override {
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> approve_signatures,
validatorsession::ValidatorSessionStats stats) override {
std::vector<BlockSignature> sigs;
for (auto &sig : signatures) {
sigs.emplace_back(BlockSignature{sig.first.bits256_value(), std::move(sig.second)});
@ -210,7 +213,7 @@ std::unique_ptr<validatorsession::ValidatorSession::Callback> ValidatorGroup::ma
auto P = td::PromiseCreator::lambda([](td::Result<td::Unit>) {});
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(P));
std::move(stats), std::move(P));
}
void on_block_skipped(td::uint32 round) override {
td::actor::send_closure(id_, &ValidatorGroup::skip_round, round);
@ -281,8 +284,10 @@ void ValidatorGroup::start(std::vector<BlockIdExt> prev, BlockIdExt min_masterch
td::actor::send_closure(session_, &validatorsession::ValidatorSession::start);
}
for (auto &p : postoned_accept_) {
for (auto &p : postponed_accept_) {
auto next_block_id = create_next_block_id(p.root_hash, p.file_hash);
td::actor::send_closure(manager_, &ValidatorManager::log_validator_session_stats, next_block_id,
std::move(p.stats));
auto block =
p.block.size() > 0 ? create_block(next_block_id, std::move(p.block)).move_as_ok() : td::Ref<BlockData>{};
@ -290,7 +295,7 @@ void ValidatorGroup::start(std::vector<BlockIdExt> prev, BlockIdExt min_masterch
std::move(p.approve_sigs), std::move(p.promise));
prev_block_ids_ = std::vector<BlockIdExt>{next_block_id};
}
postoned_accept_.clear();
postponed_accept_.clear();
}
void ValidatorGroup::destroy() {

View file

@ -36,7 +36,8 @@ class ValidatorGroup : public td::actor::Actor {
void validate_block_candidate(td::uint32 round_id, BlockCandidate block, td::Promise<td::uint32> promise);
void accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block, RootHash root_hash,
FileHash file_hash, std::vector<BlockSignature> signatures,
std::vector<BlockSignature> approve_signatures, td::Promise<td::Unit> promise);
std::vector<BlockSignature> approve_signatures,
validatorsession::ValidatorSessionStats stats, td::Promise<td::Unit> promise);
void skip_round(td::uint32 round);
void retry_accept_block_query(BlockIdExt block_id, td::Ref<BlockData> block, std::vector<BlockIdExt> prev,
td::Ref<BlockSignatureSet> sigs, td::Ref<BlockSignatureSet> approve_sigs,
@ -85,10 +86,11 @@ class ValidatorGroup : public td::actor::Actor {
td::BufferSlice block;
td::Ref<BlockSignatureSet> sigs;
td::Ref<BlockSignatureSet> approve_sigs;
validatorsession::ValidatorSessionStats stats;
td::Promise<td::Unit> promise;
};
std::list<PostponedAccept> postoned_accept_;
std::list<PostponedAccept> postponed_accept_;
ShardIdFull shard_;
PublicKeyHash local_id_;

View file

@ -111,6 +111,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
BlockSeqno sync_upto() const override {
return sync_upto_;
}
std::string get_session_logs_file() const override {
return session_logs_file_;
}
void set_zero_block_id(BlockIdExt block_id) override {
zero_block_id_ = block_id;
@ -161,6 +164,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
void set_sync_upto(BlockSeqno seqno) override {
sync_upto_ = seqno;
}
void set_session_logs_file(std::string f) override {
session_logs_file_ = std::move(f);
}
ValidatorManagerOptionsImpl *make_copy() const override {
return new ValidatorManagerOptionsImpl(*this);
@ -202,6 +208,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
std::map<CatchainSeqno, std::pair<BlockSeqno, td::uint32>> unsafe_catchain_rotates_;
BlockSeqno truncate_{0};
BlockSeqno sync_upto_{0};
std::string session_logs_file_;
};
} // namespace validator

View file

@ -73,6 +73,7 @@ struct ValidatorManagerOptions : public td::CntObject {
virtual bool need_db_truncate() const = 0;
virtual BlockSeqno get_truncate_seqno() const = 0;
virtual BlockSeqno sync_upto() const = 0;
virtual std::string get_session_logs_file() const = 0;
virtual void set_zero_block_id(BlockIdExt block_id) = 0;
virtual void set_init_block_id(BlockIdExt block_id) = 0;
@ -91,6 +92,7 @@ struct ValidatorManagerOptions : public td::CntObject {
virtual void add_unsafe_catchain_rotate(BlockSeqno seqno, CatchainSeqno cc_seqno, td::uint32 value) = 0;
virtual void truncate_db(BlockSeqno seqno) = 0;
virtual void set_sync_upto(BlockSeqno seqno) = 0;
virtual void set_session_logs_file(std::string f) = 0;
static td::Ref<ValidatorManagerOptions> create(
BlockIdExt zero_block_id, BlockIdExt init_block_id,