mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add more info to session stats (#973)
* Improve validator session stats * Improve validator session stats Add got_submit_at, collation_cached, validation_cached. Fix stats cleanup. * Fix setting timestamp for cached blocks * Add serialize/deserialize time, serialized size to validator session stats, fix setting is_accepted --------- Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
d2b012c883
commit
9a543c6b28
10 changed files with 309 additions and 68 deletions
|
@ -752,7 +752,14 @@ http.server.config dhs:(vector http.server.dnsEntry) local_hosts:(vector http.se
|
||||||
|
|
||||||
---types---
|
---types---
|
||||||
|
|
||||||
validatorSession.statsProducer id:int256 candidate_id:int256 block_status:int block_timestamp:long comment:string = validatorSession.StatsProducer;
|
validatorSession.statsProducer id:int256 candidate_id:int256 block_status:int comment:string
|
||||||
|
block_timestamp:double is_accepted:Bool is_ours:Bool got_submit_at:double
|
||||||
|
collation_time:double collated_at:double collation_cached:Bool
|
||||||
|
validation_time:double validated_at:double validation_cached:Bool
|
||||||
|
gen_utime:double
|
||||||
|
approved_weight:long approved_33pct_at:double approved_66pct_at:double
|
||||||
|
signed_weight:long signed_33pct_at:double signed_66pct_at:double
|
||||||
|
serialize_time:double deserialize_time:double serialized_size:int = validatorSession.StatsProducer;
|
||||||
|
|
||||||
validatorSession.statsRound timestamp:long producers:(vector validatorSession.statsProducer) = validatorSession.StatsRound;
|
validatorSession.statsRound timestamp:long producers:(vector validatorSession.statsProducer) = validatorSession.StatsRound;
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -14,7 +14,6 @@
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
|
||||||
#include "candidate-serializer.h"
|
#include "candidate-serializer.h"
|
||||||
#include "tl-utils/tl-utils.hpp"
|
#include "tl-utils/tl-utils.hpp"
|
||||||
#include "vm/boc.h"
|
#include "vm/boc.h"
|
||||||
|
|
|
@ -76,8 +76,57 @@ struct ValidatorSessionStats {
|
||||||
PublicKeyHash id = PublicKeyHash::zero();
|
PublicKeyHash id = PublicKeyHash::zero();
|
||||||
ValidatorSessionCandidateId candidate_id = ValidatorSessionCandidateId::zero();
|
ValidatorSessionCandidateId candidate_id = ValidatorSessionCandidateId::zero();
|
||||||
int block_status = status_none;
|
int block_status = status_none;
|
||||||
td::uint64 block_timestamp = 0;
|
double block_timestamp = -1.0;
|
||||||
std::string comment;
|
std::string comment;
|
||||||
|
|
||||||
|
bool is_accepted = false;
|
||||||
|
bool is_ours = false;
|
||||||
|
double got_submit_at = -1.0;
|
||||||
|
double collation_time = -1.0;
|
||||||
|
double validation_time = -1.0;
|
||||||
|
double collated_at = -1.0;
|
||||||
|
double validated_at = -1.0;
|
||||||
|
bool collation_cached = false;
|
||||||
|
bool validation_cached = false;
|
||||||
|
double gen_utime = -1.0;
|
||||||
|
|
||||||
|
std::vector<bool> approvers, signers;
|
||||||
|
ValidatorWeight approved_weight = 0;
|
||||||
|
ValidatorWeight signed_weight = 0;
|
||||||
|
double approved_33pct_at = -1.0;
|
||||||
|
double approved_66pct_at = -1.0;
|
||||||
|
double signed_33pct_at = -1.0;
|
||||||
|
double signed_66pct_at = -1.0;
|
||||||
|
|
||||||
|
double serialize_time = -1.0;
|
||||||
|
double deserialize_time = -1.0;
|
||||||
|
td::int32 serialized_size = -1;
|
||||||
|
|
||||||
|
void set_approved_by(td::uint32 id, ValidatorWeight weight, ValidatorWeight total_weight) {
|
||||||
|
if (!approvers.at(id)) {
|
||||||
|
approvers.at(id) = true;
|
||||||
|
approved_weight += weight;
|
||||||
|
if (approved_33pct_at <= 0.0 && approved_weight >= total_weight / 3 + 1) {
|
||||||
|
approved_33pct_at = td::Clocks::system();
|
||||||
|
}
|
||||||
|
if (approved_66pct_at <= 0.0 && approved_weight >= (total_weight * 2) / 3 + 1) {
|
||||||
|
approved_66pct_at = td::Clocks::system();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_signed_by(td::uint32 id, ValidatorWeight weight, ValidatorWeight total_weight) {
|
||||||
|
if (!signers.at(id)) {
|
||||||
|
signers.at(id) = true;
|
||||||
|
signed_weight += weight;
|
||||||
|
if (signed_33pct_at <= 0.0 && signed_weight >= total_weight / 3 + 1) {
|
||||||
|
signed_33pct_at = td::Clocks::system();
|
||||||
|
}
|
||||||
|
if (signed_66pct_at <= 0.0 && signed_weight >= (total_weight * 2) / 3 + 1) {
|
||||||
|
signed_66pct_at = td::Clocks::system();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct Round {
|
struct Round {
|
||||||
td::uint64 timestamp = 0;
|
td::uint64 timestamp = 0;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "td/utils/Random.h"
|
#include "td/utils/Random.h"
|
||||||
#include "td/utils/crypto.h"
|
#include "td/utils/crypto.h"
|
||||||
#include "candidate-serializer.h"
|
#include "candidate-serializer.h"
|
||||||
|
#include "td/utils/overloaded.h"
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ void ValidatorSessionImpl::process_blocks(std::vector<catchain::CatChainBlock *>
|
||||||
|
|
||||||
for (auto &msg : msgs) {
|
for (auto &msg : msgs) {
|
||||||
VLOG(VALIDATOR_SESSION_INFO) << this << ": applying action: " << msg.get();
|
VLOG(VALIDATOR_SESSION_INFO) << this << ": applying action: " << msg.get();
|
||||||
|
stats_process_action(local_idx(), *msg);
|
||||||
real_state_ = ValidatorSessionState::action(description(), real_state_, local_idx(), att, msg.get());
|
real_state_ = ValidatorSessionState::action(description(), real_state_, local_idx(), att, msg.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +169,7 @@ void ValidatorSessionImpl::preprocess_block(catchain::CatChainBlock *block) {
|
||||||
for (auto &msg : B->actions_) {
|
for (auto &msg : B->actions_) {
|
||||||
VLOG(VALIDATOR_SESSION_INFO) << this << "[node " << description().get_source_id(block->source()) << "][block "
|
VLOG(VALIDATOR_SESSION_INFO) << this << "[node " << description().get_source_id(block->source()) << "][block "
|
||||||
<< block->hash() << "]: applying action " << msg.get();
|
<< block->hash() << "]: applying action " << msg.get();
|
||||||
|
stats_process_action(block->source(), *msg);
|
||||||
state = ValidatorSessionState::action(description(), state, block->source(), att, msg.get());
|
state = ValidatorSessionState::action(description(), state, block->source(), att, msg.get());
|
||||||
}
|
}
|
||||||
state = ValidatorSessionState::make_all(description(), state, block->source(), att);
|
state = ValidatorSessionState::make_all(description(), state, block->source(), att);
|
||||||
|
@ -222,9 +225,11 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
|
||||||
// Note: src is not necessarily equal to the sender of this message:
|
// Note: src is not necessarily equal to the sender of this message:
|
||||||
// If requested using get_broadcast_p2p, src is the creator of the block, sender possibly is some other node.
|
// If requested using get_broadcast_p2p, src is the creator of the block, sender possibly is some other node.
|
||||||
auto src_idx = description().get_source_idx(src);
|
auto src_idx = description().get_source_idx(src);
|
||||||
|
td::Timer deserialize_timer;
|
||||||
auto R =
|
auto R =
|
||||||
deserialize_candidate(data, compress_block_candidates_,
|
deserialize_candidate(data, compress_block_candidates_,
|
||||||
description().opts().max_block_size + description().opts().max_collated_data_size + 1024);
|
description().opts().max_block_size + description().opts().max_collated_data_size + 1024);
|
||||||
|
double deserialize_time = deserialize_timer.elapsed();
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
VLOG(VALIDATOR_SESSION_WARNING) << this << "[node " << src << "][broadcast " << sha256_bits256(data.as_slice())
|
VLOG(VALIDATOR_SESSION_WARNING) << this << "[node " << src << "][broadcast " << sha256_bits256(data.as_slice())
|
||||||
<< "]: failed to parse: " << R.move_as_error();
|
<< "]: failed to parse: " << R.move_as_error();
|
||||||
|
@ -255,6 +260,18 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto stat = stats_get_candidate_stat(block_round, src, block_id);
|
||||||
|
if (stat) {
|
||||||
|
if (stat->block_status == ValidatorSessionStats::status_none) {
|
||||||
|
stat->block_status = ValidatorSessionStats::status_received;
|
||||||
|
}
|
||||||
|
if (stat->block_timestamp <= 0.0) {
|
||||||
|
stat->block_timestamp = td::Clocks::system();
|
||||||
|
}
|
||||||
|
stat->deserialize_time = deserialize_time;
|
||||||
|
stat->serialized_size = data.size();
|
||||||
|
}
|
||||||
|
|
||||||
if ((td::int32)block_round < (td::int32)cur_round_ - MAX_PAST_ROUND_BLOCK ||
|
if ((td::int32)block_round < (td::int32)cur_round_ - MAX_PAST_ROUND_BLOCK ||
|
||||||
block_round >= cur_round_ + MAX_FUTURE_ROUND_BLOCK) {
|
block_round >= cur_round_ + MAX_FUTURE_ROUND_BLOCK) {
|
||||||
VLOG(VALIDATOR_SESSION_NOTICE) << this << "[node " << src << "][broadcast " << block_id
|
VLOG(VALIDATOR_SESSION_NOTICE) << this << "[node " << src << "][broadcast " << block_id
|
||||||
|
@ -291,7 +308,6 @@ 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, block_id, 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) {
|
||||||
|
@ -363,9 +379,16 @@ 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::uint32 src, td::BufferSlice proof) {
|
std::string result, td::uint32 src, td::BufferSlice proof,
|
||||||
stats_set_candidate_status(round, description().get_source_id(src), hash, ValidatorSessionStats::status_rejected,
|
double validation_time, bool validation_cached) {
|
||||||
result);
|
auto stat = stats_get_candidate_stat(round, description().get_source_id(src), hash);
|
||||||
|
if (stat) {
|
||||||
|
stat->block_status = ValidatorSessionStats::status_rejected;
|
||||||
|
stat->comment = result;
|
||||||
|
stat->validation_time = validation_time;
|
||||||
|
stat->validated_at = td::Clocks::system();
|
||||||
|
stat->validation_cached = validation_cached;
|
||||||
|
}
|
||||||
if (round != cur_round_) {
|
if (round != cur_round_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -379,9 +402,17 @@ 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 src, td::uint32 ok_from) {
|
FileHash file_hash, td::uint32 src, td::uint32 ok_from,
|
||||||
stats_set_candidate_status(round, description().get_source_id(src), hash, ValidatorSessionStats::status_approved,
|
double validation_time, bool validation_cached) {
|
||||||
PSTRING() << "ts=" << ok_from);
|
auto stat = stats_get_candidate_stat(round, description().get_source_id(src), hash);
|
||||||
|
if (stat) {
|
||||||
|
stat->block_status = ValidatorSessionStats::status_approved;
|
||||||
|
stat->comment = PSTRING() << "ts=" << ok_from;
|
||||||
|
stat->validation_time = validation_time;
|
||||||
|
stat->gen_utime = (double)ok_from;
|
||||||
|
stat->validated_at = td::Clocks::system();
|
||||||
|
stat->validation_cached = validation_cached;
|
||||||
|
}
|
||||||
if (round != cur_round_) {
|
if (round != cur_round_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -418,10 +449,8 @@ void ValidatorSessionImpl::candidate_approved_signed(td::uint32 round, Validator
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::generated_block(td::uint32 round, ValidatorSessionCandidateId root_hash,
|
void ValidatorSessionImpl::generated_block(td::uint32 round, ValidatorSessionCandidateId root_hash,
|
||||||
td::BufferSlice data, td::BufferSlice collated_data) {
|
td::BufferSlice data, td::BufferSlice collated_data, double collation_time,
|
||||||
if (round != cur_round_) {
|
bool collation_cached) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.size() > description().opts().max_block_size ||
|
if (data.size() > description().opts().max_block_size ||
|
||||||
collated_data.size() > description().opts().max_collated_data_size) {
|
collated_data.size() > description().opts().max_collated_data_size) {
|
||||||
LOG(ERROR) << this << ": generated candidate is too big. Dropping. size=" << data.size() << " "
|
LOG(ERROR) << this << ": generated candidate is too big. Dropping. size=" << data.size() << " "
|
||||||
|
@ -430,13 +459,27 @@ void ValidatorSessionImpl::generated_block(td::uint32 round, ValidatorSessionCan
|
||||||
}
|
}
|
||||||
auto file_hash = sha256_bits256(data.as_slice());
|
auto file_hash = sha256_bits256(data.as_slice());
|
||||||
auto collated_data_file_hash = sha256_bits256(collated_data.as_slice());
|
auto collated_data_file_hash = sha256_bits256(collated_data.as_slice());
|
||||||
|
auto block_id = description().candidate_id(local_idx(), root_hash, file_hash, collated_data_file_hash);
|
||||||
|
|
||||||
|
auto stat = stats_get_candidate_stat(round, local_id(), block_id);
|
||||||
|
if (stat) {
|
||||||
|
stat->block_status = ValidatorSessionStats::status_received;
|
||||||
|
stat->collation_time = collation_time;
|
||||||
|
stat->collated_at = td::Clocks::system();
|
||||||
|
stat->block_timestamp = td::Clocks::system();
|
||||||
|
stat->collation_cached = collation_cached;
|
||||||
|
}
|
||||||
|
if (round != cur_round_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::Timer serialize_timer;
|
||||||
auto b = create_tl_object<ton_api::validatorSession_candidate>(local_id().tl(), round, root_hash, std::move(data),
|
auto b = create_tl_object<ton_api::validatorSession_candidate>(local_id().tl(), round, root_hash, std::move(data),
|
||||||
std::move(collated_data));
|
std::move(collated_data));
|
||||||
|
|
||||||
auto B = serialize_candidate(b, compress_block_candidates_).move_as_ok();
|
auto B = serialize_candidate(b, compress_block_candidates_).move_as_ok();
|
||||||
|
if (stat) {
|
||||||
auto block_id = description().candidate_id(local_idx(), root_hash, file_hash, collated_data_file_hash);
|
stat->serialize_time = serialize_timer.elapsed();
|
||||||
|
stat->serialized_size = B.size();
|
||||||
|
}
|
||||||
|
|
||||||
td::actor::send_closure(catchain_, &catchain::CatChain::send_broadcast, std::move(B));
|
td::actor::send_closure(catchain_, &catchain::CatChain::send_broadcast, std::move(B));
|
||||||
|
|
||||||
|
@ -496,11 +539,11 @@ void ValidatorSessionImpl::check_generate_slot() {
|
||||||
td::PerfWarningTimer timer{"too long block generation", 1.0};
|
td::PerfWarningTimer timer{"too long block generation", 1.0};
|
||||||
|
|
||||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), print_id = print_id(), timer = std::move(timer),
|
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), print_id = print_id(), timer = std::move(timer),
|
||||||
round = cur_round_](td::Result<BlockCandidate> R) {
|
round = cur_round_](td::Result<GeneratedCandidate> R) {
|
||||||
if (R.is_ok()) {
|
if (R.is_ok()) {
|
||||||
auto c = R.move_as_ok();
|
auto c = std::move(R.ok_ref().candidate);
|
||||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::generated_block, round, c.id.root_hash,
|
td::actor::send_closure(SelfId, &ValidatorSessionImpl::generated_block, round, c.id.root_hash,
|
||||||
c.data.clone(), c.collated_data.clone());
|
c.data.clone(), c.collated_data.clone(), timer.elapsed(), R.ok().is_cached);
|
||||||
} else {
|
} else {
|
||||||
LOG(WARNING) << print_id << ": failed to generate block candidate: " << R.move_as_error();
|
LOG(WARNING) << print_id << ": failed to generate block candidate: " << R.move_as_error();
|
||||||
}
|
}
|
||||||
|
@ -550,6 +593,16 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
|
||||||
it->second->round_ = std::max<td::uint32>(it->second->round_, cur_round_);
|
it->second->round_ = std::max<td::uint32>(it->second->round_, cur_round_);
|
||||||
td::PerfWarningTimer timer{"too long block validation", 1.0};
|
td::PerfWarningTimer timer{"too long block validation", 1.0};
|
||||||
auto &B = it->second;
|
auto &B = it->second;
|
||||||
|
auto stat = stats_get_candidate_stat(B->round_, PublicKeyHash{B->src_});
|
||||||
|
if (stat) {
|
||||||
|
// Can happen if block is cached from previous round
|
||||||
|
if (stat->block_status == ValidatorSessionStats::status_none) {
|
||||||
|
stat->block_status = ValidatorSessionStats::status_received;
|
||||||
|
}
|
||||||
|
if (stat->block_timestamp <= 0.0) {
|
||||||
|
stat->block_timestamp = td::Clocks::system();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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),
|
||||||
|
@ -563,10 +616,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, src, R.ok_from());
|
file_hash, src, R.ok_from(), timer.elapsed(), R.is_cached());
|
||||||
} 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(),
|
||||||
src, R.proof());
|
src, R.proof(), timer.elapsed(), R.is_cached());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pending_approve_.insert(block_id);
|
pending_approve_.insert(block_id);
|
||||||
|
@ -824,22 +877,28 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) {
|
||||||
cur_stats_.approve_signatures = (td::uint32)export_approve_sigs.size();
|
cur_stats_.approve_signatures = (td::uint32)export_approve_sigs.size();
|
||||||
cur_stats_.approve_signatures_weight = approve_signatures_weight;
|
cur_stats_.approve_signatures_weight = approve_signatures_weight;
|
||||||
cur_stats_.creator = description().get_source_id(block->get_src_idx());
|
cur_stats_.creator = description().get_source_id(block->get_src_idx());
|
||||||
|
auto stat = stats_get_candidate_stat(cur_round_, cur_stats_.creator);
|
||||||
|
if (stat) {
|
||||||
|
stat->is_accepted = true;
|
||||||
|
}
|
||||||
|
auto stats = cur_stats_;
|
||||||
|
while (!stats.rounds.empty() && stats.rounds.size() + stats.first_round - 1 > cur_round_) {
|
||||||
|
stats.rounds.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
if (it == blocks_.end()) {
|
if (it == blocks_.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(cur_stats_));
|
std::move(export_sigs), std::move(export_approve_sigs), std::move(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(cur_stats_));
|
std::move(export_sigs), std::move(export_approve_sigs), std::move(stats));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur_round_++;
|
cur_round_++;
|
||||||
if (have_block) {
|
if (have_block) {
|
||||||
stats_init();
|
stats_init();
|
||||||
} else {
|
|
||||||
stats_add_round();
|
|
||||||
}
|
}
|
||||||
auto it2 = blocks_.begin();
|
auto it2 = blocks_.begin();
|
||||||
while (it2 != blocks_.end()) {
|
while (it2 != blocks_.end()) {
|
||||||
|
@ -997,13 +1056,35 @@ void ValidatorSessionImpl::start_up() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::stats_init() {
|
void ValidatorSessionImpl::stats_init() {
|
||||||
|
auto old_rounds = std::move(cur_stats_.rounds);
|
||||||
|
if (stats_inited_ && cur_stats_.first_round + old_rounds.size() > cur_round_) {
|
||||||
|
old_rounds.erase(old_rounds.begin(), old_rounds.end() - (cur_stats_.first_round + old_rounds.size() - cur_round_));
|
||||||
|
} else {
|
||||||
|
old_rounds.clear();
|
||||||
|
}
|
||||||
cur_stats_ = ValidatorSessionStats();
|
cur_stats_ = ValidatorSessionStats();
|
||||||
|
cur_stats_.rounds = std::move(old_rounds);
|
||||||
cur_stats_.first_round = cur_round_;
|
cur_stats_.first_round = cur_round_;
|
||||||
cur_stats_.session_id = unique_hash_;
|
cur_stats_.session_id = unique_hash_;
|
||||||
cur_stats_.total_validators = description().get_total_nodes();
|
cur_stats_.total_validators = description().get_total_nodes();
|
||||||
cur_stats_.total_weight = description().get_total_weight();
|
cur_stats_.total_weight = description().get_total_weight();
|
||||||
cur_stats_.self = description().get_source_id(local_idx());
|
cur_stats_.self = description().get_source_id(local_idx());
|
||||||
stats_add_round();
|
|
||||||
|
for (auto it = stats_pending_approve_.begin(); it != stats_pending_approve_.end(); ) {
|
||||||
|
if (it->first.first < cur_round_) {
|
||||||
|
it = stats_pending_approve_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto it = stats_pending_sign_.begin(); it != stats_pending_sign_.end(); ) {
|
||||||
|
if (it->first.first < cur_round_) {
|
||||||
|
it = stats_pending_sign_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stats_inited_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::stats_add_round() {
|
void ValidatorSessionImpl::stats_add_round() {
|
||||||
|
@ -1016,6 +1097,9 @@ void ValidatorSessionImpl::stats_add_round() {
|
||||||
if (priority >= 0) {
|
if (priority >= 0) {
|
||||||
CHECK((size_t)priority < round.producers.size());
|
CHECK((size_t)priority < round.producers.size());
|
||||||
round.producers[priority].id = description().get_source_id(i);
|
round.producers[priority].id = description().get_source_id(i);
|
||||||
|
round.producers[priority].is_ours = (local_idx() == i);
|
||||||
|
round.producers[priority].approvers.resize(description().get_total_nodes(), false);
|
||||||
|
round.producers[priority].signers.resize(description().get_total_nodes(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!round.producers.empty() && round.producers.back().id.is_zero()) {
|
while (!round.producers.empty() && round.producers.back().id.is_zero()) {
|
||||||
|
@ -1023,26 +1107,93 @@ void ValidatorSessionImpl::stats_add_round() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorSessionImpl::stats_set_candidate_status(td::uint32 round, PublicKeyHash src,
|
ValidatorSessionStats::Producer *ValidatorSessionImpl::stats_get_candidate_stat(
|
||||||
ValidatorSessionCandidateId candidate_id, int status,
|
td::uint32 round, PublicKeyHash src, ValidatorSessionCandidateId candidate_id) {
|
||||||
std::string comment) {
|
if (round < cur_stats_.first_round || round > cur_round_ + 5) {
|
||||||
if (round < cur_stats_.first_round || round - cur_stats_.first_round >= cur_stats_.rounds.size()) {
|
return nullptr;
|
||||||
return;
|
}
|
||||||
|
while (round - cur_stats_.first_round >= cur_stats_.rounds.size()) {
|
||||||
|
stats_add_round();
|
||||||
}
|
}
|
||||||
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(),
|
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()) {
|
if (it == stats_round.producers.end()) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
it->candidate_id = candidate_id;
|
if (!candidate_id.is_zero()) {
|
||||||
if (it->block_status == ValidatorSessionStats::status_none) {
|
it->candidate_id = candidate_id;
|
||||||
it->block_timestamp = (td::uint64)td::Clocks::system();
|
|
||||||
}
|
}
|
||||||
it->block_status = status;
|
auto it2 = stats_pending_approve_.find({round, it->candidate_id});
|
||||||
if (!comment.empty()) {
|
if (it2 != stats_pending_approve_.end()) {
|
||||||
it->comment = std::move(comment);
|
for (td::uint32 node_id : it2->second) {
|
||||||
|
it->set_approved_by(node_id, description().get_node_weight(node_id), description().get_total_weight());
|
||||||
|
}
|
||||||
|
stats_pending_approve_.erase(it2);
|
||||||
}
|
}
|
||||||
|
it2 = stats_pending_sign_.find({round, it->candidate_id});
|
||||||
|
if (it2 != stats_pending_sign_.end()) {
|
||||||
|
for (td::uint32 node_id : it2->second) {
|
||||||
|
it->set_signed_by(node_id, description().get_node_weight(node_id), description().get_total_weight());
|
||||||
|
}
|
||||||
|
stats_pending_sign_.erase(it2);
|
||||||
|
}
|
||||||
|
return &*it;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidatorSessionStats::Producer *ValidatorSessionImpl::stats_get_candidate_stat_by_id(
|
||||||
|
td::uint32 round, ValidatorSessionCandidateId candidate_id) {
|
||||||
|
if (round < cur_stats_.first_round || round > cur_round_ + 5) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
while (round - cur_stats_.first_round >= cur_stats_.rounds.size()) {
|
||||||
|
stats_add_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.candidate_id == candidate_id; });
|
||||||
|
if (it == stats_round.producers.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &*it;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidatorSessionImpl::stats_process_action(td::uint32 node_id, ton_api::validatorSession_round_Message &action) {
|
||||||
|
ton_api::downcast_call(action, td::overloaded(
|
||||||
|
[&](const ton_api::validatorSession_message_submittedBlock &obj) {
|
||||||
|
auto candidate_id = description().candidate_id(
|
||||||
|
node_id, obj.root_hash_, obj.file_hash_, obj.collated_data_file_hash_);
|
||||||
|
auto stat = stats_get_candidate_stat(
|
||||||
|
obj.round_, description().get_source_id(node_id), candidate_id);
|
||||||
|
if (stat && stat->got_submit_at <= 0.0) {
|
||||||
|
stat->got_submit_at = td::Clocks::system();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const ton_api::validatorSession_message_approvedBlock &obj) {
|
||||||
|
if (obj.candidate_ == skip_round_candidate_id()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto stat = stats_get_candidate_stat_by_id(obj.round_, obj.candidate_);
|
||||||
|
if (stat) {
|
||||||
|
stat->set_approved_by(node_id, description().get_node_weight(node_id),
|
||||||
|
description().get_total_weight());
|
||||||
|
} else {
|
||||||
|
stats_pending_approve_[{obj.round_, obj.candidate_}].push_back(node_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const ton_api::validatorSession_message_commit &obj) {
|
||||||
|
if (obj.candidate_ == skip_round_candidate_id()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto stat = stats_get_candidate_stat_by_id(obj.round_, obj.candidate_);
|
||||||
|
if (stat) {
|
||||||
|
stat->set_signed_by(node_id, description().get_node_weight(node_id),
|
||||||
|
description().get_total_weight());
|
||||||
|
} else {
|
||||||
|
stats_pending_sign_[{obj.round_, obj.candidate_}].push_back(node_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const auto &) {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
td::actor::ActorOwn<ValidatorSession> ValidatorSession::create(
|
td::actor::ActorOwn<ValidatorSession> ValidatorSession::create(
|
||||||
|
|
|
@ -56,6 +56,12 @@ class ValidatorSession : public td::actor::Actor {
|
||||||
td::BufferSlice proof() const {
|
td::BufferSlice proof() const {
|
||||||
return proof_.clone();
|
return proof_.clone();
|
||||||
}
|
}
|
||||||
|
bool is_cached() const {
|
||||||
|
return is_cached_;
|
||||||
|
}
|
||||||
|
void set_is_cached(bool value = true) {
|
||||||
|
is_cached_ = value;
|
||||||
|
}
|
||||||
CandidateDecision(td::uint32 ok_from) {
|
CandidateDecision(td::uint32 ok_from) {
|
||||||
ok_ = true;
|
ok_ = true;
|
||||||
ok_from_ = ok_from;
|
ok_from_ = ok_from;
|
||||||
|
@ -69,6 +75,12 @@ class ValidatorSession : public td::actor::Actor {
|
||||||
td::uint32 ok_from_ = 0;
|
td::uint32 ok_from_ = 0;
|
||||||
std::string reason_;
|
std::string reason_;
|
||||||
td::BufferSlice proof_;
|
td::BufferSlice proof_;
|
||||||
|
bool is_cached_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GeneratedCandidate {
|
||||||
|
BlockCandidate candidate;
|
||||||
|
bool is_cached = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
|
@ -76,7 +88,7 @@ class ValidatorSession : public td::actor::Actor {
|
||||||
virtual void on_candidate(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash,
|
virtual void on_candidate(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash,
|
||||||
td::BufferSlice data, td::BufferSlice collated_data,
|
td::BufferSlice data, td::BufferSlice collated_data,
|
||||||
td::Promise<CandidateDecision> promise) = 0;
|
td::Promise<CandidateDecision> promise) = 0;
|
||||||
virtual void on_generate_slot(td::uint32 round, td::Promise<BlockCandidate> promise) = 0;
|
virtual void on_generate_slot(td::uint32 round, td::Promise<GeneratedCandidate> promise) = 0;
|
||||||
virtual void on_block_committed(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash,
|
virtual void on_block_committed(td::uint32 round, PublicKey source, ValidatorSessionRootHash root_hash,
|
||||||
ValidatorSessionFileHash file_hash, td::BufferSlice data,
|
ValidatorSessionFileHash file_hash, td::BufferSlice data,
|
||||||
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> signatures,
|
std::vector<std::pair<PublicKeyHash, td::BufferSlice>> signatures,
|
||||||
|
|
|
@ -159,10 +159,19 @@ class ValidatorSessionImpl : public ValidatorSession {
|
||||||
bool compress_block_candidates_ = false;
|
bool compress_block_candidates_ = false;
|
||||||
|
|
||||||
ValidatorSessionStats cur_stats_;
|
ValidatorSessionStats cur_stats_;
|
||||||
|
bool stats_inited_ = false;
|
||||||
|
std::map<std::pair<td::uint32, ValidatorSessionCandidateId>, std::vector<td::uint32>>
|
||||||
|
stats_pending_approve_; // round, candidate_id -> approvers
|
||||||
|
std::map<std::pair<td::uint32, ValidatorSessionCandidateId>, std::vector<td::uint32>>
|
||||||
|
stats_pending_sign_; // round, candidate_id -> signers
|
||||||
void stats_init();
|
void stats_init();
|
||||||
void stats_add_round();
|
void stats_add_round();
|
||||||
void stats_set_candidate_status(td::uint32 round, PublicKeyHash src, ValidatorSessionCandidateId candidate_id,
|
ValidatorSessionStats::Producer *stats_get_candidate_stat(
|
||||||
int status, std::string comment = "");
|
td::uint32 round, PublicKeyHash src,
|
||||||
|
ValidatorSessionCandidateId candidate_id = ValidatorSessionCandidateId::zero());
|
||||||
|
ValidatorSessionStats::Producer *stats_get_candidate_stat_by_id(td::uint32 round,
|
||||||
|
ValidatorSessionCandidateId candidate_id);
|
||||||
|
void stats_process_action(td::uint32 node_id, ton_api::validatorSession_round_Message &action);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
|
ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
|
||||||
|
@ -190,17 +199,16 @@ class ValidatorSessionImpl : public ValidatorSession {
|
||||||
void process_query(PublicKeyHash src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
void process_query(PublicKeyHash src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||||
|
|
||||||
void try_approve_block(const SentBlock *block);
|
void try_approve_block(const SentBlock *block);
|
||||||
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::uint32 src,
|
||||||
td::uint32 src, td::BufferSlice proof);
|
td::BufferSlice proof, double validation_time, bool validation_cached);
|
||||||
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 src, td::uint32 ok_from);
|
td::uint32 src, td::uint32 ok_from, double validation_time, bool validation_cached);
|
||||||
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);
|
||||||
|
|
||||||
void generated_block(td::uint32 round, ValidatorSessionRootHash root_hash, td::BufferSlice data,
|
void generated_block(td::uint32 round, ValidatorSessionRootHash root_hash, td::BufferSlice data,
|
||||||
td::BufferSlice collated);
|
td::BufferSlice collated, double collation_time, bool collation_cached);
|
||||||
void signed_block(td::uint32 round, ValidatorSessionCandidateId hash, td::BufferSlice signature);
|
void signed_block(td::uint32 round, ValidatorSessionCandidateId hash, td::BufferSlice signature);
|
||||||
|
|
||||||
void end_request(td::uint32 round, ValidatorSessionCandidateId block_id) {
|
void end_request(td::uint32 round, ValidatorSessionCandidateId block_id) {
|
||||||
|
|
|
@ -2714,8 +2714,12 @@ void ValidatorManagerImpl::log_validator_session_stats(BlockIdExt block_id,
|
||||||
std::vector<tl_object_ptr<ton_api::validatorSession_statsProducer>> producers;
|
std::vector<tl_object_ptr<ton_api::validatorSession_statsProducer>> producers;
|
||||||
for (const auto &producer : round.producers) {
|
for (const auto &producer : round.producers) {
|
||||||
producers.push_back(create_tl_object<ton_api::validatorSession_statsProducer>(
|
producers.push_back(create_tl_object<ton_api::validatorSession_statsProducer>(
|
||||||
producer.id.bits256_value(), producer.candidate_id, producer.block_status, producer.block_timestamp,
|
producer.id.bits256_value(), producer.candidate_id, producer.block_status, producer.comment,
|
||||||
producer.comment));
|
producer.block_timestamp, producer.is_accepted, producer.is_ours, producer.got_submit_at,
|
||||||
|
producer.collation_time, producer.collated_at, producer.collation_cached, producer.validation_time,
|
||||||
|
producer.validated_at, producer.validation_cached, producer.gen_utime, producer.approved_weight,
|
||||||
|
producer.approved_33pct_at, producer.approved_66pct_at, producer.signed_weight, producer.signed_33pct_at,
|
||||||
|
producer.signed_66pct_at, producer.serialize_time, producer.deserialize_time, producer.serialized_size));
|
||||||
}
|
}
|
||||||
rounds.push_back(create_tl_object<ton_api::validatorSession_statsRound>(round.timestamp, std::move(producers)));
|
rounds.push_back(create_tl_object<ton_api::validatorSession_statsRound>(round.timestamp, std::move(producers)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ namespace ton {
|
||||||
|
|
||||||
namespace validator {
|
namespace validator {
|
||||||
|
|
||||||
void ValidatorGroup::generate_block_candidate(td::uint32 round_id, td::Promise<BlockCandidate> promise) {
|
void ValidatorGroup::generate_block_candidate(
|
||||||
|
td::uint32 round_id, td::Promise<validatorsession::ValidatorSession::GeneratedCandidate> promise) {
|
||||||
if (round_id > last_known_round_id_) {
|
if (round_id > last_known_round_id_) {
|
||||||
last_known_round_id_ = round_id;
|
last_known_round_id_ = round_id;
|
||||||
}
|
}
|
||||||
|
@ -37,14 +38,18 @@ void ValidatorGroup::generate_block_candidate(td::uint32 round_id, td::Promise<B
|
||||||
}
|
}
|
||||||
if (cached_collated_block_) {
|
if (cached_collated_block_) {
|
||||||
if (cached_collated_block_->result) {
|
if (cached_collated_block_->result) {
|
||||||
promise.set_result(cached_collated_block_->result.value().clone());
|
promise.set_value({cached_collated_block_->result.value().clone(), true});
|
||||||
} else {
|
} else {
|
||||||
cached_collated_block_->promises.push_back(std::move(promise));
|
cached_collated_block_->promises.push_back(promise.wrap([](BlockCandidate &&res) {
|
||||||
|
return validatorsession::ValidatorSession::GeneratedCandidate{std::move(res), true};
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cached_collated_block_ = std::make_shared<CachedCollatedBlock>();
|
cached_collated_block_ = std::make_shared<CachedCollatedBlock>();
|
||||||
cached_collated_block_->promises.push_back(std::move(promise));
|
cached_collated_block_->promises.push_back(promise.wrap([](BlockCandidate &&res) {
|
||||||
|
return validatorsession::ValidatorSession::GeneratedCandidate{std::move(res), false};
|
||||||
|
}));
|
||||||
run_collate_query(
|
run_collate_query(
|
||||||
shard_, min_ts_, min_masterchain_block_id_, prev_block_ids_,
|
shard_, min_ts_, min_masterchain_block_id_, prev_block_ids_,
|
||||||
Ed25519_PublicKey{local_id_full_.ed25519_value().raw()}, validator_set_, manager_, td::Timestamp::in(10.0),
|
Ed25519_PublicKey{local_id_full_.ed25519_value().raw()}, validator_set_, manager_, td::Timestamp::in(10.0),
|
||||||
|
@ -73,7 +78,7 @@ void ValidatorGroup::generated_block_candidate(std::shared_ptr<CachedCollatedBlo
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidate block,
|
void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidate block,
|
||||||
td::Promise<UnixTime> promise) {
|
td::Promise<std::pair<UnixTime, bool>> promise) {
|
||||||
if (round_id > last_known_round_id_) {
|
if (round_id > last_known_round_id_) {
|
||||||
last_known_round_id_ = round_id;
|
last_known_round_id_ = round_id;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +93,7 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
|
||||||
CacheKey cache_key = block_to_cache_key(block);
|
CacheKey cache_key = block_to_cache_key(block);
|
||||||
auto it = approved_candidates_cache_.find(cache_key);
|
auto it = approved_candidates_cache_.find(cache_key);
|
||||||
if (it != approved_candidates_cache_.end()) {
|
if (it != approved_candidates_cache_.end()) {
|
||||||
promise.set_result(it->second);
|
promise.set_value({it->second, true});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +118,7 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
|
||||||
ts);
|
ts);
|
||||||
td::actor::send_closure(SelfId, &ValidatorGroup::add_available_block_candidate, block.pubkey.as_bits256(),
|
td::actor::send_closure(SelfId, &ValidatorGroup::add_available_block_candidate, block.pubkey.as_bits256(),
|
||||||
block.id, block.collated_file_hash);
|
block.id, block.collated_file_hash);
|
||||||
promise.set_result(ts);
|
promise.set_value({ts, false});
|
||||||
},
|
},
|
||||||
[&](CandidateReject reject) {
|
[&](CandidateReject reject) {
|
||||||
promise.set_error(
|
promise.set_error(
|
||||||
|
@ -247,15 +252,18 @@ std::unique_ptr<validatorsession::ValidatorSession::Callback> ValidatorGroup::ma
|
||||||
void on_candidate(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash,
|
void on_candidate(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash,
|
||||||
td::BufferSlice data, td::BufferSlice collated_data,
|
td::BufferSlice data, td::BufferSlice collated_data,
|
||||||
td::Promise<validatorsession::ValidatorSession::CandidateDecision> promise) override {
|
td::Promise<validatorsession::ValidatorSession::CandidateDecision> promise) override {
|
||||||
auto P = td::PromiseCreator::lambda([id = id_, promise = std::move(promise)](td::Result<td::uint32> R) mutable {
|
auto P =
|
||||||
if (R.is_ok()) {
|
td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<std::pair<td::uint32, bool>> R) mutable {
|
||||||
promise.set_value(validatorsession::ValidatorSession::CandidateDecision{R.move_as_ok()});
|
if (R.is_ok()) {
|
||||||
} else {
|
validatorsession::ValidatorSession::CandidateDecision decision(R.ok().first);
|
||||||
auto S = R.move_as_error();
|
decision.set_is_cached(R.ok().second);
|
||||||
promise.set_value(
|
promise.set_value(std::move(decision));
|
||||||
validatorsession::ValidatorSession::CandidateDecision{S.message().c_str(), td::BufferSlice()});
|
} else {
|
||||||
}
|
auto S = R.move_as_error();
|
||||||
});
|
promise.set_value(
|
||||||
|
validatorsession::ValidatorSession::CandidateDecision{S.message().c_str(), td::BufferSlice()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
BlockCandidate candidate{Ed25519_PublicKey{source.ed25519_value().raw()},
|
BlockCandidate candidate{Ed25519_PublicKey{source.ed25519_value().raw()},
|
||||||
BlockIdExt{0, 0, 0, root_hash, sha256_bits256(data.as_slice())},
|
BlockIdExt{0, 0, 0, root_hash, sha256_bits256(data.as_slice())},
|
||||||
|
@ -264,7 +272,8 @@ std::unique_ptr<validatorsession::ValidatorSession::Callback> ValidatorGroup::ma
|
||||||
td::actor::send_closure(id_, &ValidatorGroup::validate_block_candidate, round, std::move(candidate),
|
td::actor::send_closure(id_, &ValidatorGroup::validate_block_candidate, round, std::move(candidate),
|
||||||
std::move(P));
|
std::move(P));
|
||||||
}
|
}
|
||||||
void on_generate_slot(td::uint32 round, td::Promise<BlockCandidate> promise) override {
|
void on_generate_slot(td::uint32 round,
|
||||||
|
td::Promise<validatorsession::ValidatorSession::GeneratedCandidate> promise) override {
|
||||||
td::actor::send_closure(id_, &ValidatorGroup::generate_block_candidate, round, std::move(promise));
|
td::actor::send_closure(id_, &ValidatorGroup::generate_block_candidate, round, std::move(promise));
|
||||||
}
|
}
|
||||||
void on_block_committed(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash,
|
void on_block_committed(td::uint32 round, PublicKey source, validatorsession::ValidatorSessionRootHash root_hash,
|
||||||
|
|
|
@ -34,8 +34,10 @@ class ValidatorManager;
|
||||||
|
|
||||||
class ValidatorGroup : public td::actor::Actor {
|
class ValidatorGroup : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
void generate_block_candidate(td::uint32 round_id, td::Promise<BlockCandidate> promise);
|
void generate_block_candidate(td::uint32 round_id,
|
||||||
void validate_block_candidate(td::uint32 round_id, BlockCandidate block, td::Promise<td::uint32> promise);
|
td::Promise<validatorsession::ValidatorSession::GeneratedCandidate> promise);
|
||||||
|
void validate_block_candidate(td::uint32 round_id, BlockCandidate block,
|
||||||
|
td::Promise<std::pair<UnixTime, bool>> promise);
|
||||||
void accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block, RootHash root_hash,
|
void accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block, RootHash root_hash,
|
||||||
FileHash file_hash, std::vector<BlockSignature> signatures,
|
FileHash file_hash, std::vector<BlockSignature> signatures,
|
||||||
std::vector<BlockSignature> approve_signatures,
|
std::vector<BlockSignature> approve_signatures,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue