Skip to content

Commit f84e1ad

Browse files
authored
Merge pull request #1277 from qbzzt/250123-reorg
Page for reorgs and sequencing errors
2 parents 18d0d08 + df30b6f commit f84e1ad

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

pages/stack/interop/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"op-supervisor": "OP Supervisor",
66
"superchain-weth": "Interoperable ETH",
77
"superchain-erc20": "SuperchainERC20",
8+
"reorg": "Interop reorg awareness",
89
"interop-security": "Safe interoperability",
910
"tools": "Tools",
1011
"tutorials": "Tutorials"

pages/stack/interop/reorg.mdx

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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

Comments
 (0)