reth icon indicating copy to clipboard operation
reth copied to clipboard

Optimistic syncing when `finalized_hash` is zero

Open joshieDo opened this issue 1 year ago • 2 comments

Optimistic syncing

There are situations when a CL might not have a finalized block to gives us on first sync, and still expect us to sync in an optimistic way, handling any potential reorg. Currently Pipeline and BT are not ready for that, and need to be extended.

  • [x] Engine should be able to set head hash as pipeline target (https://github.com/paradigmxyz/reth/pull/7552)
  • [x] BT should be able to unwind from a reorged optimistic target that happens on pipeline (https://github.com/paradigmxyz/reth/pull/7552)
  • [ ] Pipeline should be able to detect a reorged optimistic target during Header/Bodies stage so it does not hang looking for unexisting blocks/headers

--

Proposed Pipeline flow for Header, Bodies and Finish stage

Optimistically sync to the given unfinalized tip. When a reorg is detected, do the minimum amount of work necessary, meaning that we try to unwind to the highest unreorged block and continue.

  • Header stage:
    • Checks if we were reorged, in case we time out on obtaining a block header. If so, complete the stage to the highest unreorged block known (which now becomes the new pipeline target).
  • BodiesStage
    • Checks if we were reorged, in case we time out on obtaining a block. If so, call a Header unwind and complete the stage to the highest unreorged block known (which now becomes the new pipeline target).
  • FinishStage
    • Checks if we were reorged. If so, issue a pipeline unwind to the highest unreorged block known.

Attention: highest unreorged block known does not mean that it's a finalized block.

graph TB
  Start[Start]
  Done[Done]
subgraph HeaderStage
    HeaderExecution(Execution)
    HeaderDownloader(Downloader)
    HeaderTimeout{Timeout occurred?}
    HeaderReorg{isUnfinalizedTarget && isReorged}
    TruncateGap(Truncate Gap)
    HeaderUnwind(HeaderUnwind)
end
  Start --> |Unfinalized target block| HeaderDownloader
  HeaderDownloader --> HeaderTimeout
  HeaderTimeout --> |Yes| HeaderReorg
  HeaderTimeout --> |No| HeaderExecution
  HeaderReorg --> |No| HeaderDownloader
  HeaderReorg --> |Yes| TruncateGap
  TruncateGap --> |New target block| HeaderExecution
  HeaderExecution --> |Unfinalized target block| BodiesDownloader
subgraph BodiesStage
    BodiesExecution(Execution)
    BodiesDownloader(Downloader)
    BodiesTimeout{Timeout occurred?}
    BodiesReorg{isUnfinalizedTarget && isReorged}
    TruncateGap(Truncate Gap)
end
  BodiesDownloader --> BodiesTimeout
  BodiesTimeout --> |Yes| BodiesReorg
  BodiesTimeout --> |No| BodiesExecution
  BodiesReorg --> |No| BodiesDownloader
  BodiesReorg --> |"Yes 1*"| HeaderUnwind
  HeaderUnwind --> BodiesExecution
subgraph Other Stages
    OtherStagesExecution(Execution)
end
    BodiesExecution --> OtherStagesExecution
subgraph FinishStage
    FinishExecution(Execution)
    FinishReorg{isUnfinalizedTarget && isReorged}
end
    OtherStagesExecution --> FinishExecution
    FinishExecution --> FinishReorg
    FinishReorg --> |"Yes (N blocks)"| PipelineUnwind("PipelineUnwind (N)")
    FinishReorg --> |No| Done
  1. We can either call HeaderStage::unwind from the body stage, or end the current stage with the new target block and then call pipeline unwind to the new target block

Additional context

No response

joshieDo avatar Apr 07 '24 17:04 joshieDo

This issue is stale because it has been open for 21 days with no activity.

github-actions[bot] avatar Apr 29 '24 01:04 github-actions[bot]

@joshieDo please link the PR you have open for this

onbjerg avatar Apr 29 '24 09:04 onbjerg