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
23d0635b
Unverified
Commit
23d0635b
authored
Sep 05, 2023
by
OptimismBot
Committed by
GitHub
Sep 05, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7080 from ethereum-optimism/refcell/game-gauge
feat(op-challenger): Game GaugeVec
parents
1d861eb5
07cf16db
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
240 additions
and
166 deletions
+240
-166
agent.go
op-challenger/game/fault/agent.go
+6
-5
agent_test.go
op-challenger/game/fault/agent_test.go
+14
-13
loader.go
op-challenger/game/fault/loader.go
+3
-2
loader_test.go
op-challenger/game/fault/loader_test.go
+5
-4
player.go
op-challenger/game/fault/player.go
+20
-20
player_test.go
op-challenger/game/fault/player_test.go
+18
-17
responder.go
op-challenger/game/fault/responder/responder.go
+6
-5
responder_test.go
op-challenger/game/fault/responder/responder_test.go
+4
-3
types.go
op-challenger/game/fault/types/types.go
+0
-31
types_test.go
op-challenger/game/fault/types/types_test.go
+0
-23
monitor.go
op-challenger/game/monitor.go
+0
-4
monitor_test.go
op-challenger/game/monitor_test.go
+1
-2
coordinator.go
op-challenger/game/scheduler/coordinator.go
+26
-5
coordinator_test.go
op-challenger/game/scheduler/coordinator_test.go
+17
-9
scheduler.go
op-challenger/game/scheduler/scheduler.go
+6
-2
scheduler_test.go
op-challenger/game/scheduler/scheduler_test.go
+3
-2
types.go
op-challenger/game/scheduler/types.go
+6
-4
worker.go
op-challenger/game/scheduler/worker.go
+1
-1
worker_test.go
op-challenger/game/scheduler/worker_test.go
+9
-7
service.go
op-challenger/game/service.go
+2
-1
types.go
op-challenger/game/types/types.go
+35
-0
types_test.go
op-challenger/game/types/types_test.go
+30
-0
metrics.go
op-challenger/metrics/metrics.go
+20
-2
noop.go
op-challenger/metrics/noop.go
+8
-4
No files found.
op-challenger/game/fault/agent.go
View file @
23d0635b
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"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"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
)
)
...
@@ -14,7 +15,7 @@ import (
...
@@ -14,7 +15,7 @@ import (
// Responder takes a response action & executes.
// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
// For full op-challenger this means executing the transaction on chain.
type
Responder
interface
{
type
Responder
interface
{
CallResolve
(
ctx
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
CallResolve
(
ctx
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
Resolve
(
ctx
context
.
Context
)
error
Resolve
(
ctx
context
.
Context
)
error
Respond
(
ctx
context
.
Context
,
response
types
.
Claim
)
error
Respond
(
ctx
context
.
Context
,
response
types
.
Claim
)
error
Step
(
ctx
context
.
Context
,
stepData
types
.
StepCallData
)
error
Step
(
ctx
context
.
Context
,
stepData
types
.
StepCallData
)
error
...
@@ -74,10 +75,10 @@ func (a *Agent) Act(ctx context.Context) error {
...
@@ -74,10 +75,10 @@ func (a *Agent) Act(ctx context.Context) error {
// shouldResolve returns true if the agent should resolve the game.
// shouldResolve returns true if the agent should resolve the game.
// This method will return false if the game is still in progress.
// This method will return false if the game is still in progress.
func
(
a
*
Agent
)
shouldResolve
(
status
t
ypes
.
GameStatus
)
bool
{
func
(
a
*
Agent
)
shouldResolve
(
status
gameT
ypes
.
GameStatus
)
bool
{
expected
:=
t
ypes
.
GameStatusDefenderWon
expected
:=
gameT
ypes
.
GameStatusDefenderWon
if
a
.
agreeWithProposedOutput
{
if
a
.
agreeWithProposedOutput
{
expected
=
t
ypes
.
GameStatusChallengerWon
expected
=
gameT
ypes
.
GameStatusChallengerWon
}
}
if
expected
!=
status
{
if
expected
!=
status
{
a
.
log
.
Warn
(
"Game will be lost"
,
"expected"
,
expected
,
"actual"
,
status
)
a
.
log
.
Warn
(
"Game will be lost"
,
"expected"
,
expected
,
"actual"
,
status
)
...
@@ -89,7 +90,7 @@ func (a *Agent) shouldResolve(status types.GameStatus) bool {
...
@@ -89,7 +90,7 @@ func (a *Agent) shouldResolve(status types.GameStatus) bool {
// Returns true if the game is resolvable (regardless of whether it was actually resolved)
// Returns true if the game is resolvable (regardless of whether it was actually resolved)
func
(
a
*
Agent
)
tryResolve
(
ctx
context
.
Context
)
bool
{
func
(
a
*
Agent
)
tryResolve
(
ctx
context
.
Context
)
bool
{
status
,
err
:=
a
.
responder
.
CallResolve
(
ctx
)
status
,
err
:=
a
.
responder
.
CallResolve
(
ctx
)
if
err
!=
nil
||
status
==
t
ypes
.
GameStatusInProgress
{
if
err
!=
nil
||
status
==
gameT
ypes
.
GameStatusInProgress
{
return
false
return
false
}
}
if
!
a
.
shouldResolve
(
status
)
{
if
!
a
.
shouldResolve
(
status
)
{
...
...
op-challenger/game/fault/agent_test.go
View file @
23d0635b
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"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"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
...
@@ -19,16 +20,16 @@ import (
...
@@ -19,16 +20,16 @@ import (
func
TestShouldResolve
(
t
*
testing
.
T
)
{
func
TestShouldResolve
(
t
*
testing
.
T
)
{
t
.
Run
(
"AgreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"AgreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
agent
,
_
,
_
:=
setupTestAgent
(
t
,
true
)
agent
,
_
,
_
:=
setupTestAgent
(
t
,
true
)
require
.
False
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusDefenderWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusDefenderWon
))
require
.
True
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusChallengerWon
))
require
.
True
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusChallengerWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusInProgress
))
require
.
False
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusInProgress
))
})
})
t
.
Run
(
"DisagreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"DisagreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
agent
,
_
,
_
:=
setupTestAgent
(
t
,
false
)
agent
,
_
,
_
:=
setupTestAgent
(
t
,
false
)
require
.
True
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusDefenderWon
))
require
.
True
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusDefenderWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusChallengerWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusChallengerWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
t
ypes
.
GameStatusInProgress
))
require
.
False
(
t
,
agent
.
shouldResolve
(
gameT
ypes
.
GameStatusInProgress
))
})
})
}
}
...
@@ -38,31 +39,31 @@ func TestDoNotMakeMovesWhenGameIsResolvable(t *testing.T) {
...
@@ -38,31 +39,31 @@ func TestDoNotMakeMovesWhenGameIsResolvable(t *testing.T) {
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
agreeWithProposedOutput
bool
agreeWithProposedOutput
bool
callResolveStatus
t
ypes
.
GameStatus
callResolveStatus
gameT
ypes
.
GameStatus
shouldResolve
bool
shouldResolve
bool
}{
}{
{
{
name
:
"Agree_Losing"
,
name
:
"Agree_Losing"
,
agreeWithProposedOutput
:
true
,
agreeWithProposedOutput
:
true
,
callResolveStatus
:
t
ypes
.
GameStatusDefenderWon
,
callResolveStatus
:
gameT
ypes
.
GameStatusDefenderWon
,
shouldResolve
:
false
,
shouldResolve
:
false
,
},
},
{
{
name
:
"Agree_Winning"
,
name
:
"Agree_Winning"
,
agreeWithProposedOutput
:
true
,
agreeWithProposedOutput
:
true
,
callResolveStatus
:
t
ypes
.
GameStatusChallengerWon
,
callResolveStatus
:
gameT
ypes
.
GameStatusChallengerWon
,
shouldResolve
:
true
,
shouldResolve
:
true
,
},
},
{
{
name
:
"Disagree_Losing"
,
name
:
"Disagree_Losing"
,
agreeWithProposedOutput
:
false
,
agreeWithProposedOutput
:
false
,
callResolveStatus
:
t
ypes
.
GameStatusChallengerWon
,
callResolveStatus
:
gameT
ypes
.
GameStatusChallengerWon
,
shouldResolve
:
false
,
shouldResolve
:
false
,
},
},
{
{
name
:
"Disagree_Winning"
,
name
:
"Disagree_Winning"
,
agreeWithProposedOutput
:
false
,
agreeWithProposedOutput
:
false
,
callResolveStatus
:
t
ypes
.
GameStatusDefenderWon
,
callResolveStatus
:
gameT
ypes
.
GameStatusDefenderWon
,
shouldResolve
:
true
,
shouldResolve
:
true
,
},
},
}
}
...
@@ -126,14 +127,14 @@ func (s *stubClaimLoader) FetchClaims(ctx context.Context) ([]types.Claim, error
...
@@ -126,14 +127,14 @@ func (s *stubClaimLoader) FetchClaims(ctx context.Context) ([]types.Claim, error
type
stubResponder
struct
{
type
stubResponder
struct
{
callResolveCount
int
callResolveCount
int
callResolveStatus
t
ypes
.
GameStatus
callResolveStatus
gameT
ypes
.
GameStatus
callResolveErr
error
callResolveErr
error
resolveCount
int
resolveCount
int
resolveErr
error
resolveErr
error
}
}
func
(
s
*
stubResponder
)
CallResolve
(
ctx
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
{
func
(
s
*
stubResponder
)
CallResolve
(
ctx
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
{
s
.
callResolveCount
++
s
.
callResolveCount
++
return
s
.
callResolveStatus
,
s
.
callResolveErr
return
s
.
callResolveStatus
,
s
.
callResolveErr
}
}
...
...
op-challenger/game/fault/loader.go
View file @
23d0635b
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -49,9 +50,9 @@ func NewLoaderFromBindings(fdgAddr common.Address, client bind.ContractCaller) (
...
@@ -49,9 +50,9 @@ func NewLoaderFromBindings(fdgAddr common.Address, client bind.ContractCaller) (
}
}
// GetGameStatus returns the current game status.
// GetGameStatus returns the current game status.
func
(
l
*
loader
)
GetGameStatus
(
ctx
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
{
func
(
l
*
loader
)
GetGameStatus
(
ctx
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
{
status
,
err
:=
l
.
caller
.
Status
(
&
bind
.
CallOpts
{
Context
:
ctx
})
status
,
err
:=
l
.
caller
.
Status
(
&
bind
.
CallOpts
{
Context
:
ctx
})
return
t
ypes
.
GameStatus
(
status
),
err
return
gameT
ypes
.
GameStatus
(
status
),
err
}
}
// GetClaimCount returns the number of claims in the game.
// GetClaimCount returns the number of claims in the game.
...
...
op-challenger/game/fault/loader_test.go
View file @
23d0635b
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"testing"
"testing"
"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"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -30,15 +31,15 @@ func TestLoader_GetGameStatus(t *testing.T) {
...
@@ -30,15 +31,15 @@ func TestLoader_GetGameStatus(t *testing.T) {
}{
}{
{
{
name
:
"challenger won status"
,
name
:
"challenger won status"
,
status
:
uint8
(
t
ypes
.
GameStatusChallengerWon
),
status
:
uint8
(
gameT
ypes
.
GameStatusChallengerWon
),
},
},
{
{
name
:
"defender won status"
,
name
:
"defender won status"
,
status
:
uint8
(
t
ypes
.
GameStatusDefenderWon
),
status
:
uint8
(
gameT
ypes
.
GameStatusDefenderWon
),
},
},
{
{
name
:
"in progress status"
,
name
:
"in progress status"
,
status
:
uint8
(
t
ypes
.
GameStatusInProgress
),
status
:
uint8
(
gameT
ypes
.
GameStatusInProgress
),
},
},
{
{
name
:
"error bubbled up"
,
name
:
"error bubbled up"
,
...
@@ -57,7 +58,7 @@ func TestLoader_GetGameStatus(t *testing.T) {
...
@@ -57,7 +58,7 @@ func TestLoader_GetGameStatus(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
mockStatusError
)
require
.
ErrorIs
(
t
,
err
,
mockStatusError
)
}
else
{
}
else
{
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
t
ypes
.
GameStatus
(
test
.
status
),
status
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatus
(
test
.
status
),
status
)
}
}
})
})
}
}
...
...
op-challenger/game/fault/player.go
View file @
23d0635b
...
@@ -11,6 +11,7 @@ import (
...
@@ -11,6 +11,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"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"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
...
@@ -22,7 +23,7 @@ import (
...
@@ -22,7 +23,7 @@ import (
type
actor
func
(
ctx
context
.
Context
)
error
type
actor
func
(
ctx
context
.
Context
)
error
type
GameInfo
interface
{
type
GameInfo
interface
{
GetGameStatus
(
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
GetGameStatus
(
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
GetClaimCount
(
context
.
Context
)
(
uint64
,
error
)
GetClaimCount
(
context
.
Context
)
(
uint64
,
error
)
}
}
...
@@ -31,8 +32,7 @@ type GamePlayer struct {
...
@@ -31,8 +32,7 @@ type GamePlayer struct {
agreeWithProposedOutput
bool
agreeWithProposedOutput
bool
loader
GameInfo
loader
GameInfo
logger
log
.
Logger
logger
log
.
Logger
status
gameTypes
.
GameStatus
completed
bool
}
}
func
NewGamePlayer
(
func
NewGamePlayer
(
...
@@ -57,14 +57,14 @@ func NewGamePlayer(
...
@@ -57,14 +57,14 @@ func NewGamePlayer(
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch game status: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to fetch game status: %w"
,
err
)
}
}
if
status
!=
t
ypes
.
GameStatusInProgress
{
if
status
!=
gameT
ypes
.
GameStatusInProgress
{
logger
.
Info
(
"Game already resolved"
,
"status"
,
status
)
logger
.
Info
(
"Game already resolved"
,
"status"
,
status
)
// Game is already complete so skip creating the trace provider, loading game inputs etc.
// Game is already complete so skip creating the trace provider, loading game inputs etc.
return
&
GamePlayer
{
return
&
GamePlayer
{
logger
:
logger
,
logger
:
logger
,
loader
:
loader
,
loader
:
loader
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
completed
:
true
,
status
:
status
,
// Act function does nothing because the game is already complete
// Act function does nothing because the game is already complete
act
:
func
(
ctx
context
.
Context
)
error
{
act
:
func
(
ctx
context
.
Context
)
error
{
return
nil
return
nil
...
@@ -111,32 +111,32 @@ func NewGamePlayer(
...
@@ -111,32 +111,32 @@ func NewGamePlayer(
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
loader
:
loader
,
loader
:
loader
,
logger
:
logger
,
logger
:
logger
,
completed
:
status
!=
types
.
GameStatusInProgres
s
,
status
:
statu
s
,
},
nil
},
nil
}
}
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
gameTypes
.
GameStatus
{
if
g
.
completed
{
if
g
.
status
!=
gameTypes
.
GameStatusInProgress
{
// Game is already complete so don't try to perform further actions.
// Game is already complete so don't try to perform further actions.
g
.
logger
.
Trace
(
"Skipping completed game"
)
g
.
logger
.
Trace
(
"Skipping completed game"
)
return
true
return
g
.
status
}
}
g
.
logger
.
Trace
(
"Checking if actions are required"
)
g
.
logger
.
Trace
(
"Checking if actions are required"
)
if
err
:=
g
.
act
(
ctx
);
err
!=
nil
{
if
err
:=
g
.
act
(
ctx
);
err
!=
nil
{
g
.
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
g
.
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
}
}
if
status
,
err
:=
g
.
loader
.
GetGameStatus
(
ctx
);
err
!=
nil
{
status
,
err
:=
g
.
loader
.
GetGameStatus
(
ctx
)
if
err
!=
nil
{
g
.
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
g
.
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
}
else
{
return
gameTypes
.
GameStatusInProgress
g
.
logGameStatus
(
ctx
,
status
)
g
.
completed
=
status
!=
types
.
GameStatusInProgress
return
g
.
completed
}
}
return
false
g
.
logGameStatus
(
ctx
,
status
)
g
.
status
=
status
return
status
}
}
func
(
g
*
GamePlayer
)
logGameStatus
(
ctx
context
.
Context
,
status
t
ypes
.
GameStatus
)
{
func
(
g
*
GamePlayer
)
logGameStatus
(
ctx
context
.
Context
,
status
gameT
ypes
.
GameStatus
)
{
if
status
==
t
ypes
.
GameStatusInProgress
{
if
status
==
gameT
ypes
.
GameStatusInProgress
{
claimCount
,
err
:=
g
.
loader
.
GetClaimCount
(
ctx
)
claimCount
,
err
:=
g
.
loader
.
GetClaimCount
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
g
.
logger
.
Error
(
"Failed to get claim count for in progress game"
,
"err"
,
err
)
g
.
logger
.
Error
(
"Failed to get claim count for in progress game"
,
"err"
,
err
)
...
@@ -145,11 +145,11 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus)
...
@@ -145,11 +145,11 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus)
g
.
logger
.
Info
(
"Game info"
,
"claims"
,
claimCount
,
"status"
,
status
)
g
.
logger
.
Info
(
"Game info"
,
"claims"
,
claimCount
,
"status"
,
status
)
return
return
}
}
var
expectedStatus
t
ypes
.
GameStatus
var
expectedStatus
gameT
ypes
.
GameStatus
if
g
.
agreeWithProposedOutput
{
if
g
.
agreeWithProposedOutput
{
expectedStatus
=
t
ypes
.
GameStatusChallengerWon
expectedStatus
=
gameT
ypes
.
GameStatusChallengerWon
}
else
{
}
else
{
expectedStatus
=
t
ypes
.
GameStatusDefenderWon
expectedStatus
=
gameT
ypes
.
GameStatusDefenderWon
}
}
if
expectedStatus
==
status
{
if
expectedStatus
==
status
{
g
.
logger
.
Info
(
"Game won"
,
"status"
,
status
)
g
.
logger
.
Info
(
"Game won"
,
"status"
,
status
)
...
...
op-challenger/game/fault/player_test.go
View file @
23d0635b
...
@@ -7,6 +7,7 @@ import (
...
@@ -7,6 +7,7 @@ import (
"testing"
"testing"
"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"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
...
@@ -22,8 +23,8 @@ var (
...
@@ -22,8 +23,8 @@ var (
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
handler
,
game
,
actor
:=
setupProgressGameTest
(
t
,
true
)
handler
,
game
,
actor
:=
setupProgressGameTest
(
t
,
true
)
actor
.
actErr
=
errors
.
New
(
"boom"
)
actor
.
actErr
=
errors
.
New
(
"boom"
)
done
:=
game
.
ProgressGame
(
context
.
Background
())
status
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
gameTypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
...
@@ -38,42 +39,42 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) {
...
@@ -38,42 +39,42 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) {
func
TestProgressGame_LogGameStatus
(
t
*
testing
.
T
)
{
func
TestProgressGame_LogGameStatus
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
status
t
ypes
.
GameStatus
status
gameT
ypes
.
GameStatus
agreeWithOutput
bool
agreeWithOutput
bool
logLevel
log
.
Lvl
logLevel
log
.
Lvl
logMsg
string
logMsg
string
}{
}{
{
{
name
:
"GameLostAsDefender"
,
name
:
"GameLostAsDefender"
,
status
:
t
ypes
.
GameStatusChallengerWon
,
status
:
gameT
ypes
.
GameStatusChallengerWon
,
agreeWithOutput
:
false
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlError
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
logMsg
:
"Game lost"
,
},
},
{
{
name
:
"GameLostAsChallenger"
,
name
:
"GameLostAsChallenger"
,
status
:
t
ypes
.
GameStatusDefenderWon
,
status
:
gameT
ypes
.
GameStatusDefenderWon
,
agreeWithOutput
:
true
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlError
,
logLevel
:
log
.
LvlError
,
logMsg
:
"Game lost"
,
logMsg
:
"Game lost"
,
},
},
{
{
name
:
"GameWonAsDefender"
,
name
:
"GameWonAsDefender"
,
status
:
t
ypes
.
GameStatusDefenderWon
,
status
:
gameT
ypes
.
GameStatusDefenderWon
,
agreeWithOutput
:
false
,
agreeWithOutput
:
false
,
logLevel
:
log
.
LvlInfo
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
logMsg
:
"Game won"
,
},
},
{
{
name
:
"GameWonAsChallenger"
,
name
:
"GameWonAsChallenger"
,
status
:
t
ypes
.
GameStatusChallengerWon
,
status
:
gameT
ypes
.
GameStatusChallengerWon
,
agreeWithOutput
:
true
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlInfo
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game won"
,
logMsg
:
"Game won"
,
},
},
{
{
name
:
"GameInProgress"
,
name
:
"GameInProgress"
,
status
:
t
ypes
.
GameStatusInProgress
,
status
:
gameT
ypes
.
GameStatusInProgress
,
agreeWithOutput
:
true
,
agreeWithOutput
:
true
,
logLevel
:
log
.
LvlInfo
,
logLevel
:
log
.
LvlInfo
,
logMsg
:
"Game info"
,
logMsg
:
"Game info"
,
...
@@ -85,9 +86,9 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
...
@@ -85,9 +86,9 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
handler
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
test
.
agreeWithOutput
)
handler
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
test
.
agreeWithOutput
)
gameState
.
status
=
test
.
status
gameState
.
status
=
test
.
status
done
:=
game
.
ProgressGame
(
context
.
Background
())
status
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
test
.
status
!=
types
.
GameStatusInProgress
,
done
,
"should be done when not in progress"
)
require
.
Equal
(
t
,
test
.
status
,
status
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
require
.
Equal
(
t
,
test
.
status
,
errLog
.
GetContextValue
(
"status"
))
require
.
Equal
(
t
,
test
.
status
,
errLog
.
GetContextValue
(
"status"
))
...
@@ -96,19 +97,19 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
...
@@ -96,19 +97,19 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
}
}
func
TestDoNotActOnCompleteGame
(
t
*
testing
.
T
)
{
func
TestDoNotActOnCompleteGame
(
t
*
testing
.
T
)
{
for
_
,
status
:=
range
[]
types
.
GameStatus
{
types
.
GameStatusChallengerWon
,
t
ypes
.
GameStatusDefenderWon
}
{
for
_
,
status
:=
range
[]
gameTypes
.
GameStatus
{
gameTypes
.
GameStatusChallengerWon
,
gameT
ypes
.
GameStatusDefenderWon
}
{
t
.
Run
(
status
.
String
(),
func
(
t
*
testing
.
T
)
{
t
.
Run
(
status
.
String
(),
func
(
t
*
testing
.
T
)
{
_
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
true
)
_
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
true
)
gameState
.
status
=
status
gameState
.
status
=
status
done
:=
game
.
ProgressGame
(
context
.
Background
())
fetched
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"acts the first time"
)
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"acts the first time"
)
require
.
True
(
t
,
done
,
"should be done"
)
require
.
Equal
(
t
,
status
,
fetched
)
// Should not act when it knows the game is already complete
// Should not act when it knows the game is already complete
done
=
game
.
ProgressGame
(
context
.
Background
())
fetched
=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"does not act after game is complete"
)
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"does not act after game is complete"
)
require
.
True
(
t
,
done
,
"should still be done"
)
require
.
Equal
(
t
,
status
,
fetched
)
})
})
}
}
}
}
...
@@ -166,7 +167,7 @@ func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.C
...
@@ -166,7 +167,7 @@ func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.C
}
}
type
stubGameState
struct
{
type
stubGameState
struct
{
status
t
ypes
.
GameStatus
status
gameT
ypes
.
GameStatus
claimCount
uint64
claimCount
uint64
callCount
int
callCount
int
actErr
error
actErr
error
...
@@ -178,7 +179,7 @@ func (s *stubGameState) Act(ctx context.Context) error {
...
@@ -178,7 +179,7 @@ func (s *stubGameState) Act(ctx context.Context) error {
return
s
.
actErr
return
s
.
actErr
}
}
func
(
s
*
stubGameState
)
GetGameStatus
(
ctx
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
{
func
(
s
*
stubGameState
)
GetGameStatus
(
ctx
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
{
return
s
.
status
,
nil
return
s
.
status
,
nil
}
}
...
...
op-challenger/game/fault/responder/responder.go
View file @
23d0635b
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum"
...
@@ -81,23 +82,23 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b
...
@@ -81,23 +82,23 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b
// CallResolve determines if the resolve function on the fault dispute game contract
// CallResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns the game status if the call would succeed, errors otherwise.
// would succeed. Returns the game status if the call would succeed, errors otherwise.
func
(
r
*
faultResponder
)
CallResolve
(
ctx
context
.
Context
)
(
t
ypes
.
GameStatus
,
error
)
{
func
(
r
*
faultResponder
)
CallResolve
(
ctx
context
.
Context
)
(
gameT
ypes
.
GameStatus
,
error
)
{
txData
,
err
:=
r
.
buildResolveData
()
txData
,
err
:=
r
.
buildResolveData
()
if
err
!=
nil
{
if
err
!=
nil
{
return
t
ypes
.
GameStatusInProgress
,
err
return
gameT
ypes
.
GameStatusInProgress
,
err
}
}
res
,
err
:=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
res
,
err
:=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
To
:
&
r
.
fdgAddr
,
To
:
&
r
.
fdgAddr
,
Data
:
txData
,
Data
:
txData
,
},
nil
)
},
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
return
t
ypes
.
GameStatusInProgress
,
err
return
gameT
ypes
.
GameStatusInProgress
,
err
}
}
var
status
uint8
var
status
uint8
if
err
=
r
.
fdgAbi
.
UnpackIntoInterface
(
&
status
,
"resolve"
,
res
);
err
!=
nil
{
if
err
=
r
.
fdgAbi
.
UnpackIntoInterface
(
&
status
,
"resolve"
,
res
);
err
!=
nil
{
return
t
ypes
.
GameStatusInProgress
,
err
return
gameT
ypes
.
GameStatusInProgress
,
err
}
}
return
t
ypes
.
GameStatusFromUint8
(
status
)
return
gameT
ypes
.
GameStatusFromUint8
(
status
)
}
}
// Resolve executes a resolve transaction to resolve a fault dispute game.
// Resolve executes a resolve transaction to resolve a fault dispute game.
...
...
op-challenger/game/fault/responder/responder_test.go
View file @
23d0635b
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
...
@@ -32,7 +33,7 @@ func TestCallResolve(t *testing.T) {
...
@@ -32,7 +33,7 @@ func TestCallResolve(t *testing.T) {
mockTxMgr
.
callFails
=
true
mockTxMgr
.
callFails
=
true
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockCallError
)
require
.
ErrorIs
(
t
,
err
,
mockCallError
)
require
.
Equal
(
t
,
t
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
0
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
0
,
mockTxMgr
.
calls
)
})
})
...
@@ -41,7 +42,7 @@ func TestCallResolve(t *testing.T) {
...
@@ -41,7 +42,7 @@ func TestCallResolve(t *testing.T) {
mockTxMgr
.
callBytes
=
[]
byte
{
0x00
,
0x01
}
mockTxMgr
.
callBytes
=
[]
byte
{
0x00
,
0x01
}
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
Error
(
t
,
err
)
require
.
Error
(
t
,
err
)
require
.
Equal
(
t
,
t
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
})
})
...
@@ -49,7 +50,7 @@ func TestCallResolve(t *testing.T) {
...
@@ -49,7 +50,7 @@ func TestCallResolve(t *testing.T) {
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
t
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
})
})
}
}
...
...
op-challenger/game/fault/types/types.go
View file @
23d0635b
...
@@ -3,7 +3,6 @@ package types
...
@@ -3,7 +3,6 @@ package types
import
(
import
(
"context"
"context"
"errors"
"errors"
"fmt"
"math/big"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -13,36 +12,6 @@ var (
...
@@ -13,36 +12,6 @@ var (
ErrGameDepthReached
=
errors
.
New
(
"game depth reached"
)
ErrGameDepthReached
=
errors
.
New
(
"game depth reached"
)
)
)
type
GameStatus
uint8
const
(
GameStatusInProgress
GameStatus
=
iota
GameStatusChallengerWon
GameStatusDefenderWon
)
// String returns the string representation of the game status.
func
(
s
GameStatus
)
String
()
string
{
switch
s
{
case
GameStatusInProgress
:
return
"In Progress"
case
GameStatusChallengerWon
:
return
"Challenger Won"
case
GameStatusDefenderWon
:
return
"Defender Won"
default
:
return
"Unknown"
}
}
// GameStatusFromUint8 returns a game status from the uint8 representation.
func
GameStatusFromUint8
(
i
uint8
)
(
GameStatus
,
error
)
{
if
i
>
2
{
return
GameStatus
(
i
),
fmt
.
Errorf
(
"invalid game status: %d"
,
i
)
}
return
GameStatus
(
i
),
nil
}
// PreimageOracleData encapsulates the preimage oracle data
// PreimageOracleData encapsulates the preimage oracle data
// to load into the onchain oracle.
// to load into the onchain oracle.
type
PreimageOracleData
struct
{
type
PreimageOracleData
struct
{
...
...
op-challenger/game/fault/types/types_test.go
View file @
23d0635b
package
types
package
types
import
(
import
(
"fmt"
"testing"
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
var
validGameStatuses
=
[]
GameStatus
{
GameStatusInProgress
,
GameStatusChallengerWon
,
GameStatusDefenderWon
,
}
func
TestGameStatusFromUint8
(
t
*
testing
.
T
)
{
for
_
,
status
:=
range
validGameStatuses
{
t
.
Run
(
fmt
.
Sprintf
(
"Valid Game Status %v"
,
status
),
func
(
t
*
testing
.
T
)
{
parsed
,
err
:=
GameStatusFromUint8
(
uint8
(
status
))
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
status
,
parsed
)
})
}
t
.
Run
(
"Invalid"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
GameStatusFromUint8
(
3
)
require
.
Error
(
t
,
err
)
require
.
Equal
(
t
,
GameStatus
(
3
),
status
)
})
}
func
TestNewPreimageOracleData
(
t
*
testing
.
T
)
{
func
TestNewPreimageOracleData
(
t
*
testing
.
T
)
{
t
.
Run
(
"LocalData"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"LocalData"
,
func
(
t
*
testing
.
T
)
{
data
:=
NewPreimageOracleData
([]
byte
{
1
,
2
,
3
},
[]
byte
{
4
,
5
,
6
},
7
)
data
:=
NewPreimageOracleData
([]
byte
{
1
,
2
,
3
},
[]
byte
{
4
,
5
,
6
},
7
)
...
...
op-challenger/game/monitor.go
View file @
23d0635b
...
@@ -8,7 +8,6 @@ import (
...
@@ -8,7 +8,6 @@ import (
"time"
"time"
"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-service/clock"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
...
@@ -27,7 +26,6 @@ type gameScheduler interface {
...
@@ -27,7 +26,6 @@ type gameScheduler interface {
type
gameMonitor
struct
{
type
gameMonitor
struct
{
logger
log
.
Logger
logger
log
.
Logger
metrics
metrics
.
Metricer
clock
clock
.
Clock
clock
clock
.
Clock
source
gameSource
source
gameSource
scheduler
gameScheduler
scheduler
gameScheduler
...
@@ -38,7 +36,6 @@ type gameMonitor struct {
...
@@ -38,7 +36,6 @@ type gameMonitor struct {
func
newGameMonitor
(
func
newGameMonitor
(
logger
log
.
Logger
,
logger
log
.
Logger
,
m
metrics
.
Metricer
,
cl
clock
.
Clock
,
cl
clock
.
Clock
,
source
gameSource
,
source
gameSource
,
scheduler
gameScheduler
,
scheduler
gameScheduler
,
...
@@ -48,7 +45,6 @@ func newGameMonitor(
...
@@ -48,7 +45,6 @@ func newGameMonitor(
)
*
gameMonitor
{
)
*
gameMonitor
{
return
&
gameMonitor
{
return
&
gameMonitor
{
logger
:
logger
,
logger
:
logger
,
metrics
:
m
,
clock
:
cl
,
clock
:
cl
,
scheduler
:
scheduler
,
scheduler
:
scheduler
,
source
:
source
,
source
:
source
,
...
...
op-challenger/game/monitor_test.go
View file @
23d0635b
...
@@ -6,7 +6,6 @@ import (
...
@@ -6,7 +6,6 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -101,7 +100,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
...
@@ -101,7 +100,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
return
i
,
nil
return
i
,
nil
}
}
sched
:=
&
stubScheduler
{}
sched
:=
&
stubScheduler
{}
monitor
:=
newGameMonitor
(
logger
,
metrics
.
NoopMetrics
,
clock
.
SystemClock
,
source
,
sched
,
time
.
Duration
(
0
),
fetchBlockNum
,
allowedGames
)
monitor
:=
newGameMonitor
(
logger
,
clock
.
SystemClock
,
source
,
sched
,
time
.
Duration
(
0
),
fetchBlockNum
,
allowedGames
)
return
monitor
,
source
,
sched
return
monitor
,
source
,
sched
}
}
...
...
op-challenger/game/scheduler/coordinator.go
View file @
23d0635b
...
@@ -5,6 +5,8 @@ import (
...
@@ -5,6 +5,8 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/exp/slices"
"golang.org/x/exp/slices"
...
@@ -17,7 +19,7 @@ type PlayerCreator func(address common.Address, dir string) (GamePlayer, error)
...
@@ -17,7 +19,7 @@ type PlayerCreator func(address common.Address, dir string) (GamePlayer, error)
type
gameState
struct
{
type
gameState
struct
{
player
GamePlayer
player
GamePlayer
inflight
bool
inflight
bool
resolved
bool
status
types
.
GameStatus
}
}
// coordinator manages the set of current games, queues games to be played (on separate worker threads) and
// coordinator manages the set of current games, queues games to be played (on separate worker threads) and
...
@@ -31,6 +33,7 @@ type coordinator struct {
...
@@ -31,6 +33,7 @@ type coordinator struct {
resultQueue
<-
chan
job
resultQueue
<-
chan
job
logger
log
.
Logger
logger
log
.
Logger
m
SchedulerMetricer
createPlayer
PlayerCreator
createPlayer
PlayerCreator
states
map
[
common
.
Address
]
*
gameState
states
map
[
common
.
Address
]
*
gameState
disk
DiskManager
disk
DiskManager
...
@@ -49,18 +52,35 @@ func (c *coordinator) schedule(ctx context.Context, games []common.Address) erro
...
@@ -49,18 +52,35 @@ func (c *coordinator) schedule(ctx context.Context, games []common.Address) erro
}
}
}
}
var
gamesInProgress
int
var
gamesChallengerWon
int
var
gamesDefenderWon
int
var
errs
[]
error
var
errs
[]
error
var
jobs
[]
job
// Next collect all the jobs to schedule and ensure all games are recorded in the states map.
// Next collect all the jobs to schedule and ensure all games are recorded in the states map.
// Otherwise, results may start being processed before all games are recorded, resulting in existing
// Otherwise, results may start being processed before all games are recorded, resulting in existing
// data directories potentially being deleted for games that are required.
// data directories potentially being deleted for games that are required.
var
jobs
[]
job
for
_
,
addr
:=
range
games
{
for
_
,
addr
:=
range
games
{
if
j
,
err
:=
c
.
createJob
(
addr
);
err
!=
nil
{
if
j
,
err
:=
c
.
createJob
(
addr
);
err
!=
nil
{
errs
=
append
(
errs
,
err
)
errs
=
append
(
errs
,
err
)
}
else
if
j
!=
nil
{
}
else
if
j
!=
nil
{
jobs
=
append
(
jobs
,
*
j
)
jobs
=
append
(
jobs
,
*
j
)
}
}
state
,
ok
:=
c
.
states
[
addr
]
if
ok
{
switch
state
.
status
{
case
types
.
GameStatusInProgress
:
gamesInProgress
++
case
types
.
GameStatusDefenderWon
:
gamesDefenderWon
++
case
types
.
GameStatusChallengerWon
:
gamesChallengerWon
++
}
}
else
{
c
.
logger
.
Warn
(
"Game not found in states map"
,
"game"
,
addr
)
}
}
}
c
.
m
.
RecordGamesStatus
(
gamesInProgress
,
gamesChallengerWon
,
gamesDefenderWon
)
// Finally, enqueue the jobs
// Finally, enqueue the jobs
for
_
,
j
:=
range
jobs
{
for
_
,
j
:=
range
jobs
{
...
@@ -114,7 +134,7 @@ func (c *coordinator) processResult(j job) error {
...
@@ -114,7 +134,7 @@ func (c *coordinator) processResult(j job) error {
return
fmt
.
Errorf
(
"game %v received unexpected result: %w"
,
j
.
addr
,
errUnknownGame
)
return
fmt
.
Errorf
(
"game %v received unexpected result: %w"
,
j
.
addr
,
errUnknownGame
)
}
}
state
.
inflight
=
false
state
.
inflight
=
false
state
.
resolved
=
j
.
resolved
state
.
status
=
j
.
status
c
.
deleteResolvedGameFiles
()
c
.
deleteResolvedGameFiles
()
return
nil
return
nil
}
}
...
@@ -122,7 +142,7 @@ func (c *coordinator) processResult(j job) error {
...
@@ -122,7 +142,7 @@ func (c *coordinator) processResult(j job) error {
func
(
c
*
coordinator
)
deleteResolvedGameFiles
()
{
func
(
c
*
coordinator
)
deleteResolvedGameFiles
()
{
var
keepGames
[]
common
.
Address
var
keepGames
[]
common
.
Address
for
addr
,
state
:=
range
c
.
states
{
for
addr
,
state
:=
range
c
.
states
{
if
!
state
.
resolved
||
state
.
inflight
{
if
state
.
status
==
types
.
GameStatusInProgress
||
state
.
inflight
{
keepGames
=
append
(
keepGames
,
addr
)
keepGames
=
append
(
keepGames
,
addr
)
}
}
}
}
...
@@ -131,9 +151,10 @@ func (c *coordinator) deleteResolvedGameFiles() {
...
@@ -131,9 +151,10 @@ func (c *coordinator) deleteResolvedGameFiles() {
}
}
}
}
func
newCoordinator
(
logger
log
.
Logger
,
jobQueue
chan
<-
job
,
resultQueue
<-
chan
job
,
createPlayer
PlayerCreator
,
disk
DiskManager
)
*
coordinator
{
func
newCoordinator
(
logger
log
.
Logger
,
m
SchedulerMetricer
,
jobQueue
chan
<-
job
,
resultQueue
<-
chan
job
,
createPlayer
PlayerCreator
,
disk
DiskManager
)
*
coordinator
{
return
&
coordinator
{
return
&
coordinator
{
logger
:
logger
,
logger
:
logger
,
m
:
m
,
jobQueue
:
jobQueue
,
jobQueue
:
jobQueue
,
resultQueue
:
resultQueue
,
resultQueue
:
resultQueue
,
createPlayer
:
createPlayer
,
createPlayer
:
createPlayer
,
...
...
op-challenger/game/scheduler/coordinator_test.go
View file @
23d0635b
...
@@ -5,6 +5,8 @@ import (
...
@@ -5,6 +5,8 @@ import (
"fmt"
"fmt"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
...
@@ -140,7 +142,7 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
...
@@ -140,7 +142,7 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
require
.
NoError
(
t
,
c
.
schedule
(
ctx
,
[]
common
.
Address
{
gameAddr3
}))
require
.
NoError
(
t
,
c
.
schedule
(
ctx
,
[]
common
.
Address
{
gameAddr3
}))
require
.
Len
(
t
,
workQueue
,
1
)
require
.
Len
(
t
,
workQueue
,
1
)
j
:=
<-
workQueue
j
:=
<-
workQueue
j
.
resolved
=
true
j
.
status
=
types
.
GameStatusDefenderWon
require
.
NoError
(
t
,
c
.
processResult
(
j
))
require
.
NoError
(
t
,
c
.
processResult
(
j
))
// But ensure its data directory is marked as existing
// But ensure its data directory is marked as existing
disk
.
DirForGame
(
gameAddr3
)
disk
.
DirForGame
(
gameAddr3
)
...
@@ -155,7 +157,9 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
...
@@ -155,7 +157,9 @@ func TestDeleteDataForResolvedGames(t *testing.T) {
// Game 3 hasn't yet progressed (update is still in flight)
// Game 3 hasn't yet progressed (update is still in flight)
for
i
:=
0
;
i
<
len
(
gameAddrs
)
-
1
;
i
++
{
for
i
:=
0
;
i
<
len
(
gameAddrs
)
-
1
;
i
++
{
j
:=
<-
workQueue
j
:=
<-
workQueue
j
.
resolved
=
j
.
addr
==
gameAddr2
if
j
.
addr
==
gameAddr2
{
j
.
status
=
types
.
GameStatusDefenderWon
}
require
.
NoError
(
t
,
c
.
processResult
(
j
))
require
.
NoError
(
t
,
c
.
processResult
(
j
))
}
}
...
@@ -229,20 +233,20 @@ func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan jo
...
@@ -229,20 +233,20 @@ func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan jo
created
:
make
(
map
[
common
.
Address
]
*
stubGame
),
created
:
make
(
map
[
common
.
Address
]
*
stubGame
),
}
}
disk
:=
&
stubDiskManager
{
gameDirExists
:
make
(
map
[
common
.
Address
]
bool
)}
disk
:=
&
stubDiskManager
{
gameDirExists
:
make
(
map
[
common
.
Address
]
bool
)}
c
:=
newCoordinator
(
logger
,
workQueue
,
resultQueue
,
games
.
CreateGame
,
disk
)
c
:=
newCoordinator
(
logger
,
metrics
.
NoopMetrics
,
workQueue
,
resultQueue
,
games
.
CreateGame
,
disk
)
return
c
,
workQueue
,
resultQueue
,
games
,
disk
return
c
,
workQueue
,
resultQueue
,
games
,
disk
}
}
type
stubGame
struct
{
type
stubGame
struct
{
addr
common
.
Address
addr
common
.
Address
progressCount
int
progressCount
int
done
bool
status
types
.
GameStatus
dir
string
dir
string
}
}
func
(
g
*
stubGame
)
ProgressGame
(
_
context
.
Context
)
bool
{
func
(
g
*
stubGame
)
ProgressGame
(
_
context
.
Context
)
types
.
GameStatus
{
g
.
progressCount
++
g
.
progressCount
++
return
g
.
done
return
g
.
status
}
}
type
createdGames
struct
{
type
createdGames
struct
{
...
@@ -259,10 +263,14 @@ func (c *createdGames) CreateGame(addr common.Address, dir string) (GamePlayer,
...
@@ -259,10 +263,14 @@ func (c *createdGames) CreateGame(addr common.Address, dir string) (GamePlayer,
if
_
,
exists
:=
c
.
created
[
addr
];
exists
{
if
_
,
exists
:=
c
.
created
[
addr
];
exists
{
c
.
t
.
Fatalf
(
"game %v already exists"
,
addr
)
c
.
t
.
Fatalf
(
"game %v already exists"
,
addr
)
}
}
status
:=
types
.
GameStatusInProgress
if
addr
==
c
.
createCompleted
{
status
=
types
.
GameStatusDefenderWon
}
game
:=
&
stubGame
{
game
:=
&
stubGame
{
addr
:
addr
,
addr
:
addr
,
done
:
addr
==
c
.
createCompleted
,
status
:
status
,
dir
:
dir
,
dir
:
dir
,
}
}
c
.
created
[
addr
]
=
game
c
.
created
[
addr
]
=
game
return
game
,
nil
return
game
,
nil
...
...
op-challenger/game/scheduler/scheduler.go
View file @
23d0635b
...
@@ -11,6 +11,10 @@ import (
...
@@ -11,6 +11,10 @@ import (
var
ErrBusy
=
errors
.
New
(
"busy scheduling previous update"
)
var
ErrBusy
=
errors
.
New
(
"busy scheduling previous update"
)
type
SchedulerMetricer
interface
{
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
}
type
Scheduler
struct
{
type
Scheduler
struct
{
logger
log
.
Logger
logger
log
.
Logger
coordinator
*
coordinator
coordinator
*
coordinator
...
@@ -22,7 +26,7 @@ type Scheduler struct {
...
@@ -22,7 +26,7 @@ type Scheduler struct {
cancel
func
()
cancel
func
()
}
}
func
NewScheduler
(
logger
log
.
Logger
,
disk
DiskManager
,
maxConcurrency
uint
,
createPlayer
PlayerCreator
)
*
Scheduler
{
func
NewScheduler
(
logger
log
.
Logger
,
m
SchedulerMetricer
,
disk
DiskManager
,
maxConcurrency
uint
,
createPlayer
PlayerCreator
)
*
Scheduler
{
// Size job and results queues to be fairly small so backpressure is applied early
// Size job and results queues to be fairly small so backpressure is applied early
// but with enough capacity to keep the workers busy
// but with enough capacity to keep the workers busy
jobQueue
:=
make
(
chan
job
,
maxConcurrency
*
2
)
jobQueue
:=
make
(
chan
job
,
maxConcurrency
*
2
)
...
@@ -34,7 +38,7 @@ func NewScheduler(logger log.Logger, disk DiskManager, maxConcurrency uint, crea
...
@@ -34,7 +38,7 @@ func NewScheduler(logger log.Logger, disk DiskManager, maxConcurrency uint, crea
return
&
Scheduler
{
return
&
Scheduler
{
logger
:
logger
,
logger
:
logger
,
coordinator
:
newCoordinator
(
logger
,
jobQueue
,
resultQueue
,
createPlayer
,
disk
),
coordinator
:
newCoordinator
(
logger
,
m
,
jobQueue
,
resultQueue
,
createPlayer
,
disk
),
maxConcurrency
:
maxConcurrency
,
maxConcurrency
:
maxConcurrency
,
scheduleQueue
:
scheduleQueue
,
scheduleQueue
:
scheduleQueue
,
jobQueue
:
jobQueue
,
jobQueue
:
jobQueue
,
...
...
op-challenger/game/scheduler/scheduler_test.go
View file @
23d0635b
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"context"
"context"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
...
@@ -18,7 +19,7 @@ func TestSchedulerProcessesGames(t *testing.T) {
...
@@ -18,7 +19,7 @@ func TestSchedulerProcessesGames(t *testing.T) {
}
}
removeExceptCalls
:=
make
(
chan
[]
common
.
Address
)
removeExceptCalls
:=
make
(
chan
[]
common
.
Address
)
disk
:=
&
trackingDiskManager
{
removeExceptCalls
:
removeExceptCalls
}
disk
:=
&
trackingDiskManager
{
removeExceptCalls
:
removeExceptCalls
}
s
:=
NewScheduler
(
logger
,
disk
,
2
,
createPlayer
)
s
:=
NewScheduler
(
logger
,
metrics
.
NoopMetrics
,
disk
,
2
,
createPlayer
)
s
.
Start
(
ctx
)
s
.
Start
(
ctx
)
gameAddr1
:=
common
.
Address
{
0xaa
}
gameAddr1
:=
common
.
Address
{
0xaa
}
...
@@ -46,7 +47,7 @@ func TestReturnBusyWhenScheduleQueueFull(t *testing.T) {
...
@@ -46,7 +47,7 @@ func TestReturnBusyWhenScheduleQueueFull(t *testing.T) {
}
}
removeExceptCalls
:=
make
(
chan
[]
common
.
Address
)
removeExceptCalls
:=
make
(
chan
[]
common
.
Address
)
disk
:=
&
trackingDiskManager
{
removeExceptCalls
:
removeExceptCalls
}
disk
:=
&
trackingDiskManager
{
removeExceptCalls
:
removeExceptCalls
}
s
:=
NewScheduler
(
logger
,
disk
,
2
,
createPlayer
)
s
:=
NewScheduler
(
logger
,
metrics
.
NoopMetrics
,
disk
,
2
,
createPlayer
)
// Scheduler not started - first call fills the queue
// Scheduler not started - first call fills the queue
require
.
NoError
(
t
,
s
.
Schedule
([]
common
.
Address
{{
0xaa
}}))
require
.
NoError
(
t
,
s
.
Schedule
([]
common
.
Address
{{
0xaa
}}))
...
...
op-challenger/game/scheduler/types.go
View file @
23d0635b
...
@@ -4,10 +4,12 @@ import (
...
@@ -4,10 +4,12 @@ import (
"context"
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
)
)
type
GamePlayer
interface
{
type
GamePlayer
interface
{
ProgressGame
(
ctx
context
.
Context
)
bool
ProgressGame
(
ctx
context
.
Context
)
types
.
GameStatus
}
}
type
DiskManager
interface
{
type
DiskManager
interface
{
...
@@ -16,7 +18,7 @@ type DiskManager interface {
...
@@ -16,7 +18,7 @@ type DiskManager interface {
}
}
type
job
struct
{
type
job
struct
{
addr
common
.
Address
addr
common
.
Address
player
GamePlayer
player
GamePlayer
resolved
bool
status
types
.
GameStatus
}
}
op-challenger/game/scheduler/worker.go
View file @
23d0635b
...
@@ -15,7 +15,7 @@ func progressGames(ctx context.Context, in <-chan job, out chan<- job, wg *sync.
...
@@ -15,7 +15,7 @@ func progressGames(ctx context.Context, in <-chan job, out chan<- job, wg *sync.
case
<-
ctx
.
Done
()
:
case
<-
ctx
.
Done
()
:
return
return
case
j
:=
<-
in
:
case
j
:=
<-
in
:
j
.
resolved
=
j
.
player
.
ProgressGame
(
ctx
)
j
.
status
=
j
.
player
.
ProgressGame
(
ctx
)
out
<-
j
out
<-
j
}
}
}
}
...
...
op-challenger/game/scheduler/worker_test.go
View file @
23d0635b
...
@@ -6,6 +6,8 @@ import (
...
@@ -6,6 +6,8 @@ import (
"testing"
"testing"
"time"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
...
@@ -20,17 +22,17 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
...
@@ -20,17 +22,17 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
go
progressGames
(
ctx
,
in
,
out
,
&
wg
)
go
progressGames
(
ctx
,
in
,
out
,
&
wg
)
in
<-
job
{
in
<-
job
{
player
:
&
stubPlayer
{
done
:
false
},
player
:
&
stubPlayer
{
status
:
types
.
GameStatusInProgress
},
}
}
in
<-
job
{
in
<-
job
{
player
:
&
stubPlayer
{
done
:
true
},
player
:
&
stubPlayer
{
status
:
types
.
GameStatusDefenderWon
},
}
}
result1
:=
readWithTimeout
(
t
,
out
)
result1
:=
readWithTimeout
(
t
,
out
)
result2
:=
readWithTimeout
(
t
,
out
)
result2
:=
readWithTimeout
(
t
,
out
)
require
.
Equal
(
t
,
result1
.
resolved
,
false
)
require
.
Equal
(
t
,
result1
.
status
,
types
.
GameStatusInProgress
)
require
.
Equal
(
t
,
result2
.
resolved
,
true
)
require
.
Equal
(
t
,
result2
.
status
,
types
.
GameStatusDefenderWon
)
// Cancel the context which should exit the worker
// Cancel the context which should exit the worker
cancel
()
cancel
()
...
@@ -38,11 +40,11 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
...
@@ -38,11 +40,11 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) {
}
}
type
stubPlayer
struct
{
type
stubPlayer
struct
{
done
bool
status
types
.
GameStatus
}
}
func
(
s
*
stubPlayer
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
func
(
s
*
stubPlayer
)
ProgressGame
(
ctx
context
.
Context
)
types
.
GameStatus
{
return
s
.
done
return
s
.
status
}
}
func
readWithTimeout
[
T
any
](
t
*
testing
.
T
,
ch
<-
chan
T
)
T
{
func
readWithTimeout
[
T
any
](
t
*
testing
.
T
,
ch
<-
chan
T
)
T
{
...
...
op-challenger/game/service.go
View file @
23d0635b
...
@@ -69,13 +69,14 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
...
@@ -69,13 +69,14 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se
disk
:=
newDiskManager
(
cfg
.
Datadir
)
disk
:=
newDiskManager
(
cfg
.
Datadir
)
sched
:=
scheduler
.
NewScheduler
(
sched
:=
scheduler
.
NewScheduler
(
logger
,
logger
,
m
,
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
,
client
)
return
fault
.
NewGamePlayer
(
ctx
,
logger
,
m
,
cfg
,
dir
,
addr
,
txMgr
,
client
)
})
})
monitor
:=
newGameMonitor
(
logger
,
m
,
cl
,
loader
,
sched
,
cfg
.
GameWindow
,
client
.
BlockNumber
,
cfg
.
GameAllowlist
)
monitor
:=
newGameMonitor
(
logger
,
cl
,
loader
,
sched
,
cfg
.
GameWindow
,
client
.
BlockNumber
,
cfg
.
GameAllowlist
)
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordUp
()
m
.
RecordUp
()
...
...
op-challenger/game/types/types.go
0 → 100644
View file @
23d0635b
package
types
import
(
"fmt"
)
type
GameStatus
uint8
const
(
GameStatusInProgress
GameStatus
=
iota
GameStatusChallengerWon
GameStatusDefenderWon
)
// String returns the string representation of the game status.
func
(
s
GameStatus
)
String
()
string
{
switch
s
{
case
GameStatusInProgress
:
return
"In Progress"
case
GameStatusChallengerWon
:
return
"Challenger Won"
case
GameStatusDefenderWon
:
return
"Defender Won"
default
:
return
"Unknown"
}
}
// GameStatusFromUint8 returns a game status from the uint8 representation.
func
GameStatusFromUint8
(
i
uint8
)
(
GameStatus
,
error
)
{
if
i
>
2
{
return
GameStatus
(
i
),
fmt
.
Errorf
(
"invalid game status: %d"
,
i
)
}
return
GameStatus
(
i
),
nil
}
op-challenger/game/types/types_test.go
0 → 100644
View file @
23d0635b
package
types
import
(
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
var
validGameStatuses
=
[]
GameStatus
{
GameStatusInProgress
,
GameStatusChallengerWon
,
GameStatusDefenderWon
,
}
func
TestGameStatusFromUint8
(
t
*
testing
.
T
)
{
for
_
,
status
:=
range
validGameStatuses
{
t
.
Run
(
fmt
.
Sprintf
(
"Valid Game Status %v"
,
status
),
func
(
t
*
testing
.
T
)
{
parsed
,
err
:=
GameStatusFromUint8
(
uint8
(
status
))
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
status
,
parsed
)
})
}
t
.
Run
(
"Invalid"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
GameStatusFromUint8
(
3
)
require
.
Error
(
t
,
err
)
require
.
Equal
(
t
,
GameStatus
(
3
),
status
)
})
}
op-challenger/metrics/metrics.go
View file @
23d0635b
...
@@ -24,6 +24,8 @@ type Metricer interface {
...
@@ -24,6 +24,8 @@ type Metricer interface {
RecordGameStep
()
RecordGameStep
()
RecordGameMove
()
RecordGameMove
()
RecordCannonExecutionTime
(
t
float64
)
RecordCannonExecutionTime
(
t
float64
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
}
}
type
Metrics
struct
{
type
Metrics
struct
{
...
@@ -36,9 +38,12 @@ type Metrics struct {
...
@@ -36,9 +38,12 @@ type Metrics struct {
info
prometheus
.
GaugeVec
info
prometheus
.
GaugeVec
up
prometheus
.
Gauge
up
prometheus
.
Gauge
moves
prometheus
.
Counter
moves
prometheus
.
Counter
steps
prometheus
.
Counter
steps
prometheus
.
Counter
cannonExecutionTime
prometheus
.
Histogram
cannonExecutionTime
prometheus
.
Histogram
trackedGames
prometheus
.
GaugeVec
}
}
var
_
Metricer
=
(
*
Metrics
)(
nil
)
var
_
Metricer
=
(
*
Metrics
)(
nil
)
...
@@ -82,6 +87,13 @@ func NewMetrics() *Metrics {
...
@@ -82,6 +87,13 @@ func NewMetrics() *Metrics {
Help
:
"Time (in seconds) to execute cannon"
,
Help
:
"Time (in seconds) to execute cannon"
,
Buckets
:
append
([]
float64
{
1.0
,
10.0
},
prometheus
.
ExponentialBuckets
(
30.0
,
2.0
,
14
)
...
),
Buckets
:
append
([]
float64
{
1.0
,
10.0
},
prometheus
.
ExponentialBuckets
(
30.0
,
2.0
,
14
)
...
),
}),
}),
trackedGames
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Name
:
"tracked_games"
,
Help
:
"Number of games being tracked by the challenger"
,
},
[]
string
{
"status"
,
}),
}
}
}
}
...
@@ -120,3 +132,9 @@ func (m *Metrics) RecordGameStep() {
...
@@ -120,3 +132,9 @@ func (m *Metrics) RecordGameStep() {
func
(
m
*
Metrics
)
RecordCannonExecutionTime
(
t
float64
)
{
func
(
m
*
Metrics
)
RecordCannonExecutionTime
(
t
float64
)
{
m
.
cannonExecutionTime
.
Observe
(
t
)
m
.
cannonExecutionTime
.
Observe
(
t
)
}
}
func
(
m
*
Metrics
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
{
m
.
trackedGames
.
WithLabelValues
(
"in_progress"
)
.
Set
(
float64
(
inProgress
))
m
.
trackedGames
.
WithLabelValues
(
"defender_won"
)
.
Set
(
float64
(
defenderWon
))
m
.
trackedGames
.
WithLabelValues
(
"challenger_won"
)
.
Set
(
float64
(
challengerWon
))
}
op-challenger/metrics/noop.go
View file @
23d0635b
...
@@ -10,8 +10,12 @@ type noopMetrics struct {
...
@@ -10,8 +10,12 @@ type noopMetrics struct {
var
NoopMetrics
Metricer
=
new
(
noopMetrics
)
var
NoopMetrics
Metricer
=
new
(
noopMetrics
)
func
(
*
noopMetrics
)
RecordInfo
(
version
string
)
{}
func
(
*
noopMetrics
)
RecordInfo
(
version
string
)
{}
func
(
*
noopMetrics
)
RecordUp
()
{}
func
(
*
noopMetrics
)
RecordUp
()
{}
func
(
*
noopMetrics
)
RecordGameMove
()
{}
func
(
*
noopMetrics
)
RecordGameStep
()
{}
func
(
*
noopMetrics
)
RecordGameMove
()
{}
func
(
*
noopMetrics
)
RecordGameStep
()
{}
func
(
*
noopMetrics
)
RecordCannonExecutionTime
(
t
float64
)
{}
func
(
*
noopMetrics
)
RecordCannonExecutionTime
(
t
float64
)
{}
func
(
*
noopMetrics
)
RecordGamesStatus
(
inProgress
,
defenderWon
,
challengerWon
int
)
{}
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