From 62e46fff0694eabb6ace5335e505eadaea70119c Mon Sep 17 00:00:00 2001 From: Jakub Zajkowski Date: Mon, 29 Jun 2026 12:37:10 +0200 Subject: [PATCH] Addressing race conditions in executing proposals --- node/src/components/block_validator.rs | 9 ++++++++- node/src/reactor/main_reactor/validate.rs | 24 ++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/node/src/components/block_validator.rs b/node/src/components/block_validator.rs index 289f0c7609..9f00f5b9e4 100644 --- a/node/src/components/block_validator.rs +++ b/node/src/components/block_validator.rs @@ -433,7 +433,14 @@ impl BlockValidator { pending_requests .into_iter() - .flat_map(|request| self.handle_new_request(effect_builder, request)) + .flat_map(|request| { + match self.try_handle_as_existing_request(effect_builder, request) { + MaybeHandled::Handled(effects) => effects, + MaybeHandled::NotHandled(request) => { + self.handle_new_request(effect_builder, request) + } + } + }) .collect() } diff --git a/node/src/reactor/main_reactor/validate.rs b/node/src/reactor/main_reactor/validate.rs index 8972956d6f..5ec2e5b42e 100644 --- a/node/src/reactor/main_reactor/validate.rs +++ b/node/src/reactor/main_reactor/validate.rs @@ -46,13 +46,23 @@ impl MainReactor { let execution_pre_state = self.contract_runtime.execution_pre_state(); let next_consensus_height = self.consensus.next_executed_height(); - if next_consensus_height != 0 - && next_consensus_height != execution_pre_state.next_block_height() - { - warn!( - "Validate: misalignment of expected block height between consensus and contract runtime" - ); - return ValidateInstruction::CatchUp; + let next_execution_height = execution_pre_state.next_block_height(); + if next_consensus_height != 0 { + // A difference of exactly 1 where execution is ahead is expected: execution + // updates execution_pre_state synchronously, but consensus.next_executed_height + // only advances after the BlockAdded event propagates through handle_meta_block. + // Triggering CatchUp on this transient single-block gap causes a self-reinforcing + // loop (refresh_contract_runtime keeps the gap at 1) that takes minutes to escape. + let is_misaligned = next_execution_height < next_consensus_height + || next_execution_height > next_consensus_height.saturating_add(1); + if is_misaligned { + warn!( + next_consensus_height, + next_execution_height, + "Validate: misalignment of expected block height between consensus and contract runtime" + ); + return ValidateInstruction::CatchUp; + } } let queue_depth = self.contract_runtime.queue_depth();