Skip to content

Commit 5f23d31

Browse files
committed
fix(consensus): prevent precommit timeout during commit blocking ops (TM-B3)
Move set_step(Commit) before blocking engine execution and storage commit operations in commit_block(). This prevents precommit timeouts from being processed while state is still at Precommit step, which caused state regression to round+1 and corrupted consensus. Bug scenario: 1. WAL writes Commit entry, state still at Precommit 2. Engine execution starts (blocking ~2+ seconds) 3. Precommit timeout arrives, passes guards since step=Precommit 4. Timeout handler advances to next round, corrupting consensus Fix: Set step to Commit immediately after building commit signatures, before any blocking operations begin. The timeout handler will then correctly ignore precommit timeouts since current step is already Commit.
1 parent eca1738 commit 5f23d31

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

app/src/actors_v2/chain/tendermint_handlers.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,6 +2872,21 @@ impl ChainActor {
28722872
}
28732873
};
28742874

2875+
// CRITICAL FIX (TM-B3): Set step to Commit BEFORE blocking operations.
2876+
// This prevents precommit timeouts from triggering during engine execution
2877+
// or storage commit. The timeout handler checks current_step and will ignore
2878+
// precommit timeouts when step is already Commit.
2879+
//
2880+
// Bug scenario without this fix:
2881+
// 1. WAL writes Commit entry
2882+
// 2. Engine execution starts (BLOCKING - 2+ seconds)
2883+
// 3. Precommit timeout arrives, state is still Precommit
2884+
// 4. Timeout handler advances to round+1, corrupting consensus
2885+
{
2886+
let mut state = tendermint_state.write().await;
2887+
state.set_step(TendermintStep::Commit);
2888+
}
2889+
28752890
// 3. Write commit WAL entry BEFORE any state changes
28762891
// Also write NewRound entry for H+1 to ensure clean recovery
28772892
{
@@ -2968,11 +2983,8 @@ impl ChainActor {
29682983
*guard = commit.clone();
29692984
}
29702985

2971-
// 8. Advance state to Commit step
2972-
{
2973-
let mut state = tendermint_state.write().await;
2974-
state.set_step(TendermintStep::Commit);
2975-
}
2986+
// 8. [REMOVED - TM-B3]: set_step(Commit) now happens earlier (before blocking ops)
2987+
// to prevent precommit timeouts from corrupting state during engine execution.
29762988

29772989
// 9. Notify network peers of committed block
29782990
if let Some(ref network) = self.network_actor {

0 commit comments

Comments
 (0)