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
ea12a7ae
Unverified
Commit
ea12a7ae
authored
Sep 15, 2023
by
mergify[bot]
Committed by
GitHub
Sep 15, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into aj/fix-last-step
parents
27dbdcbe
80fdee6c
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
367 additions
and
67 deletions
+367
-67
Makefile
Makefile
+0
-1
main_test.go
op-challenger/cmd/main_test.go
+20
-0
config.go
op-challenger/config/config.go
+3
-0
config_test.go
op-challenger/config/config_test.go
+7
-0
flags.go
op-challenger/flags/flags.go
+8
-0
agent.go
op-challenger/game/fault/agent.go
+7
-1
monitor.go
op-challenger/game/monitor.go
+41
-17
monitor_test.go
op-challenger/game/monitor_test.go
+152
-38
service.go
op-challenger/game/service.go
+10
-5
helper.go
op-e2e/e2eutils/challenger/helper.go
+4
-0
game_helper.go
op-e2e/e2eutils/disputegame/game_helper.go
+45
-1
helper.go
op-e2e/e2eutils/disputegame/helper.go
+1
-1
faultproof_test.go
op-e2e/faultproof_test.go
+60
-0
rpc.go
op-node/client/rpc.go
+9
-3
No files found.
Makefile
View file @
ea12a7ae
...
@@ -109,7 +109,6 @@ devnet-down:
...
@@ -109,7 +109,6 @@ devnet-down:
devnet-clean
:
devnet-clean
:
rm
-rf
./packages/contracts-bedrock/deployments/devnetL1
rm
-rf
./packages/contracts-bedrock/deployments/devnetL1
rm
-rf
./packages/contracts-bedrock/deploy-config/devnetL1.json
rm
-rf
./.devnet
rm
-rf
./.devnet
cd
./ops-bedrock
&&
docker compose down
cd
./ops-bedrock
&&
docker compose down
docker image
ls
'ops-bedrock*'
--format
=
'{{.Repository}}'
| xargs
-r
docker rmi
docker image
ls
'ops-bedrock*'
--format
=
'{{.Repository}}'
| xargs
-r
docker rmi
...
...
op-challenger/cmd/main_test.go
View file @
ea12a7ae
...
@@ -169,6 +169,26 @@ func TestMaxConcurrency(t *testing.T) {
...
@@ -169,6 +169,26 @@ func TestMaxConcurrency(t *testing.T) {
})
})
}
}
func
TestPollInterval
(
t
*
testing
.
T
)
{
t
.
Run
(
"UsesDefault"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeCannon
))
require
.
Equal
(
t
,
config
.
DefaultPollInterval
,
cfg
.
PollInterval
)
})
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
expected
:=
100
*
time
.
Second
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
,
"--http-poll-interval"
,
"100s"
))
require
.
Equal
(
t
,
expected
,
cfg
.
PollInterval
)
})
t
.
Run
(
"Invalid"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
"invalid value
\"
abc
\"
for flag -http-poll-interval"
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
,
"--http-poll-interval"
,
"abc"
))
})
}
func
TestCannonBin
(
t
*
testing
.
T
)
{
func
TestCannonBin
(
t
*
testing
.
T
)
{
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--cannon-bin"
))
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--cannon-bin"
))
...
...
op-challenger/config/config.go
View file @
ea12a7ae
...
@@ -78,6 +78,7 @@ func ValidTraceType(value TraceType) bool {
...
@@ -78,6 +78,7 @@ func ValidTraceType(value TraceType) bool {
}
}
const
(
const
(
DefaultPollInterval
=
time
.
Second
*
12
DefaultCannonSnapshotFreq
=
uint
(
1
_000_000_000
)
DefaultCannonSnapshotFreq
=
uint
(
1
_000_000_000
)
DefaultCannonInfoFreq
=
uint
(
10
_000_000
)
DefaultCannonInfoFreq
=
uint
(
10
_000_000
)
// DefaultGameWindow is the default maximum time duration in the past
// DefaultGameWindow is the default maximum time duration in the past
...
@@ -98,6 +99,7 @@ type Config struct {
...
@@ -98,6 +99,7 @@ type Config struct {
AgreeWithProposedOutput
bool
// Temporary config if we agree or disagree with the posted output
AgreeWithProposedOutput
bool
// Temporary config if we agree or disagree with the posted output
Datadir
string
// Data Directory
Datadir
string
// Data Directory
MaxConcurrency
uint
// Maximum number of threads to use when progressing games
MaxConcurrency
uint
// Maximum number of threads to use when progressing games
PollInterval
time
.
Duration
// Polling interval for latest-block subscription when using an HTTP RPC provider
TraceType
TraceType
// Type of trace
TraceType
TraceType
// Type of trace
...
@@ -131,6 +133,7 @@ func NewConfig(
...
@@ -131,6 +133,7 @@ func NewConfig(
L1EthRpc
:
l1EthRpc
,
L1EthRpc
:
l1EthRpc
,
GameFactoryAddress
:
gameFactoryAddress
,
GameFactoryAddress
:
gameFactoryAddress
,
MaxConcurrency
:
uint
(
runtime
.
NumCPU
()),
MaxConcurrency
:
uint
(
runtime
.
NumCPU
()),
PollInterval
:
DefaultPollInterval
,
AgreeWithProposedOutput
:
agreeWithProposedOutput
,
AgreeWithProposedOutput
:
agreeWithProposedOutput
,
...
...
op-challenger/config/config_test.go
View file @
ea12a7ae
...
@@ -118,6 +118,13 @@ func TestMaxConcurrency(t *testing.T) {
...
@@ -118,6 +118,13 @@ func TestMaxConcurrency(t *testing.T) {
})
})
}
}
func
TestHttpPollInterval
(
t
*
testing
.
T
)
{
t
.
Run
(
"Default"
,
func
(
t
*
testing
.
T
)
{
config
:=
validConfig
(
TraceTypeAlphabet
)
require
.
EqualValues
(
t
,
DefaultPollInterval
,
config
.
PollInterval
)
})
}
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
config
:=
validConfig
(
TraceTypeCannon
)
config
:=
validConfig
(
TraceTypeCannon
)
config
.
CannonL2
=
""
config
.
CannonL2
=
""
...
...
op-challenger/flags/flags.go
View file @
ea12a7ae
...
@@ -70,6 +70,12 @@ var (
...
@@ -70,6 +70,12 @@ var (
EnvVars
:
prefixEnvVars
(
"MAX_CONCURRENCY"
),
EnvVars
:
prefixEnvVars
(
"MAX_CONCURRENCY"
),
Value
:
uint
(
runtime
.
NumCPU
()),
Value
:
uint
(
runtime
.
NumCPU
()),
}
}
HTTPPollInterval
=
&
cli
.
DurationFlag
{
Name
:
"http-poll-interval"
,
Usage
:
"Polling interval for latest-block subscription when using an HTTP RPC provider."
,
EnvVars
:
prefixEnvVars
(
"HTTP_POLL_INTERVAL"
),
Value
:
config
.
DefaultPollInterval
,
}
AlphabetFlag
=
&
cli
.
StringFlag
{
AlphabetFlag
=
&
cli
.
StringFlag
{
Name
:
"alphabet"
,
Name
:
"alphabet"
,
Usage
:
"Correct Alphabet Trace (alphabet trace type only)"
,
Usage
:
"Correct Alphabet Trace (alphabet trace type only)"
,
...
@@ -142,6 +148,7 @@ var requiredFlags = []cli.Flag{
...
@@ -142,6 +148,7 @@ var requiredFlags = []cli.Flag{
// optionalFlags is a list of unchecked cli flags
// optionalFlags is a list of unchecked cli flags
var
optionalFlags
=
[]
cli
.
Flag
{
var
optionalFlags
=
[]
cli
.
Flag
{
MaxConcurrencyFlag
,
MaxConcurrencyFlag
,
HTTPPollInterval
,
AlphabetFlag
,
AlphabetFlag
,
GameAllowlistFlag
,
GameAllowlistFlag
,
CannonNetworkFlag
,
CannonNetworkFlag
,
...
@@ -247,6 +254,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
...
@@ -247,6 +254,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
GameAllowlist
:
allowedGames
,
GameAllowlist
:
allowedGames
,
GameWindow
:
ctx
.
Duration
(
GameWindowFlag
.
Name
),
GameWindow
:
ctx
.
Duration
(
GameWindowFlag
.
Name
),
MaxConcurrency
:
maxConcurrency
,
MaxConcurrency
:
maxConcurrency
,
PollInterval
:
ctx
.
Duration
(
HTTPPollInterval
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
...
...
op-challenger/game/fault/agent.go
View file @
ea12a7ae
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
)
)
...
@@ -66,7 +67,12 @@ func (a *Agent) Act(ctx context.Context) error {
...
@@ -66,7 +67,12 @@ func (a *Agent) Act(ctx context.Context) error {
// Perform the actions
// Perform the actions
for
_
,
action
:=
range
actions
{
for
_
,
action
:=
range
actions
{
log
:=
a
.
log
.
New
(
"action"
,
action
.
Type
,
"is_attack"
,
action
.
IsAttack
,
"parent"
,
action
.
ParentIdx
,
"value"
,
action
.
Value
)
log
:=
a
.
log
.
New
(
"action"
,
action
.
Type
,
"is_attack"
,
action
.
IsAttack
,
"parent"
,
action
.
ParentIdx
)
if
action
.
Type
==
types
.
ActionTypeStep
{
log
=
log
.
New
(
"prestate"
,
common
.
Bytes2Hex
(
action
.
PreState
),
"proof"
,
common
.
Bytes2Hex
(
action
.
ProofData
))
}
else
{
log
=
log
.
New
(
"value"
,
action
.
Value
)
}
if
action
.
OracleData
!=
nil
{
if
action
.
OracleData
!=
nil
{
a
.
log
.
Info
(
"Updating oracle data"
,
"oracleKey"
,
action
.
OracleData
.
OracleKey
,
"oracleData"
,
action
.
OracleData
.
OracleData
)
a
.
log
.
Info
(
"Updating oracle data"
,
"oracleKey"
,
action
.
OracleData
.
OracleKey
,
"oracleData"
,
action
.
OracleData
.
OracleData
)
...
...
op-challenger/game/monitor.go
View file @
ea12a7ae
...
@@ -9,7 +9,12 @@ import (
...
@@ -9,7 +9,12 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
ethTypes
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
)
)
...
@@ -32,6 +37,20 @@ type gameMonitor struct {
...
@@ -32,6 +37,20 @@ type gameMonitor struct {
gameWindow
time
.
Duration
gameWindow
time
.
Duration
fetchBlockNumber
blockNumberFetcher
fetchBlockNumber
blockNumberFetcher
allowedGames
[]
common
.
Address
allowedGames
[]
common
.
Address
l1HeadsSub
ethereum
.
Subscription
l1Source
*
headSource
}
type
MinimalSubscriber
interface
{
EthSubscribe
(
ctx
context
.
Context
,
channel
interface
{},
args
...
interface
{})
(
ethereum
.
Subscription
,
error
)
}
type
headSource
struct
{
inner
MinimalSubscriber
}
func
(
s
*
headSource
)
SubscribeNewHead
(
ctx
context
.
Context
,
ch
chan
<-
*
ethTypes
.
Header
)
(
ethereum
.
Subscription
,
error
)
{
return
s
.
inner
.
EthSubscribe
(
ctx
,
ch
,
"newHeads"
)
}
}
func
newGameMonitor
(
func
newGameMonitor
(
...
@@ -42,6 +61,7 @@ func newGameMonitor(
...
@@ -42,6 +61,7 @@ func newGameMonitor(
gameWindow
time
.
Duration
,
gameWindow
time
.
Duration
,
fetchBlockNumber
blockNumberFetcher
,
fetchBlockNumber
blockNumberFetcher
,
allowedGames
[]
common
.
Address
,
allowedGames
[]
common
.
Address
,
l1Source
MinimalSubscriber
,
)
*
gameMonitor
{
)
*
gameMonitor
{
return
&
gameMonitor
{
return
&
gameMonitor
{
logger
:
logger
,
logger
:
logger
,
...
@@ -51,6 +71,7 @@ func newGameMonitor(
...
@@ -51,6 +71,7 @@ func newGameMonitor(
gameWindow
:
gameWindow
,
gameWindow
:
gameWindow
,
fetchBlockNumber
:
fetchBlockNumber
,
fetchBlockNumber
:
fetchBlockNumber
,
allowedGames
:
allowedGames
,
allowedGames
:
allowedGames
,
l1Source
:
&
headSource
{
inner
:
l1Source
},
}
}
}
}
...
@@ -99,29 +120,32 @@ func (m *gameMonitor) progressGames(ctx context.Context, blockNum uint64) error
...
@@ -99,29 +120,32 @@ func (m *gameMonitor) progressGames(ctx context.Context, blockNum uint64) error
return
nil
return
nil
}
}
func
(
m
*
gameMonitor
)
MonitorGames
(
ctx
context
.
Context
)
error
{
func
(
m
*
gameMonitor
)
onNewL1Head
(
ctx
context
.
Context
,
sig
eth
.
L1BlockRef
)
{
m
.
logger
.
Info
(
"Monitoring fault dispute games"
)
if
err
:=
m
.
progressGames
(
ctx
,
sig
.
Number
);
err
!=
nil
{
m
.
logger
.
Error
(
"Failed to progress games"
,
"err"
,
err
)
}
}
func
(
m
*
gameMonitor
)
resubscribeFunction
(
ctx
context
.
Context
)
event
.
ResubscribeErrFunc
{
return
func
(
innerCtx
context
.
Context
,
err
error
)
(
event
.
Subscription
,
error
)
{
if
err
!=
nil
{
m
.
logger
.
Warn
(
"resubscribing after failed L1 subscription"
,
"err"
,
err
)
}
return
eth
.
WatchHeadChanges
(
ctx
,
m
.
l1Source
,
m
.
onNewL1Head
)
}
}
blockNum
:=
uint64
(
0
)
func
(
m
*
gameMonitor
)
MonitorGames
(
ctx
context
.
Context
)
error
{
m
.
l1HeadsSub
=
event
.
ResubscribeErr
(
time
.
Second
*
10
,
m
.
resubscribeFunction
(
ctx
))
for
{
for
{
select
{
select
{
case
<-
ctx
.
Done
()
:
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
return
nil
default
:
case
err
,
ok
:=
<-
m
.
l1HeadsSub
.
Err
()
:
nextBlockNum
,
err
:=
m
.
fetchBlockNumber
(
ctx
)
if
!
ok
{
if
err
!=
nil
{
m
.
logger
.
Error
(
"Failed to load current block number"
,
"err"
,
err
)
continue
}
if
nextBlockNum
>
blockNum
{
blockNum
=
nextBlockNum
if
err
:=
m
.
progressGames
(
ctx
,
nextBlockNum
);
err
!=
nil
{
m
.
logger
.
Error
(
"Failed to progress games"
,
"err"
,
err
)
}
}
if
err
:=
m
.
clock
.
SleepCtx
(
ctx
,
time
.
Second
);
err
!=
nil
{
return
err
return
err
}
}
m
.
logger
.
Error
(
"L1 subscription error"
,
"err"
,
err
)
}
}
}
}
}
}
op-challenger/game/monitor_test.go
View file @
ea12a7ae
...
@@ -2,35 +2,40 @@ package game
...
@@ -2,35 +2,40 @@ package game
import
(
import
(
"context"
"context"
"fmt"
"math/big"
"math/big"
"testing"
"testing"
"time"
"time"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
ethtypes
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/clock"
)
)
func
TestMonitorMinGameTimestamp
(
t
*
testing
.
T
)
{
func
TestMonitorMinGameTimestamp
(
t
*
testing
.
T
)
{
t
.
Parallel
()
t
.
Parallel
()
t
.
Run
(
"zero game window returns zero"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"zero game window returns zero"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Duration
(
0
)
monitor
.
gameWindow
=
time
.
Duration
(
0
)
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
})
})
t
.
Run
(
"non-zero game window with zero clock"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"non-zero game window with zero clock"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Minute
monitor
.
gameWindow
=
time
.
Minute
monitor
.
clock
=
clock
.
NewDeterministicClock
(
time
.
Unix
(
0
,
0
))
monitor
.
clock
=
clock
.
NewDeterministicClock
(
time
.
Unix
(
0
,
0
))
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
})
})
t
.
Run
(
"minimum computed correctly"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"minimum computed correctly"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Minute
monitor
.
gameWindow
=
time
.
Minute
frozen
:=
time
.
Unix
(
int64
(
time
.
Hour
.
Seconds
()),
0
)
frozen
:=
time
.
Unix
(
int64
(
time
.
Hour
.
Seconds
()),
0
)
monitor
.
clock
=
clock
.
NewDeterministicClock
(
frozen
)
monitor
.
clock
=
clock
.
NewDeterministicClock
(
frozen
)
...
@@ -39,29 +44,95 @@ func TestMonitorMinGameTimestamp(t *testing.T) {
...
@@ -39,29 +44,95 @@ func TestMonitorMinGameTimestamp(t *testing.T) {
})
})
}
}
func
TestMonitorExitsWhenContextDone
(
t
*
testing
.
T
)
{
// TestMonitorGames tests that the monitor can handle a new head event
monitor
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{{}})
// and resubscribe to new heads if the subscription errors.
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
func
TestMonitorGames
(
t
*
testing
.
T
)
{
cancel
()
t
.
Run
(
"Schedules games"
,
func
(
t
*
testing
.
T
)
{
err
:=
monitor
.
MonitorGames
(
ctx
)
addr1
:=
common
.
Address
{
0xaa
}
require
.
ErrorIs
(
t
,
err
,
context
.
Canceled
)
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
sched
,
mockHeadSource
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
source
.
games
=
[]
FaultDisputeGame
{
newFDG
(
addr1
,
9999
),
newFDG
(
addr2
,
9999
)}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
go
func
()
{
headerNotSent
:=
true
waitErr
:=
wait
.
For
(
context
.
Background
(),
100
*
time
.
Millisecond
,
func
()
(
bool
,
error
)
{
if
len
(
sched
.
scheduled
)
>=
1
{
return
true
,
nil
}
if
mockHeadSource
.
sub
==
nil
{
return
false
,
nil
}
if
headerNotSent
{
mockHeadSource
.
sub
.
headers
<-
&
ethtypes
.
Header
{
Number
:
big
.
NewInt
(
1
),
}
headerNotSent
=
false
}
return
false
,
nil
})
require
.
NoError
(
t
,
waitErr
)
mockHeadSource
.
err
=
fmt
.
Errorf
(
"eth subscribe test error"
)
cancel
()
}()
err
:=
monitor
.
MonitorGames
(
ctx
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
sched
.
scheduled
,
1
)
require
.
Equal
(
t
,
[]
common
.
Address
{
addr1
,
addr2
},
sched
.
scheduled
[
0
])
})
t
.
Run
(
"Resubscribes on error"
,
func
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
sched
,
mockHeadSource
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
source
.
games
=
[]
FaultDisputeGame
{
newFDG
(
addr1
,
9999
),
newFDG
(
addr2
,
9999
)}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
go
func
()
{
headerNotSent
:=
true
waitErr
:=
wait
.
For
(
context
.
Background
(),
100
*
time
.
Millisecond
,
func
()
(
bool
,
error
)
{
return
mockHeadSource
.
sub
!=
nil
,
nil
})
require
.
NoError
(
t
,
waitErr
)
mockHeadSource
.
sub
.
errChan
<-
fmt
.
Errorf
(
"test error"
)
waitErr
=
wait
.
For
(
context
.
Background
(),
100
*
time
.
Millisecond
,
func
()
(
bool
,
error
)
{
if
len
(
sched
.
scheduled
)
>=
1
{
return
true
,
nil
}
if
mockHeadSource
.
sub
==
nil
{
return
false
,
nil
}
if
headerNotSent
{
mockHeadSource
.
sub
.
headers
<-
&
ethtypes
.
Header
{
Number
:
big
.
NewInt
(
1
),
}
headerNotSent
=
false
}
return
false
,
nil
})
require
.
NoError
(
t
,
waitErr
)
mockHeadSource
.
err
=
fmt
.
Errorf
(
"eth subscribe test error"
)
cancel
()
}()
err
:=
monitor
.
MonitorGames
(
ctx
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
sched
.
scheduled
,
1
)
require
.
Equal
(
t
,
[]
common
.
Address
{
addr1
,
addr2
},
sched
.
scheduled
[
0
])
})
}
}
func
TestMonitorCreateAndProgressGameAgents
(
t
*
testing
.
T
)
{
func
TestMonitorCreateAndProgressGameAgents
(
t
*
testing
.
T
)
{
monitor
,
source
,
sched
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
,
source
,
sched
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
addr1
:=
common
.
Address
{
0xaa
}
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
addr2
:=
common
.
Address
{
0xbb
}
source
.
games
=
[]
FaultDisputeGame
{
source
.
games
=
[]
FaultDisputeGame
{
newFDG
(
addr1
,
9999
),
newFDG
(
addr2
,
9999
)}
{
Proxy
:
addr1
,
Timestamp
:
9999
,
},
{
Proxy
:
addr2
,
Timestamp
:
9999
,
},
}
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
(),
uint64
(
1
)))
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
(),
uint64
(
1
)))
...
@@ -72,18 +143,8 @@ func TestMonitorCreateAndProgressGameAgents(t *testing.T) {
...
@@ -72,18 +143,8 @@ func TestMonitorCreateAndProgressGameAgents(t *testing.T) {
func
TestMonitorOnlyScheduleSpecifiedGame
(
t
*
testing
.
T
)
{
func
TestMonitorOnlyScheduleSpecifiedGame
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0xaa
}
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
sched
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
addr2
})
monitor
,
source
,
sched
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
addr2
})
source
.
games
=
[]
FaultDisputeGame
{
newFDG
(
addr1
,
9999
),
newFDG
(
addr2
,
9999
)}
source
.
games
=
[]
FaultDisputeGame
{
{
Proxy
:
addr1
,
Timestamp
:
9999
,
},
{
Proxy
:
addr2
,
Timestamp
:
9999
,
},
}
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
(),
uint64
(
1
)))
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
(),
uint64
(
1
)))
...
@@ -91,7 +152,17 @@ func TestMonitorOnlyScheduleSpecifiedGame(t *testing.T) {
...
@@ -91,7 +152,17 @@ func TestMonitorOnlyScheduleSpecifiedGame(t *testing.T) {
require
.
Equal
(
t
,
[]
common
.
Address
{
addr2
},
sched
.
scheduled
[
0
])
require
.
Equal
(
t
,
[]
common
.
Address
{
addr2
},
sched
.
scheduled
[
0
])
}
}
func
setupMonitorTest
(
t
*
testing
.
T
,
allowedGames
[]
common
.
Address
)
(
*
gameMonitor
,
*
stubGameSource
,
*
stubScheduler
)
{
func
newFDG
(
proxy
common
.
Address
,
timestamp
uint64
)
FaultDisputeGame
{
return
FaultDisputeGame
{
Proxy
:
proxy
,
Timestamp
:
timestamp
,
}
}
func
setupMonitorTest
(
t
*
testing
.
T
,
allowedGames
[]
common
.
Address
,
)
(
*
gameMonitor
,
*
stubGameSource
,
*
stubScheduler
,
*
mockNewHeadSource
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
source
:=
&
stubGameSource
{}
source
:=
&
stubGameSource
{}
i
:=
uint64
(
1
)
i
:=
uint64
(
1
)
...
@@ -100,15 +171,58 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
...
@@ -100,15 +171,58 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
return
i
,
nil
return
i
,
nil
}
}
sched
:=
&
stubScheduler
{}
sched
:=
&
stubScheduler
{}
monitor
:=
newGameMonitor
(
logger
,
clock
.
SystemClock
,
source
,
sched
,
time
.
Duration
(
0
),
fetchBlockNum
,
allowedGames
)
mockHeadSource
:=
&
mockNewHeadSource
{}
return
monitor
,
source
,
sched
monitor
:=
newGameMonitor
(
logger
,
clock
.
SystemClock
,
source
,
sched
,
time
.
Duration
(
0
),
fetchBlockNum
,
allowedGames
,
mockHeadSource
,
)
return
monitor
,
source
,
sched
,
mockHeadSource
}
type
mockNewHeadSource
struct
{
sub
*
mockSubscription
err
error
}
func
(
m
*
mockNewHeadSource
)
EthSubscribe
(
ctx
context
.
Context
,
ch
any
,
args
...
any
,
)
(
ethereum
.
Subscription
,
error
)
{
errChan
:=
make
(
chan
error
)
m
.
sub
=
&
mockSubscription
{
errChan
,
(
ch
)
.
(
chan
<-
*
ethtypes
.
Header
)}
if
m
.
err
!=
nil
{
return
nil
,
m
.
err
}
return
m
.
sub
,
nil
}
type
mockSubscription
struct
{
errChan
chan
error
headers
chan
<-
*
ethtypes
.
Header
}
func
(
m
*
mockSubscription
)
Unsubscribe
()
{}
func
(
m
*
mockSubscription
)
Err
()
<-
chan
error
{
return
m
.
errChan
}
}
type
stubGameSource
struct
{
type
stubGameSource
struct
{
games
[]
FaultDisputeGame
games
[]
FaultDisputeGame
}
}
func
(
s
*
stubGameSource
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
earliest
uint64
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
func
(
s
*
stubGameSource
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
earliest
uint64
,
blockNumber
*
big
.
Int
,
)
([]
FaultDisputeGame
,
error
)
{
return
s
.
games
,
nil
return
s
.
games
,
nil
}
}
...
...
op-challenger/game/service.go
View file @
ea12a7ae
...
@@ -10,6 +10,7 @@ import (
...
@@ -10,6 +10,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/version"
"github.com/ethereum-optimism/optimism/op-challenger/version"
opClient
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/clock"
oppprof
"github.com/ethereum-optimism/optimism/op-service/pprof"
oppprof
"github.com/ethereum-optimism/optimism/op-service/pprof"
...
@@ -34,7 +35,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
...
@@ -34,7 +35,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
return
nil
,
fmt
.
Errorf
(
"failed to create the transaction manager: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to create the transaction manager: %w"
,
err
)
}
}
c
lient
,
err
:=
client
.
DialEthClientWithTimeout
(
client
.
DefaultDialTimeout
,
logger
,
cfg
.
L1EthRpc
)
l1C
lient
,
err
:=
client
.
DialEthClientWithTimeout
(
client
.
DefaultDialTimeout
,
logger
,
cfg
.
L1EthRpc
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to dial L1: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to dial L1: %w"
,
err
)
}
}
...
@@ -57,10 +58,10 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
...
@@ -57,10 +58,10 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
logger
.
Error
(
"error starting metrics server"
,
"err"
,
err
)
logger
.
Error
(
"error starting metrics server"
,
"err"
,
err
)
}
}
}()
}()
m
.
StartBalanceMetrics
(
ctx
,
logger
,
c
lient
,
txMgr
.
From
())
m
.
StartBalanceMetrics
(
ctx
,
logger
,
l1C
lient
,
txMgr
.
From
())
}
}
factory
,
err
:=
bindings
.
NewDisputeGameFactory
(
cfg
.
GameFactoryAddress
,
c
lient
)
factory
,
err
:=
bindings
.
NewDisputeGameFactory
(
cfg
.
GameFactoryAddress
,
l1C
lient
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault dispute game factory contract: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault dispute game factory contract: %w"
,
err
)
}
}
...
@@ -73,10 +74,14 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
...
@@ -73,10 +74,14 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
disk
,
disk
,
cfg
.
MaxConcurrency
,
cfg
.
MaxConcurrency
,
func
(
addr
common
.
Address
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
func
(
addr
common
.
Address
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
return
fault
.
NewGamePlayer
(
ctx
,
logger
,
m
,
cfg
,
dir
,
addr
,
txMgr
,
c
lient
)
return
fault
.
NewGamePlayer
(
ctx
,
logger
,
m
,
cfg
,
dir
,
addr
,
txMgr
,
l1C
lient
)
})
})
monitor
:=
newGameMonitor
(
logger
,
cl
,
loader
,
sched
,
cfg
.
GameWindow
,
client
.
BlockNumber
,
cfg
.
GameAllowlist
)
pollClient
,
err
:=
opClient
.
NewRPCWithClient
(
ctx
,
logger
,
cfg
.
L1EthRpc
,
opClient
.
NewBaseRPCClient
(
l1Client
.
Client
()),
cfg
.
PollInterval
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create RPC client: %w"
,
err
)
}
monitor
:=
newGameMonitor
(
logger
,
cl
,
loader
,
sched
,
cfg
.
GameWindow
,
l1Client
.
BlockNumber
,
cfg
.
GameAllowlist
,
pollClient
)
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordUp
()
m
.
RecordUp
()
...
...
op-e2e/e2eutils/challenger/helper.go
View file @
ea12a7ae
...
@@ -145,6 +145,10 @@ func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *co
...
@@ -145,6 +145,10 @@ func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *co
_
,
err
:=
os
.
Stat
(
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"
)
require
.
NoError
(
t
,
err
,
"cannon pre-state should be built. Make sure you've run make cannon-prestate"
)
}
}
if
cfg
.
PollInterval
==
0
{
cfg
.
PollInterval
=
time
.
Second
}
return
&
cfg
return
&
cfg
}
}
...
...
op-e2e/e2eutils/disputegame/game_helper.go
View file @
ea12a7ae
...
@@ -65,7 +65,7 @@ func (g *FaultGameHelper) MaxDepth(ctx context.Context) int64 {
...
@@ -65,7 +65,7 @@ func (g *FaultGameHelper) MaxDepth(ctx context.Context) int64 {
}
}
func
(
g
*
FaultGameHelper
)
waitForClaim
(
ctx
context
.
Context
,
errorMsg
string
,
predicate
func
(
claim
ContractClaim
)
bool
)
{
func
(
g
*
FaultGameHelper
)
waitForClaim
(
ctx
context
.
Context
,
errorMsg
string
,
predicate
func
(
claim
ContractClaim
)
bool
)
{
timedCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
timedCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
2
*
time
.
Minute
)
defer
cancel
()
defer
cancel
()
err
:=
wait
.
For
(
timedCtx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
err
:=
wait
.
For
(
timedCtx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
count
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
timedCtx
})
count
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
timedCtx
})
...
@@ -89,6 +89,31 @@ func (g *FaultGameHelper) waitForClaim(ctx context.Context, errorMsg string, pre
...
@@ -89,6 +89,31 @@ func (g *FaultGameHelper) waitForClaim(ctx context.Context, errorMsg string, pre
}
}
}
}
func
(
g
*
FaultGameHelper
)
waitForNoClaim
(
ctx
context
.
Context
,
errorMsg
string
,
predicate
func
(
claim
ContractClaim
)
bool
)
{
timedCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
3
*
time
.
Minute
)
defer
cancel
()
err
:=
wait
.
For
(
timedCtx
,
time
.
Second
,
func
()
(
bool
,
error
)
{
count
,
err
:=
g
.
game
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
timedCtx
})
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 will fail on.
for
i
:=
count
.
Int64
()
-
1
;
i
>=
0
;
i
--
{
claimData
,
err
:=
g
.
game
.
ClaimData
(
&
bind
.
CallOpts
{
Context
:
timedCtx
},
big
.
NewInt
(
i
))
if
err
!=
nil
{
return
false
,
fmt
.
Errorf
(
"retrieve claim %v: %w"
,
i
,
err
)
}
if
predicate
(
claimData
)
{
return
false
,
nil
}
}
return
true
,
nil
})
if
err
!=
nil
{
// Avoid waiting time capturing game data when there's no error
g
.
require
.
NoErrorf
(
err
,
"%v
\n
%v"
,
errorMsg
,
g
.
gameData
(
ctx
))
}
}
func
(
g
*
FaultGameHelper
)
GetClaimValue
(
ctx
context
.
Context
,
claimIdx
int64
)
common
.
Hash
{
func
(
g
*
FaultGameHelper
)
GetClaimValue
(
ctx
context
.
Context
,
claimIdx
int64
)
common
.
Hash
{
g
.
WaitForClaimCount
(
ctx
,
claimIdx
+
1
)
g
.
WaitForClaimCount
(
ctx
,
claimIdx
+
1
)
claim
:=
g
.
getClaim
(
ctx
,
claimIdx
)
claim
:=
g
.
getClaim
(
ctx
,
claimIdx
)
...
@@ -105,6 +130,16 @@ func (g *FaultGameHelper) getClaim(ctx context.Context, claimIdx int64) Contract
...
@@ -105,6 +130,16 @@ func (g *FaultGameHelper) getClaim(ctx context.Context, claimIdx int64) Contract
return
claimData
return
claimData
}
}
func
(
g
*
FaultGameHelper
)
WaitForClaimAtDepth
(
ctx
context
.
Context
,
depth
int
)
{
g
.
waitForClaim
(
ctx
,
fmt
.
Sprintf
(
"Could not find claim depth %v"
,
depth
),
func
(
claim
ContractClaim
)
bool
{
pos
:=
types
.
NewPositionFromGIndex
(
claim
.
Position
.
Uint64
())
return
pos
.
Depth
()
==
depth
})
}
func
(
g
*
FaultGameHelper
)
WaitForClaimAtMaxDepth
(
ctx
context
.
Context
,
countered
bool
)
{
func
(
g
*
FaultGameHelper
)
WaitForClaimAtMaxDepth
(
ctx
context
.
Context
,
countered
bool
)
{
maxDepth
:=
g
.
MaxDepth
(
ctx
)
maxDepth
:=
g
.
MaxDepth
(
ctx
)
g
.
waitForClaim
(
g
.
waitForClaim
(
...
@@ -116,6 +151,15 @@ func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered
...
@@ -116,6 +151,15 @@ func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered
})
})
}
}
func
(
g
*
FaultGameHelper
)
WaitForAllClaimsCountered
(
ctx
context
.
Context
)
{
g
.
waitForNoClaim
(
ctx
,
"Did not find all claims countered"
,
func
(
claim
ContractClaim
)
bool
{
return
!
claim
.
Countered
})
}
func
(
g
*
FaultGameHelper
)
Resolve
(
ctx
context
.
Context
)
{
func
(
g
*
FaultGameHelper
)
Resolve
(
ctx
context
.
Context
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
time
.
Minute
)
defer
cancel
()
defer
cancel
()
...
...
op-e2e/e2eutils/disputegame/helper.go
View file @
ea12a7ae
...
@@ -100,7 +100,7 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
...
@@ -100,7 +100,7 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
l2BlockNumber
:=
h
.
waitForProposals
(
ctx
)
l2BlockNumber
:=
h
.
waitForProposals
(
ctx
)
l1Head
:=
h
.
checkpointL1Block
(
ctx
)
l1Head
:=
h
.
checkpointL1Block
(
ctx
)
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
1
*
time
.
Minute
)
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
2
*
time
.
Minute
)
defer
cancel
()
defer
cancel
()
trace
:=
alphabet
.
NewTraceProvider
(
claimedAlphabet
,
alphabetGameDepth
)
trace
:=
alphabet
.
NewTraceProvider
(
claimedAlphabet
,
alphabetGameDepth
)
...
...
op-e2e/faultproof_test.go
View file @
ea12a7ae
...
@@ -341,6 +341,66 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) {
...
@@ -341,6 +341,66 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) {
}
}
}
}
func
TestCannonPoisonedPostState
(
t
*
testing
.
T
)
{
t
.
Skip
(
"Known failure case"
)
InitParallel
(
t
)
ctx
:=
context
.
Background
()
sys
,
l1Client
:=
startFaultDisputeSystem
(
t
)
t
.
Cleanup
(
sys
.
Close
)
l1Endpoint
:=
sys
.
NodeEndpoint
(
"l1"
)
l2Endpoint
:=
sys
.
NodeEndpoint
(
"sequencer"
)
disputeGameFactory
:=
disputegame
.
NewFactoryHelper
(
t
,
ctx
,
sys
.
cfg
.
L1Deployments
,
l1Client
)
game
,
correctTrace
:=
disputeGameFactory
.
StartCannonGameWithCorrectRoot
(
ctx
,
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
,
l1Endpoint
,
l2Endpoint
,
challenger
.
WithPrivKey
(
sys
.
cfg
.
Secrets
.
Mallory
),
)
require
.
NotNil
(
t
,
game
)
game
.
LogGameData
(
ctx
)
// Honest first attack at "honest" level
correctTrace
.
Attack
(
ctx
,
0
)
// Honest defense at "dishonest" level
correctTrace
.
Defend
(
ctx
,
1
)
// Dishonest attack at "honest" level - honest move would be to defend
game
.
Attack
(
ctx
,
2
,
common
.
Hash
{
0x03
,
0xaa
})
// Start the honest challenger
game
.
StartChallenger
(
ctx
,
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
,
l1Endpoint
,
l2Endpoint
,
"Honest"
,
// Agree with the proposed output, so disagree with the root claim
challenger
.
WithAgreeProposedOutput
(
true
),
challenger
.
WithPrivKey
(
sys
.
cfg
.
Secrets
.
Bob
),
)
// Start dishonest challenger that posts correct claims
game
.
StartChallenger
(
ctx
,
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
,
l1Endpoint
,
l2Endpoint
,
"DishonestCorrect"
,
// Disagree with the proposed output, so agree with the root claim
challenger
.
WithAgreeProposedOutput
(
false
),
challenger
.
WithPrivKey
(
sys
.
cfg
.
Secrets
.
Mallory
),
)
// Give the challengers time to progress down the full game depth
depth
:=
game
.
MaxDepth
(
ctx
)
for
i
:=
3
;
i
<=
int
(
depth
);
i
++
{
game
.
WaitForClaimAtDepth
(
ctx
,
i
)
game
.
LogGameData
(
ctx
)
}
// Wait for all the leaf nodes to be countered
// Wait for the challengers to drive the game down to the leaf node which should be countered
game
.
WaitForAllClaimsCountered
(
ctx
)
// Time travel past when the game will be resolvable.
sys
.
TimeTravelClock
.
AdvanceTime
(
game
.
GameDuration
(
ctx
))
require
.
NoError
(
t
,
wait
.
ForNextBlock
(
ctx
,
l1Client
))
game
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
game
.
LogGameData
(
ctx
)
}
// setupDisputeGameForInvalidOutputRoot sets up an L2 chain with at least one valid output root followed by an invalid output root.
// setupDisputeGameForInvalidOutputRoot sets up an L2 chain with at least one valid output root followed by an invalid output root.
// A cannon dispute game is started to dispute the invalid output root with the correct root claim provided.
// A cannon dispute game is started to dispute the invalid output root with the correct root claim provided.
// An honest challenger is run to defend the root claim (ie disagree with the invalid output root).
// An honest challenger is run to defend the root claim (ie disagree with the invalid output root).
...
...
op-node/client/rpc.go
View file @
ea12a7ae
...
@@ -80,9 +80,11 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption)
...
@@ -80,9 +80,11 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption)
return
nil
,
fmt
.
Errorf
(
"rpc option %d failed to apply to RPC config: %w"
,
i
,
err
)
return
nil
,
fmt
.
Errorf
(
"rpc option %d failed to apply to RPC config: %w"
,
i
,
err
)
}
}
}
}
if
cfg
.
backoffAttempts
<
1
{
// default to at least 1 attempt, or it always fails to dial.
if
cfg
.
backoffAttempts
<
1
{
// default to at least 1 attempt, or it always fails to dial.
cfg
.
backoffAttempts
=
1
cfg
.
backoffAttempts
=
1
}
}
underlying
,
err
:=
dialRPCClientWithBackoff
(
ctx
,
lgr
,
addr
,
cfg
.
backoffAttempts
,
cfg
.
gethRPCOptions
...
)
underlying
,
err
:=
dialRPCClientWithBackoff
(
ctx
,
lgr
,
addr
,
cfg
.
backoffAttempts
,
cfg
.
gethRPCOptions
...
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -94,11 +96,15 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption)
...
@@ -94,11 +96,15 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption)
wrapped
=
NewRateLimitingClient
(
wrapped
,
rate
.
Limit
(
cfg
.
limit
),
cfg
.
burst
)
wrapped
=
NewRateLimitingClient
(
wrapped
,
rate
.
Limit
(
cfg
.
limit
),
cfg
.
burst
)
}
}
return
NewRPCWithClient
(
ctx
,
lgr
,
addr
,
wrapped
,
cfg
.
httpPollInterval
)
}
// NewRPCWithClient builds a new polling client with the given underlying RPC client.
func
NewRPCWithClient
(
ctx
context
.
Context
,
lgr
log
.
Logger
,
addr
string
,
underlying
RPC
,
pollInterval
time
.
Duration
)
(
RPC
,
error
)
{
if
httpRegex
.
MatchString
(
addr
)
{
if
httpRegex
.
MatchString
(
addr
)
{
wrapped
=
NewPollingClient
(
ctx
,
lgr
,
wrapped
,
WithPollRate
(
cfg
.
httpP
ollInterval
))
underlying
=
NewPollingClient
(
ctx
,
lgr
,
underlying
,
WithPollRate
(
p
ollInterval
))
}
}
return
underlying
,
nil
return
wrapped
,
nil
}
}
// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional.
// Dials a JSON-RPC endpoint repeatedly, with a backoff, until a client connection is established. Auth is optional.
...
...
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