Commit d653ea62 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Tidy up modules (#6413)

* op-challenger: Remove dependency from config to flags.

Now all CLI logic is encapsulated in cmd and flags module, with config and fault modules being focussed on business logic.

* op-challenger: Move shared types into a types module

Makes it much simpler to avoid dependency cycles by having core type definitions in a different module to the service wiring code that creates everything.

* op-e2e: Update for new challenger modules.
parent e7a25442
...@@ -60,7 +60,7 @@ func run(args []string, action ConfigAction) error { ...@@ -60,7 +60,7 @@ func run(args []string, action ConfigAction) error {
} }
logger.Info("Starting op-challenger", "version", VersionWithMeta) logger.Info("Starting op-challenger", "version", VersionWithMeta)
cfg, err := config.NewConfigFromCLI(ctx) cfg, err := flags.NewConfigFromCLI(ctx)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/flags"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -39,12 +38,12 @@ func TestLogLevel(t *testing.T) { ...@@ -39,12 +38,12 @@ func TestLogLevel(t *testing.T) {
func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs()) cfg := configForArgs(t, addRequiredArgs())
defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), flags.TraceTypeAlphabet, alphabetTrace, cannonDatadir, true, 4) defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, alphabetTrace, cannonDatadir, true, 4)
require.Equal(t, defaultCfg, cfg) require.Equal(t, defaultCfg, cfg)
} }
func TestDefaultConfigIsValid(t *testing.T) { func TestDefaultConfigIsValid(t *testing.T) {
cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), flags.TraceTypeAlphabet, alphabetTrace, cannonDatadir, true, 4) cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, alphabetTrace, cannonDatadir, true, 4)
require.NoError(t, cfg.Check()) require.NoError(t, cfg.Check())
} }
...@@ -66,7 +65,7 @@ func TestTraceType(t *testing.T) { ...@@ -66,7 +65,7 @@ func TestTraceType(t *testing.T) {
verifyArgsInvalid(t, "flag trace-type is required", addRequiredArgsExcept("--trace-type")) verifyArgsInvalid(t, "flag trace-type is required", addRequiredArgsExcept("--trace-type"))
}) })
for _, traceType := range flags.TraceTypes { for _, traceType := range config.TraceTypes {
traceType := traceType traceType := traceType
t.Run("Valid_"+traceType.String(), func(t *testing.T) { t.Run("Valid_"+traceType.String(), func(t *testing.T) {
cfg := configForArgs(t, addRequiredArgsExcept("--trace-type", "--trace-type", traceType.String())) cfg := configForArgs(t, addRequiredArgsExcept("--trace-type", "--trace-type", traceType.String()))
...@@ -172,7 +171,7 @@ func requiredArgs() map[string]string { ...@@ -172,7 +171,7 @@ func requiredArgs() map[string]string {
"--agree-with-proposed-output": agreeWithProposedOutput, "--agree-with-proposed-output": agreeWithProposedOutput,
"--l1-eth-rpc": l1EthRpc, "--l1-eth-rpc": l1EthRpc,
"--game-address": gameAddressValue, "--game-address": gameAddressValue,
"--trace-type": flags.TraceTypeAlphabet.String(), "--trace-type": "alphabet",
"--alphabet": alphabetTrace, "--alphabet": alphabetTrace,
"--cannon-datadir": cannonDatadir, "--cannon-datadir": cannonDatadir,
} }
......
...@@ -2,14 +2,10 @@ package config ...@@ -2,14 +2,10 @@ package config
import ( import (
"errors" "errors"
"strings" "fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
"github.com/ethereum-optimism/optimism/op-challenger/flags"
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
) )
var ( var (
...@@ -20,6 +16,36 @@ var ( ...@@ -20,6 +16,36 @@ var (
ErrMissingGameAddress = errors.New("missing game address") ErrMissingGameAddress = errors.New("missing game address")
) )
type TraceType string
const (
TraceTypeAlphabet TraceType = "alphabet"
TraceTypeCannon TraceType = "cannon"
)
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon}
func (t TraceType) String() string {
return string(t)
}
func (t *TraceType) Set(value string) error {
if !ValidTraceType(TraceType(value)) {
return fmt.Errorf("unknown trace type: %q", value)
}
*t = TraceType(value)
return nil
}
func ValidTraceType(value TraceType) bool {
for _, t := range TraceTypes {
if t == value {
return true
}
}
return false
}
// Config is a well typed config that is parsed from the CLI params. // Config is a well typed config that is parsed from the CLI params.
// This also contains config options for auxiliary services. // This also contains config options for auxiliary services.
// It is used to initialize the challenger. // It is used to initialize the challenger.
...@@ -29,9 +55,9 @@ type Config struct { ...@@ -29,9 +55,9 @@ type Config struct {
AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output
GameDepth int // Depth of the game tree GameDepth int // Depth of the game tree
TraceType flags.TraceType // Type of trace TraceType TraceType // Type of trace
AlphabetTrace string // String for the AlphabetTraceProvider AlphabetTrace string // String for the AlphabetTraceProvider
CannonDatadir string // Cannon Data Directory for the CannonTraceProvider CannonDatadir string // Cannon Data Directory for the CannonTraceProvider
TxMgrConfig txmgr.CLIConfig TxMgrConfig txmgr.CLIConfig
} }
...@@ -39,7 +65,7 @@ type Config struct { ...@@ -39,7 +65,7 @@ type Config struct {
func NewConfig( func NewConfig(
l1EthRpc string, l1EthRpc string,
gameAddress common.Address, gameAddress common.Address,
traceType flags.TraceType, traceType TraceType,
alphabetTrace string, alphabetTrace string,
cannonDatadir string, cannonDatadir string,
agreeWithProposedOutput bool, agreeWithProposedOutput bool,
...@@ -70,10 +96,10 @@ func (c Config) Check() error { ...@@ -70,10 +96,10 @@ func (c Config) Check() error {
if c.TraceType == "" { if c.TraceType == "" {
return ErrMissingTraceType return ErrMissingTraceType
} }
if c.TraceType == flags.TraceTypeCannon && c.CannonDatadir == "" { if c.TraceType == TraceTypeCannon && c.CannonDatadir == "" {
return ErrMissingCannonDatadir return ErrMissingCannonDatadir
} }
if c.TraceType == flags.TraceTypeAlphabet && c.AlphabetTrace == "" { if c.TraceType == TraceTypeAlphabet && c.AlphabetTrace == "" {
return ErrMissingAlphabetTrace return ErrMissingAlphabetTrace
} }
if err := c.TxMgrConfig.Check(); err != nil { if err := c.TxMgrConfig.Check(); err != nil {
...@@ -81,30 +107,3 @@ func (c Config) Check() error { ...@@ -81,30 +107,3 @@ func (c Config) Check() error {
} }
return nil return nil
} }
// NewConfigFromCLI parses the Config from the provided flags or environment variables.
func NewConfigFromCLI(ctx *cli.Context) (*Config, error) {
if err := flags.CheckRequired(ctx); err != nil {
return nil, err
}
dgfAddress, err := opservice.ParseAddress(ctx.String(flags.DGFAddressFlag.Name))
if err != nil {
return nil, err
}
txMgrConfig := txmgr.ReadCLIConfig(ctx)
traceTypeFlag := flags.TraceType(strings.ToLower(ctx.String(flags.TraceTypeFlag.Name)))
return &Config{
// Required Flags
L1EthRpc: ctx.String(flags.L1EthRpcFlag.Name),
TraceType: traceTypeFlag,
GameAddress: dgfAddress,
AlphabetTrace: ctx.String(flags.AlphabetFlag.Name),
CannonDatadir: ctx.String(flags.CannonDatadirFlag.Name),
AgreeWithProposedOutput: ctx.Bool(flags.AgreeWithProposedOutputFlag.Name),
GameDepth: ctx.Int(flags.GameDepthFlag.Name),
TxMgrConfig: txMgrConfig,
}, nil
}
...@@ -3,7 +3,6 @@ package config ...@@ -3,7 +3,6 @@ package config
import ( import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/flags"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -18,27 +17,27 @@ var ( ...@@ -18,27 +17,27 @@ var (
gameDepth = 4 gameDepth = 4
) )
func validConfig(traceType flags.TraceType) Config { func validConfig(traceType TraceType) Config {
cfg := NewConfig(validL1EthRpc, validGameAddress, traceType, validAlphabetTrace, validCannonDatadir, agreeWithProposedOutput, gameDepth) cfg := NewConfig(validL1EthRpc, validGameAddress, traceType, validAlphabetTrace, validCannonDatadir, agreeWithProposedOutput, gameDepth)
return cfg return cfg
} }
// TestValidConfigIsValid checks that the config provided by validConfig is actually valid // TestValidConfigIsValid checks that the config provided by validConfig is actually valid
func TestValidConfigIsValid(t *testing.T) { func TestValidConfigIsValid(t *testing.T) {
err := validConfig(flags.TraceTypeCannon).Check() err := validConfig(TraceTypeCannon).Check()
require.NoError(t, err) require.NoError(t, err)
} }
func TestTxMgrConfig(t *testing.T) { func TestTxMgrConfig(t *testing.T) {
t.Run("Invalid", func(t *testing.T) { t.Run("Invalid", func(t *testing.T) {
config := validConfig(flags.TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.TxMgrConfig = txmgr.CLIConfig{} config.TxMgrConfig = txmgr.CLIConfig{}
require.Equal(t, config.Check().Error(), "must provide a L1 RPC url") require.Equal(t, config.Check().Error(), "must provide a L1 RPC url")
}) })
} }
func TestL1EthRpcRequired(t *testing.T) { func TestL1EthRpcRequired(t *testing.T) {
config := validConfig(flags.TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.L1EthRpc = "" config.L1EthRpc = ""
require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC) require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC)
config.L1EthRpc = validL1EthRpc config.L1EthRpc = validL1EthRpc
...@@ -46,7 +45,7 @@ func TestL1EthRpcRequired(t *testing.T) { ...@@ -46,7 +45,7 @@ func TestL1EthRpcRequired(t *testing.T) {
} }
func TestGameAddressRequired(t *testing.T) { func TestGameAddressRequired(t *testing.T) {
config := validConfig(flags.TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.GameAddress = common.Address{} config.GameAddress = common.Address{}
require.ErrorIs(t, config.Check(), ErrMissingGameAddress) require.ErrorIs(t, config.Check(), ErrMissingGameAddress)
config.GameAddress = validGameAddress config.GameAddress = validGameAddress
...@@ -54,7 +53,7 @@ func TestGameAddressRequired(t *testing.T) { ...@@ -54,7 +53,7 @@ func TestGameAddressRequired(t *testing.T) {
} }
func TestAlphabetTraceRequired(t *testing.T) { func TestAlphabetTraceRequired(t *testing.T) {
config := validConfig(flags.TraceTypeAlphabet) config := validConfig(TraceTypeAlphabet)
config.AlphabetTrace = "" config.AlphabetTrace = ""
require.ErrorIs(t, config.Check(), ErrMissingAlphabetTrace) require.ErrorIs(t, config.Check(), ErrMissingAlphabetTrace)
config.AlphabetTrace = validAlphabetTrace config.AlphabetTrace = validAlphabetTrace
...@@ -62,7 +61,7 @@ func TestAlphabetTraceRequired(t *testing.T) { ...@@ -62,7 +61,7 @@ func TestAlphabetTraceRequired(t *testing.T) {
} }
func TestCannonTraceRequired(t *testing.T) { func TestCannonTraceRequired(t *testing.T) {
config := validConfig(flags.TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.CannonDatadir = "" config.CannonDatadir = ""
require.ErrorIs(t, config.Check(), ErrMissingCannonDatadir) require.ErrorIs(t, config.Check(), ErrMissingCannonDatadir)
config.CannonDatadir = validCannonDatadir config.CannonDatadir = validCannonDatadir
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -81,7 +82,7 @@ func TestBuildFaultStepData(t *testing.T) { ...@@ -81,7 +82,7 @@ func TestBuildFaultStepData(t *testing.T) {
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t, false)
data, err := responder.buildStepTxData(StepCallData{ data, err := responder.buildStepTxData(types.StepCallData{
ClaimIndex: 2, ClaimIndex: 2,
IsAttack: false, IsAttack: false,
StateData: []byte{0x01}, StateData: []byte{0x01},
......
...@@ -5,9 +5,19 @@ import ( ...@@ -5,9 +5,19 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
type Responder interface {
CanResolve(ctx context.Context) bool
Resolve(ctx context.Context) error
Respond(ctx context.Context, response types.Claim) error
Step(ctx context.Context, stepData types.StepCallData) error
}
type Agent struct { type Agent struct {
solver *Solver solver *Solver
loader Loader loader Loader
...@@ -17,7 +27,7 @@ type Agent struct { ...@@ -17,7 +27,7 @@ type Agent struct {
log log.Logger log log.Logger
} }
func NewAgent(loader Loader, maxDepth int, trace TraceProvider, responder Responder, agreeWithProposedOutput bool, log log.Logger) *Agent { func NewAgent(loader Loader, maxDepth int, trace types.TraceProvider, responder Responder, agreeWithProposedOutput bool, log log.Logger) *Agent {
return &Agent{ return &Agent{
solver: NewSolver(maxDepth, trace), solver: NewSolver(maxDepth, trace),
loader: loader, loader: loader,
...@@ -67,7 +77,7 @@ func (a *Agent) tryResolve(ctx context.Context) bool { ...@@ -67,7 +77,7 @@ func (a *Agent) tryResolve(ctx context.Context) bool {
} }
// newGameFromContracts initializes a new game state from the state in the contract // newGameFromContracts initializes a new game state from the state in the contract
func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) { func (a *Agent) newGameFromContracts(ctx context.Context) (types.Game, error) {
claims, err := a.loader.FetchClaims(ctx) claims, err := a.loader.FetchClaims(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch claims: %w", err) return nil, fmt.Errorf("failed to fetch claims: %w", err)
...@@ -75,7 +85,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) { ...@@ -75,7 +85,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) {
if len(claims) == 0 { if len(claims) == 0 {
return nil, errors.New("no claims") return nil, errors.New("no claims")
} }
game := NewGameState(a.agreeWithProposedOutput, claims[0], uint64(a.maxDepth)) game := types.NewGameState(a.agreeWithProposedOutput, claims[0], uint64(a.maxDepth))
if err := game.PutAll(claims[1:]); err != nil { if err := game.PutAll(claims[1:]); err != nil {
return nil, fmt.Errorf("failed to load claims into the local state: %w", err) return nil, fmt.Errorf("failed to load claims into the local state: %w", err)
} }
...@@ -83,7 +93,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) { ...@@ -83,7 +93,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) {
} }
// move determines & executes the next move given a claim // move determines & executes the next move given a claim
func (a *Agent) move(ctx context.Context, claim Claim, game Game) error { func (a *Agent) move(ctx context.Context, claim types.Claim, game types.Game) error {
nextMove, err := a.solver.NextMove(claim, game.AgreeWithClaimLevel(claim)) nextMove, err := a.solver.NextMove(claim, game.AgreeWithClaimLevel(claim))
if err != nil { if err != nil {
return fmt.Errorf("execute next move: %w", err) return fmt.Errorf("execute next move: %w", err)
...@@ -105,7 +115,7 @@ func (a *Agent) move(ctx context.Context, claim Claim, game Game) error { ...@@ -105,7 +115,7 @@ func (a *Agent) move(ctx context.Context, claim Claim, game Game) error {
} }
// step determines & executes the next step against a leaf claim through the responder // step determines & executes the next step against a leaf claim through the responder
func (a *Agent) step(ctx context.Context, claim Claim, game Game) error { func (a *Agent) step(ctx context.Context, claim types.Claim, game types.Game) error {
if claim.Depth() != a.maxDepth { if claim.Depth() != a.maxDepth {
return nil return nil
} }
...@@ -129,7 +139,7 @@ func (a *Agent) step(ctx context.Context, claim Claim, game Game) error { ...@@ -129,7 +139,7 @@ func (a *Agent) step(ctx context.Context, claim Claim, game Game) error {
a.log.Info("Performing step", "is_attack", step.IsAttack, a.log.Info("Performing step", "is_attack", step.IsAttack,
"depth", step.LeafClaim.Depth(), "index_at_depth", step.LeafClaim.IndexAtDepth(), "value", step.LeafClaim.Value) "depth", step.LeafClaim.Depth(), "index_at_depth", step.LeafClaim.IndexAtDepth(), "value", step.LeafClaim.Value)
callData := StepCallData{ callData := types.StepCallData{
ClaimIndex: uint64(step.LeafClaim.ContractIndex), ClaimIndex: uint64(step.LeafClaim.ContractIndex),
IsAttack: step.IsAttack, IsAttack: step.IsAttack,
StateData: step.PreState, StateData: step.PreState,
......
...@@ -4,11 +4,12 @@ import ( ...@@ -4,11 +4,12 @@ import (
"math/big" "math/big"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var _ TraceProvider = (*AlphabetProvider)(nil) var _ types.TraceProvider = (*AlphabetProvider)(nil)
// AlphabetProvider is a [TraceProvider] that provides claims for specific // AlphabetProvider is a [TraceProvider] that provides claims for specific
// indices in the given trace. // indices in the given trace.
...@@ -29,7 +30,7 @@ func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider { ...@@ -29,7 +30,7 @@ func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider {
func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, []byte, error) { func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
// The index cannot be larger than the maximum index as computed by the depth. // The index cannot be larger than the maximum index as computed by the depth.
if i >= ap.maxLen { if i >= ap.maxLen {
return nil, nil, ErrIndexTooLarge return nil, nil, types.ErrIndexTooLarge
} }
// We extend the deepest hash to the maximum depth if the trace is not expansive. // We extend the deepest hash to the maximum depth if the trace is not expansive.
if i >= uint64(len(ap.state)) { if i >= uint64(len(ap.state)) {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -66,7 +67,7 @@ func TestGetPreimage_Succeeds(t *testing.T) { ...@@ -66,7 +67,7 @@ func TestGetPreimage_Succeeds(t *testing.T) {
func TestGetPreimage_TooLargeIndex_Fails(t *testing.T) { func TestGetPreimage_TooLargeIndex_Fails(t *testing.T) {
ap := NewAlphabetProvider("abc", 2) ap := NewAlphabetProvider("abc", 2)
_, _, err := ap.GetPreimage(4) _, _, err := ap.GetPreimage(4)
require.ErrorIs(t, err, ErrIndexTooLarge) require.ErrorIs(t, err, types.ErrIndexTooLarge)
} }
// TestGet_Succeeds tests the Get function. // TestGet_Succeeds tests the Get function.
...@@ -83,7 +84,7 @@ func TestGet_Succeeds(t *testing.T) { ...@@ -83,7 +84,7 @@ func TestGet_Succeeds(t *testing.T) {
func TestGet_IndexTooLarge(t *testing.T) { func TestGet_IndexTooLarge(t *testing.T) {
ap := NewAlphabetProvider("abc", 2) ap := NewAlphabetProvider("abc", 2)
_, err := ap.Get(4) _, err := ap.Get(4)
require.ErrorIs(t, err, ErrIndexTooLarge) require.ErrorIs(t, err, types.ErrIndexTooLarge)
} }
// TestGet_Extends tests the Get function with an index that is larger // TestGet_Extends tests the Get function with an index that is larger
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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"
...@@ -59,9 +60,9 @@ func (fc *FaultCaller) LogGameInfo(ctx context.Context) { ...@@ -59,9 +60,9 @@ func (fc *FaultCaller) LogGameInfo(ctx context.Context) {
// 0: In Progress // 0: In Progress
// 1: Challenger Won // 1: Challenger Won
// 2: Defender Won // 2: Defender Won
func (fc *FaultCaller) GetGameStatus(ctx context.Context) (GameStatus, error) { func (fc *FaultCaller) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
status, err := fc.Status(&bind.CallOpts{Context: ctx}) status, err := fc.Status(&bind.CallOpts{Context: ctx})
return GameStatus(status), err return types.GameStatus(status), err
} }
// GetClaimDataLength returns the number of claims in the game. // GetClaimDataLength returns the number of claims in the game.
...@@ -79,13 +80,13 @@ func (fc *FaultCaller) LogClaimDataLength(ctx context.Context) { ...@@ -79,13 +80,13 @@ func (fc *FaultCaller) LogClaimDataLength(ctx context.Context) {
} }
// GameStatusString returns the current game status as a string. // GameStatusString returns the current game status as a string.
func GameStatusString(status GameStatus) string { func GameStatusString(status types.GameStatus) string {
switch status { switch status {
case GameStatusInProgress: case types.GameStatusInProgress:
return "In Progress" return "In Progress"
case GameStatusChallengerWon: case types.GameStatusChallengerWon:
return "Challenger Won" return "Challenger Won"
case GameStatusDefenderWon: case types.GameStatusDefenderWon:
return "Defender Won" return "Defender Won"
default: default:
return "Unknown" return "Unknown"
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"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/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -40,7 +41,7 @@ func TestFaultCaller_GetGameStatus(t *testing.T) { ...@@ -40,7 +41,7 @@ func TestFaultCaller_GetGameStatus(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
caller FaultDisputeGameCaller caller FaultDisputeGameCaller
expectedStatus GameStatus expectedStatus types.GameStatus
expectedErr error expectedErr error
}{ }{
{ {
...@@ -48,7 +49,7 @@ func TestFaultCaller_GetGameStatus(t *testing.T) { ...@@ -48,7 +49,7 @@ func TestFaultCaller_GetGameStatus(t *testing.T) {
caller: &mockFaultDisputeGameCaller{ caller: &mockFaultDisputeGameCaller{
status: 1, status: 1,
}, },
expectedStatus: GameStatusChallengerWon, expectedStatus: types.GameStatusChallengerWon,
expectedErr: nil, expectedErr: nil,
}, },
{ {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"math/big" "math/big"
"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"
) )
...@@ -22,7 +23,7 @@ type ClaimFetcher interface { ...@@ -22,7 +23,7 @@ type ClaimFetcher interface {
// Loader is a minimal interface for loading onchain [Claim] data. // Loader is a minimal interface for loading onchain [Claim] data.
type Loader interface { type Loader interface {
FetchClaims(ctx context.Context) ([]Claim, error) FetchClaims(ctx context.Context) ([]types.Claim, error)
} }
// loader pulls in fault dispute game claim data periodically and over subscriptions. // loader pulls in fault dispute game claim data periodically and over subscriptions.
...@@ -38,20 +39,20 @@ func NewLoader(claimFetcher ClaimFetcher) *loader { ...@@ -38,20 +39,20 @@ func NewLoader(claimFetcher ClaimFetcher) *loader {
} }
// fetchClaim fetches a single [Claim] with a hydrated parent. // fetchClaim fetches a single [Claim] with a hydrated parent.
func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (Claim, error) { func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim, error) {
callOpts := bind.CallOpts{ callOpts := bind.CallOpts{
Context: ctx, Context: ctx,
} }
fetchedClaim, err := l.claimFetcher.ClaimData(&callOpts, new(big.Int).SetUint64(arrIndex)) fetchedClaim, err := l.claimFetcher.ClaimData(&callOpts, new(big.Int).SetUint64(arrIndex))
if err != nil { if err != nil {
return Claim{}, err return types.Claim{}, err
} }
claim := Claim{ claim := types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: fetchedClaim.Claim, Value: fetchedClaim.Claim,
Position: NewPositionFromGIndex(fetchedClaim.Position.Uint64()), Position: types.NewPositionFromGIndex(fetchedClaim.Position.Uint64()),
}, },
Countered: fetchedClaim.Countered, Countered: fetchedClaim.Countered,
Clock: fetchedClaim.Clock.Uint64(), Clock: fetchedClaim.Clock.Uint64(),
...@@ -63,11 +64,11 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (Claim, error) ...@@ -63,11 +64,11 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (Claim, error)
parentIndex := uint64(fetchedClaim.ParentIndex) parentIndex := uint64(fetchedClaim.ParentIndex)
parentClaim, err := l.claimFetcher.ClaimData(&callOpts, new(big.Int).SetUint64(parentIndex)) parentClaim, err := l.claimFetcher.ClaimData(&callOpts, new(big.Int).SetUint64(parentIndex))
if err != nil { if err != nil {
return Claim{}, err return types.Claim{}, err
} }
claim.Parent = ClaimData{ claim.Parent = types.ClaimData{
Value: parentClaim.Claim, Value: parentClaim.Claim,
Position: NewPositionFromGIndex(parentClaim.Position.Uint64()), Position: types.NewPositionFromGIndex(parentClaim.Position.Uint64()),
} }
} }
...@@ -75,7 +76,7 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (Claim, error) ...@@ -75,7 +76,7 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (Claim, error)
} }
// FetchClaims fetches all claims from the fault dispute game. // FetchClaims fetches all claims from the fault dispute game.
func (l *loader) FetchClaims(ctx context.Context) ([]Claim, error) { func (l *loader) FetchClaims(ctx context.Context) ([]types.Claim, error) {
// Get the current claim count. // Get the current claim count.
claimCount, err := l.claimFetcher.ClaimDataLen(&bind.CallOpts{ claimCount, err := l.claimFetcher.ClaimDataLen(&bind.CallOpts{
Context: ctx, Context: ctx,
...@@ -85,7 +86,7 @@ func (l *loader) FetchClaims(ctx context.Context) ([]Claim, error) { ...@@ -85,7 +86,7 @@ func (l *loader) FetchClaims(ctx context.Context) ([]Claim, error) {
} }
// Fetch each claim and build a list. // Fetch each claim and build a list.
claimList := make([]Claim, claimCount.Uint64()) claimList := make([]types.Claim, claimCount.Uint64())
for i := uint64(0); i < claimCount.Uint64(); i++ { for i := uint64(0); i < claimCount.Uint64(); i++ {
claim, err := l.fetchClaim(ctx, i) claim, err := l.fetchClaim(ctx, i)
if err != nil { if err != nil {
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"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/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -94,41 +95,41 @@ func TestLoader_FetchClaims_Succeeds(t *testing.T) { ...@@ -94,41 +95,41 @@ func TestLoader_FetchClaims_Succeeds(t *testing.T) {
loader := NewLoader(mockClaimFetcher) loader := NewLoader(mockClaimFetcher)
claims, err := loader.FetchClaims(context.Background()) claims, err := loader.FetchClaims(context.Background())
require.NoError(t, err) require.NoError(t, err)
require.ElementsMatch(t, []Claim{ require.ElementsMatch(t, []types.Claim{
{ {
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: expectedClaims[0].Claim, Value: expectedClaims[0].Claim,
Position: NewPositionFromGIndex(expectedClaims[0].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[0].Position.Uint64()),
}, },
Parent: ClaimData{ Parent: types.ClaimData{
Value: expectedClaims[0].Claim, Value: expectedClaims[0].Claim,
Position: NewPositionFromGIndex(expectedClaims[0].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[0].Position.Uint64()),
}, },
Countered: false, Countered: false,
Clock: uint64(0), Clock: uint64(0),
ContractIndex: 0, ContractIndex: 0,
}, },
{ {
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: expectedClaims[1].Claim, Value: expectedClaims[1].Claim,
Position: NewPositionFromGIndex(expectedClaims[1].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[1].Position.Uint64()),
}, },
Parent: ClaimData{ Parent: types.ClaimData{
Value: expectedClaims[0].Claim, Value: expectedClaims[0].Claim,
Position: NewPositionFromGIndex(expectedClaims[1].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[1].Position.Uint64()),
}, },
Countered: false, Countered: false,
Clock: uint64(0), Clock: uint64(0),
ContractIndex: 1, ContractIndex: 1,
}, },
{ {
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: expectedClaims[2].Claim, Value: expectedClaims[2].Claim,
Position: NewPositionFromGIndex(expectedClaims[2].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[2].Position.Uint64()),
}, },
Parent: ClaimData{ Parent: types.ClaimData{
Value: expectedClaims[0].Claim, Value: expectedClaims[0].Claim,
Position: NewPositionFromGIndex(expectedClaims[2].Position.Uint64()), Position: types.NewPositionFromGIndex(expectedClaims[2].Position.Uint64()),
}, },
Countered: false, Countered: false,
Clock: uint64(0), Clock: uint64(0),
......
...@@ -4,11 +4,12 @@ import ( ...@@ -4,11 +4,12 @@ import (
"context" "context"
"time" "time"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
type GameInfo interface { type GameInfo interface {
GetGameStatus(context.Context) (GameStatus, error) GetGameStatus(context.Context) (types.GameStatus, error)
LogGameInfo(ctx context.Context) LogGameInfo(ctx context.Context)
} }
...@@ -43,11 +44,11 @@ func progressGame(ctx context.Context, logger log.Logger, agreeWithProposedOutpu ...@@ -43,11 +44,11 @@ func progressGame(ctx context.Context, logger log.Logger, agreeWithProposedOutpu
if status, err := caller.GetGameStatus(ctx); err != nil { if status, err := caller.GetGameStatus(ctx); err != nil {
logger.Warn("Unable to retrieve game status", "err", err) logger.Warn("Unable to retrieve game status", "err", err)
} else if status != 0 { } else if status != 0 {
var expectedStatus GameStatus var expectedStatus types.GameStatus
if agreeWithProposedOutput { if agreeWithProposedOutput {
expectedStatus = GameStatusChallengerWon expectedStatus = types.GameStatusChallengerWon
} else { } else {
expectedStatus = GameStatusDefenderWon expectedStatus = types.GameStatusDefenderWon
} }
if expectedStatus == status { if expectedStatus == status {
logger.Info("Game won", "status", GameStatusString(status)) logger.Info("Game won", "status", GameStatusString(status))
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -43,7 +44,7 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) { ...@@ -43,7 +44,7 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) {
func TestProgressGame_LogErrorWhenGameLost(t *testing.T) { func TestProgressGame_LogErrorWhenGameLost(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
status GameStatus status types.GameStatus
agreeWithOutput bool agreeWithOutput bool
logLevel log.Lvl logLevel log.Lvl
logMsg string logMsg string
...@@ -51,7 +52,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) { ...@@ -51,7 +52,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) {
}{ }{
{ {
name: "GameLostAsDefender", name: "GameLostAsDefender",
status: GameStatusChallengerWon, status: types.GameStatusChallengerWon,
agreeWithOutput: false, agreeWithOutput: false,
logLevel: log.LvlError, logLevel: log.LvlError,
logMsg: "Game lost", logMsg: "Game lost",
...@@ -59,7 +60,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) { ...@@ -59,7 +60,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) {
}, },
{ {
name: "GameLostAsChallenger", name: "GameLostAsChallenger",
status: GameStatusDefenderWon, status: types.GameStatusDefenderWon,
agreeWithOutput: true, agreeWithOutput: true,
logLevel: log.LvlError, logLevel: log.LvlError,
logMsg: "Game lost", logMsg: "Game lost",
...@@ -67,7 +68,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) { ...@@ -67,7 +68,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) {
}, },
{ {
name: "GameWonAsDefender", name: "GameWonAsDefender",
status: GameStatusDefenderWon, status: types.GameStatusDefenderWon,
agreeWithOutput: false, agreeWithOutput: false,
logLevel: log.LvlInfo, logLevel: log.LvlInfo,
logMsg: "Game won", logMsg: "Game won",
...@@ -75,7 +76,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) { ...@@ -75,7 +76,7 @@ func TestProgressGame_LogErrorWhenGameLost(t *testing.T) {
}, },
{ {
name: "GameWonAsChallenger", name: "GameWonAsChallenger",
status: GameStatusChallengerWon, status: types.GameStatusChallengerWon,
agreeWithOutput: true, agreeWithOutput: true,
logLevel: log.LvlInfo, logLevel: log.LvlInfo,
logMsg: "Game won", logMsg: "Game won",
...@@ -120,12 +121,12 @@ func (a *stubActor) Act(ctx context.Context) error { ...@@ -120,12 +121,12 @@ func (a *stubActor) Act(ctx context.Context) error {
} }
type stubGameInfo struct { type stubGameInfo struct {
status GameStatus status types.GameStatus
err error err error
logCount int logCount int
} }
func (s *stubGameInfo) GetGameStatus(ctx context.Context) (GameStatus, error) { func (s *stubGameInfo) GetGameStatus(ctx context.Context) (types.GameStatus, error) {
return s.status, s.err return s.status, s.err
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
types2 "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" "github.com/ethereum/go-ethereum"
...@@ -62,7 +63,7 @@ func (r *faultResponder) buildResolveData() ([]byte, error) { ...@@ -62,7 +63,7 @@ func (r *faultResponder) buildResolveData() ([]byte, error) {
} }
// BuildTx builds the transaction for the [faultResponder]. // BuildTx builds the transaction for the [faultResponder].
func (r *faultResponder) BuildTx(ctx context.Context, response Claim) ([]byte, error) { func (r *faultResponder) BuildTx(ctx context.Context, response types2.Claim) ([]byte, error) {
if response.DefendsParent() { if response.DefendsParent() {
txData, err := r.buildFaultDefendData(response.ParentContractIndex, response.ValueBytes()) txData, err := r.buildFaultDefendData(response.ParentContractIndex, response.ValueBytes())
if err != nil { if err != nil {
...@@ -103,7 +104,7 @@ func (r *faultResponder) Resolve(ctx context.Context) error { ...@@ -103,7 +104,7 @@ func (r *faultResponder) Resolve(ctx context.Context) error {
} }
// Respond takes a [Claim] and executes the response action. // Respond takes a [Claim] and executes the response action.
func (r *faultResponder) Respond(ctx context.Context, response Claim) error { func (r *faultResponder) Respond(ctx context.Context, response types2.Claim) error {
txData, err := r.BuildTx(ctx, response) txData, err := r.BuildTx(ctx, response)
if err != nil { if err != nil {
return err return err
...@@ -131,7 +132,7 @@ func (r *faultResponder) sendTxAndWait(ctx context.Context, txData []byte) error ...@@ -131,7 +132,7 @@ func (r *faultResponder) sendTxAndWait(ctx context.Context, txData []byte) error
} }
// buildStepTxData creates the transaction data for the step function. // buildStepTxData creates the transaction data for the step function.
func (r *faultResponder) buildStepTxData(stepData StepCallData) ([]byte, error) { func (r *faultResponder) buildStepTxData(stepData types2.StepCallData) ([]byte, error) {
return r.fdgAbi.Pack( return r.fdgAbi.Pack(
"step", "step",
big.NewInt(int64(stepData.ClaimIndex)), big.NewInt(int64(stepData.ClaimIndex)),
...@@ -142,7 +143,7 @@ func (r *faultResponder) buildStepTxData(stepData StepCallData) ([]byte, error) ...@@ -142,7 +143,7 @@ func (r *faultResponder) buildStepTxData(stepData StepCallData) ([]byte, error)
} }
// Step accepts step data and executes the step on the fault dispute game contract. // Step accepts step data and executes the step on the fault dispute game contract.
func (r *faultResponder) Step(ctx context.Context, stepData StepCallData) error { func (r *faultResponder) Step(ctx context.Context, stepData types2.StepCallData) error {
txData, err := r.buildStepTxData(stepData) txData, err := r.buildStepTxData(stepData)
if err != nil { if err != nil {
return err return err
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
types2 "github.com/ethereum-optimism/optimism/op-challenger/fault/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"
...@@ -107,14 +108,14 @@ func TestResponder_Resolve_Success(t *testing.T) { ...@@ -107,14 +108,14 @@ func TestResponder_Resolve_Success(t *testing.T) {
// bubbles up the error returned by the [txmgr.Send] method. // bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Respond_SendFails(t *testing.T) { func TestResponder_Respond_SendFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true) responder, mockTxMgr := newTestFaultResponder(t, true)
err := responder.Respond(context.Background(), Claim{ err := responder.Respond(context.Background(), types2.Claim{
ClaimData: ClaimData{ ClaimData: types2.ClaimData{
Value: common.Hash{0x01}, Value: common.Hash{0x01},
Position: NewPositionFromGIndex(2), Position: types2.NewPositionFromGIndex(2),
}, },
Parent: ClaimData{ Parent: types2.ClaimData{
Value: common.Hash{0x02}, Value: common.Hash{0x02},
Position: NewPositionFromGIndex(1), Position: types2.NewPositionFromGIndex(1),
}, },
ContractIndex: 0, ContractIndex: 0,
ParentContractIndex: 0, ParentContractIndex: 0,
...@@ -127,14 +128,14 @@ func TestResponder_Respond_SendFails(t *testing.T) { ...@@ -127,14 +128,14 @@ func TestResponder_Respond_SendFails(t *testing.T) {
// succeeds when the tx candidate is successfully sent through the txmgr. // succeeds when the tx candidate is successfully sent through the txmgr.
func TestResponder_Respond_Success(t *testing.T) { func TestResponder_Respond_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false) responder, mockTxMgr := newTestFaultResponder(t, false)
err := responder.Respond(context.Background(), Claim{ err := responder.Respond(context.Background(), types2.Claim{
ClaimData: ClaimData{ ClaimData: types2.ClaimData{
Value: common.Hash{0x01}, Value: common.Hash{0x01},
Position: NewPositionFromGIndex(2), Position: types2.NewPositionFromGIndex(2),
}, },
Parent: ClaimData{ Parent: types2.ClaimData{
Value: common.Hash{0x02}, Value: common.Hash{0x02},
Position: NewPositionFromGIndex(1), Position: types2.NewPositionFromGIndex(1),
}, },
ContractIndex: 0, ContractIndex: 0,
ParentContractIndex: 0, ParentContractIndex: 0,
...@@ -147,14 +148,14 @@ func TestResponder_Respond_Success(t *testing.T) { ...@@ -147,14 +148,14 @@ func TestResponder_Respond_Success(t *testing.T) {
// returns a tx candidate with the correct data for an attack tx. // returns a tx candidate with the correct data for an attack tx.
func TestResponder_BuildTx_Attack(t *testing.T) { func TestResponder_BuildTx_Attack(t *testing.T) {
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t, false)
responseClaim := Claim{ responseClaim := types2.Claim{
ClaimData: ClaimData{ ClaimData: types2.ClaimData{
Value: common.Hash{0x01}, Value: common.Hash{0x01},
Position: NewPositionFromGIndex(2), Position: types2.NewPositionFromGIndex(2),
}, },
Parent: ClaimData{ Parent: types2.ClaimData{
Value: common.Hash{0x02}, Value: common.Hash{0x02},
Position: NewPositionFromGIndex(1), Position: types2.NewPositionFromGIndex(1),
}, },
ContractIndex: 0, ContractIndex: 0,
ParentContractIndex: 7, ParentContractIndex: 7,
...@@ -178,14 +179,14 @@ func TestResponder_BuildTx_Attack(t *testing.T) { ...@@ -178,14 +179,14 @@ func TestResponder_BuildTx_Attack(t *testing.T) {
// returns a tx candidate with the correct data for a defend tx. // returns a tx candidate with the correct data for a defend tx.
func TestResponder_BuildTx_Defend(t *testing.T) { func TestResponder_BuildTx_Defend(t *testing.T) {
responder, _ := newTestFaultResponder(t, false) responder, _ := newTestFaultResponder(t, false)
responseClaim := Claim{ responseClaim := types2.Claim{
ClaimData: ClaimData{ ClaimData: types2.ClaimData{
Value: common.Hash{0x01}, Value: common.Hash{0x01},
Position: NewPositionFromGIndex(3), Position: types2.NewPositionFromGIndex(3),
}, },
Parent: ClaimData{ Parent: types2.ClaimData{
Value: common.Hash{0x02}, Value: common.Hash{0x02},
Position: NewPositionFromGIndex(6), Position: types2.NewPositionFromGIndex(6),
}, },
ContractIndex: 0, ContractIndex: 0,
ParentContractIndex: 7, ParentContractIndex: 7,
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,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/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"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/flags" "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-optimism/optimism/op-service/txmgr/metrics" "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
...@@ -52,11 +52,11 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se ...@@ -52,11 +52,11 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
return nil, fmt.Errorf("failed to create the responder: %w", err) return nil, fmt.Errorf("failed to create the responder: %w", err)
} }
var trace TraceProvider var trace types.TraceProvider
switch cfg.TraceType { switch cfg.TraceType {
case flags.TraceTypeCannon: case config.TraceTypeCannon:
trace = cannon.NewCannonTraceProvider(cfg.CannonDatadir) trace = cannon.NewCannonTraceProvider(cfg.CannonDatadir)
case flags.TraceTypeAlphabet: case config.TraceTypeAlphabet:
trace = NewAlphabetProvider(cfg.AlphabetTrace, uint64(cfg.GameDepth)) trace = NewAlphabetProvider(cfg.AlphabetTrace, uint64(cfg.GameDepth))
default: default:
return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType) return nil, fmt.Errorf("unsupported trace type: %v", cfg.TraceType)
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -13,12 +14,12 @@ var ( ...@@ -13,12 +14,12 @@ var (
// Solver uses a [TraceProvider] to determine the moves to make in a dispute game. // Solver uses a [TraceProvider] to determine the moves to make in a dispute game.
type Solver struct { type Solver struct {
TraceProvider types.TraceProvider
gameDepth int gameDepth int
} }
// NewSolver creates a new [Solver] using the provided [TraceProvider]. // NewSolver creates a new [Solver] using the provided [TraceProvider].
func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver { func NewSolver(gameDepth int, traceProvider types.TraceProvider) *Solver {
return &Solver{ return &Solver{
traceProvider, traceProvider,
gameDepth, gameDepth,
...@@ -26,7 +27,7 @@ func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver { ...@@ -26,7 +27,7 @@ func NewSolver(gameDepth int, traceProvider TraceProvider) *Solver {
} }
// NextMove returns the next move to make given the current state of the game. // NextMove returns the next move to make given the current state of the game.
func (s *Solver) NextMove(claim Claim, agreeWithClaimLevel bool) (*Claim, error) { func (s *Solver) NextMove(claim types.Claim, agreeWithClaimLevel bool) (*types.Claim, error) {
if agreeWithClaimLevel { if agreeWithClaimLevel {
return nil, nil return nil, nil
} }
...@@ -38,7 +39,7 @@ func (s *Solver) NextMove(claim Claim, agreeWithClaimLevel bool) (*Claim, error) ...@@ -38,7 +39,7 @@ func (s *Solver) NextMove(claim Claim, agreeWithClaimLevel bool) (*Claim, error)
return s.handleMiddle(claim) return s.handleMiddle(claim)
} }
func (s *Solver) handleRoot(claim Claim) (*Claim, error) { func (s *Solver) handleRoot(claim types.Claim) (*types.Claim, error) {
agree, err := s.agreeWithClaim(claim.ClaimData) agree, err := s.agreeWithClaim(claim.ClaimData)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -53,7 +54,7 @@ func (s *Solver) handleRoot(claim Claim) (*Claim, error) { ...@@ -53,7 +54,7 @@ func (s *Solver) handleRoot(claim Claim) (*Claim, error) {
} }
} }
func (s *Solver) handleMiddle(claim Claim) (*Claim, error) { func (s *Solver) handleMiddle(claim types.Claim) (*types.Claim, error) {
claimCorrect, err := s.agreeWithClaim(claim.ClaimData) claimCorrect, err := s.agreeWithClaim(claim.ClaimData)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -69,7 +70,7 @@ func (s *Solver) handleMiddle(claim Claim) (*Claim, error) { ...@@ -69,7 +70,7 @@ func (s *Solver) handleMiddle(claim Claim) (*Claim, error) {
} }
type StepData struct { type StepData struct {
LeafClaim Claim LeafClaim types.Claim
IsAttack bool IsAttack bool
PreState []byte PreState []byte
ProofData []byte ProofData []byte
...@@ -77,7 +78,7 @@ type StepData struct { ...@@ -77,7 +78,7 @@ type StepData struct {
// AttemptStep determines what step should occur for a given leaf claim. // AttemptStep determines what step should occur for a given leaf claim.
// An error will be returned if the claim is not at the max depth. // An error will be returned if the claim is not at the max depth.
func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, error) { func (s *Solver) AttemptStep(claim types.Claim, agreeWithClaimLevel bool) (StepData, error) {
if claim.Depth() != s.gameDepth { if claim.Depth() != s.gameDepth {
return StepData{}, errors.New("cannot step on non-leaf claims") return StepData{}, errors.New("cannot step on non-leaf claims")
} }
...@@ -114,41 +115,41 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e ...@@ -114,41 +115,41 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
} }
// attack returns a response that attacks the claim. // attack returns a response that attacks the claim.
func (s *Solver) attack(claim Claim) (*Claim, error) { func (s *Solver) attack(claim types.Claim) (*types.Claim, error) {
position := claim.Attack() position := claim.Attack()
value, err := s.traceAtPosition(position) value, err := s.traceAtPosition(position)
if err != nil { if err != nil {
return nil, fmt.Errorf("attack claim: %w", err) return nil, fmt.Errorf("attack claim: %w", err)
} }
return &Claim{ return &types.Claim{
ClaimData: ClaimData{Value: value, Position: position}, ClaimData: types.ClaimData{Value: value, Position: position},
Parent: claim.ClaimData, Parent: claim.ClaimData,
ParentContractIndex: claim.ContractIndex, ParentContractIndex: claim.ContractIndex,
}, nil }, nil
} }
// defend returns a response that defends the claim. // defend returns a response that defends the claim.
func (s *Solver) defend(claim Claim) (*Claim, error) { func (s *Solver) defend(claim types.Claim) (*types.Claim, error) {
position := claim.Defend() position := claim.Defend()
value, err := s.traceAtPosition(position) value, err := s.traceAtPosition(position)
if err != nil { if err != nil {
return nil, fmt.Errorf("defend claim: %w", err) return nil, fmt.Errorf("defend claim: %w", err)
} }
return &Claim{ return &types.Claim{
ClaimData: ClaimData{Value: value, Position: position}, ClaimData: types.ClaimData{Value: value, Position: position},
Parent: claim.ClaimData, Parent: claim.ClaimData,
ParentContractIndex: claim.ContractIndex, ParentContractIndex: claim.ContractIndex,
}, nil }, nil
} }
// agreeWithClaim returns true if the claim is correct according to the internal [TraceProvider]. // agreeWithClaim returns true if the claim is correct according to the internal [TraceProvider].
func (s *Solver) agreeWithClaim(claim ClaimData) (bool, error) { func (s *Solver) agreeWithClaim(claim types.ClaimData) (bool, error) {
ourValue, err := s.traceAtPosition(claim.Position) ourValue, err := s.traceAtPosition(claim.Position)
return ourValue == claim.Value, err return ourValue == claim.Value, err
} }
// traceAtPosition returns the [common.Hash] from internal [TraceProvider] at the given [Position]. // traceAtPosition returns the [common.Hash] from internal [TraceProvider] at the given [Position].
func (s *Solver) traceAtPosition(p Position) (common.Hash, error) { func (s *Solver) traceAtPosition(p types.Position) (common.Hash, error) {
index := p.TraceIndex(s.gameDepth) index := p.TraceIndex(s.gameDepth)
hash, err := s.Get(index) hash, err := s.Get(index)
return hash, err return hash, err
......
...@@ -3,6 +3,7 @@ package fault ...@@ -3,6 +3,7 @@ package fault
import ( import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -23,52 +24,52 @@ func TestSolver_NextMove_Opponent(t *testing.T) { ...@@ -23,52 +24,52 @@ func TestSolver_NextMove_Opponent(t *testing.T) {
// The following claims are created using the state: "abcdexyz". // The following claims are created using the state: "abcdexyz".
// The responses are the responses we expect from the solver. // The responses are the responses we expect from the solver.
indices := []struct { indices := []struct {
claim Claim claim types.Claim
response ClaimData response types.ClaimData
}{ }{
{ {
Claim{ types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: alphabetClaim(7, "z"), Value: alphabetClaim(7, "z"),
Position: NewPosition(0, 0), Position: types.NewPosition(0, 0),
}, },
// Root claim has no parent // Root claim has no parent
}, },
ClaimData{ types.ClaimData{
Value: alphabetClaim(3, "d"), Value: alphabetClaim(3, "d"),
Position: NewPosition(1, 0), Position: types.NewPosition(1, 0),
}, },
}, },
{ {
Claim{ types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: alphabetClaim(3, "d"), Value: alphabetClaim(3, "d"),
Position: NewPosition(1, 0), Position: types.NewPosition(1, 0),
}, },
Parent: ClaimData{ Parent: types.ClaimData{
Value: alphabetClaim(7, "h"), Value: alphabetClaim(7, "h"),
Position: NewPosition(0, 0), Position: types.NewPosition(0, 0),
}, },
}, },
ClaimData{ types.ClaimData{
Value: alphabetClaim(5, "f"), Value: alphabetClaim(5, "f"),
Position: NewPosition(2, 2), Position: types.NewPosition(2, 2),
}, },
}, },
{ {
Claim{ types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: alphabetClaim(5, "x"), Value: alphabetClaim(5, "x"),
Position: NewPosition(2, 2), Position: types.NewPosition(2, 2),
}, },
Parent: ClaimData{ Parent: types.ClaimData{
Value: alphabetClaim(7, "h"), Value: alphabetClaim(7, "h"),
Position: NewPosition(1, 1), Position: types.NewPosition(1, 1),
}, },
}, },
ClaimData{ types.ClaimData{
Value: alphabetClaim(4, "e"), Value: alphabetClaim(4, "e"),
Position: NewPosition(3, 4), Position: types.NewPosition(3, 4),
}, },
}, },
} }
...@@ -85,10 +86,10 @@ func TestNoMoveAgainstOwnLevel(t *testing.T) { ...@@ -85,10 +86,10 @@ func TestNoMoveAgainstOwnLevel(t *testing.T) {
mallory := NewAlphabetProvider("abcdepqr", uint64(maxDepth)) mallory := NewAlphabetProvider("abcdepqr", uint64(maxDepth))
solver := NewSolver(maxDepth, mallory) solver := NewSolver(maxDepth, mallory)
claim := Claim{ claim := types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
Value: alphabetClaim(7, "z"), Value: alphabetClaim(7, "z"),
Position: NewPosition(0, 0), Position: types.NewPosition(0, 0),
}, },
// Root claim has no parent // Root claim has no parent
} }
...@@ -104,10 +105,10 @@ func TestAttemptStep(t *testing.T) { ...@@ -104,10 +105,10 @@ func TestAttemptStep(t *testing.T) {
solver := NewSolver(maxDepth, canonicalProvider) solver := NewSolver(maxDepth, canonicalProvider)
_, _, middle, bottom := createTestClaims() _, _, middle, bottom := createTestClaims()
zero := Claim{ zero := types.Claim{
ClaimData: ClaimData{ ClaimData: types.ClaimData{
// Zero value is a purposely disagree with claim value "a" // Zero value is a purposely disagree with claim value "a"
Position: NewPosition(3, 0), Position: types.NewPosition(3, 0),
}, },
} }
...@@ -150,3 +151,39 @@ func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error ...@@ -150,3 +151,39 @@ func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error
} }
return preimage, []byte{byte(i)}, nil return preimage, []byte{byte(i)}, nil
} }
func createTestClaims() (types.Claim, types.Claim, types.Claim, types.Claim) {
// root & middle are from the trace "abcdexyz"
// top & bottom are from the trace "abcdefgh"
root := types.Claim{
ClaimData: types.ClaimData{
Value: common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000077a"),
Position: types.NewPosition(0, 0),
},
// Root claim has no parent
}
top := types.Claim{
ClaimData: types.ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000364"),
Position: types.NewPosition(1, 0),
},
Parent: root.ClaimData,
}
middle := types.Claim{
ClaimData: types.ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000578"),
Position: types.NewPosition(2, 2),
},
Parent: top.ClaimData,
}
bottom := types.Claim{
ClaimData: types.ClaimData{
Value: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000465"),
Position: types.NewPosition(3, 4),
},
Parent: middle.ClaimData,
}
return root, top, middle, bottom
}
package fault package types
import ( import (
"errors" "errors"
...@@ -26,7 +26,7 @@ type Game interface { ...@@ -26,7 +26,7 @@ type Game interface {
// IsDuplicate returns true if the provided [Claim] already exists in the game state. // IsDuplicate returns true if the provided [Claim] already exists in the game state.
IsDuplicate(claim Claim) bool IsDuplicate(claim Claim) bool
// AgreeWithLevel returns if the game state agrees with the provided claim level. // AgreeWithClaimLevel returns if the game state agrees with the provided claim level.
AgreeWithClaimLevel(claim Claim) bool AgreeWithClaimLevel(claim Claim) bool
} }
......
package fault package types
import ( import (
"testing" "testing"
......
package fault package types
import ( import (
"testing" "testing"
......
package fault package types
import ( import (
"context"
"errors" "errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -83,12 +82,3 @@ func (c *Claim) IsRoot() bool { ...@@ -83,12 +82,3 @@ func (c *Claim) IsRoot() bool {
func (c *Claim) DefendsParent() bool { func (c *Claim) DefendsParent() bool {
return (c.IndexAtDepth() >> 1) != c.Parent.IndexAtDepth() return (c.IndexAtDepth() >> 1) != c.Parent.IndexAtDepth()
} }
// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
type Responder interface {
CanResolve(ctx context.Context) bool
Resolve(ctx context.Context) error
Respond(ctx context.Context, response Claim) error
Step(ctx context.Context, stepData StepCallData) error
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/ethereum-optimism/optimism/op-challenger/config"
openum "github.com/ethereum-optimism/optimism/op-service/enum" openum "github.com/ethereum-optimism/optimism/op-service/enum"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
...@@ -20,36 +21,6 @@ func prefixEnvVars(name string) []string { ...@@ -20,36 +21,6 @@ func prefixEnvVars(name string) []string {
return opservice.PrefixEnvVar(envVarPrefix, name) return opservice.PrefixEnvVar(envVarPrefix, name)
} }
type TraceType string
const (
TraceTypeAlphabet TraceType = "alphabet"
TraceTypeCannon TraceType = "cannon"
)
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon}
func (t TraceType) String() string {
return string(t)
}
func (t *TraceType) Set(value string) error {
if !ValidTraceType(TraceType(value)) {
return fmt.Errorf("unknown trace type: %q", value)
}
*t = TraceType(value)
return nil
}
func ValidTraceType(value TraceType) bool {
for _, t := range TraceTypes {
if t == value {
return true
}
}
return false
}
var ( var (
// Required Flags // Required Flags
L1EthRpcFlag = &cli.StringFlag{ L1EthRpcFlag = &cli.StringFlag{
...@@ -64,10 +35,10 @@ var ( ...@@ -64,10 +35,10 @@ var (
} }
TraceTypeFlag = &cli.GenericFlag{ TraceTypeFlag = &cli.GenericFlag{
Name: "trace-type", Name: "trace-type",
Usage: "The trace type. Valid options: " + openum.EnumString(TraceTypes), Usage: "The trace type. Valid options: " + openum.EnumString(config.TraceTypes),
EnvVars: prefixEnvVars("TRACE_TYPE"), EnvVars: prefixEnvVars("TRACE_TYPE"),
Value: func() *TraceType { Value: func() *config.TraceType {
out := TraceType("") // No default value out := config.TraceType("") // No default value
return &out return &out
}(), }(),
} }
...@@ -125,18 +96,45 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -125,18 +96,45 @@ func CheckRequired(ctx *cli.Context) error {
return fmt.Errorf("flag %s is required", f.Names()[0]) return fmt.Errorf("flag %s is required", f.Names()[0])
} }
} }
gameType := TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name))) gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType { switch gameType {
case TraceTypeCannon: case config.TraceTypeCannon:
if !ctx.IsSet(CannonDatadirFlag.Name) { if !ctx.IsSet(CannonDatadirFlag.Name) {
return fmt.Errorf("flag %s is required", "cannon-datadir") return fmt.Errorf("flag %s is required", "cannon-datadir")
} }
case TraceTypeAlphabet: case config.TraceTypeAlphabet:
if !ctx.IsSet(AlphabetFlag.Name) { if !ctx.IsSet(AlphabetFlag.Name) {
return fmt.Errorf("flag %s is required", "alphabet") return fmt.Errorf("flag %s is required", "alphabet")
} }
default: default:
return fmt.Errorf("invalid trace type. must be one of %v", TraceTypes) return fmt.Errorf("invalid trace type. must be one of %v", config.TraceTypes)
} }
return nil return nil
} }
// NewConfigFromCLI parses the Config from the provided flags or environment variables.
func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
if err := CheckRequired(ctx); err != nil {
return nil, err
}
dgfAddress, err := opservice.ParseAddress(ctx.String(DGFAddressFlag.Name))
if err != nil {
return nil, err
}
txMgrConfig := txmgr.ReadCLIConfig(ctx)
traceTypeFlag := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
return &config.Config{
// Required Flags
L1EthRpc: ctx.String(L1EthRpcFlag.Name),
TraceType: traceTypeFlag,
GameAddress: dgfAddress,
AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonDatadir: ctx.String(CannonDatadirFlag.Name),
AgreeWithProposedOutput: ctx.Bool(AgreeWithProposedOutputFlag.Name),
GameDepth: ctx.Int(GameDepthFlag.Name),
TxMgrConfig: txMgrConfig,
}, nil
}
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault" "github.com/ethereum-optimism/optimism/op-challenger/fault"
"github.com/ethereum-optimism/optimism/op-challenger/flags" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-service/client/utils" "github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
...@@ -107,7 +107,7 @@ func (g *FaultGameHelper) StartChallenger(ctx context.Context, l1Endpoint string ...@@ -107,7 +107,7 @@ func (g *FaultGameHelper) StartChallenger(ctx context.Context, l1Endpoint string
func(c *config.Config) { func(c *config.Config) {
c.GameAddress = g.addr c.GameAddress = g.addr
c.GameDepth = alphabetGameDepth c.GameDepth = alphabetGameDepth
c.TraceType = flags.TraceTypeAlphabet c.TraceType = config.TraceTypeAlphabet
// By default the challenger agrees with the root claim (thus disagrees with the proposed output) // By default the challenger agrees with the root claim (thus disagrees with the proposed output)
// This can be overridden by passing in options // This can be overridden by passing in options
c.AlphabetTrace = g.claimedAlphabet c.AlphabetTrace = g.claimedAlphabet
...@@ -169,7 +169,7 @@ func (g *FaultGameHelper) WaitForClaim(ctx context.Context, predicate func(claim ...@@ -169,7 +169,7 @@ func (g *FaultGameHelper) WaitForClaim(ctx context.Context, predicate func(claim
func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered bool) { func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered bool) {
g.WaitForClaim(ctx, func(claim ContractClaim) bool { g.WaitForClaim(ctx, func(claim ContractClaim) bool {
pos := fault.NewPositionFromGIndex(claim.Position.Uint64()) pos := types.NewPositionFromGIndex(claim.Position.Uint64())
return pos.Depth() == g.maxDepth && claim.Countered == countered return pos.Depth() == g.maxDepth && claim.Countered == countered
}) })
} }
......
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