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
80fdee6c
Unverified
Commit
80fdee6c
authored
Sep 15, 2023
by
OptimismBot
Committed by
GitHub
Sep 15, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7073 from ethereum-optimism/refcell/redo-subscription
feat: Head Subscriptions
parents
119b3310
ea82c698
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
256 additions
and
66 deletions
+256
-66
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
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
+1
-1
helper.go
op-e2e/e2eutils/disputegame/helper.go
+1
-1
rpc.go
op-node/client/rpc.go
+9
-3
No files found.
Makefile
View file @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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/monitor.go
View file @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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 @
80fdee6c
...
@@ -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
})
...
...
op-e2e/e2eutils/disputegame/helper.go
View file @
80fdee6c
...
@@ -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-node/client/rpc.go
View file @
80fdee6c
...
@@ -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