Skip to content

[1.2.3] Apply blocks mid-production when our branch is locked out by a strong QC#1888

Open
heifner wants to merge 1 commit intoAntelopeIO:release/1.2from
heifner:fix-abort-production-on-strong-qc-lockout-1.2
Open

[1.2.3] Apply blocks mid-production when our branch is locked out by a strong QC#1888
heifner wants to merge 1 commit intoAntelopeIO:release/1.2from
heifner:fix-abort-production-on-strong-qc-lockout-1.2

Conversation

@heifner
Copy link
Copy Markdown
Contributor

@heifner heifner commented May 1, 2026

Backport of #1887 to release/1.2.

See #1887 for full rationale and the consensus argument. This PR contains the same change adapted to the 1.2 branch:

  • block_handle::locks_out_branch_of() helper (identical to main).
  • producer_plugin::on_incoming_block gate change (identical logic; uses controller::apply_blocks_result::complete to match the 1.2 return convention).
  • locks_out_branch_of_test unit test (identical to main).

Differences vs #1887:

  • Test changes to tests/nodeos_late_block_test.py are dropped — that test does not exist on release/1.2.

…ut by a strong QC

Previously, while a node was inside its own producing slot, on_incoming_block
would unconditionally early-return and defer apply_blocks until the slot ended.
That avoids interrupting block production mid-block, but it also keeps the
producer signing on a known-doomed branch when the rest of the network has
already moved on.

Add a new block_handle::locks_out_branch_of() helper that reports whether a
given block carries a strong QC for a block not in another head's ancestry --
a condition that, under Savanna's strong-vote locking rule, means no future
QC can ever form on that head's branch and the branch can never win
fork-choice. Use it in on_incoming_block to bypass the in_producing_mode
early-return only when the fork-database best head locks out the applied
head's branch. Normal in-slot operation is unchanged; only the
provably-doomed case falls through to apply_blocks immediately.

The check runs on the application thread (where on_incoming_block executes
via the read_write executor queue) so it can safely read both
chain.fork_db_head() and chain.head(). The helper itself is also
thread-safe: block_state_ptr is a shared_ptr and the underlying
finality_core is immutable post-construction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant