Header Sync

Header pallet on the target chain, keeps track of the forks, but requires finality for blocks that perform authority set changes. That means, it won't sync a fork with authority set change unless that change finalized.

sequenceDiagram participant Source Chain participant Relayer participant Target Chain Note right of Target Chain: Best: 0, Finalized: 0 Source Chain ->> Source Chain: Import Block 1 Source Chain ->> Source Chain: Import Block 2 Relayer ->> Target Chain: Submit Block 1 Note right of Target Chain: Best: 1, Finalized: 0 Relayer ->> Target Chain: Submit Block 2 Note right of Target Chain: Best: 2, Finalized: 0 Source Chain ->> Source Chain: Import Block 2' Relayer ->> Target Chain: Submit Block 2' Note right of Target Chain: Best: 2 or 2', Finalized: 0 Source Chain ->> Source Chain: Finalize Block 2' Relayer ->> Target Chain: Submit Finality of Block 2' Note right of Target Chain: Best: 2', Finalized: 2'

Message Delivery (single lane)

Pending messages are stored on-chain (source) so the relayer code is completely stateless - it can read all the details from the chain.

Delivering pending messages requires finality first.

sequenceDiagram participant Source Chain participant Relayer participant Target Chain Source Chain ->> Source Chain: Queue Message 1 Source Chain ->> Source Chain: Queue Message 2 Source Chain ->> Source Chain: Queue Message 3 Note left of Source Chain: Queued Messages: [1, 2, 3, ] Note left of Source Chain: Reward for [1, 2, 3, ] reserved Relayer ->> Target Chain: Deliver Messages 1..2 Note right of Target Chain: Target chain dispatches the messages.
To Confirm: {1..2 => relayer_1} Relayer ->> Source Chain: Delivery Confirmation of 1..2 Note left of Source Chain: Queued Messages: [3, ] Note left of Source Chain: Reward payout for [1, 2, ] Relayer -->> Target Chain: Confirmed Messages 1..2 Note right of Target Chain: To Confirm: {} Note over Relayer, Target Chain: (this is not a separate transaction,
it's bundled with the "Deliver Messages" proof)