mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Catchain improvements (#698)
* Fix "sgn" in fift; fix marking infinite loops as noterurn in func * TON-P1-1: Remove unused catchain queries * TON-P1-15: Avoid synchronization with self * TON-P1-3, TON-P1-17: Disallow more than one candidate per src per round (to prevent flood), add checks to process_broadcast * TON-P1-10: Fix fast/slow attempts * TON-P1-14: Add named constants * TON-P1-18, TON-P1-19: Alloc temporary memory in the same way as persistent memory * TON-P1-20: Add comment to choose_blocks_to_approve * TON-P1-16: Avoid creating two catchain blocks on need_new_block * TON-P1-8: Add some validation to validator-engine parameters * TON-P1-6: Don't allow sending the same block many times Many requests for the same block are not unusual (however, there's no need to answer them all) * TON-P1-2: Enable prohibiting dependencies from blamed nodes (2.7.5 in CatChain doc), fix processing blame proofs * Best practices bp-6: Fix incorrect warning bp-7: Remove unused code bp-8: Bring back PerfWarningTimer logging (only when no callback) bp-9: Remove unnecessary condition bp-11: Remove commented-out code bp-13: Divide code in validator-session-state Adherence to Specification: Fix typo
This commit is contained in:
parent
7878578dba
commit
5abfe2337e
27 changed files with 1417 additions and 1303 deletions
|
@ -203,7 +203,23 @@ void ValidatorSessionImpl::preprocess_block(catchain::CatChainBlock *block) {
|
|||
<< "ms: state=" << state->get_hash(description());
|
||||
}
|
||||
|
||||
void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice data) {
|
||||
bool ValidatorSessionImpl::ensure_candidate_unique(td::uint32 src_idx, td::uint32 round,
|
||||
ValidatorSessionCandidateId block_id) {
|
||||
auto it = src_round_candidate_[src_idx].find(round);
|
||||
if (it != src_round_candidate_[src_idx].end() && it->second != block_id) {
|
||||
VLOG(VALIDATOR_SESSION_WARNING) << this << "[node " << description_->get_source_adnl_id(src_idx) << "][candidate "
|
||||
<< block_id << "]: this node already has candidate in round " << round;
|
||||
return false;
|
||||
}
|
||||
src_round_candidate_[src_idx][round] = block_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice data,
|
||||
td::optional<ValidatorSessionCandidateId> expected_id,
|
||||
bool is_overlay_broadcast) {
|
||||
// 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.
|
||||
auto src_idx = description().get_source_idx(src);
|
||||
auto R = fetch_tl_object<ton_api::validatorSession_candidate>(data.clone(), true);
|
||||
if (R.is_error()) {
|
||||
|
@ -230,6 +246,12 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
|
|||
auto block_round = static_cast<td::uint32>(candidate->round_);
|
||||
auto block_id = description().candidate_id(src_idx, candidate->root_hash_, file_hash, collated_data_file_hash);
|
||||
|
||||
if (expected_id && expected_id.value() != block_id) {
|
||||
VLOG(VALIDATOR_SESSION_WARNING) << this << "[node " << src << "][broadcast " << sha256_bits256(data.as_slice())
|
||||
<< "]: id mismatch";
|
||||
return;
|
||||
}
|
||||
|
||||
if ((td::int32)block_round < (td::int32)cur_round_ - MAX_PAST_ROUND_BLOCK ||
|
||||
block_round >= cur_round_ + MAX_FUTURE_ROUND_BLOCK) {
|
||||
VLOG(VALIDATOR_SESSION_NOTICE) << this << "[node " << src << "][broadcast " << block_id
|
||||
|
@ -250,6 +272,10 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_overlay_broadcast && !ensure_candidate_unique(src_idx, block_round, block_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
blocks_[block_id] = std::move(candidate);
|
||||
|
||||
VLOG(VALIDATOR_SESSION_WARNING) << this << ": received broadcast " << block_id;
|
||||
|
@ -508,7 +534,11 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
|
|||
}
|
||||
|
||||
if (block) {
|
||||
auto T = td::Timestamp::at(round_started_at_.at() + description().get_delay(block->get_src_idx()) + 2.0);
|
||||
if (!ensure_candidate_unique(block->get_src_idx(), cur_round_, SentBlock::get_block_id(block))) {
|
||||
return;
|
||||
}
|
||||
auto T = td::Timestamp::at(round_started_at_.at() + description().get_delay(block->get_src_idx()) +
|
||||
REQUEST_BROADCAST_P2P_DELAY);
|
||||
auto it = blocks_.find(block_id);
|
||||
|
||||
if (it != blocks_.end()) {
|
||||
|
@ -545,16 +575,18 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
|
|||
auto id = description().get_source_id(v[td::Random::fast(0, static_cast<td::int32>(v.size() - 1))]);
|
||||
auto src_id = description().get_source_id(block->get_src_idx());
|
||||
active_requests_.insert(block_id);
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), id, src_id, print_id = print_id(),
|
||||
hash = block_id, round = cur_round_](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::end_request, round, hash);
|
||||
if (R.is_error()) {
|
||||
VLOG(VALIDATOR_SESSION_WARNING)
|
||||
<< print_id << ": failed to get candidate " << hash << " from " << id << ": " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::process_broadcast, src_id, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), id, src_id, print_id = print_id(), hash = block_id, round = cur_round_,
|
||||
candidate_id = SentBlock::get_block_id(block)](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::end_request, round, hash);
|
||||
if (R.is_error()) {
|
||||
VLOG(VALIDATOR_SESSION_WARNING) << print_id << ": failed to get candidate " << hash << " from " << id
|
||||
<< ": " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::process_broadcast, src_id, R.move_as_ok(),
|
||||
candidate_id, false);
|
||||
}
|
||||
});
|
||||
|
||||
get_broadcast_p2p(id, block->get_file_hash(), block->get_collated_data_file_hash(),
|
||||
description().get_source_id(block->get_src_idx()), cur_round_, block->get_root_hash(),
|
||||
|
@ -586,10 +618,11 @@ void ValidatorSessionImpl::get_broadcast_p2p(PublicKeyHash node, ValidatorSessio
|
|||
round,
|
||||
create_tl_object<ton_api::validatorSession_candidateId>(src.tl(), root_hash, file_hash, collated_data_file_hash));
|
||||
|
||||
td::actor::send_closure(catchain_, &catchain::CatChain::send_query_via, node, "download candidate",
|
||||
std::move(promise), timeout, serialize_tl_object(obj, true),
|
||||
description().opts().max_block_size + description().opts().max_collated_data_size + 1024,
|
||||
rldp_);
|
||||
td::actor::send_closure(
|
||||
catchain_, &catchain::CatChain::send_query_via, node, "download candidate", std::move(promise), timeout,
|
||||
serialize_tl_object(obj, true),
|
||||
description().opts().max_block_size + description().opts().max_collated_data_size + MAX_CANDIDATE_EXTRA_SIZE,
|
||||
rldp_);
|
||||
}
|
||||
|
||||
void ValidatorSessionImpl::check_sign_slot() {
|
||||
|
@ -745,7 +778,6 @@ void ValidatorSessionImpl::on_new_round(td::uint32 round) {
|
|||
|
||||
while (cur_round_ < round) {
|
||||
auto block = real_state_->get_committed_block(description(), cur_round_);
|
||||
//CHECK(block);
|
||||
auto sigs = real_state_->get_committed_block_signatures(description(), cur_round_);
|
||||
CHECK(sigs);
|
||||
auto approve_sigs = real_state_->get_committed_block_approve_signatures(description(), cur_round_);
|
||||
|
@ -838,7 +870,8 @@ void ValidatorSessionImpl::on_catchain_started() {
|
|||
auto broadcast = create_tl_object<ton_api::validatorSession_candidate>(
|
||||
src.tl(), round, root_hash, std::move(B.data), std::move(B.collated_data));
|
||||
td::actor::send_closure(SelfId, &ValidatorSessionImpl::process_broadcast, src,
|
||||
serialize_tl_object(broadcast, true));
|
||||
serialize_tl_object(broadcast, true), td::optional<ValidatorSessionCandidateId>(),
|
||||
false);
|
||||
}
|
||||
});
|
||||
callback_->get_approved_candidate(description().get_source_public_key(x->get_src_idx()), x->get_root_hash(),
|
||||
|
@ -866,6 +899,7 @@ ValidatorSessionImpl::ValidatorSessionImpl(catchain::CatChainSessionId session_i
|
|||
, overlay_manager_(overlays)
|
||||
, allow_unsafe_self_blocks_resync_(allow_unsafe_self_blocks_resync) {
|
||||
description_ = ValidatorSessionDescription::create(std::move(opts), nodes, local_id);
|
||||
src_round_candidate_.resize(description_->get_total_nodes());
|
||||
}
|
||||
|
||||
void ValidatorSessionImpl::start() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue