Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion op-challenger/cmd/credits.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func listCredits(ctx context.Context, game contracts.FaultDisputeGameContract) e
if err != nil {
return fmt.Errorf("failed to load claims: %w", err)
}
metadata, err := game.GetGameMetadata(ctx, rpcblock.Latest)
metadata, err := game.GetExtendedMetadata(ctx, rpcblock.Latest)
if err != nil {
return fmt.Errorf("failed to load metadata: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion op-challenger/cmd/list_claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func ListClaims(ctx *cli.Context) error {
}

func listClaims(ctx context.Context, game contracts.FaultDisputeGameContract, verbose bool) error {
metadata, err := game.GetGameMetadata(ctx, rpcblock.Latest)
metadata, err := game.GetExtendedMetadata(ctx, rpcblock.Latest)
if err != nil {
return fmt.Errorf("failed to retrieve metadata: %w", err)
}
Expand Down
18 changes: 10 additions & 8 deletions op-challenger/cmd/list_games.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func listGames(ctx context.Context, caller *batching.MultiCaller, factory *contr
var wg sync.WaitGroup
for idx, game := range games {
idx := idx
gameContract, err := contracts.NewFaultDisputeGameContract(ctx, metrics.NoopContractMetrics, game.Proxy, caller)
gameContract, err := contracts.NewDisputeGameContractForGame(ctx, metrics.NoopContractMetrics, caller, game)
if err != nil {
return fmt.Errorf("failed to create dispute game contract: %w", err)
}
Expand All @@ -112,20 +112,22 @@ func listGames(ctx context.Context, caller *batching.MultiCaller, factory *contr
wg.Add(1)
go func() {
defer wg.Done()
metadata, err := gameContract.GetGameMetadata(ctx, rpcblock.ByHash(block))
metadata, err := gameContract.GetMetadata(ctx, rpcblock.ByHash(block))
if err != nil {
infos[idx].err = fmt.Errorf("failed to retrieve metadata for game %v: %w", gameProxy, err)
return
}
infos[idx].status = metadata.Status
infos[idx].l2BlockNum = metadata.L2SequenceNum
infos[idx].rootClaim = metadata.RootClaim
claimCount, err := gameContract.GetClaimCount(ctx)
if err != nil {
infos[idx].err = fmt.Errorf("failed to retrieve claim count for game %v: %w", gameProxy, err)
return
infos[idx].rootClaim = metadata.ProposedRoot
if fdg, ok := gameContract.(contracts.FaultDisputeGameContract); ok {
claimCount, err := fdg.GetClaimCount(ctx)
if err != nil {
infos[idx].err = fmt.Errorf("failed to retrieve claim count for game %v: %w", gameProxy, err)
return
}
infos[idx].claimCount = claimCount
}
infos[idx].claimCount = claimCount
}()
}
wg.Wait()
Expand Down
59 changes: 59 additions & 0 deletions op-challenger/game/fault/contracts/disputegame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package contracts

import (
"context"
"errors"
"time"

"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
"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/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)

var ErrUnsupportedGameType = errors.New("unsupported game type")

type GenericGameMetadata struct {
L1Head common.Hash
L2SequenceNum uint64
ProposedRoot common.Hash
Status gameTypes.GameStatus
}

type DisputeGameContract interface {
GetL1Head(ctx context.Context) (common.Hash, error)
GetStatus(ctx context.Context) (gameTypes.GameStatus, error)
GetGameRange(ctx context.Context) (prestateBlock uint64, poststateBlock uint64, retErr error)
GetMetadata(ctx context.Context, block rpcblock.Block) (GenericGameMetadata, error)

GetResolvedAt(ctx context.Context, block rpcblock.Block) (time.Time, error)
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
ResolveTx() (txmgr.TxCandidate, error)
}

func NewDisputeGameContractForGame(ctx context.Context, metrics metrics.ContractMetricer, caller *batching.MultiCaller, game gameTypes.GameMetadata) (DisputeGameContract, error) {
return NewDisputeGameContract(ctx, metrics, caller, types.GameType(game.GameType), game.Proxy)
}

func NewDisputeGameContract(ctx context.Context, metrics metrics.ContractMetricer, caller *batching.MultiCaller, gameType types.GameType, addr common.Address) (DisputeGameContract, error) {
switch gameType {
case types.SuperCannonGameType, types.SuperCannonKonaGameType, types.SuperPermissionedGameType, types.SuperAsteriscKonaGameType:
return NewSuperFaultDisputeGameContract(ctx, metrics, addr, caller)

case types.CannonGameType,
types.PermissionedGameType,
types.CannonKonaGameType,
types.AsteriscGameType,
types.AlphabetGameType,
types.FastGameType,
types.AsteriscKonaGameType:
return NewPreInteropFaultDisputeGameContract(ctx, metrics, addr, caller)
case types.OptimisticZKGameType:
return NewOptimisticZKDisputeGameContract(metrics, addr, caller)
default:
return nil, ErrUnsupportedGameType
}
}
45 changes: 35 additions & 10 deletions op-challenger/game/fault/contracts/faultdisputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ type GameMetadata struct {
L2BlockNumberChallenger common.Address
}

// GetGameMetadata returns the game's L1 head, L2 block number, root claim, status, max clock duration, and is l2 block number challenged.
func (f *FaultDisputeGameContractLatest) GetGameMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetGameMetadata")()
// GetExtendedMetadata returns the game's L1 head, L2 block number, root claim, status, max clock duration, and is l2 block number challenged.
func (f *FaultDisputeGameContractLatest) GetExtendedMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetExtendedMetadata")()
results, err := f.multiCaller.Call(ctx, block,
f.contract.Call(methodL1Head),
f.contract.Call(methodL2BlockNumber),
Expand Down Expand Up @@ -247,6 +247,36 @@ func (f *FaultDisputeGameContractLatest) GetGameMetadata(ctx context.Context, bl
}, nil
}

// GetMetadata returns the basic game metadata
func (f *FaultDisputeGameContractLatest) GetMetadata(ctx context.Context, block rpcblock.Block) (GenericGameMetadata, error) {
defer f.metrics.StartContractRequest("GetMetadata")()
results, err := f.multiCaller.Call(ctx, block,
f.contract.Call(methodL1Head),
f.contract.Call(methodL2BlockNumber),
f.contract.Call(methodRootClaim),
f.contract.Call(methodStatus),
)
if err != nil {
return GenericGameMetadata{}, fmt.Errorf("failed to retrieve game metadata: %w", err)
}
if len(results) != 4 {
return GenericGameMetadata{}, fmt.Errorf("expected 4 results but got %v", len(results))
}
l1Head := results[0].GetHash(0)
l2BlockNumber := results[1].GetBigInt(0).Uint64()
rootClaim := results[2].GetHash(0)
status, err := gameTypes.GameStatusFromUint8(results[3].GetUint8(0))
if err != nil {
return GenericGameMetadata{}, fmt.Errorf("failed to convert game status: %w", err)
}
return GenericGameMetadata{
L1Head: l1Head,
L2SequenceNum: l2BlockNumber,
ProposedRoot: rootClaim,
Status: status,
}, nil
}

func (f *FaultDisputeGameContractLatest) GetResolvedAt(ctx context.Context, block rpcblock.Block) (time.Time, error) {
defer f.metrics.StartContractRequest("GetResolvedAt")()
result, err := f.multiCaller.SingleCall(ctx, block, f.contract.Call(methodResolvedAt))
Expand Down Expand Up @@ -642,10 +672,9 @@ func (f *FaultDisputeGameContractLatest) decodeClaim(result *batching.CallResult
}

type FaultDisputeGameContract interface {
DisputeGameContract
GetBalanceAndDelay(ctx context.Context, block rpcblock.Block) (*big.Int, time.Duration, common.Address, error)
GetGameRange(ctx context.Context) (prestateBlock uint64, poststateBlock uint64, retErr error)
GetGameMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error)
GetResolvedAt(ctx context.Context, block rpcblock.Block) (time.Time, error)
GetExtendedMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error)
GetStartingRootHash(ctx context.Context) (common.Hash, error)
GetSplitDepth(ctx context.Context) (types.Depth, error)
GetCredit(ctx context.Context, recipient common.Address) (*big.Int, gameTypes.GameStatus, error)
Expand All @@ -660,8 +689,6 @@ type FaultDisputeGameContract interface {
GetClockExtension(ctx context.Context) (time.Duration, error)
GetMaxGameDepth(ctx context.Context) (types.Depth, error)
GetAbsolutePrestateHash(ctx context.Context) (common.Hash, error)
GetL1Head(ctx context.Context) (common.Hash, error)
GetStatus(ctx context.Context) (gameTypes.GameStatus, error)
GetClaimCount(ctx context.Context) (uint64, error)
GetClaim(ctx context.Context, idx uint64) (types.Claim, error)
GetAllClaims(ctx context.Context, block rpcblock.Block) ([]types.Claim, error)
Expand All @@ -673,8 +700,6 @@ type FaultDisputeGameContract interface {
StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error)
CallResolveClaim(ctx context.Context, claimIdx uint64) error
ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error)
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
ResolveTx() (txmgr.TxCandidate, error)
Vm(ctx context.Context) (*VMContract, error)
GetBondDistributionMode(ctx context.Context, block rpcblock.Block) (types.BondDistributionMode, error)
}
4 changes: 2 additions & 2 deletions op-challenger/game/fault/contracts/faultdisputegame0180.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ type FaultDisputeGameContract0180 struct {
}

// GetGameMetadata returns the game's L1 head, L2 block number, root claim, status, and max clock duration.
func (f *FaultDisputeGameContract0180) GetGameMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetGameMetadata")()
func (f *FaultDisputeGameContract0180) GetExtendedMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetExtendedMetadata")()
results, err := f.multiCaller.Call(ctx, block,
f.contract.Call(methodL1Head),
f.contract.Call(methodL2BlockNumber),
Expand Down
4 changes: 2 additions & 2 deletions op-challenger/game/fault/contracts/faultdisputegame080.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type FaultDisputeGameContract080 struct {
}

// GetGameMetadata returns the game's L1 head, L2 block number, root claim, status, and max clock duration.
func (f *FaultDisputeGameContract080) GetGameMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetGameMetadata")()
func (f *FaultDisputeGameContract080) GetExtendedMetadata(ctx context.Context, block rpcblock.Block) (GameMetadata, error) {
defer f.metrics.StartContractRequest("GetExtendedMetadata")()
results, err := f.multiCaller.Call(ctx, block,
f.contract.Call(methodL1Head),
f.contract.Call(methodL2BlockNumber),
Expand Down
35 changes: 33 additions & 2 deletions op-challenger/game/fault/contracts/faultdisputegame_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, block rpcblock.Block, cla
})
}

func TestGetBlockRange(t *testing.T) {
func TestGetGameRange(t *testing.T) {
for _, version := range versions {
version := version
t.Run(version.String(), func(t *testing.T) {
Expand Down Expand Up @@ -601,7 +601,7 @@ func TestGetGameMetadata(t *testing.T) {
} else {
t.Skip("Can't have challenged L2 block number on this contract version")
}
actual, err := contract.GetGameMetadata(context.Background(), block)
actual, err := contract.GetExtendedMetadata(context.Background(), block)
expected := GameMetadata{
L1Head: expectedL1Head,
L2SequenceNum: expectedL2BlockNumber,
Expand All @@ -617,6 +617,37 @@ func TestGetGameMetadata(t *testing.T) {
}
}

func TestGetMetadata(t *testing.T) {
for _, version := range versions {
version := version
t.Run(version.String(), func(t *testing.T) {
stubRpc, contract := setupFaultDisputeGameTest(t, version)
expectedL1Head := common.Hash{0x0a, 0x0b}
expectedL2BlockNumber := uint64(123)
expectedRootClaim := common.Hash{0x01, 0x02}
expectedStatus := types.GameStatusChallengerWon
block := rpcblock.ByNumber(889)
stubRpc.SetResponse(fdgAddr, methodL1Head, block, nil, []interface{}{expectedL1Head})
if version.IsSuperGame() {
stubRpc.SetResponse(fdgAddr, methodL2SequenceNumber, block, nil, []interface{}{new(big.Int).SetUint64(expectedL2BlockNumber)})
} else {
stubRpc.SetResponse(fdgAddr, methodL2BlockNumber, block, nil, []interface{}{new(big.Int).SetUint64(expectedL2BlockNumber)})
}
stubRpc.SetResponse(fdgAddr, methodRootClaim, block, nil, []interface{}{expectedRootClaim})
stubRpc.SetResponse(fdgAddr, methodStatus, block, nil, []interface{}{expectedStatus})
actual, err := contract.GetMetadata(context.Background(), block)
expected := GenericGameMetadata{
L1Head: expectedL1Head,
L2SequenceNum: expectedL2BlockNumber,
ProposedRoot: expectedRootClaim,
Status: expectedStatus,
}
require.NoError(t, err)
require.Equal(t, expected, actual)
})
}
}

func TestGetStartingRootHash(t *testing.T) {
for _, version := range versions {
version := version
Expand Down
Loading
Loading