Commit 7a21469e authored by Adrian Sutton's avatar Adrian Sutton

op-challenger: Don't progress completed games

parent 0200fa46
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/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"
"github.com/ethereum/go-ethereum/ethclient"
) )
type FaultDisputeGameCaller interface { type FaultDisputeGameCaller interface {
...@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller { ...@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller {
} }
} }
func NewFaultCallerFromBindings(fdgAddr common.Address, client *ethclient.Client) (*FaultCaller, error) { func NewFaultCallerFromBindings(fdgAddr common.Address, client bind.ContractCaller) (*FaultCaller, error) {
caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client) caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon" "github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"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/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
...@@ -38,7 +38,7 @@ func NewGamePlayer( ...@@ -38,7 +38,7 @@ func NewGamePlayer(
cfg *config.Config, cfg *config.Config,
addr common.Address, addr common.Address,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client, client bind.ContractCaller,
) (*GamePlayer, error) { ) (*GamePlayer, error) {
logger = logger.New("game", addr) logger = logger.New("game", addr)
contract, err := bindings.NewFaultDisputeGameCaller(addr, client) contract, err := bindings.NewFaultDisputeGameCaller(addr, client)
...@@ -100,6 +100,15 @@ func NewGamePlayer( ...@@ -100,6 +100,15 @@ func NewGamePlayer(
} }
func (g *GamePlayer) ProgressGame(ctx context.Context) bool { func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
status, err := g.caller.GetGameStatus(ctx)
if err != nil {
g.logger.Warn("Unable to retrieve game status", "err", err)
return false
}
if status != types.GameStatusInProgress {
// Game is already complete so don't try to perform further actions.
return true
}
g.logger.Trace("Checking if actions are required") g.logger.Trace("Checking if actions are required")
if err := g.agent.Act(ctx); err != nil { if err := g.agent.Act(ctx); err != nil {
g.logger.Error("Error when acting on game", "err", err) g.logger.Error("Error when acting on game", "err", err)
......
...@@ -12,14 +12,14 @@ import ( ...@@ -12,14 +12,14 @@ import (
) )
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.err = errors.New("boom") actor.actErr = errors.New("boom")
done := game.ProgressGame(context.Background()) done := game.ProgressGame(context.Background())
require.False(t, done, "should not be done") require.False(t, done, "should not be done")
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")
require.Equal(t, actor.err, errLog.GetContextValue("err")) require.Equal(t, actor.actErr, errLog.GetContextValue("err"))
// Should still log game status // Should still log game status
msg := handler.FindLog(log.LvlInfo, "Game info") msg := handler.FindLog(log.LvlInfo, "Game info")
...@@ -92,11 +92,12 @@ func TestProgressGame_LogGameStatus(t *testing.T) { ...@@ -92,11 +92,12 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
for _, test := range tests { for _, test := range tests {
test := test test := test
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
handler, game, actor, gameInfo := setupProgressGameTest(t, test.agreeWithOutput) handler, game, gameState := setupProgressGameTest(t, test.agreeWithOutput)
gameInfo.status = test.status gameState.preStatus = types.GameStatusInProgress
gameState.postStatus = test.status
done := game.ProgressGame(context.Background()) done := game.ProgressGame(context.Background())
require.Equal(t, 1, actor.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 != types.GameStatusInProgress, done, "should be done when not in progress")
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")
...@@ -105,43 +106,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) { ...@@ -105,43 +106,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
} }
} }
func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.CapturingHandler, *GamePlayer, *stubActor, *stubGameInfo) { func TestDoNotActOnCompleteGame(t *testing.T) {
for _, status := range []types.GameStatus{types.GameStatusChallengerWon, types.GameStatusDefenderWon} {
t.Run(status.String(), func(t *testing.T) {
handler, game, gameState := setupProgressGameTest(t, true)
gameState.preStatus = status
done := game.ProgressGame(context.Background())
require.Equal(t, 0, gameState.callCount, "should not perform actions")
require.True(t, done, "should be done")
require.Empty(t, handler.Logs, "should not log game status")
})
}
}
func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.CapturingHandler, *GamePlayer, *stubGameState) {
logger := testlog.Logger(t, log.LvlDebug) logger := testlog.Logger(t, log.LvlDebug)
handler := &testlog.CapturingHandler{ handler := &testlog.CapturingHandler{
Delegate: logger.GetHandler(), Delegate: logger.GetHandler(),
} }
logger.SetHandler(handler) logger.SetHandler(handler)
actor := &stubActor{} gameState := &stubGameState{claimCount: 1}
gameInfo := &stubGameInfo{claimCount: 1}
game := &GamePlayer{ game := &GamePlayer{
agent: actor, agent: gameState,
agreeWithProposedOutput: agreeWithProposedRoot, agreeWithProposedOutput: agreeWithProposedRoot,
caller: gameInfo, caller: gameState,
logger: logger, logger: logger,
} }
return handler, game, actor, gameInfo return handler, game, gameState
} }
type stubActor struct { type stubGameState struct {
callCount int preStatus types.GameStatus
err error postStatus types.GameStatus
claimCount uint64
callCount int
actErr error
Err error
} }
func (a *stubActor) Act(ctx context.Context) error { func (s *stubGameState) Act(ctx context.Context) error {
a.callCount++ s.callCount++
return a.err return s.actErr
} }
type stubGameInfo struct { func (s *stubGameState) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
status types.GameStatus if s.callCount == 0 {
claimCount uint64 return s.preStatus, nil
err error }
} return s.postStatus, nil
func (s *stubGameInfo) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
return s.status, s.err
} }
func (s *stubGameInfo) GetClaimCount(ctx context.Context) (uint64, error) { func (s *stubGameState) GetClaimCount(ctx context.Context) (uint64, error) {
return s.claimCount, s.err return s.claimCount, nil
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment