Skip to content

Runner

The Runner (source) is the chain follower state machine. It holds the current Phase and manages block processing, rollbacks, and finality pruning.

Phase

data Phase m cf col op block inv
    = InRestoration (Restoring m (T m cf col op) block inv)
    | InFollowing   (Following m (T m cf col op) block inv)

The chain follower is always in one of two phases:

  • InRestoration -- bulk ingestion, no rollback support. The backend processes blocks at full speed without computing inverses.
  • InFollowing -- near the chain tip, rollback support active. Each block produces inverse operations stored in the rollback column.

Phase transitions happen via the backend's toFollowing / toRestoring continuations, which run in the outer monad (typically IO).

processBlock

processBlock
    :: (Ord slot, GCompare col, Monad m)
    => RollbackCol col slot inv ()
    -> slot
    -> block
    -> Phase m cf col op block inv
    -> T m cf col op (Phase m cf col op block inv)

Behavior depends on the current phase:

Restoration mode -- calls restore on the backend continuation. No inverse operations, no rollback storage. Returns the next InRestoration phase.

Following mode -- calls follow on the backend continuation, which returns (inv, next). The inverse is wrapped in a RollbackPoint and stored atomically in the same transaction via Rollbacks.storeRollbackPoint. Returns the next InFollowing phase.

Transaction atomicity

The backend's column mutations and the rollback point storage happen in the same Transaction. If the transaction fails, both are rolled back. This ensures the rollback column always reflects the actual backend state.

Sequence: processBlock in Following Mode

sequenceDiagram
    participant Caller
    participant Runner
    participant Backend
    participant Store as Rollback Store

    Caller->>Runner: processBlock col slot block (InFollowing f)
    Runner->>Backend: follow f block
    Backend-->>Runner: (inv, nextFollowing)
    Runner->>Store: storeRollbackPoint col slot (RollbackPoint [inv] Nothing)
    Store-->>Runner: ()
    Runner-->>Caller: InFollowing nextFollowing

rollbackTo

rollbackTo
    :: (Ord slot, Monad m, GCompare col)
    => RollbackCol col slot inv ()
    -> Following m (T m cf col op) block inv
    -> slot
    -> T m cf col op Rollbacks.RollbackResult

Only valid in following mode. Delegates to Rollbacks.rollbackTo, passing a callback that applies each RollbackPoint's inverses via the backend's applyInverse.

The store walks backward from the tip, applying inverses in reverse chronological order and deleting each rollback point. The target slot's point is kept.

Returns RollbackSucceeded n (number of points deleted) or RollbackImpossible if the target slot was not found.