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
e409d0d1
Unverified
Commit
e409d0d1
authored
Aug 07, 2023
by
OptimismBot
Committed by
GitHub
Aug 07, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6621 from ethereum-optimism/aj/cannon-e2e
op-e2e: Add initial e2e test for cannon dispute game
parents
b604d42e
e0b84e56
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
285 additions
and
134 deletions
+285
-134
helper.go
op-e2e/e2eutils/challenger/helper.go
+14
-0
alphabet_helper.go
op-e2e/e2eutils/disputegame/alphabet_helper.go
+33
-0
cannon_helper.go
op-e2e/e2eutils/disputegame/cannon_helper.go
+35
-0
game_helper.go
op-e2e/e2eutils/disputegame/game_helper.go
+111
-0
helper.go
op-e2e/e2eutils/disputegame/helper.go
+65
-134
faultproof_test.go
op-e2e/faultproof_test.go
+27
-0
No files found.
op-e2e/e2eutils/challenger/helper.go
View file @
e409d0d1
...
...
@@ -3,6 +3,7 @@ package challenger
import
(
"context"
"errors"
"os"
"testing"
"time"
...
...
@@ -40,6 +41,19 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st
require
.
NotEmpty
(
t
,
cfg
.
TxMgrConfig
.
PrivateKey
,
"Missing private key for TxMgrConfig"
)
require
.
NoError
(
t
,
cfg
.
Check
(),
"op-challenger config should be valid"
)
if
cfg
.
CannonBin
!=
""
{
_
,
err
:=
os
.
Stat
(
cfg
.
CannonBin
)
require
.
NoError
(
t
,
err
,
"cannon should be built. Make sure you've run make cannon-prestate"
)
}
if
cfg
.
CannonServer
!=
""
{
_
,
err
:=
os
.
Stat
(
cfg
.
CannonServer
)
require
.
NoError
(
t
,
err
,
"op-program should be built. Make sure you've run make cannon-prestate"
)
}
if
cfg
.
CannonAbsolutePreState
!=
""
{
_
,
err
:=
os
.
Stat
(
cfg
.
CannonAbsolutePreState
)
require
.
NoError
(
t
,
err
,
"cannon pre-state should be built. Make sure you've run make cannon-prestate"
)
}
errCh
:=
make
(
chan
error
,
1
)
ctx
,
cancel
:=
context
.
WithCancel
(
ctx
)
go
func
()
{
...
...
op-e2e/e2eutils/disputegame/alphabet_helper.go
0 → 100644
View file @
e409d0d1
package
disputegame
import
(
"context"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
)
type
AlphabetGameHelper
struct
{
FaultGameHelper
claimedAlphabet
string
}
func
(
g
*
AlphabetGameHelper
)
StartChallenger
(
ctx
context
.
Context
,
l1Endpoint
string
,
name
string
,
options
...
challenger
.
Option
)
*
challenger
.
Helper
{
opts
:=
[]
challenger
.
Option
{
func
(
c
*
config
.
Config
)
{
c
.
GameAddress
=
g
.
addr
c
.
GameDepth
=
alphabetGameDepth
c
.
TraceType
=
config
.
TraceTypeAlphabet
// By default the challenger agrees with the root claim (thus disagrees with the proposed output)
// This can be overridden by passing in options
c
.
AlphabetTrace
=
g
.
claimedAlphabet
c
.
AgreeWithProposedOutput
=
false
},
}
opts
=
append
(
opts
,
options
...
)
c
:=
challenger
.
NewChallenger
(
g
.
t
,
ctx
,
l1Endpoint
,
name
,
opts
...
)
g
.
t
.
Cleanup
(
func
()
{
_
=
c
.
Close
()
})
return
c
}
op-e2e/e2eutils/disputegame/cannon_helper.go
0 → 100644
View file @
e409d0d1
package
disputegame
import
(
"context"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
)
type
CannonGameHelper
struct
{
FaultGameHelper
}
func
(
g
*
CannonGameHelper
)
StartChallenger
(
ctx
context
.
Context
,
l1Endpoint
string
,
l2Endpoint
string
,
name
string
,
options
...
challenger
.
Option
)
*
challenger
.
Helper
{
opts
:=
[]
challenger
.
Option
{
func
(
c
*
config
.
Config
)
{
c
.
GameAddress
=
g
.
addr
c
.
GameDepth
=
cannonGameDepth
c
.
TraceType
=
config
.
TraceTypeCannon
c
.
AgreeWithProposedOutput
=
false
c
.
CannonL2
=
l2Endpoint
c
.
CannonBin
=
"../cannon/bin/cannon"
c
.
CannonDatadir
=
g
.
t
.
TempDir
()
c
.
CannonServer
=
"../op-program/bin/op-program"
c
.
CannonAbsolutePreState
=
"../op-program/bin/prestate.json"
c
.
CannonSnapshotFreq
=
config
.
DefaultCannonSnapshotFreq
},
}
opts
=
append
(
opts
,
options
...
)
c
:=
challenger
.
NewChallenger
(
g
.
t
,
ctx
,
l1Endpoint
,
name
,
opts
...
)
g
.
t
.
Cleanup
(
func
()
{
_
=
c
.
Close
()
})
return
c
}
op-e2e/e2eutils/disputegame/game_helper.go
0 → 100644
View file @
e409d0d1
package
disputegame
import
(
"context"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
type
FaultGameHelper
struct
{
t
*
testing
.
T
require
*
require
.
Assertions
client
*
ethclient
.
Client
opts
*
bind
.
TransactOpts
game
*
bindings
.
FaultDisputeGame
maxDepth
int
addr
common
.
Address
}
func
(
g
*
FaultGameHelper
)
GameDuration
(
ctx
context
.
Context
)
time
.
Duration
{
duration
,
err
:=
g
.
game
.
GAMEDURATION
(
&
bind
.
CallOpts
{
Context
:
ctx
})
g
.
require
.
NoError
(
err
,
"failed to get game duration"
)
return
time
.
Duration
(
duration
)
*
time
.
Second
}
func
(
g
*
FaultGameHelper
)
WaitForClaimCount
(
ctx
context
.
Context
,
count
int64
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
actual
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
err
}
g
.
t
.
Log
(
"Waiting for claim count"
,
"current"
,
actual
,
"expected"
,
count
,
"game"
,
g
.
addr
)
return
actual
.
Cmp
(
big
.
NewInt
(
count
))
==
0
,
nil
})
g
.
require
.
NoError
(
err
)
}
type
ContractClaim
struct
{
ParentIndex
uint32
Countered
bool
Claim
[
32
]
byte
Position
*
big
.
Int
Clock
*
big
.
Int
}
func
(
g
*
FaultGameHelper
)
WaitForClaim
(
ctx
context
.
Context
,
predicate
func
(
claim
ContractClaim
)
bool
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
count
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"retrieve number of claims: %w"
,
err
)
}
// Search backwards because the new claims are at the end and more likely the ones we want.
for
i
:=
count
.
Int64
()
-
1
;
i
>=
0
;
i
--
{
claimData
,
err
:=
g
.
game
.
ClaimData
(
&
bind
.
CallOpts
{
Context
:
ctx
},
big
.
NewInt
(
i
))
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"retrieve claim %v: %w"
,
i
,
err
)
}
if
predicate
(
claimData
)
{
return
true
,
nil
}
}
return
false
,
nil
})
g
.
require
.
NoError
(
err
)
}
func
(
g
*
FaultGameHelper
)
WaitForClaimAtMaxDepth
(
ctx
context
.
Context
,
countered
bool
)
{
g
.
WaitForClaim
(
ctx
,
func
(
claim
ContractClaim
)
bool
{
pos
:=
types
.
NewPositionFromGIndex
(
claim
.
Position
.
Uint64
())
return
pos
.
Depth
()
==
g
.
maxDepth
&&
claim
.
Countered
==
countered
})
}
func
(
g
*
FaultGameHelper
)
Resolve
(
ctx
context
.
Context
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
defer
cancel
()
tx
,
err
:=
g
.
game
.
Resolve
(
g
.
opts
)
g
.
require
.
NoError
(
err
)
_
,
err
=
utils
.
WaitReceiptOK
(
ctx
,
g
.
client
,
tx
.
Hash
())
g
.
require
.
NoError
(
err
)
}
func
(
g
*
FaultGameHelper
)
WaitForGameStatus
(
ctx
context
.
Context
,
expected
Status
)
{
g
.
t
.
Logf
(
"Waiting for game %v to have status %v"
,
g
.
addr
,
expected
)
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
30
*
time
.
Second
)
defer
cancel
()
status
,
err
:=
g
.
game
.
Status
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"game status unavailable: %w"
,
err
)
}
g
.
t
.
Logf
(
"Game %v has state %v, waiting for state %v"
,
g
.
addr
,
Status
(
status
),
expected
)
return
expected
==
Status
(
status
),
nil
})
g
.
require
.
NoError
(
err
,
"wait for game status"
)
}
op-e2e/e2eutils/disputegame/helper.go
View file @
e409d0d1
...
...
@@ -11,10 +11,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -22,8 +19,10 @@ import (
"github.com/stretchr/testify/require"
)
const
faultGameType
uint8
=
0
const
alphabetGameType
uint8
=
0
const
cannonGameType
uint8
=
1
const
alphabetGameDepth
=
4
const
cannonGameDepth
=
64
const
lastAlphabetTraceIndex
=
1
<<
alphabetGameDepth
-
1
type
Status
uint8
...
...
@@ -86,38 +85,20 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, deployments *genesis.L1
}
}
func
(
h
*
FactoryHelper
)
StartAlphabetGame
(
ctx
context
.
Context
,
claimedAlphabet
string
)
*
FaultGameHelper
{
// Wait for two output proposals to be published
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
2
*
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
index
,
err
:=
h
.
l2oo
.
LatestOutputIndex
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
h
.
t
.
Logf
(
"Could not get latest output index: %v"
,
err
.
Error
())
return
false
,
nil
}
h
.
t
.
Logf
(
"Latest output index: %v"
,
index
)
return
index
.
Cmp
(
big
.
NewInt
(
1
))
>=
0
,
nil
})
h
.
require
.
NoError
(
err
,
"Did not get two output roots"
)
func
(
h
*
FactoryHelper
)
StartAlphabetGame
(
ctx
context
.
Context
,
claimedAlphabet
string
)
*
AlphabetGameHelper
{
h
.
waitForProposals
(
ctx
)
l1Head
:=
h
.
checkpointL1Block
(
ctx
)
ctx
,
cancel
=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
ctx
,
cancel
:
=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
defer
cancel
()
// Store the current block in the oracle
tx
,
err
:=
h
.
blockOracle
.
Checkpoint
(
h
.
opts
)
h
.
require
.
NoError
(
err
)
r
,
err
:=
utils
.
WaitReceiptOK
(
ctx
,
h
.
client
,
tx
.
Hash
())
h
.
require
.
NoError
(
err
,
"failed to store block in blockoracle"
)
l1Head
:=
new
(
big
.
Int
)
.
Sub
(
r
.
BlockNumber
,
big
.
NewInt
(
1
))
trace
:=
alphabet
.
NewTraceProvider
(
claimedAlphabet
,
alphabetGameDepth
)
rootClaim
,
err
:=
trace
.
Get
(
ctx
,
lastAlphabetTraceIndex
)
h
.
require
.
NoError
(
err
,
"get root claim"
)
extraData
:=
make
([]
byte
,
64
)
binary
.
BigEndian
.
PutUint64
(
extraData
[
24
:
],
uint64
(
8
))
binary
.
BigEndian
.
PutUint64
(
extraData
[
56
:
],
l1Head
.
Uint64
())
tx
,
err
=
h
.
factory
.
Create
(
h
.
opts
,
faul
tGameType
,
rootClaim
,
extraData
)
tx
,
err
:=
h
.
factory
.
Create
(
h
.
opts
,
alphabe
tGameType
,
rootClaim
,
extraData
)
h
.
require
.
NoError
(
err
,
"create fault dispute game"
)
rcpt
,
err
:=
utils
.
WaitReceiptOK
(
ctx
,
h
.
client
,
tx
.
Hash
())
h
.
require
.
NoError
(
err
,
"wait for create fault dispute game receipt to be OK"
)
...
...
@@ -126,129 +107,79 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
h
.
require
.
NoError
(
err
)
game
,
err
:=
bindings
.
NewFaultDisputeGame
(
createdEvent
.
DisputeProxy
,
h
.
client
)
h
.
require
.
NoError
(
err
)
return
&
FaultGameHelper
{
t
:
h
.
t
,
require
:
h
.
require
,
client
:
h
.
client
,
opts
:
h
.
opts
,
game
:
game
,
maxDepth
:
alphabetGameDepth
,
addr
:
createdEvent
.
DisputeProxy
,
claimedAlphabet
:
claimedAlphabet
,
}
}
type
FaultGameHelper
struct
{
t
*
testing
.
T
require
*
require
.
Assertions
client
*
ethclient
.
Client
opts
*
bind
.
TransactOpts
game
*
bindings
.
FaultDisputeGame
maxDepth
int
addr
common
.
Address
claimedAlphabet
string
}
func
(
g
*
FaultGameHelper
)
StartChallenger
(
ctx
context
.
Context
,
l1Endpoint
string
,
name
string
,
options
...
challenger
.
Option
)
*
challenger
.
Helper
{
opts
:=
[]
challenger
.
Option
{
func
(
c
*
config
.
Config
)
{
c
.
GameAddress
=
g
.
addr
c
.
GameDepth
=
alphabetGameDepth
c
.
TraceType
=
config
.
TraceTypeAlphabet
// By default the challenger agrees with the root claim (thus disagrees with the proposed output)
// This can be overridden by passing in options
c
.
AlphabetTrace
=
g
.
claimedAlphabet
c
.
AgreeWithProposedOutput
=
false
return
&
AlphabetGameHelper
{
FaultGameHelper
:
FaultGameHelper
{
t
:
h
.
t
,
require
:
h
.
require
,
client
:
h
.
client
,
opts
:
h
.
opts
,
game
:
game
,
maxDepth
:
alphabetGameDepth
,
addr
:
createdEvent
.
DisputeProxy
,
},
claimedAlphabet
:
claimedAlphabet
,
}
opts
=
append
(
opts
,
options
...
)
c
:=
challenger
.
NewChallenger
(
g
.
t
,
ctx
,
l1Endpoint
,
name
,
opts
...
)
g
.
t
.
Cleanup
(
func
()
{
_
=
c
.
Close
()
})
return
c
}
func
(
g
*
FaultGameHelper
)
GameDuration
(
ctx
context
.
Context
)
time
.
Duration
{
duration
,
err
:=
g
.
game
.
GAMEDURATION
(
&
bind
.
CallOpts
{
Context
:
ctx
})
g
.
require
.
NoError
(
err
,
"failed to get game duration"
)
return
time
.
Duration
(
duration
)
*
time
.
Second
}
func
(
h
*
FactoryHelper
)
StartCannonGame
(
ctx
context
.
Context
,
rootClaim
common
.
Hash
)
*
CannonGameHelper
{
h
.
waitForProposals
(
ctx
)
l1Head
:=
h
.
checkpointL1Block
(
ctx
)
func
(
g
*
FaultGameHelper
)
WaitForClaimCount
(
ctx
context
.
Context
,
count
int64
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
1
*
time
.
Second
,
func
()
(
bool
,
error
)
{
actual
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
err
}
g
.
t
.
Log
(
"Waiting for claim count"
,
"current"
,
actual
,
"expected"
,
count
,
"game"
,
g
.
addr
)
return
actual
.
Cmp
(
big
.
NewInt
(
count
))
==
0
,
nil
})
g
.
require
.
NoError
(
err
)
}
type
ContractClaim
struct
{
ParentIndex
uint32
Countered
bool
Claim
[
32
]
byte
Position
*
big
.
Int
Clock
*
big
.
Int
extraData
:=
make
([]
byte
,
64
)
binary
.
BigEndian
.
PutUint64
(
extraData
[
24
:
],
uint64
(
8
))
binary
.
BigEndian
.
PutUint64
(
extraData
[
56
:
],
l1Head
.
Uint64
())
tx
,
err
:=
h
.
factory
.
Create
(
h
.
opts
,
cannonGameType
,
rootClaim
,
extraData
)
h
.
require
.
NoError
(
err
,
"create fault dispute game"
)
rcpt
,
err
:=
utils
.
WaitReceiptOK
(
ctx
,
h
.
client
,
tx
.
Hash
())
h
.
require
.
NoError
(
err
,
"wait for create fault dispute game receipt to be OK"
)
h
.
require
.
Len
(
rcpt
.
Logs
,
1
,
"should have emitted a single DisputeGameCreated event"
)
createdEvent
,
err
:=
h
.
factory
.
ParseDisputeGameCreated
(
*
rcpt
.
Logs
[
0
])
h
.
require
.
NoError
(
err
)
game
,
err
:=
bindings
.
NewFaultDisputeGame
(
createdEvent
.
DisputeProxy
,
h
.
client
)
h
.
require
.
NoError
(
err
)
return
&
CannonGameHelper
{
FaultGameHelper
:
FaultGameHelper
{
t
:
h
.
t
,
require
:
h
.
require
,
client
:
h
.
client
,
opts
:
h
.
opts
,
game
:
game
,
maxDepth
:
cannonGameDepth
,
addr
:
createdEvent
.
DisputeProxy
,
},
}
}
func
(
g
*
FaultGameHelper
)
WaitForClaim
(
ctx
context
.
Context
,
predicate
func
(
claim
ContractClaim
)
bool
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
// waitForProposals waits until there are at least two proposals in the output oracle
// This is the minimum required for creating a game.
func
(
h
*
FactoryHelper
)
waitForProposals
(
ctx
context
.
Context
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
2
*
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
1
*
time
.
Second
,
func
()
(
bool
,
error
)
{
count
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
ctx
})
err
:=
utils
.
WaitFor
(
ctx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
index
,
err
:=
h
.
l2oo
.
LatestOutputIndex
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"retrieve number of claims: %w"
,
err
)
}
// Search backwards because the new claims are at the end and more likely the ones we want.
for
i
:=
count
.
Int64
()
-
1
;
i
>=
0
;
i
--
{
claimData
,
err
:=
g
.
game
.
ClaimData
(
&
bind
.
CallOpts
{
Context
:
ctx
},
big
.
NewInt
(
i
))
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"retrieve claim %v: %w"
,
i
,
err
)
}
if
predicate
(
claimData
)
{
return
true
,
nil
}
h
.
t
.
Logf
(
"Could not get latest output index: %v"
,
err
.
Error
())
return
false
,
nil
}
return
false
,
nil
})
g
.
require
.
NoError
(
err
)
}
func
(
g
*
FaultGameHelper
)
WaitForClaimAtMaxDepth
(
ctx
context
.
Context
,
countered
bool
)
{
g
.
WaitForClaim
(
ctx
,
func
(
claim
ContractClaim
)
bool
{
pos
:=
types
.
NewPositionFromGIndex
(
claim
.
Position
.
Uint64
())
return
pos
.
Depth
()
==
g
.
maxDepth
&&
claim
.
Countered
==
countered
h
.
t
.
Logf
(
"Latest output index: %v"
,
index
)
return
index
.
Cmp
(
big
.
NewInt
(
1
))
>=
0
,
nil
})
h
.
require
.
NoError
(
err
,
"Did not get two output roots"
)
}
func
(
g
*
FaultGameHelper
)
Resolve
(
ctx
context
.
Context
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
defer
cancel
()
tx
,
err
:=
g
.
game
.
Resolve
(
g
.
opts
)
g
.
require
.
NoError
(
err
)
_
,
err
=
utils
.
WaitReceiptOK
(
ctx
,
g
.
client
,
tx
.
Hash
())
g
.
require
.
NoError
(
err
)
}
func
(
g
*
FaultGameHelper
)
WaitForGameStatus
(
ctx
context
.
Context
,
expected
Status
)
{
g
.
t
.
Logf
(
"Waiting for game %v to have status %v"
,
g
.
addr
,
expected
)
// checkpointL1Block stores the current L1 block in the oracle
// Returns the L1 block number that was stored as the checkpoint
func
(
h
*
FactoryHelper
)
checkpointL1Block
(
ctx
context
.
Context
)
*
big
.
Int
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
defer
cancel
()
err
:=
utils
.
WaitFor
(
ctx
,
1
*
time
.
Second
,
func
()
(
bool
,
error
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
30
*
time
.
Second
)
defer
cancel
()
status
,
err
:=
g
.
game
.
Status
(
&
bind
.
CallOpts
{
Context
:
ctx
})
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"game status unavailable: %w"
,
err
)
}
g
.
t
.
Logf
(
"Game %v has state %v, waiting for state %v"
,
g
.
addr
,
Status
(
status
),
expected
)
return
expected
==
Status
(
status
),
nil
})
g
.
require
.
NoError
(
err
,
"wait for game status"
)
// Store the current block in the oracle
tx
,
err
:=
h
.
blockOracle
.
Checkpoint
(
h
.
opts
)
h
.
require
.
NoError
(
err
)
r
,
err
:=
utils
.
WaitReceiptOK
(
ctx
,
h
.
client
,
tx
.
Hash
())
h
.
require
.
NoError
(
err
,
"failed to store block in block oracle"
)
return
new
(
big
.
Int
)
.
Sub
(
r
.
BlockNumber
,
big
.
NewInt
(
1
))
}
op-e2e/faultproof_test.go
View file @
e409d0d1
...
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
...
...
@@ -143,6 +144,32 @@ func TestChallengerCompleteDisputeGame(t *testing.T) {
}
}
func
TestCannonDisputeGame
(
t
*
testing
.
T
)
{
t
.
Skip
(
"CLI-4290: op-challenger doesn't handle trace extension correctly for cannon"
)
InitParallel
(
t
)
ctx
:=
context
.
Background
()
sys
,
l1Client
:=
startFaultDisputeSystem
(
t
)
t
.
Cleanup
(
sys
.
Close
)
disputeGameFactory
:=
disputegame
.
NewFactoryHelper
(
t
,
ctx
,
sys
.
cfg
.
L1Deployments
,
l1Client
)
game
:=
disputeGameFactory
.
StartCannonGame
(
ctx
,
common
.
Hash
{
0xaa
})
require
.
NotNil
(
t
,
game
)
game
.
StartChallenger
(
ctx
,
sys
.
NodeEndpoint
(
"l1"
),
sys
.
NodeEndpoint
(
"sequencer"
),
"Challenger"
,
func
(
c
*
config
.
Config
)
{
c
.
AgreeWithProposedOutput
=
true
// Agree with the proposed output, so disagree with the root claim
c
.
TxMgrConfig
.
PrivateKey
=
e2eutils
.
EncodePrivKeyToString
(
sys
.
cfg
.
Secrets
.
Alice
)
})
// Challenger should counter the root claim
game
.
WaitForClaimCount
(
ctx
,
2
)
sys
.
TimeTravelClock
.
AdvanceTime
(
game
.
GameDuration
(
ctx
))
require
.
NoError
(
t
,
utils
.
WaitNextBlock
(
ctx
,
l1Client
))
game
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
}
func
startFaultDisputeSystem
(
t
*
testing
.
T
)
(
*
System
,
*
ethclient
.
Client
)
{
cfg
:=
DefaultSystemConfig
(
t
)
delete
(
cfg
.
Nodes
,
"verifier"
)
...
...
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