Skip to content

Commit 7810271

Browse files
authored
Merge pull request #1779 from ton-blockchain/optimize-collate
Optimize optimistic collation
2 parents 8a49651 + ff010ef commit 7810271

33 files changed

+1034
-415
lines changed

blockchain-explorer/blockchain-explorer-query.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,8 @@ HttpQueryBlockSearch::HttpQueryBlockSearch(std::map<std::string, std::string> op
525525
}
526526
if (opts.count("utime") == 1) {
527527
try {
528-
seqno_ = static_cast<td::uint32>(std::stoull(opts["utime"]));
529-
mode_ = 1;
528+
utime_ = static_cast<td::uint32>(std::stoull(opts["utime"]));
529+
mode_ = 4;
530530
} catch (...) {
531531
error_ = td::Status::Error("cannot parse utime");
532532
return;

crypto/vm/boc-compression.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(const std::vecto
283283
continue;
284284

285285
int delta = rank[boc_graph[node][j]] - i - 2; // Always >= 0 because of above check
286-
size_t required_bits = 1 + (31 ^ __builtin_clz(node_count - i - 3));
286+
size_t required_bits = 1 + (31 ^ td::count_leading_zeroes32(node_count - i - 3));
287287

288288
if (required_bits < 8 - (result.size() + 1) % 8 + 1) {
289289
append_uint(result, delta, required_bits);
@@ -494,7 +494,7 @@ td::Result<std::vector<td::Ref<vm::Cell>>> boc_decompress_improved_structure_lz4
494494
for (int j = 0; j < cell_refs_cnt[i]; ++j) {
495495
if (!boc_graph[i][j]) {
496496
size_t pref_size = (orig_size - bit_reader.size());
497-
size_t required_bits = 1 + (31 ^ __builtin_clz(node_count - i - 3));
497+
size_t required_bits = 1 + (31 ^ td::count_leading_zeroes32(node_count - i - 3));
498498

499499
if (required_bits < 8 - (pref_size + 1) % 8 + 1) {
500500
TRY_RESULT_ASSIGN(boc_graph[i][j], read_uint(bit_reader, required_bits));

tl/generate/scheme/ton_api.tl

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -962,10 +962,6 @@ validatorStats.blockStats
962962
ext_msgs:validatorStats.blockStats.extMsgsStats transactions:int shard_configuration:(vector tonNode.blockIdExt)
963963
old_out_msg_queue_size:long new_out_msg_queue_size:long msg_queue_cleaned:int
964964
neighbors:(vector validatorStats.blockStats.neighborStats) = validatorStats.BlockStats;
965-
validatorStats.collateWorkTimeStats
966-
total:double optimistic_apply:double queue_cleanup:double prelim_storage_stat:double trx_tvm:double trx_storage_stat:double
967-
trx_other:double final_storage_stat:double create_block:double create_collated_data:double create_block_candidate:double
968-
= validatorStats.CollateWorkTimeStats;
969965
validatorStats.storageStatCacheStats
970966
small_cnt:long small_cells:long hit_cnt:long hit_cells:long miss_cnt:long miss_cells:long = validatorStats.StorageStatCacheStats;
971967

@@ -974,22 +970,20 @@ validatorStats.collatedBlock
974970
bytes:int collated_data_bytes:int attempt:int
975971
self:int256 is_validator:Bool
976972
total_time:double work_time:double cpu_work_time:double time_stats:string
977-
work_time_real_stats:validatorStats.collateWorkTimeStats
978-
work_time_cpu_stats:validatorStats.collateWorkTimeStats
973+
work_time_real_stats:string
974+
work_time_cpu_stats:string
979975
block_limits:validatorStats.blockLimitsStatus
980976
block_stats:validatorStats.blockStats
981977
storage_stat_cache:validatorStats.storageStatCacheStats = validatorSession.stats.CollatedBlock;
982978

983-
validatorStats.validateWorkTimeStats
984-
total:double trx_tvm:double trx_storage_stat:double trx_other:double = validatorStats.ValidateWorkTimeStats;
985979
validatorStats.validatedBlock
986980
block_id:tonNode.blockIdExt collated_data_hash:int256 validated_at:double
987981
self:int256
988982
valid:Bool comment:string
989983
bytes:int collated_data_bytes:int
990-
total_time:double work_time:double cpu_work_time:double
991-
work_time_real_stats:validatorStats.validateWorkTimeStats
992-
work_time_cpu_stats:validatorStats.validateWorkTimeStats
984+
total_time:double work_time:double cpu_work_time:double time_stats:string
985+
work_time_real_stats:string
986+
work_time_cpu_stats:string
993987
storage_stat_cache:validatorStats.storageStatCacheStats = validatorStats.ValidatedBlock;
994988

995989
validatorStats.newValidatorGroup.node id:int256 pubkey:PublicKey adnl_id:int256 weight:long = validatorStats.newValidatorGroup.Node;
@@ -1008,7 +1002,7 @@ validatorStats.collatorNodeResponse self:int256 validator_id:int256 timestamp:do
10081002
collatorNode.candidate source:PublicKey id:tonNode.blockIdExt data:bytes collated_data:bytes = collatorNode.Candidate;
10091003
collatorNode.compressedCandidate flags:# source:PublicKey id:tonNode.blockIdExt decompressed_size:int data:bytes = collatorNode.Candidate;
10101004
collatorNode.compressedCandidateV2 flags:# source:PublicKey id:tonNode.blockIdExt data:bytes = collatorNode.Candidate;
1011-
collatorNode.pong flags:# = collatorNode.Pong;
1005+
collatorNode.pong#5bbf0521 flags:# version:flags.0?int = collatorNode.Pong;
10121006
collatorNode.error code:int message:string = collatorNode.Error;
10131007

10141008
shardBlockVerifier.subscribed flags:# = shardBlockVerifier.Subscribed;
@@ -1017,6 +1011,9 @@ shardBlockVerifier.confirmBlocks blocks:(vector tonNode.blockIdExt) = shardBlock
10171011
---functions---
10181012
collatorNode.generateBlock shard:tonNode.shardId cc_seqno:int prev_blocks:(vector tonNode.blockIdExt)
10191013
creator:int256 round:int first_block_round:int priority:int = collatorNode.Candidate;
1014+
collatorNode.generateBlockOptimistic shard:tonNode.shardId cc_seqno:int prev_blocks:(vector tonNode.blockIdExt)
1015+
creator:int256 round:int first_block_round:int priority:int = collatorNode.Candidate;
1016+
collatorNode.requestBlockCallback flags:# block_id:tonNode.BlockIdExt = collatorNode.Candidate;
10201017
collatorNode.ping flags:# = collatorNode.Pong;
10211018

10221019
shardBlockVerifier.subscribe shard:tonNode.shardId flags:# = shardBlockVerifier.Subscribed;

tl/generate/scheme/ton_api.tlo

-312 Bytes
Binary file not shown.

ton/ton-types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ struct Ed25519_PrivateKey {
411411

412412
struct Ed25519_PublicKey {
413413
Bits256 _pubkey;
414+
Ed25519_PublicKey() : _pubkey(td::Bits256::zero()) {
415+
}
414416
explicit Ed25519_PublicKey(const Bits256& x) : _pubkey(x) {
415417
}
416418
explicit Ed25519_PublicKey(const td::ConstBitPtr x) : _pubkey(x) {

validator-session/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ target_include_directories(validatorsession PUBLIC
2626
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/..
2727
${OPENSSL_INCLUDE_DIR}
2828
)
29-
target_link_libraries(validatorsession PRIVATE tdutils tdactor adnl rldp tl_api dht tdfec overlay catchain)
29+
target_link_libraries(validatorsession PRIVATE tdutils tdactor adnl rldp2 tl_api dht tdfec overlay catchain)

validator-session/validator-session-types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ struct NewValidatorGroupStats {
230230
std::vector<BlockIdExt> prev;
231231
td::uint32 self_idx = 0;
232232
PublicKeyHash self = PublicKeyHash::zero();
233-
std::vector<Node> nodes;
233+
std::vector<Node> nodes{};
234234

235235
tl_object_ptr<ton_api::validatorStats_newValidatorGroup> tl() const {
236236
std::vector<tl_object_ptr<ton_api::tonNode_blockIdExt>> prev_arr;
@@ -257,7 +257,7 @@ struct EndValidatorGroupStats {
257257
ValidatorSessionId session_id = ValidatorSessionId::zero();
258258
double timestamp = -1.0;
259259
PublicKeyHash self = PublicKeyHash::zero();
260-
std::vector<Node> nodes;
260+
std::vector<Node> nodes{};
261261

262262
tl_object_ptr<ton_api::validatorStats_endValidatorGroup> tl() const {
263263
std::vector<tl_object_ptr<ton_api::validatorStats_endValidatorGroup_node>> nodes_arr;

validator-session/validator-session.cpp

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,24 @@ void ValidatorSessionImpl::process_broadcast(PublicKeyHash src, td::BufferSlice
294294
<< "]: duplicate optimistic broadcast for round " << block_round;
295295
return;
296296
}
297+
int priority = description().get_node_priority(src_idx, block_round);
298+
if (priority < 0) {
299+
VLOG(VALIDATOR_SESSION_WARNING) << this << "[node " << src << "][broadcast " << sha256_bits256(data.as_slice())
300+
<< "]: node is not a producer in round " << block_round;
301+
return;
302+
}
297303
if (block_round > cur_round_) {
298304
OptimisticBroadcast &optimistic_broadcast = optimistic_broadcasts_[{block_round, src_idx}];
299305
optimistic_broadcast.candidate = std::move(candidate);
300306
optimistic_broadcast.prev_candidate_id = optimistic_prev_candidate;
301307
optimistic_broadcast.broadcast_info = broadcast_info;
302308
VLOG(VALIDATOR_SESSION_WARNING) << this << ": received optimistic broadcast " << block_id << " from " << src
303309
<< ", round " << block_round;
310+
validate_optimistic_broadcast(
311+
BlockSourceInfo{description().get_source_public_key(src_idx),
312+
BlockCandidatePriority{block_round, block_round, priority}},
313+
optimistic_broadcast.candidate->root_hash_, optimistic_broadcast.candidate->data_.clone(),
314+
optimistic_broadcast.candidate->collated_data_.clone(), optimistic_broadcast.prev_candidate_id);
304315
return;
305316
}
306317
if (SentBlock::get_block_id(real_state_->get_committed_block(description(), block_round - 1)) !=
@@ -336,7 +347,7 @@ void ValidatorSessionImpl::process_received_block(td::uint32 block_round, Public
336347
}
337348
}
338349
stat->deserialize_time = info.deserialize_time;
339-
stat->serialized_size = info.serialized_size;
350+
stat->serialized_size = (int)info.serialized_size;
340351
stat->block_id.root_hash = candidate->root_hash_;
341352
stat->block_id.file_hash = info.file_hash;
342353
stat->collated_data_hash = info.collated_data_hash;
@@ -361,6 +372,12 @@ void ValidatorSessionImpl::process_received_block(td::uint32 block_round, Public
361372
}
362373

363374
blocks_[block_id] = std::move(candidate);
375+
if (auto it = block_waiters_.find(block_id); it != block_waiters_.end()) {
376+
for (auto &promise : it->second) {
377+
promise.set_result(td::Unit());
378+
}
379+
block_waiters_.erase(it);
380+
}
364381

365382
VLOG(VALIDATOR_SESSION_WARNING) << this << ": received broadcast " << block_id;
366383
if (block_round != cur_round_) {
@@ -381,6 +398,37 @@ void ValidatorSessionImpl::process_received_block(td::uint32 block_round, Public
381398
}
382399
}
383400

401+
void ValidatorSessionImpl::validate_optimistic_broadcast(BlockSourceInfo source_info,
402+
ValidatorSessionRootHash root_hash, td::BufferSlice data,
403+
td::BufferSlice collated_data,
404+
ValidatorSessionCandidateId prev_candidate_id) {
405+
if (source_info.priority.round <= cur_round_) {
406+
VLOG(VALIDATOR_SESSION_DEBUG) << this << ": validate optimistic broadcast from "
407+
<< source_info.source.compute_short_id() << " : too old";
408+
return;
409+
}
410+
auto it = blocks_.find(prev_candidate_id);
411+
if (it == blocks_.end()) {
412+
VLOG(VALIDATOR_SESSION_DEBUG) << this << ": validate optimistic broadcast from "
413+
<< source_info.source.compute_short_id() << " : wait for prev block";
414+
block_waiters_[prev_candidate_id].push_back(
415+
[=, SelfId = actor_id(this), data = std::move(data),
416+
collated_data = std::move(collated_data)](td::Result<td::Unit> R) mutable {
417+
if (R.is_ok()) {
418+
td::actor::send_closure(SelfId, &ValidatorSessionImpl::validate_optimistic_broadcast, source_info,
419+
root_hash, std::move(data), std::move(collated_data), prev_candidate_id);
420+
}
421+
});
422+
return;
423+
}
424+
VLOG(VALIDATOR_SESSION_DEBUG) << this << ": validate optimistic broadcast from "
425+
<< source_info.source.compute_short_id();
426+
callback_->on_optimistic_candidate(
427+
source_info, root_hash, std::move(data), std::move(collated_data),
428+
description().get_source_public_key(description().get_source_idx(PublicKeyHash{it->second->src_})),
429+
it->second->root_hash_, it->second->data_.clone(), it->second->collated_data_.clone());
430+
}
431+
384432
void ValidatorSessionImpl::process_message(PublicKeyHash src, td::BufferSlice data) {
385433
}
386434

@@ -473,7 +521,7 @@ void ValidatorSessionImpl::candidate_decision_ok(td::uint32 round, ValidatorSess
473521
stat->block_status = ValidatorSessionStats::status_approved;
474522
stat->comment = PSTRING() << "ts=" << ok_from;
475523
stat->validation_time = validation_time;
476-
stat->gen_utime = (double)ok_from;
524+
stat->gen_utime = (int)ok_from;
477525
stat->validated_at = td::Clocks::system();
478526
stat->validation_cached = validation_cached;
479527
}
@@ -528,7 +576,11 @@ void ValidatorSessionImpl::generated_block(td::uint32 round, GeneratedCandidate
528576
stat->block_status = ValidatorSessionStats::status_received;
529577
stat->collation_time = collation_time;
530578
stat->collated_at = td::Clocks::system();
531-
stat->got_block_at = td::Clocks::system();
579+
if (auto it = sent_candidates_.find(block_id); it != sent_candidates_.end()) {
580+
stat->got_block_at = it->second.sent_at;
581+
} else {
582+
stat->got_block_at = td::Clocks::system();
583+
}
532584
stat->got_block_by = ValidatorSessionStats::recv_collated;
533585
stat->collation_cached = c.is_cached;
534586
stat->self_collated = c.self_collated;
@@ -548,6 +600,12 @@ void ValidatorSessionImpl::generated_block(td::uint32 round, GeneratedCandidate
548600
blocks_[block_id] = create_tl_object<ton_api::validatorSession_candidate>(
549601
local_id().tl(), round, c.candidate.id.root_hash, std::move(c.candidate.data),
550602
std::move(c.candidate.collated_data));
603+
if (auto it = block_waiters_.find(block_id); it != block_waiters_.end()) {
604+
for (auto &promise : it->second) {
605+
promise.set_result(td::Unit());
606+
}
607+
block_waiters_.erase(it);
608+
}
551609
pending_generate_ = false;
552610
generated_ = true;
553611
generated_block_ = block_id;
@@ -738,7 +796,6 @@ void ValidatorSessionImpl::try_approve_block(const SentBlock *block) {
738796
VLOG(VALIDATOR_SESSION_WARNING) << print_id << ": failed to get candidate " << hash << " from " << id
739797
<< ": " << R.move_as_error();
740798
} else {
741-
LOG(ERROR) << "QQQQQ Got block " << R.ok().size();
742799
td::actor::send_closure(SelfId, &ValidatorSessionImpl::process_broadcast, src_id, R.move_as_ok(),
743800
candidate_id, false, false);
744801
}
@@ -1082,7 +1139,7 @@ ValidatorSessionImpl::ValidatorSessionImpl(catchain::CatChainSessionId session_i
10821139
PublicKeyHash local_id, std::vector<ValidatorSessionNode> nodes,
10831140
std::unique_ptr<Callback> callback,
10841141
td::actor::ActorId<keyring::Keyring> keyring,
1085-
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,
1142+
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp2::Rldp> rldp,
10861143
td::actor::ActorId<overlay::Overlays> overlays, std::string db_root,
10871144
std::string db_suffix, bool allow_unsafe_self_blocks_resync)
10881145
: unique_hash_(session_id)
@@ -1206,7 +1263,6 @@ void ValidatorSessionImpl::start_up() {
12061263
virtual_state_ = real_state_;
12071264

12081265
check_all();
1209-
td::actor::send_closure(rldp_, &rldp::Rldp::add_id, description().get_source_adnl_id(local_idx()));
12101266
}
12111267

12121268
void ValidatorSessionImpl::stats_init() {
@@ -1365,25 +1421,49 @@ void ValidatorSessionImpl::process_approve(td::uint32 node_id, td::uint32 round,
13651421
bool is_approved_66pct = stat->approved_66pct_at > 0.0;
13661422

13671423
if (allow_optimistic_generation_ && !was_approved_66pct && is_approved_66pct && cur_round_ == round &&
1368-
description().get_node_priority(local_idx(), round + 1) == 0 && blocks_.contains(candidate_id)) {
1369-
auto &block = blocks_[candidate_id];
1370-
if (cur_round_ == first_block_round_ &&
1371-
description().get_node_priority(description().get_source_idx(PublicKeyHash{block->src_}), cur_round_) == 0) {
1372-
callback_->generate_block_optimistic(BlockSourceInfo{description().get_source_public_key(local_idx()),
1373-
BlockCandidatePriority{round + 1, round + 1, 0}},
1374-
block->data_.clone(), block->root_hash_, stat->block_id.file_hash,
1375-
[=, SelfId = actor_id(this)](td::Result<GeneratedCandidate> R) {
1376-
if (R.is_error()) {
1377-
return;
1378-
}
1379-
td::actor::send_closure(
1380-
SelfId, &ValidatorSessionImpl::generated_optimistic_candidate,
1381-
round + 1, R.move_as_ok(), candidate_id);
1382-
});
1424+
cur_round_ == first_block_round_ && description().get_node_priority(local_idx(), round + 1) == 0 &&
1425+
blocks_.contains(candidate_id) &&
1426+
description().get_node_priority(description().get_source_idx(stat->validator_id), cur_round_) == 0) {
1427+
if (blocks_.contains(candidate_id)) {
1428+
generate_block_optimistic(round, candidate_id);
1429+
} else {
1430+
block_waiters_[candidate_id].push_back([=, SelfId = actor_id(this)](td::Result<td::Unit> R) {
1431+
if (R.is_ok()) {
1432+
td::actor::send_closure(SelfId, &ValidatorSessionImpl::generate_block_optimistic, round, candidate_id);
1433+
}
1434+
});
13831435
}
13841436
}
13851437
}
13861438

1439+
void ValidatorSessionImpl::generate_block_optimistic(td::uint32 cur_round,
1440+
ValidatorSessionCandidateId prev_candidate_id) {
1441+
if (cur_round != cur_round_) {
1442+
return;
1443+
}
1444+
auto it = blocks_.find(prev_candidate_id);
1445+
if (it == blocks_.end()) {
1446+
return;
1447+
}
1448+
auto &block = it->second;
1449+
auto stat = stats_get_candidate_stat_by_id(cur_round, prev_candidate_id);
1450+
if (!stat) {
1451+
return;
1452+
}
1453+
callback_->generate_block_optimistic(BlockSourceInfo{description().get_source_public_key(local_idx()),
1454+
BlockCandidatePriority{cur_round + 1, cur_round + 1, 0}},
1455+
block->data_.clone(), block->root_hash_, stat->block_id.file_hash,
1456+
[=, SelfId = actor_id(this)](td::Result<GeneratedCandidate> R) {
1457+
if (R.is_error()) {
1458+
LOG(DEBUG) << "Optimistic generation error: " << R.move_as_error();
1459+
return;
1460+
}
1461+
td::actor::send_closure(SelfId,
1462+
&ValidatorSessionImpl::generated_optimistic_candidate,
1463+
cur_round + 1, R.move_as_ok(), prev_candidate_id);
1464+
});
1465+
}
1466+
13871467
void ValidatorSessionImpl::generated_optimistic_candidate(td::uint32 round, GeneratedCandidate candidate,
13881468
ValidatorSessionCandidateId prev_candidate) {
13891469
if (cur_round_ > round) {
@@ -1396,7 +1476,7 @@ td::actor::ActorOwn<ValidatorSession> ValidatorSession::create(
13961476
catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
13971477
std::vector<ValidatorSessionNode> nodes, std::unique_ptr<Callback> callback,
13981478
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,
1399-
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays, std::string db_root,
1479+
td::actor::ActorId<rldp2::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays, std::string db_root,
14001480
std::string db_suffix, bool allow_unsafe_self_blocks_resync) {
14011481
return td::actor::create_actor<ValidatorSessionImpl>("session", session_id, std::move(opts), local_id,
14021482
std::move(nodes), std::move(callback), keyring, adnl, rldp,

0 commit comments

Comments
 (0)