Context
The syncer stores verified block data and wakes application callers that are waiting on syncer.subscribe so proposal and verification work can continue once a requested block is locally available. The finalizer receives notarized-block updates from the syncer through a bounded mailbox for speculative finalization tracking.
These two consumers are independent for already cached blocks: application subscribers need the local block, while the finalizer update is a downstream notification. Normal syncer flow should not require finalizer mailbox progress before releasing subscribers for data the syncer already has.
Claim
During honest operation, finalizer mailbox backpressure can occur while syncer handles a notarization for a block already cached locally; while the actor is awaiting FinalizerMailbox::report, later syncer.subscribe messages for that block remain queued, so proposal or verification tasks can miss consensus deadlines despite the block already being available. The syncer awaits finalizer notarized-block reporting before it can process later mailbox work, including new subscriptions for the same already cached block.
Flow
The path is reachable when syncer handles a notarization or resolver-delivered notarized data for a block already present locally while the finalizer mailbox send is slow or blocked, and the application sends a subscription for that block after the syncer has entered the blocked report await. Existing subscribers registered before cache_block are not the affected set, because cache_block notifies them before the finalizer report.
Impact
Honest proposal or verification futures can miss consensus timeouts because later block subscription messages are queued behind speculative finalizer reporting. The impact is node-local syncer actor backpressure, not proof that subscribers already registered before the notarization are withheld until finalizer progress.
Root Cause
The syncer awaits the bounded finalizer mailbox send inside the same actor turn that should remain available to service later local block subscribers.
Code
- Engine startup passes the finalizer mailbox as the syncer's application reporter: https://github.com/SeismicSystems/summit/blob/ed2c5c8/node/src/engine.rs#L455.
FinalizerMailbox::report awaits a bounded mailbox send for SyncerUpdate: https://github.com/SeismicSystems/summit/blob/ed2c5c8/finalizer/src/ingress.rs#L484.
- For a live notarization whose block is already local, syncer calls
cache_block, then awaits application.report(Update::NotarizedBlock(...)), then calls notify_subscribers again: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L588, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L590, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L591, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L592.
- Resolver-delivered notarized data uses the same actor-blocking shape: it calls
cache_block, stores the notarization, awaits the finalizer report, then calls notify_subscribers again: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1128, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1133, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1136.
cache_block itself notifies current subscribers before writing the block to cache, so the vulnerable start condition is later subscribe messages queued while the actor is blocked, not pre-existing subscribers waiting for the post-report notify_subscribers: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1271, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1273, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1274.
notify_subscribers is the path that completes waiting block subscriptions: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1155.
- Application proposal and verification paths wait on
syncer.subscribe for parent/current blocks before they can continue: https://github.com/SeismicSystems/summit/blob/ed2c5c8/application/src/actor.rs#L247, https://github.com/SeismicSystems/summit/blob/ed2c5c8/application/src/actor.rs#L371.
Related Issues/PRs
The following existing items touch the same trust boundary, adjacent root cause, or likely remediation stack.
Note that #356 is wakeup ordering behind finalizer mailbox sends.
Fix
Avoid awaiting speculative finalizer notarized-block reporting on the syncer actor path that must continue receiving local subscriptions. Consider making NotarizedBlock finalizer delivery best-effort or independently buffered from subscriber serving. Add an integration test where finalizer mailbox backpressure does not delay a later syncer.subscribe response for an already cached notarized block.
Context
The syncer stores verified block data and wakes application callers that are waiting on
syncer.subscribeso proposal and verification work can continue once a requested block is locally available. The finalizer receives notarized-block updates from the syncer through a bounded mailbox for speculative finalization tracking.These two consumers are independent for already cached blocks: application subscribers need the local block, while the finalizer update is a downstream notification. Normal syncer flow should not require finalizer mailbox progress before releasing subscribers for data the syncer already has.
Claim
During honest operation, finalizer mailbox backpressure can occur while syncer handles a notarization for a block already cached locally; while the actor is awaiting
FinalizerMailbox::report, latersyncer.subscribemessages for that block remain queued, so proposal or verification tasks can miss consensus deadlines despite the block already being available. The syncer awaits finalizer notarized-block reporting before it can process later mailbox work, including new subscriptions for the same already cached block.Flow
The path is reachable when syncer handles a notarization or resolver-delivered notarized data for a block already present locally while the finalizer mailbox send is slow or blocked, and the application sends a subscription for that block after the syncer has entered the blocked report await. Existing subscribers registered before
cache_blockare not the affected set, becausecache_blocknotifies them before the finalizer report.Impact
Honest proposal or verification futures can miss consensus timeouts because later block subscription messages are queued behind speculative finalizer reporting. The impact is node-local syncer actor backpressure, not proof that subscribers already registered before the notarization are withheld until finalizer progress.
Root Cause
The syncer awaits the bounded finalizer mailbox send inside the same actor turn that should remain available to service later local block subscribers.
Code
FinalizerMailbox::reportawaits a bounded mailbox send forSyncerUpdate: https://github.com/SeismicSystems/summit/blob/ed2c5c8/finalizer/src/ingress.rs#L484.cache_block, then awaitsapplication.report(Update::NotarizedBlock(...)), then callsnotify_subscribersagain: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L588, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L590, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L591, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L592.cache_block, stores the notarization, awaits the finalizer report, then callsnotify_subscribersagain: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1128, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1133, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1136.cache_blockitself notifies current subscribers before writing the block to cache, so the vulnerable start condition is later subscribe messages queued while the actor is blocked, not pre-existing subscribers waiting for the post-reportnotify_subscribers: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1271, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1273, https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1274.notify_subscribersis the path that completes waiting block subscriptions: https://github.com/SeismicSystems/summit/blob/ed2c5c8/syncer/src/actor.rs#L1155.syncer.subscribefor parent/current blocks before they can continue: https://github.com/SeismicSystems/summit/blob/ed2c5c8/application/src/actor.rs#L247, https://github.com/SeismicSystems/summit/blob/ed2c5c8/application/src/actor.rs#L371.Related Issues/PRs
The following existing items touch the same trust boundary, adjacent root cause, or likely remediation stack.
Note that #356 is wakeup ordering behind finalizer mailbox sends.
Fix
Avoid awaiting speculative finalizer notarized-block reporting on the syncer actor path that must continue receiving local subscriptions. Consider making
NotarizedBlockfinalizer delivery best-effort or independently buffered from subscriber serving. Add an integration test where finalizer mailbox backpressure does not delay a latersyncer.subscriberesponse for an already cached notarized block.