fix: try to execute orphaned blocks after executing finalized block#141
Merged
matthias-wright merged 5 commits intomainfrom Mar 11, 2026
Merged
fix: try to execute orphaned blocks after executing finalized block#141matthias-wright merged 5 commits intomainfrom
matthias-wright merged 5 commits intomainfrom
Conversation
828577b to
f2a2e07
Compare
f2a2e07 to
052e72e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_blockruns, advances canonical height to 2171, prunes orphans ≤ 2171, but never checks if orphaned blocks at 2172 can now be processed (handle_notarized_blockdoes 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).