|
| 1 | +--- |
| 2 | +title: Interop reorg awareness |
| 3 | +lang: en-US |
| 4 | +description: How Superchain interop enables low-latency interop and avoids the double-spend problem. |
| 5 | +--- |
| 6 | + |
| 7 | +import { Callout } from 'nextra/components' |
| 8 | +import Image from 'next/image' |
| 9 | + |
| 10 | +import { InteropCallout } from '@/components/WipCallout' |
| 11 | + |
| 12 | +<InteropCallout /> |
| 13 | + |
| 14 | +# Interop reorg awareness |
| 15 | + |
| 16 | +[A chain reorganization, or “reorg”,](https://www.alchemy.com/overviews/what-is-a-reorg#what-happens-to-reorgs-after-the-merge) happens when validators disagree on the most accurate version of the blockchain. |
| 17 | +If not handled correctly, reorgs in a cross-chain context could result in a [double-spend problem](https://en.wikipedia.org/wiki/Double-spending). |
| 18 | +The most frequent solution to mitigate the double-spend problem is to wait for Ethereum finality; however, that solution results in high latency cross-chain communication and a poor user experience. |
| 19 | + |
| 20 | +<details> |
| 21 | + |
| 22 | +<summary>What is double-spending?</summary> |
| 23 | + |
| 24 | +```mermaid |
| 25 | +
|
| 26 | +flowchart LR |
| 27 | + subgraph init ["Initiating transaction (source chain)"] |
| 28 | + burn(tokens burned) |
| 29 | + burn-->send(send) |
| 30 | + end |
| 31 | + subgraph exec ["Executing transaction (destination chain)"] |
| 32 | + send==initiating message==>receive(receive) |
| 33 | + receive-->mint(tokens minted) |
| 34 | + end |
| 35 | +``` |
| 36 | + |
| 37 | +In a normal asset transfer tokens are burned on the source chain first, then a message is sent to the destination chain. |
| 38 | +When that message is received, the tokens are minted on the destination chain, where the user can now use those tokens. |
| 39 | + |
| 40 | +```mermaid |
| 41 | +
|
| 42 | +flowchart LR |
| 43 | + subgraph init ["Not really the source chain"] |
| 44 | + err((error)) |
| 45 | + end |
| 46 | + subgraph exec ["Executing transaction (destination chain)"] |
| 47 | + err==initiating message==>receive(receive) |
| 48 | + receive-->mint(tokens minted) |
| 49 | + end |
| 50 | +``` |
| 51 | + |
| 52 | +A double-spend problem occurs when the destination chain receives a valid initiating message, but due to issues on the source chain, such as a reorg, that initiating transaction is no longer valid. |
| 53 | +When that happens, the tokens are still on the source chain, but they are also on the destination chain. |
| 54 | + |
| 55 | +</details> |
| 56 | + |
| 57 | +Most solutions to mitigate the double-spend problem rely on [L1 finality](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/#finality). However, that solution results in high latency and poor user experience. |
| 58 | + |
| 59 | +To mitigate the double-spend problem while delivering a low-latency cross-chain experience, Superchain interop uses [block safety levels](./explainer#block-safety-levels). |
| 60 | +This means users can transfer assets across chains in the Superchain with 1-block latency, and should a reorg happen, either both the source and destination transactions would remain, or both of them would revert. |
| 61 | +In every case, there is no window of opportunity to double spend. |
| 62 | + |
| 63 | +## Block safety levels |
| 64 | + |
| 65 | +```mermaid |
| 66 | +
|
| 67 | +graph LR |
| 68 | + classDef finalized fill:#CCC |
| 69 | + classDef safe fill:#8F8 |
| 70 | + classDef unsafe fill:#F89 |
| 71 | +
|
| 72 | + subgraph A ["Chain A"] |
| 73 | + A100["A<sub>100</sub>"]-->A101["A<sub>101</sub>"]-->A102["A<sub>102</sub>"]-->A103["A<sub>103</sub>"] |
| 74 | + end |
| 75 | + subgraph B ["Chain B"] |
| 76 | + B300["B<sub>300</sub>"]-->B301["B<sub>301</sub>"]-->B302["B<sub>302</sub>"]-->B303["B<sub>303</sub>"] |
| 77 | + end |
| 78 | + A101-.->B302 |
| 79 | + B300-.->A100 |
| 80 | + class A100,B300,B301 safe |
| 81 | + class A101,A102,A103,B302,B303 unsafe |
| 82 | +``` |
| 83 | + |
| 84 | +In the diagram above, solid arrows are the derivation of a block from the previous block in the chain. |
| 85 | +Dotted arrows go from the block with the initiating message (the source) to the block with the executing message (the destination). |
| 86 | +Blocks can either be finalized (grey), cross-safe (green), or unsafe (red). |
| 87 | +Blockchain A has only written block A<sub>100</sub> to the blockchain. |
| 88 | +As a result, block A<sub>101</sub> is unsafe, and so are all the blocks that depend on it, directly (A<sub>102</sub> and B<sub>302</sub>) or indirectly (A<sub>103</sub> and B<sub>303</sub>). |
| 89 | +Blocks B<sub>302</sub> and B<sub>303</sub> may be *local-safe* (if they are written to L1), but they cannot be *cross-safe* because they depend on a block that isn't. |
| 90 | +If all goes well, eventually A<sub>101</sub> will be written to L1, turn safe, and then the blocks that depend on it can become safe as well. |
| 91 | + |
| 92 | +The message between A<sub>101</sub> and B<sub>302</sub> can be an asset moving across the bridge. |
| 93 | +In that case, the initiating message (A<sub>101</sub>) burns `n` tokens on the source chain (A), and the executing message (B<sub>302</sub>) mints `n` tokens on the destination chain (B). |
| 94 | + |
| 95 | +### L1 reorg |
| 96 | + |
| 97 | +In this case, an L1 block is replaced, and the new block either contains the same blob with chain data that was contained in the old block, or it doesn't. |
| 98 | +If the new block contains the same blob, the change is meaningless from the L2 perspective. |
| 99 | +If the new block does not contain the same blob, then the sequencer on the chain will know it is missing and reposts it. |
| 100 | + |
| 101 | +So L1 reorgs are basically invisible to L2. |
| 102 | + |
| 103 | +### Equivocation |
| 104 | + |
| 105 | +Sequencers inform the rest of the Superchain about a new block in two ways: |
| 106 | + |
| 107 | +- The gossip protocol, which is typically used as soon as the block is created. |
| 108 | + The problem is that the gossip protocol does not create a commitment. |
| 109 | +- Posting to L1, which typically happens a few minutes after the block is created. |
| 110 | + The reason is cost, it is a lot cheaper if compression and L1 posting are done in large batches, rather than for each individual block. |
| 111 | + |
| 112 | + |
| 113 | +Equivocation happens when a sequencer publishes a block using the gossip protocol that is different from the one that eventually gets written to L1. |
| 114 | +In this case, the block that is written to L1 (let's call it A'<sub>101</sub>) is the valid one, and that causes every dependent block to be recalculated. |
| 115 | + |
| 116 | +```mermaid |
| 117 | +
|
| 118 | +graph LR |
| 119 | + classDef finalized fill:#CCC |
| 120 | + classDef safe fill:#8F8 |
| 121 | + classDef unsafe fill:#F89 |
| 122 | +
|
| 123 | + subgraph A ["Chain A"] |
| 124 | + A100["A<sub>100</sub>"]-->A101["A<sub>101</sub>"]-->A102["A<sub>102</sub>"]-->A103["A<sub>103</sub>"] |
| 125 | + A100-->A101b["A'<sub>101</sub>"]-->A102b["A'<sub>102</sub>"]-->A103b["A'<sub>103</sub>"] |
| 126 | + end |
| 127 | + subgraph B ["Chain B"] |
| 128 | + B300["B<sub>300</sub>"]-->B301["B<sub>301</sub>"]-->B302["B<sub>302</sub>"]-->B303["B<sub>303</sub>"] |
| 129 | + B300-->B301b["B'<sub>301</sub>"]-->B302b["B'<sub>302</sub>"]-->B303b["B'<sub>303</sub>"] |
| 130 | + end |
| 131 | + subgraph C ["Chain C"] |
| 132 | + C200["C<sub>200</sub>"]-->C201["C<sub>201</sub>"]-->C202["C<sub>202</sub>"]-->C203["C<sub>203</sub>"] |
| 133 | + C202-->C203b["C'<sub>203</sub>"] |
| 134 | + end |
| 135 | + A101-.->B302 |
| 136 | + A101-.->B301 |
| 137 | + A101b-.->B302b |
| 138 | + A101b-.->B301b |
| 139 | + B300-.->A100 |
| 140 | + B302-.->C203 |
| 141 | + B302b-.->C203b |
| 142 | + C200-.->B301 |
| 143 | + class C200 finalized |
| 144 | + class A100,B300,C201,C202 safe |
| 145 | + class A101b,A102b,A103b,B301b,B302b,B303b,C203b safe |
| 146 | + class A101,A102,A103,B301,B302,B303,C203 unsafe |
| 147 | +``` |
| 148 | + |
| 149 | +Note that a block can only depend directly on a block in a separate chain if the block includes an executing message that uses an initiating message from that block. |
| 150 | +So the change from A<sub>101</sub> to A'<sub>101</sub> cannot invalidate any existing safe blocks. |
| 151 | + |
| 152 | +### Invalid block |
| 153 | + |
| 154 | +If a block is invalid, even if it is posted on L1, the canonical chain replaces it with a block that only includes the deposit transactions, those transactions posted to L1. |
| 155 | + |
| 156 | +<details> |
| 157 | + |
| 158 | +<summary>What makes a block invalid?</summary> |
| 159 | + |
| 160 | +There are several potential reasons: |
| 161 | + |
| 162 | +- The block posted to L1 includes incorrect information, for example because it relied on a node on a different blockchain for interop and that node reported incorrect information. |
| 163 | +- The block was never posted. |
| 164 | + After a timeout of twelve hours all the verifiers will assume that the block that should have been posted is a deposit-only block. |
| 165 | + |
| 166 | +</details> |
| 167 | + |
| 168 | +This is functionally equivalent to equivocation, and dealt with the same way, so it can change unsafe blocks but only those blocks. |
| 169 | + |
| 170 | +{/* |
| 171 | +### L2 reorg |
| 172 | +
|
| 173 | +An L2 reorg could happen after the sequencer is decentralized. |
| 174 | +In that case, there is a deterministic FCU (fork choice update), just as there is on L1. |
| 175 | +At worst, some unsafe blocks need to be recalculated (if one fork is chosen over another). |
| 176 | +*/} |
| 177 | + |
| 178 | +## Next steps |
| 179 | + |
| 180 | +- Build a [revolutionary app](/app-developers/get-started) that uses multiple blockchains within the Superchain. |
| 181 | +- Deploy a [SuperchainERC20](./tutorials/deploy-superchain-erc20) to the Superchain. |
| 182 | +- View more [interop tutorials](./tutorials). |
0 commit comments