Commit 0fbd62c8 authored by refcell.eth's avatar refcell.eth Committed by GitHub

fix(op-challenger): Update Alphabet Trace Provider with Starting L2 Block Number (#8812)

* op-challenger: fix alphabet trace provider to use l2 block number

* fix up step function calculations

* fix challenger tests

* op-challenger: convert the absolute prestate directly to a big int

* op-challenger: stash inlined calculations to implement iterative step loop

* fix state data construction

* fix(op-challenger): Iterative Step Loop Implementation (#8843)

* Fix formatting.

---------
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
parent 883979c1
......@@ -3,6 +3,7 @@ package fault
import (
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
......@@ -57,7 +58,7 @@ func TestLoadClaimsWhenGameNotResolvable(t *testing.T) {
responder.callResolveErr = errors.New("game is not resolvable")
responder.callResolveClaimErr = errors.New("claim is not resolvable")
depth := types.Depth(4)
claimBuilder := test.NewClaimBuilder(t, depth, alphabet.NewTraceProvider("abcdefg", depth))
claimBuilder := test.NewClaimBuilder(t, depth, alphabet.NewTraceProvider(big.NewInt(0), depth))
claimLoader.claims = []types.Claim{
claimBuilder.CreateRootClaim(true),
......@@ -74,7 +75,7 @@ func setupTestAgent(t *testing.T) (*Agent, *stubClaimLoader, *stubResponder) {
logger := testlog.Logger(t, log.LvlInfo)
claimLoader := &stubClaimLoader{}
depth := types.Depth(4)
provider := alphabet.NewTraceProvider("abcd", depth)
provider := alphabet.NewTraceProvider(big.NewInt(0), depth)
responder := &stubResponder{}
agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, logger)
return agent, claimLoader, responder
......
......@@ -3,6 +3,7 @@ package solver
import (
"context"
"encoding/hex"
"math/big"
"testing"
faulttest "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
......@@ -14,7 +15,8 @@ import (
func TestCalculateNextActions(t *testing.T) {
maxDepth := types.Depth(4)
claimBuilder := faulttest.NewAlphabetClaimBuilder(t, maxDepth)
startingL2BlockNumber := big.NewInt(0)
claimBuilder := faulttest.NewAlphabetClaimBuilder(t, startingL2BlockNumber, maxDepth)
tests := []struct {
name string
......
......@@ -14,7 +14,8 @@ import (
func TestAttemptStep(t *testing.T) {
maxDepth := types.Depth(3)
claimBuilder := faulttest.NewAlphabetClaimBuilder(t, maxDepth)
startingL2BlockNumber := big.NewInt(0)
claimBuilder := faulttest.NewAlphabetClaimBuilder(t, startingL2BlockNumber, maxDepth)
// Last accessible leaf is the second last trace index
// The root node is used for the last trace index and can only be attacked.
......
......@@ -2,22 +2,23 @@ package test
import (
"context"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
)
func NewAlphabetWithProofProvider(t *testing.T, maxDepth types.Depth, oracleError error) *alphabetWithProofProvider {
func NewAlphabetWithProofProvider(t *testing.T, startingL2BlockNumber *big.Int, maxDepth types.Depth, oracleError error) *alphabetWithProofProvider {
return &alphabetWithProofProvider{
alphabet.NewTraceProvider("abcdefghijklmnopqrstuvwxyz", maxDepth),
alphabet.NewTraceProvider(startingL2BlockNumber, maxDepth),
maxDepth,
oracleError,
}
}
func NewAlphabetClaimBuilder(t *testing.T, maxDepth types.Depth) *ClaimBuilder {
alphabetProvider := NewAlphabetWithProofProvider(t, maxDepth, nil)
func NewAlphabetClaimBuilder(t *testing.T, startingL2BlockNumber *big.Int, maxDepth types.Depth) *ClaimBuilder {
alphabetProvider := NewAlphabetWithProofProvider(t, startingL2BlockNumber, maxDepth, nil)
return NewClaimBuilder(t, maxDepth, alphabetProvider)
}
......
......@@ -15,8 +15,8 @@ import (
func TestAccessor_UsesSelector(t *testing.T) {
ctx := context.Background()
depth := types.Depth(4)
provider1 := test.NewAlphabetWithProofProvider(t, depth, nil)
provider2 := alphabet.NewTraceProvider("qrstuv", depth)
provider1 := test.NewAlphabetWithProofProvider(t, big.NewInt(0), depth, nil)
provider2 := alphabet.NewTraceProvider(big.NewInt(0), depth)
claim := types.Claim{}
game := types.NewGameState([]types.Claim{claim}, depth)
pos1 := types.NewPositionFromGIndex(big.NewInt(4))
......
......@@ -2,6 +2,7 @@ package alphabet
import (
"context"
"math/big"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
......@@ -10,6 +11,7 @@ import (
)
var absolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060")
var absolutePrestateInt = new(big.Int).SetBytes(absolutePrestate)
var _ types.PrestateProvider = (*AlphabetPrestateProvider)(nil)
......
package alphabet
import (
"bytes"
"context"
"errors"
"fmt"
"math/big"
"strings"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
......@@ -28,38 +28,52 @@ var (
// indices in the given trace.
type AlphabetTraceProvider struct {
AlphabetPrestateProvider
state []string
depth types.Depth
maxLen uint64
startingBlockNumber *big.Int
depth types.Depth
maxLen uint64
}
// NewTraceProvider returns a new [AlphabetProvider].
func NewTraceProvider(state string, depth types.Depth) *AlphabetTraceProvider {
func NewTraceProvider(startingBlockNumber *big.Int, depth types.Depth) *AlphabetTraceProvider {
return &AlphabetTraceProvider{
state: strings.Split(state, ""),
depth: depth,
maxLen: uint64(1 << depth),
startingBlockNumber: startingBlockNumber,
depth: depth,
maxLen: 1 << depth,
}
}
func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, i types.Position) ([]byte, []byte, *types.PreimageOracleData, error) {
traceIndex := i.TraceIndex(ap.depth)
if traceIndex.Cmp(common.Big0) == 0 {
return absolutePrestate, []byte{}, nil, nil
func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, pos types.Position) ([]byte, []byte, *types.PreimageOracleData, error) {
posIndex := pos.TraceIndex(ap.depth)
key := preimage.LocalIndexKey(L2ClaimBlockNumberLocalIndex).PreimageKey()
preimageData := types.NewPreimageOracleData(key[:], ap.startingBlockNumber.Bytes(), 0)
if posIndex.Cmp(common.Big0) == 0 {
return absolutePrestate, []byte{}, preimageData, nil
}
// We want the pre-state which is the value prior to the one requested
traceIndex = traceIndex.Sub(traceIndex, big.NewInt(1))
// The index cannot be larger than the maximum index as computed by the depth.
if traceIndex.Cmp(big.NewInt(int64(ap.maxLen))) >= 0 {
return nil, nil, nil, fmt.Errorf("%w traceIndex: %v max: %v pos: %v", ErrIndexTooLarge, traceIndex, ap.maxLen, i)
prestateTraceIndex := posIndex.Sub(posIndex, big.NewInt(1))
if prestateTraceIndex.Cmp(new(big.Int).SetUint64(ap.maxLen)) >= 0 {
return nil, nil, nil, fmt.Errorf("%w depth: %v index: %v max: %v", ErrIndexTooLarge, ap.depth, posIndex, ap.maxLen)
}
// We extend the deepest hash to the maximum depth if the trace is not expansive.
if traceIndex.Cmp(big.NewInt(int64(len(ap.state)))) >= 0 {
return ap.GetStepData(ctx, types.NewPosition(ap.depth, big.NewInt(int64(len(ap.state)))))
claim := BuildAlphabetPreimage(big.NewInt(0), absolutePrestateInt)
for i := big.NewInt(0); i.Cmp(posIndex) < 0; i = i.Add(i, big.NewInt(1)) {
claim = ap.step(claim)
}
key := preimage.LocalIndexKey(L2ClaimBlockNumberLocalIndex).PreimageKey()
preimageData := types.NewPreimageOracleData(key[:], nil, 0)
return BuildAlphabetPreimage(traceIndex, ap.state[traceIndex.Uint64()]), []byte{}, preimageData, nil
return claim, []byte{}, preimageData, nil
}
// step accepts the trace index and claim and returns the stepped trace index and claim.
func (ap *AlphabetTraceProvider) step(stateData []byte) []byte {
// Decode the stateData into the trace index and claim
traceIndex := new(big.Int).SetBytes(stateData[:32])
claim := stateData[32:]
if bytes.Equal(claim, absolutePrestate) {
initTraceIndex := new(big.Int).Lsh(ap.startingBlockNumber, 4)
initClaim := new(big.Int).Add(absolutePrestateInt, initTraceIndex)
return BuildAlphabetPreimage(initTraceIndex, initClaim)
}
stepTraceIndex := new(big.Int).Add(traceIndex, big.NewInt(1))
stepClaim := new(big.Int).Add(new(big.Int).SetBytes(claim), big.NewInt(1))
return BuildAlphabetPreimage(stepTraceIndex, stepClaim)
}
// Get returns the claim value at the given index in the trace.
......@@ -77,9 +91,9 @@ func (ap *AlphabetTraceProvider) Get(ctx context.Context, i types.Position) (com
return alphabetStateHash(claimBytes), nil
}
// BuildAlphabetPreimage constructs the claim bytes for the index and state item.
func BuildAlphabetPreimage(i *big.Int, letter string) []byte {
return append(i.FillBytes(make([]byte, 32)), LetterToBytes(letter)...)
// BuildAlphabetPreimage constructs the claim bytes for the index and claim.
func BuildAlphabetPreimage(i *big.Int, blockNumber *big.Int) []byte {
return append(i.FillBytes(make([]byte, 32)), blockNumber.FillBytes(make([]byte, 32))...)
}
func alphabetStateHash(state []byte) common.Hash {
......@@ -87,10 +101,3 @@ func alphabetStateHash(state []byte) common.Hash {
h[0] = mipsevm.VMStatusInvalid
return h
}
// LetterToBytes converts a letter to a 32 byte array
func LetterToBytes(letter string) []byte {
out := make([]byte, 32)
out[31] = byte(letter[0])
return out
}
......@@ -13,15 +13,44 @@ import (
"github.com/stretchr/testify/require"
)
func alphabetClaim(index *big.Int, letter string) common.Hash {
return alphabetStateHash(BuildAlphabetPreimage(index, letter))
func alphabetClaim(index *big.Int, claim *big.Int) common.Hash {
return alphabetStateHash(BuildAlphabetPreimage(index, claim))
}
func TestAlphabetProvider_Step(t *testing.T) {
depth := types.Depth(2)
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
// Start at the absolute prestate as the stateData
claim := BuildAlphabetPreimage(big.NewInt(0), absolutePrestateInt)
claim = ap.step(claim)
startingTraceIndex := new(big.Int).Lsh(startingL2BlockNumber, 4)
startingClaim := new(big.Int).Add(absolutePrestateInt, startingTraceIndex)
require.Equal(t, BuildAlphabetPreimage(startingTraceIndex, startingClaim), claim)
// Step again, which should increment both the claim and trace index by 1
claim = ap.step(claim)
nextTraceIndex := new(big.Int).Add(startingTraceIndex, big.NewInt(1))
nextClaim := new(big.Int).Add(startingClaim, big.NewInt(1))
require.Equal(t, BuildAlphabetPreimage(nextTraceIndex, nextClaim), claim)
// Step again, which should increment both the claim and trace index by 1
claim = ap.step(claim)
nextTraceIndex = new(big.Int).Add(nextTraceIndex, big.NewInt(1))
nextClaim = new(big.Int).Add(nextClaim, big.NewInt(1))
require.Equal(t, BuildAlphabetPreimage(nextTraceIndex, nextClaim), claim)
}
// TestAlphabetProvider_Get_ClaimsByTraceIndex tests the [fault.AlphabetProvider] Get function.
func TestAlphabetProvider_Get_ClaimsByTraceIndex(t *testing.T) {
// Create a new alphabet provider.
depth := types.Depth(3)
canonicalProvider := NewTraceProvider("abcdefgh", depth)
startingL2BlockNumber := big.NewInt(1)
sbn := new(big.Int).Lsh(startingL2BlockNumber, 4)
startingTraceIndex := new(big.Int).Add(absolutePrestateInt, sbn)
canonicalProvider := NewTraceProvider(startingL2BlockNumber, depth)
// Build a list of traces.
traces := []struct {
......@@ -30,15 +59,15 @@ func TestAlphabetProvider_Get_ClaimsByTraceIndex(t *testing.T) {
}{
{
types.NewPosition(depth, big.NewInt(7)),
alphabetClaim(big.NewInt(7), "h"),
alphabetClaim(new(big.Int).Add(sbn, big.NewInt(6)), new(big.Int).Add(startingTraceIndex, big.NewInt(6))),
},
{
types.NewPosition(depth, big.NewInt(3)),
alphabetClaim(big.NewInt(3), "d"),
alphabetClaim(new(big.Int).Add(sbn, big.NewInt(2)), new(big.Int).Add(startingTraceIndex, big.NewInt(2))),
},
{
types.NewPosition(depth, big.NewInt(5)),
alphabetClaim(big.NewInt(5), "f"),
alphabetClaim(new(big.Int).Add(sbn, big.NewInt(4)), new(big.Int).Add(startingTraceIndex, big.NewInt(4))),
},
}
......@@ -54,15 +83,16 @@ func TestAlphabetProvider_Get_ClaimsByTraceIndex(t *testing.T) {
// returns the correct pre-image for a index.
func TestGetStepData_Succeeds(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
expected := BuildAlphabetPreimage(big.NewInt(0), "a")
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
expected := BuildAlphabetPreimage(big.NewInt(0), absolutePrestateInt)
pos := types.NewPosition(depth, big.NewInt(1))
retrieved, proof, data, err := ap.GetStepData(context.Background(), pos)
require.NoError(t, err)
require.Equal(t, expected, retrieved)
require.Empty(t, proof)
key := preimage.LocalIndexKey(L2ClaimBlockNumberLocalIndex).PreimageKey()
expectedLocalContextData := types.NewPreimageOracleData(key[:], nil, 0)
expectedLocalContextData := types.NewPreimageOracleData(key[:], startingL2BlockNumber.Bytes(), 0)
require.Equal(t, expectedLocalContextData, data)
}
......@@ -70,7 +100,8 @@ func TestGetStepData_Succeeds(t *testing.T) {
// function errors if the index is too large.
func TestGetStepData_TooLargeIndex_Fails(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
pos := types.NewPosition(depth, big.NewInt(5))
_, _, _, err := ap.GetStepData(context.Background(), pos)
require.ErrorIs(t, err, ErrIndexTooLarge)
......@@ -79,11 +110,12 @@ func TestGetStepData_TooLargeIndex_Fails(t *testing.T) {
// TestGet_Succeeds tests the Get function.
func TestGet_Succeeds(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
pos := types.NewPosition(depth, big.NewInt(0))
claim, err := ap.Get(context.Background(), pos)
require.NoError(t, err)
expected := alphabetClaim(big.NewInt(0), "a")
expected := alphabetClaim(big.NewInt(0), absolutePrestateInt)
require.Equal(t, expected, claim)
}
......@@ -91,7 +123,8 @@ func TestGet_Succeeds(t *testing.T) {
// greater than the number of indices: 2^depth - 1.
func TestGet_IndexTooLarge(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
pos := types.NewPosition(depth, big.NewInt(4))
_, err := ap.Get(context.Background(), pos)
require.ErrorIs(t, err, ErrIndexTooLarge)
......@@ -99,7 +132,8 @@ func TestGet_IndexTooLarge(t *testing.T) {
func TestGet_DepthTooLarge(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
startingL2BlockNumber := big.NewInt(1)
ap := NewTraceProvider(startingL2BlockNumber, depth)
pos := types.NewPosition(depth+1, big.NewInt(0))
_, err := ap.Get(context.Background(), pos)
require.ErrorIs(t, err, ErrIndexTooLarge)
......@@ -109,10 +143,13 @@ func TestGet_DepthTooLarge(t *testing.T) {
// than the trace, but smaller than the maximum depth.
func TestGet_Extends(t *testing.T) {
depth := types.Depth(2)
ap := NewTraceProvider("abc", depth)
startingL2BlockNumber := big.NewInt(1)
sbn := new(big.Int).Lsh(startingL2BlockNumber, 4)
startingTraceIndex := new(big.Int).Add(absolutePrestateInt, sbn)
ap := NewTraceProvider(startingL2BlockNumber, depth)
pos := types.NewPosition(depth, big.NewInt(3))
claim, err := ap.Get(context.Background(), pos)
require.NoError(t, err)
expected := alphabetClaim(big.NewInt(2), "c")
expected := alphabetClaim(new(big.Int).Add(sbn, big.NewInt(2)), new(big.Int).Add(startingTraceIndex, big.NewInt(2)))
require.Equal(t, expected, claim)
}
......@@ -24,7 +24,7 @@ func NewOutputAlphabetTraceAccessor(
) (*trace.Accessor, error) {
outputProvider := NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, splitDepth, prestateBlock, poststateBlock)
alphabetCreator := func(ctx context.Context, localContext common.Hash, depth types.Depth, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
provider := alphabet.NewTraceProvider(localContext.Hex(), depth)
provider := alphabet.NewTraceProvider(agreed.L2BlockNumber, depth)
return provider, nil
}
cache := NewProviderCache(m, "output_alphabet_provider", alphabetCreator)
......
......@@ -26,7 +26,7 @@ func TestProviderCache(t *testing.T) {
depth := types.Depth(6)
var createdProvider types.TraceProvider
creator := func(ctx context.Context, localContext common.Hash, depth types.Depth, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
createdProvider = alphabet.NewTraceProvider("abcdef", depth)
createdProvider = alphabet.NewTraceProvider(big.NewInt(0), depth)
return createdProvider, nil
}
localContext1 := common.Hash{0xdd}
......
......@@ -303,17 +303,17 @@ func asBottomTraceProvider(t *testing.T, actual types.TraceProvider) *bottomTrac
}
func setupAlphabetSplitSelector(t *testing.T) (*alphabet.AlphabetTraceProvider, trace.ProviderSelector, *test.GameBuilder) {
top := alphabet.NewTraceProvider("abcdef", splitDepth)
top := alphabet.NewTraceProvider(big.NewInt(0), splitDepth)
bottomCreator := func(ctx context.Context, depth types.Depth, pre types.Claim, post types.Claim) (types.TraceProvider, error) {
return &bottomTraceProvider{
pre: pre,
post: post,
AlphabetTraceProvider: alphabet.NewTraceProvider(post.Value.Hex(), depth),
AlphabetTraceProvider: alphabet.NewTraceProvider(big.NewInt(0), depth),
}, nil
}
selector := NewSplitProviderSelector(top, splitDepth, bottomCreator)
claimBuilder := test.NewAlphabetClaimBuilder(t, gameDepth)
claimBuilder := test.NewAlphabetClaimBuilder(t, big.NewInt(0), gameDepth)
gameBuilder := claimBuilder.GameBuilder(true)
return top, selector, gameBuilder
}
......
......@@ -11,7 +11,7 @@ import (
)
func TestTranslate(t *testing.T) {
orig := alphabet.NewTraceProvider("abcdefghij", 4)
orig := alphabet.NewTraceProvider(big.NewInt(0), 4)
translated := Translate(orig, 3)
// All nodes on the first translated layer, map to GIndex 1
for i := int64(8); i <= 15; i++ {
......@@ -50,7 +50,7 @@ func requireSameValue(t *testing.T, a types.TraceProvider, aGIdx int64, b types.
}
func TestTranslate_AbsolutePreStateCommitment(t *testing.T) {
orig := alphabet.NewTraceProvider("abcdefghij", 4)
orig := alphabet.NewTraceProvider(big.NewInt(0), 4)
translated := Translate(orig, 3)
origValue, err := orig.AbsolutePreStateCommitment(context.Background())
require.NoError(t, err)
......
......@@ -2,6 +2,7 @@ package disputegame
import (
"context"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
......@@ -31,7 +32,7 @@ func (g *AlphabetGameHelper) CreateHonestActor(alphabetTrace string, depth types
t: g.t,
require: g.require,
game: &g.FaultGameHelper,
correctTrace: alphabet.NewTraceProvider(alphabetTrace, depth),
correctTrace: alphabet.NewTraceProvider(big.NewInt(0), depth),
}
}
......
......@@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
......@@ -13,9 +12,7 @@ import (
"github.com/stretchr/testify/require"
)
func TestOutputAlphabetGame(t *testing.T) {
// TODO(client-pod#43) Fix alphabet trace provider and re-enable.
t.Skip("client-pod#43: AlphabetTraceProvider not using the new alphabet vm spec")
func TestOutputAlphabetGame_ChallengerWins(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -27,35 +24,42 @@ func TestOutputAlphabetGame(t *testing.T) {
opts := challenger.WithPrivKey(sys.Cfg.Secrets.Alice)
game.StartChallenger(ctx, "sequencer", "Challenger", opts)
game.LogGameData(ctx)
// Challenger should post an output root to counter claims down to the leaf level of the top game
splitDepth := game.SplitDepth(ctx)
for i := int64(1); types.Depth(i) < splitDepth; i += 2 {
game.WaitForCorrectOutputRoot(ctx, i)
game.Attack(ctx, i, common.Hash{0xaa})
game.LogGameData(ctx)
claim := game.RootClaim(ctx)
for claim.IsOutputRoot(ctx) && !claim.IsOutputRootLeaf(ctx) {
if claim.AgreesWithOutputRoot() {
// If the latest claim agrees with the output root, expect the honest challenger to counter it
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
claim.RequireCorrectOutputRoot(ctx)
} else {
// Otherwise we should counter
claim = claim.Attack(ctx, common.Hash{0xaa})
game.LogGameData(ctx)
}
}
// Wait for the challenger to post the first claim in the alphabet trace
game.WaitForClaimAtDepth(ctx, splitDepth+1)
// Wait for the challenger to post the first claim in the cannon trace
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
game.Attack(ctx, int64(splitDepth)+1, common.Hash{0x00, 0xcc})
gameDepth := game.MaxDepth(ctx)
for i := splitDepth + 3; i < gameDepth; i += 2 {
// Wait for challenger to respond
game.WaitForClaimAtDepth(ctx, types.Depth(i))
game.LogGameData(ctx)
// Respond to push the game down to the max depth
game.Defend(ctx, int64(i), common.Hash{0x00, 0xdd})
game.LogGameData(ctx)
// Attack the root of the cannon trace subgame
claim = claim.Attack(ctx, common.Hash{0x00, 0xcc})
for !claim.IsMaxDepth(ctx) {
if claim.AgreesWithOutputRoot() {
// If the latest claim supports the output root, wait for the honest challenger to respond
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
} else {
// Otherwise we need to counter the honest claim
claim = claim.Defend(ctx, common.Hash{0x00, 0xdd})
game.LogGameData(ctx)
}
}
game.LogGameData(ctx)
// Challenger should be able to call step and counter the leaf claim.
game.WaitForClaimAtMaxDepth(ctx, true)
claim.WaitForCountered(ctx)
game.LogGameData(ctx)
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
......@@ -63,9 +67,7 @@ func TestOutputAlphabetGame(t *testing.T) {
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
}
func TestOutputAlphabetGameWithValidOutputRoot(t *testing.T) {
// TODO(client-pod#43) Fix alphabet trace provider and re-enable.
t.Skip("client-pod#43: AlphabetTraceProvider not using the new alphabet vm spec")
func TestOutputAlphabetGame_ValidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -82,17 +84,14 @@ func TestOutputAlphabetGameWithValidOutputRoot(t *testing.T) {
opts := challenger.WithPrivKey(sys.Cfg.Secrets.Alice)
game.StartChallenger(ctx, "sequencer", "Challenger", opts)
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
for !claim.IsMaxDepth(ctx) {
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
// Dishonest actor always attacks with the correct trace
claim = correctTrace.AttackClaim(ctx, claim)
claim = claim.WaitForCounterClaim(ctx)
game.LogGameData(ctx)
}
game.LogGameData(ctx)
// Challenger should be able to call step and counter the leaf claim.
game.WaitForClaimAtMaxDepth(ctx, true)
game.LogGameData(ctx)
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
......
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