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
cbedb215
Unverified
Commit
cbedb215
authored
Aug 18, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-challenger: Support tracking multiple alphabet games
parent
f09a411e
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
388 additions
and
204 deletions
+388
-204
provider.go
op-challenger/fault/cannon/provider.go
+4
-4
factory.go
op-challenger/fault/factory.go
+0
-5
game.go
op-challenger/fault/game.go
+120
-0
game_test.go
op-challenger/fault/game_test.go
+126
-0
monitor.go
op-challenger/fault/monitor.go
+65
-40
monitor_test.go
op-challenger/fault/monitor_test.go
+60
-92
service.go
op-challenger/fault/service.go
+12
-61
cannon_helper.go
op-e2e/e2eutils/disputegame/cannon_helper.go
+1
-1
faultproof_test.go
op-e2e/faultproof_test.go
+0
-1
No files found.
op-challenger/fault/cannon/provider.go
View file @
cbedb215
...
...
@@ -50,17 +50,17 @@ type CannonTraceProvider struct {
lastProof
*
proofData
}
func
NewTraceProvider
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
l1Client
bind
.
ContractCaller
)
(
*
CannonTraceProvider
,
error
)
{
func
NewTraceProvider
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
l1Client
bind
.
ContractCaller
,
gameAddr
common
.
Address
)
(
*
CannonTraceProvider
,
error
)
{
l2Client
,
err
:=
ethclient
.
DialContext
(
ctx
,
cfg
.
CannonL2
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"dial l2 client %v: %w"
,
cfg
.
CannonL2
,
err
)
}
defer
l2Client
.
Close
()
// Not needed after fetching the inputs
gameCaller
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
cfg
.
GameAddress
,
l1Client
)
gameCaller
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
gameAddr
,
l1Client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create caller for game %v: %w"
,
cfg
.
GameAddress
,
err
)
return
nil
,
fmt
.
Errorf
(
"create caller for game %v: %w"
,
gameAddr
,
err
)
}
localInputs
,
err
:=
fetchLocalInputs
(
ctx
,
cfg
.
GameAddress
,
gameCaller
,
l2Client
)
localInputs
,
err
:=
fetchLocalInputs
(
ctx
,
gameAddr
,
gameCaller
,
l2Client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"fetch local game inputs: %w"
,
err
)
}
...
...
op-challenger/fault/factory.go
View file @
cbedb215
...
...
@@ -31,11 +31,6 @@ type FaultDisputeGame struct {
Proxy
common
.
Address
}
// GameLoader is a minimal interface for fetching on chain dispute games.
type
GameLoader
interface
{
FetchAllGamesAtBlock
(
ctx
context
.
Context
)
([]
FaultDisputeGame
,
error
)
}
type
gameLoader
struct
{
caller
MinimalDisputeGameFactoryCaller
}
...
...
op-challenger/fault/game.go
0 → 100644
View file @
cbedb215
package
fault
import
(
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
type
Actor
interface
{
Act
(
ctx
context
.
Context
)
error
}
type
GameInfo
interface
{
GetGameStatus
(
context
.
Context
)
(
types
.
GameStatus
,
error
)
LogGameInfo
(
ctx
context
.
Context
)
}
type
Game
struct
{
agent
Actor
agreeWithProposedOutput
bool
caller
GameInfo
logger
log
.
Logger
}
func
NewGame
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
addr
common
.
Address
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
,
)
(
*
Game
,
error
)
{
contract
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
addr
,
client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault dispute game contract: %w"
,
err
)
}
loader
:=
NewLoader
(
contract
)
gameDepth
,
err
:=
loader
.
FetchGameDepth
(
ctx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch the game depth: %w"
,
err
)
}
var
provider
types
.
TraceProvider
var
updater
types
.
OracleUpdater
switch
cfg
.
TraceType
{
case
config
.
TraceTypeCannon
:
provider
,
err
=
cannon
.
NewTraceProvider
(
ctx
,
logger
,
cfg
,
client
,
addr
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create cannon trace provider: %w"
,
err
)
}
updater
,
err
=
cannon
.
NewOracleUpdater
(
ctx
,
logger
,
txMgr
,
addr
,
client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the cannon updater: %w"
,
err
)
}
case
config
.
TraceTypeAlphabet
:
provider
=
alphabet
.
NewTraceProvider
(
cfg
.
AlphabetTrace
,
gameDepth
)
updater
=
alphabet
.
NewOracleUpdater
(
logger
)
default
:
return
nil
,
fmt
.
Errorf
(
"unsupported trace type: %v"
,
cfg
.
TraceType
)
}
if
err
:=
ValidateAbsolutePrestate
(
ctx
,
provider
,
loader
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to validate absolute prestate: %w"
,
err
)
}
gameLogger
:=
logger
.
New
(
"game"
,
addr
)
responder
,
err
:=
NewFaultResponder
(
gameLogger
,
txMgr
,
addr
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the responder: %w"
,
err
)
}
caller
,
err
:=
NewFaultCallerFromBindings
(
addr
,
client
,
gameLogger
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault contract: %w"
,
err
)
}
return
&
Game
{
agent
:
NewAgent
(
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
gameLogger
),
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
caller
:
caller
,
logger
:
gameLogger
,
},
nil
}
func
(
g
*
Game
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
g
.
logger
.
Trace
(
"Checking if actions are required"
)
if
err
:=
g
.
agent
.
Act
(
ctx
);
err
!=
nil
{
g
.
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
}
if
status
,
err
:=
g
.
caller
.
GetGameStatus
(
ctx
);
err
!=
nil
{
g
.
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
}
else
if
status
!=
0
{
var
expectedStatus
types
.
GameStatus
if
g
.
agreeWithProposedOutput
{
expectedStatus
=
types
.
GameStatusChallengerWon
}
else
{
expectedStatus
=
types
.
GameStatusDefenderWon
}
if
expectedStatus
==
status
{
g
.
logger
.
Info
(
"Game won"
,
"status"
,
status
)
}
else
{
g
.
logger
.
Error
(
"Game lost"
,
"status"
,
status
)
}
return
true
}
else
{
g
.
caller
.
LogGameInfo
(
ctx
)
}
return
false
}
op-challenger/fault/game_test.go
0 → 100644
View file @
cbedb215
package
fault
import
(
"context"
"errors"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
func
TestProgressGameAndLogState
(
t
*
testing
.
T
)
{
_
,
game
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
,
true
)
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameInfo
.
logCount
,
"should log latest game state"
)
}
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
handler
,
game
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
,
true
)
actor
.
err
=
errors
.
New
(
"boom"
)
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameInfo
.
logCount
,
"should log latest game state"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
require
.
Equal
(
t
,
actor
.
err
,
errLog
.
GetContextValue
(
"err"
))
}
func
TestProgressGame_LogErrorWhenGameLost
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
status
types
.
GameStatus
agreeWithOutput
bool
logLevel
log
.
Lvl
logMsg
string
}{
{
name
:
"GameLostAsDefender"
,
status
:
types
.
GameStatusChallengerWon
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
},
{
name
:
"GameLostAsChallenger"
,
status
:
types
.
GameStatusDefenderWon
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
},
{
name
:
"GameWonAsDefender"
,
status
:
types
.
GameStatusDefenderWon
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
},
{
name
:
"GameWonAsChallenger"
,
status
:
types
.
GameStatusChallengerWon
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
handler
,
game
,
_
,
gameInfo
:=
setupProgressGameTest
(
t
,
test
.
agreeWithOutput
)
gameInfo
.
status
=
test
.
status
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
True
(
t
,
done
,
"should be done"
)
require
.
Equal
(
t
,
0
,
gameInfo
.
logCount
,
"should not log latest game state"
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
require
.
Equal
(
t
,
test
.
status
,
errLog
.
GetContextValue
(
"status"
))
})
}
}
func
setupProgressGameTest
(
t
*
testing
.
T
,
agreeWithProposedRoot
bool
)
(
*
testlog
.
CapturingHandler
,
*
Game
,
*
stubActor
,
*
stubGameInfo
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
handler
:=
&
testlog
.
CapturingHandler
{
Delegate
:
logger
.
GetHandler
(),
}
logger
.
SetHandler
(
handler
)
actor
:=
&
stubActor
{}
gameInfo
:=
&
stubGameInfo
{}
game
:=
&
Game
{
agent
:
actor
,
agreeWithProposedOutput
:
agreeWithProposedRoot
,
caller
:
gameInfo
,
logger
:
logger
,
}
return
handler
,
game
,
actor
,
gameInfo
}
type
stubActor
struct
{
callCount
int
err
error
}
func
(
a
*
stubActor
)
Act
(
ctx
context
.
Context
)
error
{
a
.
callCount
++
return
a
.
err
}
type
stubGameInfo
struct
{
status
types
.
GameStatus
err
error
logCount
int
}
func
(
s
*
stubGameInfo
)
GetGameStatus
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
{
return
s
.
status
,
s
.
err
}
func
(
s
*
stubGameInfo
)
LogGameInfo
(
ctx
context
.
Context
)
{
s
.
logCount
++
}
op-challenger/fault/monitor.go
View file @
cbedb215
...
...
@@ -2,29 +2,82 @@ package fault
import
(
"context"
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
)
type
GameInfo
interface
{
GetGameStatus
(
context
.
Context
)
(
types
.
GameStatus
,
error
)
LogGameInfo
(
ctx
context
.
Context
)
type
gameAgent
interface
{
ProgressGame
(
ctx
context
.
Context
)
bool
}
type
gameCreator
func
(
address
common
.
Address
)
(
gameAgent
,
error
)
type
blockNumberFetcher
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
// gameSource loads information about the games available to play
type
gameSource
interface
{
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
}
type
gameMonitor
struct
{
logger
log
.
Logger
source
gameSource
createGame
gameCreator
fetchBlockNumber
blockNumberFetcher
games
map
[
common
.
Address
]
gameAgent
}
type
Actor
interface
{
Act
(
ctx
context
.
Context
)
error
func
newGameMonitor
(
logger
log
.
Logger
,
fetchBlockNumber
blockNumberFetcher
,
source
gameSource
,
createGame
gameCreator
)
*
gameMonitor
{
return
&
gameMonitor
{
logger
:
logger
,
source
:
source
,
createGame
:
createGame
,
fetchBlockNumber
:
fetchBlockNumber
,
games
:
make
(
map
[
common
.
Address
]
gameAgent
),
}
}
func
MonitorGame
(
ctx
context
.
Context
,
logger
log
.
Logger
,
agreeWithProposedOutput
bool
,
actor
Actor
,
caller
GameInfo
)
error
{
logger
.
Info
(
"Monitoring fault dispute game"
,
"agreeWithOutput"
,
agreeWithProposedOutput
)
func
(
m
*
gameMonitor
)
progressGames
(
ctx
context
.
Context
)
error
{
blockNum
,
err
:=
m
.
fetchBlockNumber
(
ctx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to load current block number: %w"
,
err
)
}
games
,
err
:=
m
.
source
.
FetchAllGamesAtBlock
(
ctx
,
new
(
big
.
Int
)
.
SetUint64
(
blockNum
))
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to load games: %w"
,
err
)
}
for
_
,
game
:=
range
games
{
if
err
:=
m
.
progressGame
(
ctx
,
game
);
err
!=
nil
{
m
.
logger
.
Error
(
"Error while progressing game"
,
"game"
,
game
.
Proxy
,
"err"
,
err
)
}
}
return
nil
}
func
(
m
*
gameMonitor
)
progressGame
(
ctx
context
.
Context
,
gameData
FaultDisputeGame
)
error
{
game
,
ok
:=
m
.
games
[
gameData
.
Proxy
]
if
!
ok
{
newGame
,
err
:=
m
.
createGame
(
gameData
.
Proxy
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to progress game %v: %w"
,
gameData
.
Proxy
,
err
)
}
m
.
games
[
gameData
.
Proxy
]
=
newGame
game
=
newGame
}
game
.
ProgressGame
(
ctx
)
return
nil
}
func
(
m
*
gameMonitor
)
MonitorGames
(
ctx
context
.
Context
)
error
{
m
.
logger
.
Info
(
"Monitoring fault dispute games"
)
for
{
done
:=
progressGame
(
ctx
,
logger
,
agreeWithProposedOutput
,
actor
,
caller
)
if
done
{
return
nil
err
:=
m
.
progressGames
(
ctx
)
if
err
!=
nil
{
m
.
logger
.
Error
(
"Failed to progress games"
,
"err"
,
err
)
}
select
{
case
<-
time
.
After
(
300
*
time
.
Millisecond
)
:
...
...
@@ -34,31 +87,3 @@ func MonitorGame(ctx context.Context, logger log.Logger, agreeWithProposedOutput
}
}
}
// progressGame checks the current state of the game, and attempts to progress it by performing moves, steps or resolving
// Returns true if the game is complete or false if it needs to be monitored further
func
progressGame
(
ctx
context
.
Context
,
logger
log
.
Logger
,
agreeWithProposedOutput
bool
,
actor
Actor
,
caller
GameInfo
)
bool
{
logger
.
Trace
(
"Checking if actions are required"
)
if
err
:=
actor
.
Act
(
ctx
);
err
!=
nil
{
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
}
if
status
,
err
:=
caller
.
GetGameStatus
(
ctx
);
err
!=
nil
{
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
}
else
if
status
!=
0
{
var
expectedStatus
types
.
GameStatus
if
agreeWithProposedOutput
{
expectedStatus
=
types
.
GameStatusChallengerWon
}
else
{
expectedStatus
=
types
.
GameStatusDefenderWon
}
if
expectedStatus
==
status
{
logger
.
Info
(
"Game won"
,
"status"
,
status
)
}
else
{
logger
.
Error
(
"Game lost"
,
"status"
,
status
)
}
return
true
}
else
{
caller
.
LogGameInfo
(
ctx
)
}
return
false
}
op-challenger/fault/monitor_test.go
View file @
cbedb215
...
...
@@ -2,130 +2,98 @@ package fault
import
(
"context"
"
errors
"
"
math/big
"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
func
TestMonitorExitsWhenContextDone
(
t
*
testing
.
T
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
actor
:=
&
stubActor
{}
gameInfo
:=
&
stubGameInfo
{}
monitor
,
_
,
_
:=
setupMonitorTest
(
t
)
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
cancel
()
err
:=
MonitorGame
(
ctx
,
logger
,
true
,
actor
,
gameInfo
)
err
:=
monitor
.
MonitorGames
(
ctx
)
require
.
ErrorIs
(
t
,
err
,
context
.
Canceled
)
}
func
TestProgressGameAndLogState
(
t
*
testing
.
T
)
{
logger
,
_
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
)
done
:=
progressGame
(
context
.
Background
(),
logger
,
true
,
actor
,
gameInfo
)
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameInfo
.
logCount
,
"should log latest game state"
)
}
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
logger
,
handler
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
)
actor
.
err
=
errors
.
New
(
"Boom"
)
done
:=
progressGame
(
context
.
Background
(),
logger
,
true
,
actor
,
gameInfo
)
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameInfo
.
logCount
,
"should log latest game state"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
require
.
Equal
(
t
,
actor
.
err
,
errLog
.
GetContextValue
(
"err"
))
}
func
TestMonitorCreateAndProgressGameAgents
(
t
*
testing
.
T
)
{
monitor
,
source
,
games
:=
setupMonitorTest
(
t
)
func
TestProgressGame_LogErrorWhenGameLost
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
status
types
.
GameStatus
agreeWithOutput
bool
logLevel
log
.
Lvl
logMsg
string
}{
{
name
:
"GameLostAsDefender"
,
status
:
types
.
GameStatusChallengerWon
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
},
{
name
:
"GameLostAsChallenger"
,
status
:
types
.
GameStatusDefenderWon
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
},
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
source
.
games
=
[]
FaultDisputeGame
{
{
name
:
"GameWonAsDefender"
,
status
:
types
.
GameStatusDefenderWon
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
Proxy
:
addr1
,
Timestamp
:
big
.
NewInt
(
9999
),
},
{
name
:
"GameWonAsChallenger"
,
status
:
types
.
GameStatusChallengerWon
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
Proxy
:
addr2
,
Timestamp
:
big
.
NewInt
(
9999
),
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
logger
,
handler
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
)
gameInfo
.
status
=
test
.
status
done
:=
progressGame
(
context
.
Background
(),
logger
,
test
.
agreeWithOutput
,
actor
,
gameInfo
)
require
.
True
(
t
,
done
,
"should be done"
)
require
.
Equal
(
t
,
0
,
gameInfo
.
logCount
,
"should not log latest game state"
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
require
.
Equal
(
t
,
test
.
status
,
errLog
.
GetContextValue
(
"status"
)
)
}
)
}
err
:=
monitor
.
progressGames
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
games
.
created
,
2
,
"should create game agents"
)
require
.
Contains
(
t
,
games
.
created
,
addr1
)
require
.
Contains
(
t
,
games
.
created
,
addr2
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr1
]
.
progressCount
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr2
]
.
progressCount
)
// The stub will fail the test if a game is created with the same address multiple times
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
()),
"should only create games once"
)
require
.
Equal
(
t
,
2
,
games
.
created
[
addr1
]
.
progressCount
)
require
.
Equal
(
t
,
2
,
games
.
created
[
addr2
]
.
progressCount
)
}
func
setup
ProgressGameTest
(
t
*
testing
.
T
)
(
log
.
Logger
,
*
testlog
.
CapturingHandler
,
*
stubActor
,
*
stubGameInfo
)
{
func
setup
MonitorTest
(
t
*
testing
.
T
)
(
*
gameMonitor
,
*
stubGameSource
,
*
createdGames
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
handler
:=
&
testlog
.
CapturingHandler
{
Delegate
:
logger
.
GetHandler
(),
source
:=
&
stubGameSource
{}
games
:=
&
createdGames
{
t
:
t
,
created
:
make
(
map
[
common
.
Address
]
*
stubGame
),
}
logger
.
SetHandler
(
handler
)
actor
:=
&
stubActor
{}
gameInfo
:=
&
stubGameInfo
{}
return
logger
,
handler
,
actor
,
gameInfo
fetchBlockNum
:=
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
return
1234
,
nil
}
monitor
:=
newGameMonitor
(
logger
,
fetchBlockNum
,
source
,
games
.
CreateGame
)
return
monitor
,
source
,
games
}
type
stubGameSource
struct
{
games
[]
FaultDisputeGame
}
type
stubActor
struct
{
callCount
int
err
error
func
(
s
*
stubGameSource
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
return
s
.
games
,
nil
}
func
(
a
*
stubActor
)
Act
(
ctx
context
.
Context
)
error
{
a
.
callCount
++
return
a
.
err
type
stubGame
struct
{
addr
common
.
Address
progressCount
int
done
bool
}
type
stubGameInfo
struct
{
status
types
.
GameStatus
err
error
logCount
int
func
(
g
*
stubGame
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
g
.
progressCount
++
return
g
.
done
}
func
(
s
*
stubGameInfo
)
GetGameStatus
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
{
return
s
.
status
,
s
.
err
type
createdGames
struct
{
t
*
testing
.
T
created
map
[
common
.
Address
]
*
stubGame
}
func
(
s
*
stubGameInfo
)
LogGameInfo
(
ctx
context
.
Context
)
{
s
.
logCount
++
func
(
c
*
createdGames
)
CreateGame
(
addr
common
.
Address
)
(
gameAgent
,
error
)
{
if
_
,
exists
:=
c
.
created
[
addr
];
exists
{
c
.
t
.
Fatalf
(
"game %v already exists"
,
addr
)
}
game
:=
&
stubGame
{
addr
:
addr
}
c
.
created
[
addr
]
=
game
return
game
,
nil
}
op-challenger/fault/service.go
View file @
cbedb215
...
...
@@ -7,14 +7,12 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
...
...
@@ -26,10 +24,8 @@ type Service interface {
}
type
service
struct
{
agent
*
Agent
agreeWithProposedOutput
bool
caller
*
FaultCaller
logger
log
.
Logger
logger
log
.
Logger
monitor
*
gameMonitor
}
// NewService creates a new Service.
...
...
@@ -44,63 +40,18 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
return
nil
,
fmt
.
Errorf
(
"failed to dial L1: %w"
,
err
)
}
contract
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
cfg
.
Game
Address
,
client
)
factory
,
err
:=
bindings
.
NewDisputeGameFactory
(
cfg
.
GameFactory
Address
,
client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault dispute game contract: %w"
,
err
)
}
loader
:=
NewLoader
(
contract
)
gameDepth
,
err
:=
loader
.
FetchGameDepth
(
ctx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch the game depth: %w"
,
err
)
}
gameDepth
=
uint64
(
gameDepth
)
var
trace
types
.
TraceProvider
var
updater
types
.
OracleUpdater
switch
cfg
.
TraceType
{
case
config
.
TraceTypeCannon
:
trace
,
err
=
cannon
.
NewTraceProvider
(
ctx
,
logger
,
cfg
,
client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create cannon trace provider: %w"
,
err
)
}
updater
,
err
=
cannon
.
NewOracleUpdater
(
ctx
,
logger
,
txMgr
,
cfg
.
GameAddress
,
client
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the cannon updater: %w"
,
err
)
}
case
config
.
TraceTypeAlphabet
:
trace
=
alphabet
.
NewTraceProvider
(
cfg
.
AlphabetTrace
,
gameDepth
)
updater
=
alphabet
.
NewOracleUpdater
(
logger
)
default
:
return
nil
,
fmt
.
Errorf
(
"unsupported trace type: %v"
,
cfg
.
TraceType
)
}
return
newTypedService
(
ctx
,
logger
,
cfg
,
loader
,
gameDepth
,
client
,
trace
,
updater
,
txMgr
)
}
// newTypedService creates a new Service from a provided trace provider.
func
newTypedService
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
loader
Loader
,
gameDepth
uint64
,
client
*
ethclient
.
Client
,
provider
types
.
TraceProvider
,
updater
types
.
OracleUpdater
,
txMgr
txmgr
.
TxManager
)
(
*
service
,
error
)
{
if
err
:=
ValidateAbsolutePrestate
(
ctx
,
provider
,
loader
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to validate absolute prestate: %w"
,
err
)
}
gameLogger
:=
logger
.
New
(
"game"
,
cfg
.
GameAddress
)
responder
,
err
:=
NewFaultResponder
(
gameLogger
,
txMgr
,
cfg
.
GameAddress
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the responder: %w"
,
err
)
}
caller
,
err
:=
NewFaultCallerFromBindings
(
cfg
.
GameAddress
,
client
,
gameLogger
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault contract: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault dispute game factory contract: %w"
,
err
)
}
loader
:=
NewGameLoader
(
factory
)
monitor
:=
newGameMonitor
(
logger
,
client
.
BlockNumber
,
loader
,
func
(
addr
common
.
Address
)
(
gameAgent
,
error
)
{
return
NewGame
(
ctx
,
logger
,
cfg
,
addr
,
txMgr
,
client
)
})
return
&
service
{
agent
:
NewAgent
(
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
gameLogger
),
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
caller
:
caller
,
logger
:
gameLogger
,
monitor
:
monitor
,
logger
:
logger
,
},
nil
}
...
...
@@ -123,5 +74,5 @@ func ValidateAbsolutePrestate(ctx context.Context, trace types.TraceProvider, lo
// MonitorGame monitors the fault dispute game and attempts to progress it.
func
(
s
*
service
)
MonitorGame
(
ctx
context
.
Context
)
error
{
return
MonitorGame
(
ctx
,
s
.
logger
,
s
.
agreeWithProposedOutput
,
s
.
agent
,
s
.
caller
)
return
s
.
monitor
.
MonitorGames
(
ctx
)
// TODO
MonitorGame(ctx, s.logger, s.agreeWithProposedOutput, s.agent, s.caller)
}
op-e2e/e2eutils/disputegame/cannon_helper.go
View file @
cbedb215
...
...
@@ -38,7 +38,7 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
}
opts
=
append
(
opts
,
options
...
)
cfg
:=
challenger
.
NewChallengerConfig
(
g
.
t
,
l1Endpoint
,
opts
...
)
provider
,
err
:=
cannon
.
NewTraceProvider
(
ctx
,
testlog
.
Logger
(
g
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
),
cfg
,
l1Client
)
provider
,
err
:=
cannon
.
NewTraceProvider
(
ctx
,
testlog
.
Logger
(
g
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
),
cfg
,
l1Client
,
g
.
addr
)
g
.
require
.
NoError
(
err
,
"create cannon trace provider"
)
return
&
HonestHelper
{
...
...
op-e2e/faultproof_test.go
View file @
cbedb215
...
...
@@ -13,7 +13,6 @@ import (
)
func
TestCannonMultipleGames
(
t
*
testing
.
T
)
{
t
.
Skip
(
"Challenger doesn't yet support multiple games"
)
InitParallel
(
t
)
ctx
:=
context
.
Background
()
...
...
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