@@ -59,33 +59,29 @@ std::string ErrorCtx::as_string() const {
5959/* *
6060 * Constructs a ValidateQuery object.
6161 *
62- * @param shard The shard of the block being validated.
63- * @param min_masterchain_block_id The minimum allowed masterchain block reference for the block.
64- * @param prev A vector of BlockIdExt representing the previous blocks.
6562 * @param candidate The BlockCandidate to be validated.
66- * @param validator_set A reference to the ValidatorSet.
63+ * @param params Validation parameters
6764 * @param manager The ActorId of the ValidatorManager.
6865 * @param timeout The timeout for the validation.
6966 * @param promise The Promise to return the ValidateCandidateResult to.
70- * @param mode +1 - fake mode
7167 */
72- ValidateQuery::ValidateQuery (ShardIdFull shard, BlockIdExt min_masterchain_block_id, std::vector<BlockIdExt> prev,
73- BlockCandidate candidate, Ref<ValidatorSet> validator_set,
74- PublicKeyHash local_validator_id, td::actor::ActorId<ValidatorManager> manager,
75- td::Timestamp timeout, td::Promise<ValidateCandidateResult> promise, unsigned mode)
76- : shard_(shard)
68+ ValidateQuery::ValidateQuery (BlockCandidate candidate, ValidateParams params,
69+ td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
70+ td::Promise<ValidateCandidateResult> promise)
71+ : shard_(params.shard)
7772 , id_(candidate.id)
78- , min_mc_block_id(min_masterchain_block_id)
79- , prev_blocks(std::move(prev))
73+ , min_mc_block_id(params. min_masterchain_block_id)
74+ , prev_blocks(std::move(params. prev))
8075 , block_candidate(std::move(candidate))
81- , validator_set_(std::move(validator_set))
82- , local_validator_id_(local_validator_id)
76+ , validator_set_(std::move(params. validator_set))
77+ , local_validator_id_(params. local_validator_id)
8378 , manager(manager)
8479 , timeout(timeout)
8580 , main_promise(std::move(promise))
86- , is_fake_(mode & ValidateMode::fake )
81+ , is_fake_(params.is_fake )
8782 , shard_pfx_(shard_.shard)
8883 , shard_pfx_len_(ton::shard_prefix_length(shard_))
84+ , optimistic_prev_block_(std::move(params.optimistic_prev_block))
8985 , perf_timer_(" validateblock" , 0.1 , [manager](double duration) {
9086 send_closure (manager, &ValidatorManager::add_perf_timer_stat, " validateblock" , duration);
9187 }) {
@@ -350,6 +346,21 @@ void ValidateQuery::start_up() {
350346 // return;
351347 }
352348 }
349+ if (optimistic_prev_block_.not_null ()) {
350+ if (is_masterchain ()) {
351+ fatal_error (" optimistic validation in masterchain is not supported" );
352+ return ;
353+ }
354+ if (prev_blocks.size () != 1 ) {
355+ fatal_error (" optimistic prev block is not null, which is not allowed after merge" );
356+ return ;
357+ }
358+ if (prev_blocks[0 ] != optimistic_prev_block_->block_id ()) {
359+ fatal_error (" optimistic prev block is not null, but has invalid block id" );
360+ return ;
361+ }
362+ LOG (WARNING) << " Optimistic prev block id = " << optimistic_prev_block_->block_id ().to_str ();
363+ }
353364 // 2. learn latest masterchain state and block id
354365 LOG (DEBUG) << " sending get_top_masterchain_state_block() to Manager" ;
355366 ++pending;
@@ -366,17 +377,13 @@ void ValidateQuery::start_up() {
366377 }
367378 // 4. load state(s) corresponding to previous block(s) (not full-collated-data or masterchain)
368379 prev_states.resize (prev_blocks.size ());
369- if (is_masterchain () || !full_collated_data_) {
370- for (int i = 0 ; (unsigned )i < prev_blocks.size (); i++) {
371- // 4.1. load state
372- LOG (DEBUG) << " sending wait_block_state() query #" << i << " for " << prev_blocks[i].to_str () << " to Manager" ;
373- ++pending;
374- td::actor::send_closure_later (manager, &ValidatorManager::wait_block_state_short, prev_blocks[i], priority (),
375- timeout, false , [self = get_self (), i](td::Result<Ref<ShardState>> res) -> void {
376- LOG (DEBUG) << " got answer to wait_block_state_short query #" << i;
377- td::actor::send_closure_later (
378- std::move (self), &ValidateQuery::after_get_shard_state, i, std::move (res));
379- });
380+ if (is_masterchain () || !full_collated_data_) {
381+ if (optimistic_prev_block_.is_null ()) {
382+ load_prev_states ();
383+ } else {
384+ if (!process_optimistic_prev_block ()) {
385+ return ;
386+ }
380387 }
381388 }
382389 // 4. request masterchain handle and state referred to in the block
@@ -409,6 +416,84 @@ void ValidateQuery::start_up() {
409416 CHECK (pending);
410417}
411418
419+ /* *
420+ * Load previous states from DB
421+ */
422+ void ValidateQuery::load_prev_states () {
423+ for (int i = 0 ; (unsigned )i < prev_blocks.size (); i++) {
424+ // 4.1. load state
425+ LOG (DEBUG) << " sending wait_block_state() query #" << i << " for " << prev_blocks[i].to_str () << " to Manager" ;
426+ ++pending;
427+ td::actor::send_closure_later (manager, &ValidatorManager::wait_block_state_short, prev_blocks[i], priority (),
428+ timeout, false , [self = get_self (), i](td::Result<Ref<ShardState>> res) -> void {
429+ LOG (DEBUG) << " got answer to wait_block_state_short query #" << i;
430+ td::actor::send_closure_later (
431+ std::move (self), &ValidateQuery::after_get_shard_state, i, std::move (res));
432+ });
433+ }
434+ }
435+
436+ /* *
437+ * Load previous state for optimistic prev block to apply Merkle update to it
438+ */
439+ bool ValidateQuery::process_optimistic_prev_block () {
440+ std::vector<BlockIdExt> prev_prev;
441+ BlockIdExt mc_blkid;
442+ bool after_split;
443+ auto S = block::unpack_block_prev_blk_try (optimistic_prev_block_->root_cell (), optimistic_prev_block_->block_id (),
444+ prev_prev, mc_blkid, after_split);
445+ if (S.is_error ()) {
446+ return fatal_error (S.move_as_error_prefix (" failed to unpack optimistic prev block: " ));
447+ }
448+ // 4.1. load state
449+ if (prev_prev.size () == 1 ) {
450+ LOG (DEBUG) << " sending wait_block_state() query for " << prev_prev[0 ].to_str () << " to Manager (opt)" ;
451+ ++pending;
452+ td::actor::send_closure_later (manager, &ValidatorManager::wait_block_state_short, prev_prev[0 ], priority (), timeout,
453+ false , [self = get_self ()](td::Result<Ref<ShardState>> res) mutable {
454+ LOG (DEBUG) << " got answer to wait_block_state query (opt)" ;
455+ td::actor::send_closure_later (std::move (self),
456+ &ValidateQuery::after_get_shard_state_optimistic,
457+ std::move (res));
458+ });
459+ } else {
460+ CHECK (prev_prev.size () == 2 );
461+ LOG (DEBUG) << " sending wait_block_state_merge() query for " << prev_prev[0 ].to_str () << " and "
462+ << prev_prev[1 ].to_str () << " to Manager (opt)" ;
463+ ++pending;
464+ td::actor::send_closure_later (manager, &ValidatorManager::wait_block_state_merge, prev_prev[0 ], prev_prev[1 ],
465+ priority (), timeout, [self = get_self ()](td::Result<Ref<ShardState>> res) mutable {
466+ LOG (DEBUG) << " got answer to wait_block_state_merge query (opt)" ;
467+ td::actor::send_closure_later (std::move (self),
468+ &ValidateQuery::after_get_shard_state_optimistic,
469+ std::move (res));
470+ });
471+ }
472+ return true ;
473+ }
474+
475+ /* *
476+ * Callback function called after retrieving previous state for optimistic prev block
477+ *
478+ * @param res The retrieved state.
479+ */
480+ void ValidateQuery::after_get_shard_state_optimistic (td::Result<Ref<ShardState>> res) {
481+ LOG (DEBUG) << " in ValidateQuery::after_get_shard_state_optimistic()" ;
482+ if (res.is_error ()) {
483+ fatal_error (res.move_as_error ());
484+ return ;
485+ }
486+ work_timer_.resume ();
487+ auto state = res.move_as_ok ();
488+ auto S = state.write ().apply_block (optimistic_prev_block_->block_id (), optimistic_prev_block_);
489+ if (S.is_error ()) {
490+ fatal_error (S.move_as_error_prefix (" apply error: " ));
491+ return ;
492+ }
493+ work_timer_.pause ();
494+ after_get_shard_state (0 , std::move (state));
495+ }
496+
412497/* *
413498 * Unpacks and validates a block candidate.
414499 *
@@ -1619,11 +1704,16 @@ bool ValidateQuery::request_neighbor_queues() {
16191704 for (block::McShardDescr& descr : neighbors_) {
16201705 LOG (DEBUG) << " requesting outbound queue of neighbor #" << i << " : " << descr.blk_ .to_str ();
16211706 ++pending;
1622- send_closure_later (manager, &ValidatorManager::wait_block_message_queue_short, descr.blk_ , priority (), timeout,
1623- [self = get_self (), i](td::Result<Ref<MessageQueue>> res) {
1624- td::actor::send_closure (std::move (self), &ValidateQuery::got_neighbor_out_queue, i,
1625- std::move (res));
1626- });
1707+ if (int prev_idx = prev_block_idx (descr.blk_ ); prev_idx >= 0 ) {
1708+ td::actor::send_closure (actor_id (this ), &ValidateQuery::got_neighbor_out_queue, i,
1709+ prev_states.at (prev_idx)->message_queue ());
1710+ } else {
1711+ send_closure_later (manager, &ValidatorManager::wait_block_message_queue_short, descr.blk_ , priority (), timeout,
1712+ [self = get_self (), i](td::Result<Ref<MessageQueue>> res) {
1713+ td::actor::send_closure (std::move (self), &ValidateQuery::got_neighbor_out_queue, i,
1714+ std::move (res));
1715+ });
1716+ }
16271717 ++i;
16281718 }
16291719 }
0 commit comments