Skip to content

fix: try to execute orphaned blocks after executing finalized block#141

Merged
matthias-wright merged 5 commits intomainfrom
m/execute-orphaned-blocks-on-finalize
Mar 11, 2026
Merged

fix: try to execute orphaned blocks after executing finalized block#141
matthias-wright merged 5 commits intomainfrom
m/execute-orphaned-blocks-on-finalize

Conversation

@matthias-wright
Copy link
Collaborator

After a restart, Simplex will replay its journal and send all notarized/finalized blocks to the syncer, which forwards them to the finalizer.
Finalized blocks are forwarded in order. The syncer only sends the next finalized block after the finalizer acknowledged the previous one.
Notarized blocks are forwarded immediately. This is important because Simplex might try to build on a notarized block, but the new block can only be proposed once the notarized parent block was executed.
After a restart, the notarized height will far exceed the finalized height. I've seen number like notarized height 2172 and finalized height 268.
This is actually fine. The executions of the notarized blocks are not wasted, since executing a finalized block is basically a no-op if the notarized version of this block was already executed.

The issue is as follows:
To stick with the above numbers: Lets say the finalizer receives finalized block height 2171 via finalized blocks.
Then handle_finalized_block runs, advances canonical height to 2171, prunes orphans ≤ 2171, but never checks if orphaned blocks at 2172 can now be processed (handle_notarized_block does this already).
In most cases this doesn't matter, since the relevant blocks in orphaned blocks will be finalized eventually, and they will be executed at that point.
However, some notarized blocks will never be directly finalized. This is fairly likely to happen when all nodes restart at the same time. Lets say in the above example, block 2172 is notarized but never finalized. If the notarized block arrives out of order at the finalizer, it will be cached in the orphaned blocks map. Eventually, when Simplex proposes the next block using 2172 as the parent, the application actor will wait for 2172 to be executed. However, 2172 is stuck in the orphaned blocks cache.
The solution is whenever a finalized block is executed, we look up the height and block digest in the orphaned blocks cache, and see if any of the blocks can be "adopted" (if they use the finalized block as the parent).

@matthias-wright matthias-wright force-pushed the m/execute-orphaned-blocks-on-finalize branch 2 times, most recently from 828577b to f2a2e07 Compare March 11, 2026 18:31
@matthias-wright matthias-wright force-pushed the m/execute-orphaned-blocks-on-finalize branch from f2a2e07 to 052e72e Compare March 11, 2026 18:43
@matthias-wright matthias-wright merged commit bd13c7e into main Mar 11, 2026
4 checks passed
@matthias-wright matthias-wright deleted the m/execute-orphaned-blocks-on-finalize branch March 11, 2026 19:02
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