Skip to content

Commit d2cc797

Browse files
committed
Optimistic block generation
1 parent f4468b8 commit d2cc797

File tree

18 files changed

+606
-195
lines changed

18 files changed

+606
-195
lines changed

tdutils/td/utils/Timer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ class PerfLog {
160160
};
161161
template <class T>
162162
double PerfLogAction::finish(const T &result) {
163+
if (!perf_log_) {
164+
return 0.0;
165+
}
163166
if (result.is_ok()) {
164167
return perf_log_->finish_action(i_, td::Status::OK());
165168
} else {

tl/generate/scheme/ton_api.tl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ validatorSession.blockUpdate ts:long actions:(vector validatorSession.round.Mess
344344
validatorSession.candidate src:int256 round:int root_hash:int256 data:bytes collated_data:bytes = validatorSession.Candidate;
345345
validatorSession.compressedCandidate flags:# src:int256 round:int root_hash:int256 decompressed_size:int data:bytes = validatorSession.Candidate;
346346
validatorSession.compressedCandidateV2 flags:# src:int256 round:int root_hash:int256 data:bytes = validatorSession.Candidate;
347+
validatorSession.optimisticCandidateBroadcast flags:# prev_candidate_id:int256 data:bytes = validatorSession.OptimisticCandidateBroadcast;
347348

348349
validatorSession.config catchain_idle_timeout:double catchain_max_deps:int round_candidates:int next_candidate_delay:double round_attempt_duration:int
349350
max_round_attempts:int max_block_size:int max_collated_data_size:int = validatorSession.Config;
@@ -962,7 +963,7 @@ validatorStats.blockStats
962963
old_out_msg_queue_size:long new_out_msg_queue_size:long msg_queue_cleaned:int
963964
neighbors:(vector validatorStats.blockStats.neighborStats) = validatorStats.BlockStats;
964965
validatorStats.collateWorkTimeStats
965-
total:double queue_cleanup:double prelim_storage_stat:double trx_tvm:double trx_storage_stat:double
966+
total:double optimistic_apply:double queue_cleanup:double prelim_storage_stat:double trx_tvm:double trx_storage_stat:double
966967
trx_other:double final_storage_stat:double create_block:double create_collated_data:double create_block_candidate:double
967968
= validatorStats.CollateWorkTimeStats;
968969
validatorStats.storageStatCacheStats

tl/generate/scheme/ton_api.tlo

320 Bytes
Binary file not shown.

validator-session/validator-session.cpp

Lines changed: 160 additions & 40 deletions
Large diffs are not rendered by default.

validator-session/validator-session.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class ValidatorSession : public td::actor::Actor {
9393
ValidatorSessionFileHash file_hash,
9494
ValidatorSessionCollatedDataFileHash collated_data_file_hash,
9595
td::Promise<BlockCandidate> promise) = 0;
96+
virtual void generate_block_optimistic(BlockSourceInfo source_info, td::BufferSlice prev_block, RootHash prev_root_hash,
97+
FileHash prev_file_hash, td::Promise<GeneratedCandidate> promise) {
98+
}
9699
virtual ~Callback() = default;
97100
};
98101

validator-session/validator-session.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,38 @@ class ValidatorSessionImpl : public ValidatorSession {
161161
bool catchain_started_ = false;
162162
bool allow_unsafe_self_blocks_resync_;
163163
bool compress_block_candidates_ = false;
164+
bool allow_optimistic_generation_ = false;
164165

165166
ValidatorSessionStats cur_stats_;
166167
bool stats_inited_ = false;
167168
std::map<std::pair<td::uint32, ValidatorSessionCandidateId>, std::vector<td::uint32>>
168169
stats_pending_approve_; // round, candidate_id -> approvers
169170
std::map<std::pair<td::uint32, ValidatorSessionCandidateId>, std::vector<td::uint32>>
170171
stats_pending_sign_; // round, candidate_id -> signers
172+
173+
struct SentCandidateStats {
174+
bool sent = false;
175+
double sent_at = -1.0;
176+
double serialize_time = -1.0;
177+
size_t serialized_size = 0;
178+
};
179+
std::map<ValidatorSessionCandidateId, SentCandidateStats> sent_candidates_;
180+
181+
struct BroadcastInfo {
182+
ValidatorSessionCandidateId candidate_id;
183+
double received_at = -1.0;
184+
double deserialize_time = -1.0;
185+
size_t serialized_size = 0;
186+
ValidatorSessionFileHash file_hash;
187+
ValidatorSessionCollatedDataFileHash collated_data_hash;
188+
};
189+
struct OptimisticBroadcast {
190+
tl_object_ptr<ton_api::validatorSession_candidate> candidate;
191+
ValidatorSessionCandidateId prev_candidate_id;
192+
BroadcastInfo broadcast_info;
193+
};
194+
std::map<std::pair<td::uint32, td::uint32>, OptimisticBroadcast> optimistic_broadcasts_; // round, src -> broadcast
195+
171196
void stats_init();
172197
void stats_add_round();
173198
ValidatorSessionStats::Producer *stats_get_candidate_stat(
@@ -176,6 +201,10 @@ class ValidatorSessionImpl : public ValidatorSession {
176201
ValidatorSessionStats::Producer *stats_get_candidate_stat_by_id(td::uint32 round,
177202
ValidatorSessionCandidateId candidate_id);
178203
void stats_process_action(td::uint32 node_id, ton_api::validatorSession_round_Message &action);
204+
void process_approve(td::uint32 node_id, td::uint32 round, ValidatorSessionCandidateId candidate_id);
205+
206+
void generated_optimistic_candidate(td::uint32 round, GeneratedCandidate candidate,
207+
ValidatorSessionCandidateId prev_candidate);
179208

180209
public:
181210
ValidatorSessionImpl(catchain::CatChainSessionId session_id, ValidatorSessionOptions opts, PublicKeyHash local_id,
@@ -205,6 +234,9 @@ class ValidatorSessionImpl : public ValidatorSession {
205234
bool ensure_candidate_unique(td::uint32 src_idx, td::uint32 round, ValidatorSessionCandidateId block_id);
206235
void process_broadcast(PublicKeyHash src, td::BufferSlice data, td::optional<ValidatorSessionCandidateId> expected_id,
207236
bool is_overlay_broadcast, bool is_startup);
237+
void process_received_block(td::uint32 block_round, PublicKeyHash src, td::uint32 src_idx,
238+
tl_object_ptr<ton_api::validatorSession_candidate> candidate, const BroadcastInfo &info,
239+
bool is_overlay_broadcast, bool is_startup);
208240
void process_message(PublicKeyHash src, td::BufferSlice data);
209241
void process_query(PublicKeyHash src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
210242

@@ -218,6 +250,9 @@ class ValidatorSessionImpl : public ValidatorSession {
218250
td::BufferSlice signature);
219251

220252
void generated_block(td::uint32 round, GeneratedCandidate c, double collation_time);
253+
SentCandidateStats &send_candidate_broadcast(
254+
td::uint32 round, const BlockCandidate &candidate,
255+
td::optional<ValidatorSessionCandidateId> optimistic_prev_candidate = {});
221256
void signed_block(td::uint32 round, ValidatorSessionCandidateId hash, td::BufferSlice signature);
222257

223258
void end_request(td::uint32 round, ValidatorSessionCandidateId block_id) {

validator/collation-manager.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,43 @@ void CollationManager::collate_block(ShardIdFull shard, BlockIdExt min_mastercha
3838
td::Promise<GeneratedCandidate> promise, int proto_version) {
3939
if (shard.is_masterchain()) {
4040
run_collate_query(
41-
shard, min_masterchain_block_id, std::move(prev), creator, std::move(validator_set),
42-
opts_->get_collator_options(), manager_, td::Timestamp::in(10.0), promise.wrap([](BlockCandidate&& candidate) {
41+
CollateParams{.shard = shard,
42+
.min_masterchain_block_id = min_masterchain_block_id,
43+
.prev = std::move(prev),
44+
.creator = creator,
45+
.validator_set = std::move(validator_set),
46+
.collator_opts = opts_->get_collator_options()},
47+
manager_, td::Timestamp::in(10.0), std::move(cancellation_token), promise.wrap([](BlockCandidate&& candidate) {
4348
return GeneratedCandidate{.candidate = std::move(candidate), .is_cached = false, .self_collated = true};
44-
}),
45-
adnl::AdnlNodeIdShort::zero(), std::move(cancellation_token), 0);
49+
}));
4650
return;
4751
}
4852
collate_shard_block(shard, min_masterchain_block_id, std::move(prev), creator, priority, std::move(validator_set),
4953
max_answer_size, std::move(cancellation_token), std::move(promise), td::Timestamp::in(10.0),
5054
proto_version);
5155
}
5256

57+
void CollationManager::collate_next_block(ShardIdFull shard, BlockIdExt min_masterchain_block_id,
58+
BlockIdExt prev_block_id, td::BufferSlice prev_block,
59+
Ed25519_PublicKey creator, BlockCandidatePriority priority,
60+
td::Ref<ValidatorSet> validator_set, td::uint64 max_answer_size,
61+
td::CancellationToken cancellation_token,
62+
td::Promise<GeneratedCandidate> promise, int proto_version) {
63+
TRY_RESULT_PROMISE(promise, prev_block_data, create_block(prev_block_id, std::move(prev_block)));
64+
run_collate_query(
65+
CollateParams{.shard = shard,
66+
.min_masterchain_block_id = min_masterchain_block_id,
67+
.prev = {prev_block_id},
68+
.creator = creator,
69+
.validator_set = std::move(validator_set),
70+
.collator_opts = opts_->get_collator_options(),
71+
.optimistic_prev_block_ = std::move(prev_block_data)},
72+
manager_, td::Timestamp::in(10.0), std::move(cancellation_token), promise.wrap([](BlockCandidate&& candidate) {
73+
return GeneratedCandidate{.candidate = std::move(candidate), .is_cached = false, .self_collated = true};
74+
}));
75+
// TODO: request to collator node
76+
}
77+
5378
void CollationManager::collate_shard_block(ShardIdFull shard, BlockIdExt min_masterchain_block_id,
5479
std::vector<BlockIdExt> prev, Ed25519_PublicKey creator,
5580
BlockCandidatePriority priority, td::Ref<ValidatorSet> validator_set,
@@ -109,11 +134,15 @@ void CollationManager::collate_shard_block(ShardIdFull shard, BlockIdExt min_mas
109134

110135
if (selected_collator.is_zero() && s->self_collate) {
111136
run_collate_query(
112-
shard, min_masterchain_block_id, std::move(prev), creator, std::move(validator_set),
113-
opts_->get_collator_options(), manager_, td::Timestamp::in(10.0), promise.wrap([](BlockCandidate&& candidate) {
137+
CollateParams{.shard = shard,
138+
.min_masterchain_block_id = min_masterchain_block_id,
139+
.prev = std::move(prev),
140+
.creator = creator,
141+
.validator_set = std::move(validator_set),
142+
.collator_opts = opts_->get_collator_options()},
143+
manager_, td::Timestamp::in(10.0), std::move(cancellation_token), promise.wrap([](BlockCandidate&& candidate) {
114144
return GeneratedCandidate{.candidate = std::move(candidate), .is_cached = false, .self_collated = true};
115-
}),
116-
adnl::AdnlNodeIdShort::zero(), std::move(cancellation_token), 0);
145+
}));
117146
return;
118147
}
119148

validator/collation-manager.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class CollationManager : public td::actor::Actor {
3939
td::uint64 max_answer_size, td::CancellationToken cancellation_token,
4040
td::Promise<GeneratedCandidate> promise, int proto_version);
4141

42+
void collate_next_block(ShardIdFull shard, BlockIdExt min_masterchain_block_id, BlockIdExt prev_block_id,
43+
td::BufferSlice prev_block, Ed25519_PublicKey creator, BlockCandidatePriority priority,
44+
td::Ref<ValidatorSet> validator_set, td::uint64 max_answer_size,
45+
td::CancellationToken cancellation_token, td::Promise<GeneratedCandidate> promise,
46+
int proto_version);
47+
4248
void update_options(td::Ref<ValidatorManagerOptions> opts);
4349

4450
void validator_group_started(ShardIdFull shard);

validator/collator-node.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -539,18 +539,21 @@ void CollatorNode::generate_block(ShardIdFull shard, CatchainSeqno cc_seqno, std
539539
};
540540
cache_entry->started = true;
541541
cache_entry->block_seqno = block_seqno;
542-
run_collate_query(
543-
shard, last_masterchain_state_->get_block_id(), std::move(prev_blocks), Ed25519_PublicKey{td::Bits256::zero()},
544-
last_masterchain_state_->get_validator_set(shard), opts_->get_collator_options(), manager_, timeout,
545-
[=, SelfId = actor_id(this), timer = td::Timer{}](td::Result<BlockCandidate> R) {
546-
FLOG(INFO) {
547-
prefix_inner(sb, shard, cc_seqno, block_seqno, o_priority);
548-
sb << timer.elapsed() << ": " << (R.is_ok() ? "OK" : R.error().to_string());
549-
};
550-
td::actor::send_closure(SelfId, &CollatorNode::process_result, cache_entry, std::move(R));
551-
},
552-
local_id_, cache_entry->cancellation_token_source.get_cancellation_token(),
553-
CollateMode::skip_store_candidate | CollateMode::from_collator_node);
542+
run_collate_query(CollateParams{.shard = shard,
543+
.min_masterchain_block_id = last_masterchain_state_->get_block_id(),
544+
.prev = std::move(prev_blocks),
545+
.validator_set = last_masterchain_state_->get_validator_set(shard),
546+
.collator_opts = opts_->get_collator_options(),
547+
.collator_node_id = local_id_,
548+
.skip_store_candidate = true},
549+
manager_, timeout, cache_entry->cancellation_token_source.get_cancellation_token(),
550+
[=, SelfId = actor_id(this), timer = td::Timer{}](td::Result<BlockCandidate> R) {
551+
FLOG(INFO) {
552+
prefix_inner(sb, shard, cc_seqno, block_seqno, o_priority);
553+
sb << timer.elapsed() << ": " << (R.is_ok() ? "OK" : R.error().to_string());
554+
};
555+
td::actor::send_closure(SelfId, &CollatorNode::process_result, cache_entry, std::move(R));
556+
});
554557
}
555558

556559
void CollatorNode::process_result(std::shared_ptr<CacheEntry> cache_entry, td::Result<BlockCandidate> R) {

validator/fabric.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,23 @@ namespace ton {
2626

2727
namespace validator {
2828

29+
struct CollateParams {
30+
ShardIdFull shard;
31+
BlockIdExt min_masterchain_block_id;
32+
std::vector<BlockIdExt> prev;
33+
bool is_hardfork = false;
34+
Ed25519_PublicKey creator{td::Bits256::zero()};
35+
td::Ref<ValidatorSet> validator_set = {};
36+
td::Ref<CollatorOptions> collator_opts = {};
37+
adnl::AdnlNodeIdShort collator_node_id = adnl::AdnlNodeIdShort::zero();
38+
bool skip_store_candidate = false;
39+
int attempt_idx = 0;
40+
41+
// Optional - used for optimistic collation
42+
Ref<BlockData> optimistic_prev_block_ = {};
43+
};
44+
2945
enum ValidateMode { fake = 1 };
30-
enum CollateMode { skip_store_candidate = 1, from_collator_node = 2 };
3146

3247
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,
3348
td::Ref<ValidatorManagerOptions> opts);
@@ -85,15 +100,8 @@ void run_validate_query(ShardIdFull shard, BlockIdExt min_masterchain_block_id,
85100
BlockCandidate candidate, td::Ref<ValidatorSet> validator_set, PublicKeyHash local_validator_id,
86101
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
87102
td::Promise<ValidateCandidateResult> promise, unsigned mode = 0);
88-
void run_collate_query(ShardIdFull shard, const BlockIdExt& min_masterchain_block_id, std::vector<BlockIdExt> prev,
89-
Ed25519_PublicKey creator, td::Ref<ValidatorSet> validator_set,
90-
td::Ref<CollatorOptions> collator_opts, td::actor::ActorId<ValidatorManager> manager,
91-
td::Timestamp timeout, td::Promise<BlockCandidate> promise,
92-
adnl::AdnlNodeIdShort collator_node_id, td::CancellationToken cancellation_token, unsigned mode,
93-
int attempt_idx = 0);
94-
void run_collate_hardfork(ShardIdFull shard, const BlockIdExt& min_masterchain_block_id, std::vector<BlockIdExt> prev,
95-
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
96-
td::Promise<BlockCandidate> promise);
103+
void run_collate_query(CollateParams params, td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
104+
td::CancellationToken cancellation_token, td::Promise<BlockCandidate> promise);
97105
void run_liteserver_query(td::BufferSlice data, td::actor::ActorId<ValidatorManager> manager,
98106
td::actor::ActorId<LiteServerCache> cache, td::Promise<td::BufferSlice> promise);
99107
void run_fetch_account_state(WorkchainId wc, StdSmcAddress addr, td::actor::ActorId<ValidatorManager> manager,

0 commit comments

Comments
 (0)