Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
181cafc9
Unverified
Commit
181cafc9
authored
Apr 06, 2023
by
mergify[bot]
Committed by
GitHub
Apr 06, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into aj/l1-fetcher-only
parents
8ca043fc
2e55f891
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
463 additions
and
19 deletions
+463
-19
main.go
op-chain-ops/cmd/op-migrate/main.go
+9
-4
config.go
op-chain-ops/genesis/config.go
+20
-0
genesis.go
op-chain-ops/genesis/genesis.go
+2
-1
setup.go
op-e2e/setup.go
+1
-1
system_test.go
op-e2e/system_test.go
+11
-5
channel_bank.go
op-node/rollup/derive/channel_bank.go
+1
-0
commands.go
op-wheel/commands.go
+8
-2
engine.go
op-wheel/engine/engine.go
+12
-2
mainnet.json
packages/contracts-bedrock/deploy-config/mainnet.json
+2
-2
mainnet.ts
packages/contracts-bedrock/deploy-config/mainnet.ts
+1
-1
challenger_attestation.png
specs/assets/challenger_attestation.png
+0
-0
challenger_attestation_dispute_game_created.png
specs/assets/challenger_attestation_dispute_game_created.png
+0
-0
challenger_attestation_output_proposed.png
specs/assets/challenger_attestation_output_proposed.png
+0
-0
bridges.md
specs/bridges.md
+1
-1
challenger.md
specs/challenger.md
+94
-0
dispute-game-interface.md
specs/dispute-game-interface.md
+224
-0
dispute-game.md
specs/dispute-game.md
+77
-0
No files found.
op-chain-ops/cmd/op-migrate/main.go
View file @
181cafc9
...
...
@@ -3,6 +3,7 @@ package main
import
(
"context"
"encoding/json"
"errors"
"fmt"
"math/big"
"os"
...
...
@@ -168,10 +169,14 @@ func main() {
var
block
*
types
.
Block
tag
:=
config
.
L1StartingBlockTag
if
tag
.
BlockNumber
!=
nil
{
block
,
err
=
l1Client
.
BlockByNumber
(
context
.
Background
(),
big
.
NewInt
(
tag
.
BlockNumber
.
Int64
()))
}
else
if
tag
.
BlockHash
!=
nil
{
block
,
err
=
l1Client
.
BlockByHash
(
context
.
Background
(),
*
tag
.
BlockHash
)
if
tag
==
nil
{
return
errors
.
New
(
"l1StartingBlockTag cannot be nil"
)
}
log
.
Info
(
"Using L1 Starting Block Tag"
,
"tag"
,
tag
.
String
())
if
number
,
isNumber
:=
tag
.
Number
();
isNumber
{
block
,
err
=
l1Client
.
BlockByNumber
(
context
.
Background
(),
big
.
NewInt
(
number
.
Int64
()))
}
else
if
hash
,
isHash
:=
tag
.
Hash
();
isHash
{
block
,
err
=
l1Client
.
BlockByHash
(
context
.
Background
(),
hash
)
}
else
{
return
fmt
.
Errorf
(
"invalid l1StartingBlockTag in deploy config: %v"
,
tag
)
}
...
...
op-chain-ops/genesis/config.go
View file @
181cafc9
...
...
@@ -208,6 +208,11 @@ func (d *DeployConfig) Check() error {
if
d
.
L2GenesisBlockGasLimit
==
0
{
return
fmt
.
Errorf
(
"%w: L2 genesis block gas limit cannot be 0"
,
ErrInvalidDeployConfig
)
}
// When the initial resource config is made to be configurable by the DeployConfig, ensure
// that this check is updated to use the values from the DeployConfig instead of the defaults.
if
uint64
(
d
.
L2GenesisBlockGasLimit
)
<
uint64
(
defaultResourceConfig
.
MaxResourceLimit
+
defaultResourceConfig
.
SystemTxMaxGas
)
{
return
fmt
.
Errorf
(
"%w: L2 genesis block gas limit is too small"
,
ErrInvalidDeployConfig
)
}
if
d
.
L2GenesisBlockBaseFeePerGas
==
nil
{
return
fmt
.
Errorf
(
"%w: L2 genesis block base fee per gas cannot be nil"
,
ErrInvalidDeployConfig
)
}
...
...
@@ -493,3 +498,18 @@ func (m *MarshalableRPCBlockNumberOrHash) UnmarshalJSON(b []byte) error {
*
m
=
asMarshalable
return
nil
}
// Number wraps the rpc.BlockNumberOrHash Number method.
func
(
m
*
MarshalableRPCBlockNumberOrHash
)
Number
()
(
rpc
.
BlockNumber
,
bool
)
{
return
(
*
rpc
.
BlockNumberOrHash
)(
m
)
.
Number
()
}
// Hash wraps the rpc.BlockNumberOrHash Hash method.
func
(
m
*
MarshalableRPCBlockNumberOrHash
)
Hash
()
(
common
.
Hash
,
bool
)
{
return
(
*
rpc
.
BlockNumberOrHash
)(
m
)
.
Hash
()
}
// String wraps the rpc.BlockNumberOrHash String method.
func
(
m
*
MarshalableRPCBlockNumberOrHash
)
String
()
string
{
return
(
*
rpc
.
BlockNumberOrHash
)(
m
)
.
String
()
}
op-chain-ops/genesis/genesis.go
View file @
181cafc9
...
...
@@ -15,7 +15,8 @@ import (
"github.com/ethereum/go-ethereum/params"
)
const
defaultL2GasLimit
=
15
_000_000
// defaultL2GasLimit represents the default gas limit for an L2 block.
const
defaultL2GasLimit
=
30
_000_000
// NewL2Genesis will create a new L2 genesis
func
NewL2Genesis
(
config
*
DeployConfig
,
block
*
types
.
Block
)
(
*
core
.
Genesis
,
error
)
{
...
...
op-e2e/setup.go
View file @
181cafc9
...
...
@@ -68,7 +68,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
deployConfig
:=
&
genesis
.
DeployConfig
{
L1ChainID
:
900
,
L2ChainID
:
901
,
L2BlockTime
:
2
,
L2BlockTime
:
1
,
FinalizationPeriodSeconds
:
60
*
60
*
24
,
MaxSequencerDrift
:
10
,
...
...
op-e2e/system_test.go
View file @
181cafc9
...
...
@@ -589,9 +589,10 @@ func TestSystemMockP2P(t *testing.T) {
}
cfg
:=
DefaultSystemConfig
(
t
)
// slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do.
// Keep the seq window small so the L2 chain is started quick
cfg
.
DeployConfig
.
L1BlockTime
=
10
// Disable batcher, so we don't sync from L1
cfg
.
DisableBatcher
=
true
// disable at the start, so we don't miss any gossiped blocks.
cfg
.
Nodes
[
"sequencer"
]
.
Driver
.
SequencerStopped
=
true
// connect the nodes
cfg
.
P2PTopology
=
map
[
string
][]
string
{
...
...
@@ -613,6 +614,11 @@ func TestSystemMockP2P(t *testing.T) {
require
.
Nil
(
t
,
err
,
"Error starting up system"
)
defer
sys
.
Close
()
// Enable the sequencer now that everyone is ready to receive payloads.
rollupRPCClient
,
err
:=
rpc
.
DialContext
(
context
.
Background
(),
sys
.
RollupNodes
[
"sequencer"
]
.
HTTPEndpoint
())
require
.
Nil
(
t
,
err
)
require
.
NoError
(
t
,
rollupRPCClient
.
Call
(
nil
,
"admin_startSequencer"
,
sys
.
L2GenesisCfg
.
ToBlock
()
.
Hash
()))
l2Seq
:=
sys
.
Clients
[
"sequencer"
]
l2Verif
:=
sys
.
Clients
[
"verifier"
]
...
...
@@ -634,11 +640,11 @@ func TestSystemMockP2P(t *testing.T) {
require
.
Nil
(
t
,
err
,
"Sending L2 tx to sequencer"
)
// Wait for tx to be mined on the L2 sequencer chain
receiptSeq
,
err
:=
waitForTransaction
(
tx
.
Hash
(),
l2Seq
,
6
*
time
.
Duration
(
sys
.
RollupConfig
.
BlockTime
)
*
time
.
Second
)
receiptSeq
,
err
:=
waitForTransaction
(
tx
.
Hash
(),
l2Seq
,
10
*
time
.
Duration
(
sys
.
RollupConfig
.
BlockTime
)
*
time
.
Second
)
require
.
Nil
(
t
,
err
,
"Waiting for L2 tx on sequencer"
)
// Wait until the block it was first included in shows up in the safe chain on the verifier
receiptVerif
,
err
:=
waitForTransaction
(
tx
.
Hash
(),
l2Verif
,
6
*
time
.
Duration
(
sys
.
RollupConfig
.
BlockTime
)
*
time
.
Second
)
receiptVerif
,
err
:=
waitForTransaction
(
tx
.
Hash
(),
l2Verif
,
10
*
time
.
Duration
(
sys
.
RollupConfig
.
BlockTime
)
*
time
.
Second
)
require
.
Nil
(
t
,
err
,
"Waiting for L2 tx on verifier"
)
require
.
Equal
(
t
,
receiptSeq
,
receiptVerif
)
...
...
op-node/rollup/derive/channel_bank.go
View file @
181cafc9
...
...
@@ -124,6 +124,7 @@ func (cb *ChannelBank) Read() (data []byte, err error) {
if
!
ch
.
IsReady
()
{
return
nil
,
io
.
EOF
}
cb
.
log
.
Info
(
"Reading channel"
,
"channel"
,
first
,
"frames"
,
len
(
ch
.
inputs
))
delete
(
cb
.
channels
,
first
)
cb
.
channelQueue
=
cb
.
channelQueue
[
1
:
]
...
...
op-wheel/commands.go
View file @
181cafc9
...
...
@@ -78,11 +78,17 @@ var (
EnvVar
:
opservice
.
PrefixEnvVar
(
envVarPrefix
,
"BUILDING_TIME"
),
Value
:
time
.
Second
*
6
,
}
AllowGaps
=
cli
.
BoolFlag
{
Name
:
"allow-gaps"
,
Usage
:
"allow gaps in block building, like missed slots on the beacon chain."
,
EnvVar
:
opservice
.
PrefixEnvVar
(
envVarPrefix
,
"ALLOW_GAPS"
),
}
)
func
ParseBuildingArgs
(
ctx
*
cli
.
Context
)
*
engine
.
BlockBuildingSettings
{
return
&
engine
.
BlockBuildingSettings
{
BlockTime
:
ctx
.
Uint64
(
BlockTimeFlag
.
Name
),
AllowGaps
:
ctx
.
Bool
(
AllowGaps
.
Name
),
Random
:
hashFlagValue
(
RandaoFlag
.
Name
,
ctx
),
FeeRecipient
:
addrFlagValue
(
FeeRecipientFlag
.
Name
,
ctx
),
BuildTime
:
ctx
.
Duration
(
BuildingTime
.
Name
),
...
...
@@ -336,7 +342,7 @@ var (
Usage
:
"build the next block using the Engine API"
,
Flags
:
[]
cli
.
Flag
{
EngineEndpoint
,
EngineJWTPath
,
FeeRecipientFlag
,
RandaoFlag
,
BlockTimeFlag
,
BuildingTime
,
FeeRecipientFlag
,
RandaoFlag
,
BlockTimeFlag
,
BuildingTime
,
AllowGaps
,
},
// TODO: maybe support transaction and tx pool engine flags, since we use op-geth?
// TODO: reorg flag
...
...
@@ -362,7 +368,7 @@ var (
Description
:
"The block time can be changed. The execution engine must be synced to a post-Merge state first."
,
Flags
:
append
(
append
([]
cli
.
Flag
{
EngineEndpoint
,
EngineJWTPath
,
FeeRecipientFlag
,
RandaoFlag
,
BlockTimeFlag
,
BuildingTime
,
FeeRecipientFlag
,
RandaoFlag
,
BlockTimeFlag
,
BuildingTime
,
AllowGaps
,
},
oplog
.
CLIFlags
(
envVarPrefix
)
...
),
opmetrics
.
CLIFlags
(
envVarPrefix
)
...
),
Action
:
EngineAction
(
func
(
ctx
*
cli
.
Context
,
client
client
.
RPC
)
error
{
logCfg
:=
oplog
.
ReadLocalCLIConfig
(
ctx
)
...
...
op-wheel/engine/engine.go
View file @
181cafc9
...
...
@@ -95,13 +95,22 @@ func updateForkchoice(ctx context.Context, client client.RPC, head, safe, finali
}
type
BlockBuildingSettings
struct
{
BlockTime
uint64
BlockTime
uint64
// skip a block; timestamps will still increase in multiples of BlockTime like L1, but there may be gaps.
AllowGaps
bool
Random
common
.
Hash
FeeRecipient
common
.
Address
BuildTime
time
.
Duration
}
func
BuildBlock
(
ctx
context
.
Context
,
client
client
.
RPC
,
status
*
StatusData
,
settings
*
BlockBuildingSettings
)
(
*
engine
.
ExecutableData
,
error
)
{
timestamp
:=
status
.
Head
.
Time
+
settings
.
BlockTime
if
settings
.
AllowGaps
{
now
:=
uint64
(
time
.
Now
()
.
Unix
())
if
now
>
timestamp
{
timestamp
=
now
-
((
now
-
timestamp
)
%
settings
.
BlockTime
)
}
}
var
pre
engine
.
ForkChoiceResponse
if
err
:=
client
.
CallContext
(
ctx
,
&
pre
,
"engine_forkchoiceUpdatedV1"
,
engine
.
ForkchoiceStateV1
{
...
...
@@ -109,7 +118,7 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett
SafeBlockHash
:
status
.
Safe
.
Hash
,
FinalizedBlockHash
:
status
.
Finalized
.
Hash
,
},
engine
.
PayloadAttributes
{
Timestamp
:
status
.
Head
.
Time
+
settings
.
BlockTime
,
Timestamp
:
timestamp
,
Random
:
settings
.
Random
,
SuggestedFeeRecipient
:
settings
.
FeeRecipient
,
// TODO: maybe use the L2 fields to hack in tx embedding CLI option?
...
...
@@ -210,6 +219,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg
payload
,
err
:=
BuildBlock
(
ctx
,
client
,
status
,
&
BlockBuildingSettings
{
BlockTime
:
settings
.
BlockTime
,
AllowGaps
:
settings
.
AllowGaps
,
Random
:
settings
.
Random
,
FeeRecipient
:
settings
.
FeeRecipient
,
BuildTime
:
buildTime
,
...
...
packages/contracts-bedrock/deploy-config/mainnet.json
View file @
181cafc9
...
...
@@ -25,7 +25,7 @@
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"l2GenesisBlockGasLimit"
:
"0x1
7D784
0"
,
"l2GenesisBlockGasLimit"
:
"0x1
c9c38
0"
,
"l2GenesisBlockCoinbase"
:
"0x4200000000000000000000000000000000000011"
,
"l2GenesisBlockBaseFeePerGas"
:
"0x3b9aca00"
,
"gasPriceOracleOverhead"
:
2100
,
...
...
@@ -33,4 +33,4 @@
"eip1559Denominator"
:
50
,
"eip1559Elasticity"
:
10
,
"l2GenesisRegolithTimeOffset"
:
"0x0"
}
\ No newline at end of file
}
packages/contracts-bedrock/deploy-config/mainnet.ts
View file @
181cafc9
...
...
@@ -37,7 +37,7 @@ const config: DeployConfig = {
governanceTokenSymbol
:
'
OP
'
,
governanceTokenOwner
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
l2GenesisBlockGasLimit
:
'
0x1
7D784
0
'
,
l2GenesisBlockGasLimit
:
'
0x1
c9c38
0
'
,
l2GenesisBlockCoinbase
:
'
0x4200000000000000000000000000000000000011
'
,
l2GenesisBlockBaseFeePerGas
:
'
0x3b9aca00
'
,
...
...
specs/assets/challenger_attestation.png
0 → 100644
View file @
181cafc9
466 KB
specs/assets/challenger_attestation_dispute_game_created.png
0 → 100644
View file @
181cafc9
269 KB
specs/assets/challenger_attestation_output_proposed.png
0 → 100644
View file @
181cafc9
185 KB
specs/bridges.md
View file @
181cafc9
...
...
@@ -35,7 +35,7 @@ interface StandardBridge {
function finalizeBridgeERC20(address _localToken, address _remoteToken, address _from, address _to, uint256 _amount, bytes memory _extraData) external;
function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _extraData) payable external;
function messenger() view external returns (address);
function
otherBridge
() view external returns (address);
function
OTHER_BRIDGE
() view external returns (address);
}
```
...
...
specs/challenger.md
0 → 100644
View file @
181cafc9
# Challenger Specification
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
-
[
Description
](
#description
)
-
[
Terminology
](
#terminology
)
-
[
Event and Response Lifecycle
](
#event-and-response-lifecycle
)
-
[
`GameType.FAULT`
](
#gametypefault
)
-
[
`GameType.ATTESTATION`
](
#gametypeattestation
)
-
[
`GameType.VALIDITY`
](
#gametypevalidity
)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Description
The Challenger is an off-chain agent that listens for faulty claims made about the state of
the L2 on the data availability layer. It is responsible for challenging these incorrect claims
and ensuring the correctness of all finalized claims on the settlement layer.
The Challenger agent is intended to be ran as a permissionless service by participants of the network
alongside a
[
rollup-node
](
./rollup-node.md
)
. Challenger agents will be rewarded in the form of the
bond attached to the claims they disprove.
## Terminology
-
**data availability layer**
- In the context of this document, the data availability layer is the
generic term for the location where claims about the state of the layer two are made. In the context
of Optimism, this is Ethereum Mainnet.
-
**settlement layer**
- In the context of this document, the settlement layer is the location of the
bridge as well as where funds deposited to the rollup reside. In the context of Optimism, this is
Ethereum Mainnet.
-
**L2**
- In the context of this document, the layer two of the Optimistic Rollup. In the context
of Optimism, this is the Optimism Mainnet.
-
**rollup-node**
- In the context of this document, the rollup node describes the
[
rollup-node specification
](
./rollup-node.md
)
. In the context of Optimism, this is the implementation
of the
[
rollup-node specification
](
./rollup-node.md
)
, the
`op-node`
.
## Event and Response Lifecycle
The Challenger agent is expected to be able to listen for and respond to several different events
on the data availability layer. These events and responses are parameterized depending on the type
of dispute game being played, and the Challenger listens to different events and responds uniquely
to each of the different game types. For specification of dispute game types, see the
[
Dispute Game Interfaces specification
](
./dispute-game-interface.md
)
and
[
Dispute Game specification
](
./dispute-game.md
)
.
### `GameType.FAULT`
> **Warning**
> The `FAULT` game type is not yet implemented. In the first iteration of Optimism's decentralization effort,
> challengers will respond to `ATTESTATION` games only.
**Events and Responses**
*TODO*
### `GameType.ATTESTATION`
**Events and Responses**
-
[
`L2OutputOracle.OutputProposed`
](
../packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol#L57-70
)
The
`L2OutputOracle`
contract emits this event when a new output is proposed on the data availability
layer. Each time an output is proposed, the Challenger should check to see if the output is equal
the output given by the
`optimism_outputAtBlock`
endpoint of their
`rollup-node`
.
-
If it is, the Challenger should do nothing to challenge this output proposal.
-
If it is not, the Challenger should respond by creating a new
`DisputeGame`
with the
`DisputeGameType.ATTESTATION`
`gameType`
, the correct output root as the
`rootClaim`
, and the abi-encoded
`l2BlockNumber`
of the correct output root as the
`extraData`
.
!
[
Attestation `OutputProposed` Diagram
](
./assets/challenger_attestation_output_proposed.png
)
-
`DisputeGameFactory.DisputeGameCreated`
A new dispute game has been created and is ready to be reviewed. The
Challenger agent should listen for this event and check if the
`rootClaim`
of the
`AttestationDisputeGame`
created by the
`DisputeGameFactory`
is equal to the output root of their
`rollup-node`
at the game's
`l2BlockNumber`
.
-
If it is, the Challenger should sign the
[
EIP-712 typeHash
](
./dispute-game.md
)
of the struct containing the
`AttestationDisputeGame`
's
`rootClaim`
and
`l2BlockNumber`
. The Challenger should then submit the abi-encoded
signature to the
`AttetationDisputeGame`
's
`challenge`
function.
-
If it is not, the Challenger should do nothing in support of this dispute game.
!
[
Attestation `DisputeGameCreated` Diagram
](
./assets/challenger_attestation_dispute_game_created.png
)
A full diagram and lifecycle of the Challenger's role in the
`ATTESTATION`
game type can be found below:

### `GameType.VALIDITY`
**TODO**
> **Warning**
> The `VALIDITY` game type is not yet implemented. In the first iteration of Optimism's decentralization effort,
> challengers will respond to `ATTESTATION` games only. A validity proof based dispute game is a possibility,
> but fault proof based dispute games will be the primary focus of the team in the near future.
**Events and Responses**
*TODO*
specs/dispute-game-interface.md
0 → 100644
View file @
181cafc9
This diff is collapsed.
Click to expand it.
specs/dispute-game.md
0 → 100644
View file @
181cafc9
# Dispute Game
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
-
[
Attestation Dispute Game
](
#attestation-dispute-game
)
-
[
Smart Contract Implementation
](
#smart-contract-implementation
)
-
[
Attestation Structure
](
#attestation-structure
)
-
[
Why EIP-712
](
#why-eip-712
)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Attestation Dispute Game
The output attestation based dispute game shifts the current permissioned output proposal process
to a permissionless, social-consensus based architecture that can progressively decentralize over
time by increasing the size of the signer set. In this "game," output proposals can be submitted
permissionlessly. To prevent "invalid output proposals," a social quorum can revert an output proposal
when an invalid one is discovered. The set of signers is maintained in the
`SystemConfig`
contract,
and these signers will issue
[
EIP-712
](
https://eips.ethereum.org/EIPS/eip-712
)
signatures
over canonical output roots and the
`l2BlockNumber`
s they commit to as attestations. To learn more,
see the
[
DisputeGame Interface Spec
](
./dispute-game-interface.md
)
.
In the above language, an "invalid output proposal" is defined as an output proposal that represents
a non-canonical state of the L2 chain.
### Smart Contract Implementation
The
`AttestationDisputeGame`
should implement the
`IDisputeGame`
interface and also be able to call
out to the
`L2OutputOracle`
. It is expected that the
`L2OutputOracle`
will grant permissions to
`AttestationDisputeGame`
contracts to call its
`deleteL2Outputs`
function at the
*specific*
`l2BlockNumber`
that is embedded in the
`AttestationDisputeGame`
's
`extraData`
.
The
`AttestationDisputeGame`
should be configured with a quorum ratio at deploy time. It should also
maintain a set of attestor accounts, which is fetched by the
`SystemConfig`
contract and snapshotted
at deploy time. This snapshot is necessary to have a fixed upper bound on resolution cost, which in
turn gives a fix cost for the necessary bond attached to output proposals.
The ability to add and remove attestor accounts should be enabled by a single immutable
account that controls the
`SystemConfig`
. It should be impossible to remove accounts such that quorum
is not able to be reached. It is ok to allow accounts to be added or removed in the middle of an
open challenge, as it will not affect the
`signerSet`
that exists within open challenges.
A challenge is created when an alternative output root for a given
`l2BlockNumber`
is presented to the
`DisputeGameFactory`
contract. Multiple challenges should be able to run in parallel.
For simplicity, the
`AttestationDisputeGame`
does not need to track what output proposals are
committed to as part of the attestations. It only needs to check that the attested output root
is different than the proposed output root. If this is not checked, then it will be possible
to remove output proposals that are in agreement with the attestations and create a griefing vector.
#### Attestation Structure
The EIP-712
[
typeHash
](
https://eips.ethereum.org/EIPS/eip-712#rationale-for-typehash
)
should be
defined as the following:
```
solidity
TYPE_HASH = keccak256("Dispute(bytes32 outputRoot,uint256 l2BlockNumber)");
```
The components for the
`typeHash`
are as follows:
-
`outputRoot`
- The
**correct**
output root that commits to the given
`l2BlockNumber`
. This should be a
positive attestation where the
`rootClaim`
of the
`AttestationDisputeGame`
is the
**correct**
output root
for the given
`l2BlockNumber`
.
-
`l2BlockNumber`
- The L2 block number that the
`outputRoot`
commits to. The
`outputRoot`
should commit
to the entirety of the L2 state from genesis up to and including this
`l2BlockNumber`
.
### Why EIP-712
It is important to use EIP-712 to decouple the originator of the transaction and the attestor. This
will allow a decentralized network of attestors that serve attestations to bots that are responsible
for ensuring that all output proposals submitted to the network will not allow for malicious withdrawals
from the bridge.
It is important to have replay protection to ensure that attestations cannot be used more than once.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment