Commit 5edd8208 authored by Adrian Sutton's avatar Adrian Sutton

challenger: Switch output_cannon to use the new contract type.

parent 918459c4
...@@ -23,7 +23,7 @@ import ( ...@@ -23,7 +23,7 @@ import (
var ( var (
cannonGameType = uint8(0) cannonGameType = uint8(0)
outputCannonGameType = uint8(0) // TODO(client-pod#260): Switch the output cannon game type to 1 outputCannonGameType = uint8(253) // TODO(client-pod#260): Switch the output cannon game type to 1
outputAlphabetGameType = uint8(254) outputAlphabetGameType = uint8(254)
alphabetGameType = uint8(255) alphabetGameType = uint8(255)
) )
...@@ -133,9 +133,7 @@ func registerOutputCannon( ...@@ -133,9 +133,7 @@ func registerOutputCannon(
caller *batching.MultiCaller, caller *batching.MultiCaller,
l2Client cannon.L2HeaderSource) { l2Client cannon.L2HeaderSource) {
resourceCreator := func(addr common.Address) (gameTypeResources, error) { resourceCreator := func(addr common.Address) (gameTypeResources, error) {
// Currently still using the old fault dispute game contracts for output_cannon contract, err := contracts.NewOutputBisectionGameContract(addr, caller)
// as the output bisection+cannon contract isn't being deployed.
contract, err := contracts.NewFaultDisputeGameContract(addr, caller)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -156,7 +154,7 @@ type outputCannonResources struct { ...@@ -156,7 +154,7 @@ type outputCannonResources struct {
m metrics.Metricer m metrics.Metricer
cfg *config.Config cfg *config.Config
l2Client cannon.L2HeaderSource l2Client cannon.L2HeaderSource
contract *contracts.FaultDisputeGameContract // TODO(client-pod#260): Use the OutputBisectionGame Contract contract *contracts.OutputBisectionGameContract
} }
func (r *outputCannonResources) Contract() GameContract { func (r *outputCannonResources) Contract() GameContract {
...@@ -165,12 +163,11 @@ func (r *outputCannonResources) Contract() GameContract { ...@@ -165,12 +163,11 @@ func (r *outputCannonResources) Contract() GameContract {
func (r *outputCannonResources) CreateAccessor(ctx context.Context, logger log.Logger, gameDepth uint64, dir string) (faultTypes.TraceAccessor, error) { func (r *outputCannonResources) CreateAccessor(ctx context.Context, logger log.Logger, gameDepth uint64, dir string) (faultTypes.TraceAccessor, error) {
// TODO(client-pod#44): Validate absolute pre-state for split games // TODO(client-pod#44): Validate absolute pre-state for split games
// TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks agreed, disputed, err := r.contract.GetBlockRange(ctx)
agreed, disputed, err := r.contract.GetProposals(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, r.m, r.cfg, r.l2Client, r.contract, dir, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64()) accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, r.m, r.cfg, r.l2Client, r.contract, dir, gameDepth, agreed, disputed)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -17,8 +17,6 @@ import ( ...@@ -17,8 +17,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
const defaultTimeout = 5 * time.Minute
type FaultGameHelper struct { type FaultGameHelper struct {
t *testing.T t *testing.T
require *require.Assertions require *require.Assertions
...@@ -59,14 +57,6 @@ func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) { ...@@ -59,14 +57,6 @@ func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) {
} }
} }
type ContractClaim struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}
func (g *FaultGameHelper) MaxDepth(ctx context.Context) int64 { func (g *FaultGameHelper) MaxDepth(ctx context.Context) int64 {
depth, err := g.game.MAXGAMEDEPTH(&bind.CallOpts{Context: ctx}) depth, err := g.game.MAXGAMEDEPTH(&bind.CallOpts{Context: ctx})
g.require.NoError(err, "Failed to load game depth") g.require.NoError(err, "Failed to load game depth")
...@@ -252,12 +242,6 @@ func (g *FaultGameHelper) WaitForInactivity(ctx context.Context, numInactiveBloc ...@@ -252,12 +242,6 @@ func (g *FaultGameHelper) WaitForInactivity(ctx context.Context, numInactiveBloc
} }
} }
// Mover is a function that either attacks or defends the claim at parentClaimIdx
type Mover func(parentClaimIdx int64)
// Stepper is a function that attempts to perform a step against the claim at parentClaimIdx
type Stepper func(parentClaimIdx int64)
// DefendRootClaim uses the supplied Mover to perform moves in an attempt to defend the root claim. // DefendRootClaim uses the supplied Mover to perform moves in an attempt to defend the root claim.
// It is assumed that the output root being disputed is valid and that an honest op-challenger is already running. // It is assumed that the output root being disputed is valid and that an honest op-challenger is already running.
// When the game has reached the maximum depth it waits for the honest challenger to counter the leaf claim with step. // When the game has reached the maximum depth it waits for the honest challenger to counter the leaf claim with step.
...@@ -337,10 +321,6 @@ func (g *FaultGameHelper) Defend(ctx context.Context, claimIdx int64, claim comm ...@@ -337,10 +321,6 @@ func (g *FaultGameHelper) Defend(ctx context.Context, claimIdx int64, claim comm
g.require.NoError(err, "Defend transaction was not OK") g.require.NoError(err, "Defend transaction was not OK")
} }
type ErrWithData interface {
ErrorData() interface{}
}
// StepFails attempts to call step and verifies that it fails with ValidStep() // StepFails attempts to call step and verifies that it fails with ValidStep()
func (g *FaultGameHelper) StepFails(claimIdx int64, isAttack bool, stateData []byte, proof []byte) { func (g *FaultGameHelper) StepFails(claimIdx int64, isAttack bool, stateData []byte, proof []byte) {
g.t.Logf("Attempting step against claim %v isAttack: %v", claimIdx, isAttack) g.t.Logf("Attempting step against claim %v isAttack: %v", claimIdx, isAttack)
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
"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"
...@@ -34,7 +35,7 @@ import ( ...@@ -34,7 +35,7 @@ import (
const alphabetGameType uint8 = 255 const alphabetGameType uint8 = 255
const cannonGameType uint8 = 0 const cannonGameType uint8 = 0
const outputCannonGameType uint8 = 0 // TODO(client-pod#43): This should be a unique game type const outputCannonGameType uint8 = 253
const alphabetGameDepth = 4 const alphabetGameDepth = 4
var lastAlphabetTraceIndex = big.NewInt(1<<alphabetGameDepth - 1) var lastAlphabetTraceIndex = big.NewInt(1<<alphabetGameDepth - 1)
...@@ -140,7 +141,10 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s ...@@ -140,7 +141,10 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
} }
func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, rollupEndpoint string, rootClaim common.Hash) *OutputCannonGameHelper { func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, rollupEndpoint string, rootClaim common.Hash) *OutputCannonGameHelper {
extraData, _, _ := h.createDisputeGameExtraData(ctx) rollupClient, err := dial.DialRollupClientWithTimeout(ctx, 30*time.Second, testlog.Logger(h.t, log.LvlInfo), rollupEndpoint)
h.require.NoError(err)
extraData, _ := h.createBisectionGameExtraData(ctx, rollupClient)
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel() defer cancel()
...@@ -154,23 +158,20 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, rollupEndpoin ...@@ -154,23 +158,20 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, rollupEndpoin
h.require.Len(rcpt.Logs, 1, "should have emitted a single DisputeGameCreated event") h.require.Len(rcpt.Logs, 1, "should have emitted a single DisputeGameCreated event")
createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[0]) createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[0])
h.require.NoError(err) h.require.NoError(err)
game, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.client) game, err := bindings.NewOutputBisectionGame(createdEvent.DisputeProxy, h.client)
h.require.NoError(err)
rollupClient, err := dial.DialRollupClientWithTimeout(ctx, 30*time.Second, testlog.Logger(h.t, log.LvlInfo), rollupEndpoint)
h.require.NoError(err) h.require.NoError(err)
return &OutputCannonGameHelper{ return &OutputCannonGameHelper{
FaultGameHelper: FaultGameHelper{ OutputGameHelper: OutputGameHelper{
t: h.t, t: h.t,
require: h.require, require: h.require,
client: h.client, client: h.client,
opts: h.opts, opts: h.opts,
game: game, game: game,
factoryAddr: h.factoryAddr, factoryAddr: h.factoryAddr,
addr: createdEvent.DisputeProxy, addr: createdEvent.DisputeProxy,
rollupClient: rollupClient,
}, },
rollupClient: rollupClient,
} }
} }
...@@ -277,6 +278,15 @@ func (h *FactoryHelper) createCannonGame(ctx context.Context, rootClaim common.H ...@@ -277,6 +278,15 @@ func (h *FactoryHelper) createCannonGame(ctx context.Context, rootClaim common.H
} }
} }
func (h *FactoryHelper) createBisectionGameExtraData(ctx context.Context, client *sources.RollupClient) (extraData []byte, l2BlockNumber uint64) {
syncStatus, err := client.SyncStatus(ctx)
h.require.NoError(err, "failed to get sync status")
l2BlockNumber = syncStatus.SafeL2.Number
extraData = make([]byte, 32)
binary.BigEndian.PutUint64(extraData, l2BlockNumber)
return
}
func (h *FactoryHelper) createDisputeGameExtraData(ctx context.Context) (extraData []byte, l1Head *big.Int, l2BlockNumber uint64) { func (h *FactoryHelper) createDisputeGameExtraData(ctx context.Context) (extraData []byte, l1Head *big.Int, l2BlockNumber uint64) {
l2BlockNumber = h.waitForProposals(ctx) l2BlockNumber = h.waitForProposals(ctx)
l1Head = h.checkpointL1Block(ctx) l1Head = h.checkpointL1Block(ctx)
......
...@@ -2,19 +2,14 @@ package disputegame ...@@ -2,19 +2,14 @@ package disputegame
import ( import (
"context" "context"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/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-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
) )
type OutputCannonGameHelper struct { type OutputCannonGameHelper struct {
FaultGameHelper OutputGameHelper
rollupClient *sources.RollupClient
} }
func (g *OutputCannonGameHelper) StartChallenger( func (g *OutputCannonGameHelper) StartChallenger(
...@@ -39,30 +34,3 @@ func (g *OutputCannonGameHelper) StartChallenger( ...@@ -39,30 +34,3 @@ func (g *OutputCannonGameHelper) StartChallenger(
}) })
return c return c
} }
func (g *OutputCannonGameHelper) WaitForCorrectOutputRoot(ctx context.Context, claimIdx int64) {
g.WaitForClaimCount(ctx, claimIdx+1)
claim := g.getClaim(ctx, claimIdx)
err, blockNum := g.blockNumForClaim(ctx, claim)
g.require.NoError(err)
output, err := g.rollupClient.OutputAtBlock(ctx, blockNum)
g.require.NoErrorf(err, "Failed to get output at block %v", blockNum)
g.require.EqualValuesf(output.OutputRoot, claim.Claim, "Incorrect output root at claim %v. Expected to be from block %v", claimIdx, blockNum)
}
func (g *OutputCannonGameHelper) blockNumForClaim(ctx context.Context, claim ContractClaim) (error, uint64) {
proposals, err := g.game.Proposals(&bind.CallOpts{Context: ctx})
g.require.NoError(err, "failed to retrieve proposals")
prestateBlockNum := proposals.Starting.L2BlockNumber
disputedBlockNum := proposals.Disputed.L2BlockNumber
gameDepth := g.MaxDepth(ctx)
// TODO(client-pod#43): Load this from the contract
topDepth := gameDepth / 2
traceIdx := types.NewPositionFromGIndex(claim.Position).TraceIndex(int(topDepth))
blockNum := new(big.Int).Add(prestateBlockNum, traceIdx).Uint64() + 1
if blockNum > disputedBlockNum.Uint64() {
blockNum = disputedBlockNum.Uint64()
}
return err, blockNum
}
This diff is collapsed.
...@@ -31,12 +31,19 @@ func TestOutputCannonGame(t *testing.T) { ...@@ -31,12 +31,19 @@ func TestOutputCannonGame(t *testing.T) {
) )
game.LogGameData(ctx) game.LogGameData(ctx)
maxDepth := game.MaxDepth(ctx)
// Challenger should post an output root to counter claims down to the leaf level of the top game // Challenger should post an output root to counter claims down to the leaf level of the top game
// TODO(client-pod#43): Load the depth of the top game from the contract instead of deriving it splitDepth := game.SplitDepth(ctx)
for i := int64(1); i <= maxDepth/2+1; i += 2 { for i := int64(1); i < splitDepth; i += 2 {
game.WaitForCorrectOutputRoot(ctx, i) game.WaitForCorrectOutputRoot(ctx, i)
game.Attack(ctx, i, common.Hash{0xaa}) game.Attack(ctx, i, common.Hash{0xaa})
game.LogGameData(ctx) game.LogGameData(ctx)
} }
game.WaitForCorrectOutputRoot(ctx, splitDepth)
// Post the first cannon output root (with 01 status code to show the output root is invalid)
game.Attack(ctx, splitDepth, common.Hash{0x01})
// Challenger should counter
game.WaitForClaimAtDepth(ctx, int(splitDepth+2))
game.LogGameData(ctx)
} }
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