Skip to content

Commit

Permalink
op-challenger: add daItem for addlocaldata
Browse files Browse the repository at this point in the history
  • Loading branch information
dajuguan committed Oct 30, 2024
1 parent 4e956f7 commit 388bc3c
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 42 deletions.
37 changes: 37 additions & 0 deletions op-challenger/game/fault/test/alphabet2.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
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"
)

type AlphabetWithOutputRootProvider struct {
*alphabet.AlphabetTraceProvider
depth types.Depth
OracleError error
L2BlockChallenge *types.InvalidL2BlockNumberChallenge
pre bool // preOutputRoot if pre is true; postOutputRoot if pre is false
}

func (a *AlphabetWithOutputRootProvider) GetStepData(ctx context.Context, i types.Position) ([]byte, []byte, *types.PreimageOracleData, error) {
preimage, _, _, err := a.AlphabetTraceProvider.GetStepData(ctx, i)
if err != nil {
return nil, nil, nil, err
}
traceIndex := i.TraceIndex(a.depth).Uint64()
var key []byte
if a.pre {
// localPreimageKey(1) + STARTING_OUTPUT_ROOT(2)
key = []byte{0x01, 0x02}
} else {
// localPreimageKey(1) + DISPUTED_OUTPUT_ROOT(3)
key = []byte{0x01, 0x03}
}
data := types.NewPreimageOracleData(key, []byte{byte(traceIndex - 1)}, uint32(traceIndex-1))
return preimage, []byte{byte(traceIndex - 1)}, data, nil
}

func NewAlphabetWithProofProvider2(t *testing.T, startingL2BlockNumber *big.Int, maxDepth types.Depth, rootDepth types.Depth, oracleError error) *AlphabetWithProofProvider {
return &AlphabetWithProofProvider{
alphabet.NewTraceProvider2(startingL2BlockNumber, maxDepth, rootDepth),
Expand All @@ -16,3 +43,13 @@ func NewAlphabetWithProofProvider2(t *testing.T, startingL2BlockNumber *big.Int,
nil,
}
}

func NewAlphabetWithPreoutputRootProvider(t *testing.T, startingL2BlockNumber *big.Int, maxDepth types.Depth, rootDepth types.Depth, pre bool, oracleError error) *AlphabetWithOutputRootProvider {
return &AlphabetWithOutputRootProvider{
alphabet.NewTraceProvider2(startingL2BlockNumber, maxDepth, rootDepth),
maxDepth,
oracleError,
nil,
pre,
}
}
5 changes: 3 additions & 2 deletions op-challenger/game/fault/trace/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ func NewSimpleTraceAccessor(trace types.TraceProvider) *Accessor {
type ProviderSelector func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error)

func NewAccessor(selector ProviderSelector) *Accessor {
return &Accessor{selector}
return &Accessor{selector, nil}
}

type Accessor struct {
selector ProviderSelector
selector ProviderSelector
selector2 ProviderSelector2
}

func (t *Accessor) Get(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (common.Hash, error) {
Expand Down
32 changes: 28 additions & 4 deletions op-challenger/game/fault/trace/access2.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@ import (
"math/big"

"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
)

type ProviderSelector2 func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, types.DAData, error)

const (
LocalPreimageKeyStartingOutputRoot = 0x02
LocalPreimageKeyDisputedOutputRoot = 0x03
)

func NewAccessor2(selector2 ProviderSelector2) *Accessor {
return &Accessor{nil, selector2}
}

// Get the traceIdx's accestor claims hash and its merkel proof in subValues. traceIdx can be ref's traceIdx ±1.
// Params:
// - relativeTraceIdx: the trace index relative to splitDepth
Expand Down Expand Up @@ -98,7 +110,7 @@ func findAncestorProofAtDepth2(ctx context.Context, provider types.TraceProvider
func (t *Accessor) GetStepData2(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (prestate []byte, proofData []byte, preimageData *types.PreimageOracleData, err error) {
// Get oracle data
// prestate, proofData, preimageData, err = t.GetStepData(ctx, game, ref, pos)
provider, err := t.selector(ctx, game, ref, pos)
provider, outputRootDA, err := t.selector2(ctx, game, ref, pos)
if err != nil {
return nil, nil, nil, err
}
Expand All @@ -122,11 +134,23 @@ func (t *Accessor) GetStepData2(ctx context.Context, game types.Game, ref types.
return nil, nil, nil, fmt.Errorf("failed to get postStateDaItem at trace index %v: %w", postTraceIdx, err)
}
stateData := types.DAData{
Prestate: preStateDaItem,
PostState: postStateDaItem,
PreDA: preStateDaItem,
PostDA: postStateDaItem,
}

preimageData.DAData = stateData
preimageData.VMStateDA = stateData

keyType := preimage.KeyType(preimageData.OracleKey[0])
if keyType == preimage.LocalKeyType {
ident := preimageData.GetIdent()
addlocalDataDaItem := types.DAItem{}
if ident.Cmp(big.NewInt(LocalPreimageKeyStartingOutputRoot)) == 0 {
addlocalDataDaItem = outputRootDA.PreDA
} else if ident.Cmp(big.NewInt(LocalPreimageKeyDisputedOutputRoot)) == 0 {
addlocalDataDaItem = outputRootDA.PostDA
}
preimageData.OutputRootDAItem = addlocalDataDaItem
}
return prestate, proofData, preimageData, nil
}

Expand Down
75 changes: 70 additions & 5 deletions op-challenger/game/fault/trace/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,28 +119,29 @@ func TestGetStepData2(t *testing.T) {
pos := claim.Position.MoveRight()

accessor := &Accessor{
selector: func(ctx context.Context, actualGame types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error) {
selector: nil,
selector2: func(ctx context.Context, actualGame types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, types.DAData, error) {
require.Equal(t, game, actualGame)
require.Equal(t, claim, ref)
return translatedTracerovider, nil
return translatedTracerovider, types.DAData{}, nil
},
}

expectedStateDA := types.DAData{
Prestate: types.DAItem{
PreDA: types.DAItem{
DaType: types.CallDataType,
DataHash: subClaimsDep8[0][:],
Proof: append(subClaimsDep8[1][:], subClaimsDep8[2][:]...),
},
PostState: types.DAItem{
PostDA: types.DAItem{
DaType: types.CallDataType,
DataHash: subClaimsDep8[1][:],
Proof: append(subClaimsDep8[0][:], subClaimsDep8[2][:]...),
},
}

expectedPrestate, expectedProofData, expectedPreimageData, err := translatedTracerovider.GetStepData(ctx, pos)
expectedPreimageData.DAData = expectedStateDA
expectedPreimageData.VMStateDA = expectedStateDA
require.NoError(t, err)

actualPrestate, actualProofData, actualPreimageData, err := accessor.GetStepData2(ctx, game, claim, pos)
Expand All @@ -151,6 +152,70 @@ func TestGetStepData2(t *testing.T) {
require.Equal(t, expectedPreimageData, actualPreimageData)
}

func TestGetStepDataWithStartingOutputRoot(t *testing.T) {
ctx := context.Background()
traceDepth := types.Depth(4)
splitDepth := types.Depth(2)
nbits := uint64(2)
nary := int64(1) << nbits
maxDepth := traceDepth + splitDepth + types.Depth(nbits)
pre := true
provider := test.NewAlphabetWithPreoutputRootProvider(t, big.NewInt(0), traceDepth, splitDepth, pre, nil)
translatedTracerovider := Translate(provider, splitDepth+types.Depth(nary))

claimBuilder := test.NewAlphabetClaimBuilder(t, big.NewInt(0), maxDepth)
gameBuilder := claimBuilder.GameBuilder2(nary, splitDepth)
seq := gameBuilder.Seq()
claimBuilder.CreateRootClaim(test.WithValue(common.Hash{0x00}))
subClaimsDep2 := []common.Hash{{0x01}, {0x02}, {0x03}} // claim at splitDepth
seq = seq.Attack2(subClaimsDep2[:], nbits, 0)
// traces
subClaimsDep4 := []common.Hash{{0x04}}
seq = seq.Attack2(subClaimsDep4[:], nbits, 0)
subClaimsDep6 := []common.Hash{{0x61}, {0x62}, {0x63}}
seq = seq.Attack2(subClaimsDep6[:], nbits, 0)
subClaimsDep8 := []common.Hash{{0x81}, {0x82}, {0x83}}
seq.Attack2(subClaimsDep8[:], nbits, 1)

game := gameBuilder.Game
claim := game.Claims()[len(game.Claims())-1]

pos := claim.Position.MoveRight()

outputRootDA := types.DAData{
PreDA: types.DAItem{DaType: types.CallDataType, DataHash: []byte{0x01}},
PostDA: types.DAItem{DaType: types.CallDataType, DataHash: []byte{0x02}},
}

preAccessor := &Accessor{
selector: nil,
selector2: func(ctx context.Context, actualGame types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, types.DAData, error) {
require.Equal(t, game, actualGame)
require.Equal(t, claim, ref)
return translatedTracerovider, outputRootDA, nil
},
}

_, _, actualPreimageData, err := preAccessor.GetStepData2(ctx, game, claim, pos)
require.NoError(t, err)
require.Equal(t, outputRootDA.PreDA, actualPreimageData.OutputRootDAItem)

pre = false
provider = test.NewAlphabetWithPreoutputRootProvider(t, big.NewInt(0), traceDepth, splitDepth, pre, nil)
translatedTracerovider = Translate(provider, splitDepth+types.Depth(nary))
postAccessor := &Accessor{
selector: nil,
selector2: func(ctx context.Context, actualGame types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, types.DAData, error) {
require.Equal(t, game, actualGame)
require.Equal(t, claim, ref)
return translatedTracerovider, outputRootDA, nil
},
}
_, _, actualPreimageData, err = postAccessor.GetStepData2(ctx, game, claim, pos)
require.NoError(t, err)
require.Equal(t, outputRootDA.PostDA, actualPreimageData.OutputRootDAItem)
}

func TestFindAncestorProofAtDepth2(t *testing.T) {
nbits := uint64(2)
nary := int64(1) << nbits
Expand Down
54 changes: 37 additions & 17 deletions op-challenger/game/fault/trace/split/split2.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import (
)

// Get the traceIdx's accestor claims for multi-sec fault proof. traceIdx can be ref's traceIdx ±1.
func findAncestorWithTraceIndex2(game types.Game, ref types.Claim, depth types.Depth, traceIdx *big.Int) (types.Claim, error) {
func findAncestorWithTraceIndex2(game types.Game, ref types.Claim, depth types.Depth, traceIdx *big.Int) (types.Claim, types.DAItem, error) {
// If traceIdx equals -1, the absolute prestate is returned.
if traceIdx.Cmp(big.NewInt(-1)) == 0 {
return types.Claim{}, nil
return types.Claim{}, types.DAItem{}, nil
}

// If traceIdx is the right most branch, the root Claim is returned.
if new(big.Int).Add(traceIdx, big.NewInt(1)).Cmp(new(big.Int).Lsh(big.NewInt(1), uint(depth))) == 0 {
return game.RootClaim(), nil
return game.RootClaim(), types.DAItem{}, nil
}

ancestor := ref
Expand All @@ -30,7 +30,7 @@ func findAncestorWithTraceIndex2(game types.Game, ref types.Claim, depth types.D
for minTraceIndex.Cmp(traceIdx) == 1 || maxTraceIndex.Cmp(traceIdx) == -1 {
parent, err := game.GetParent(ancestor)
if err != nil {
return types.Claim{}, fmt.Errorf("failed to get ancestor of claim %v: %w", ancestor.ContractIndex, err)
return types.Claim{}, types.DAItem{}, fmt.Errorf("failed to get ancestor of claim %v: %w", ancestor.ContractIndex, err)
}

ancestor = parent
Expand All @@ -48,51 +48,71 @@ func findAncestorWithTraceIndex2(game types.Game, ref types.Claim, depth types.D
Position: types.NewPositionFromGIndex(traceIdx),
},
}
merkleProof := make([]byte, 0)
for i := int64(0); i < branch; i++ {
merkleProof = append(merkleProof, subValues[i].Bytes()...)
}

for i := branch + 1; i < int64(game.MaxAttackBranch()); i++ {
merkleProof = append(merkleProof, subValues[i].Bytes()...)
}

outputRootDAItem := types.DAItem{
DaType: types.CallDataType,
DataHash: claim.Value.Bytes(),
Proof: merkleProof,
}

return claim, nil
return claim, outputRootDAItem, nil
}

func NewSplitProviderSelector2(topProvider types.TraceProvider, topDepth types.Depth, bottomProviderCreator ProviderCreator) trace.ProviderSelector {
return func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error) {
func NewSplitProviderSelector2(topProvider types.TraceProvider, topDepth types.Depth, bottomProviderCreator ProviderCreator) trace.ProviderSelector2 {
return func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, types.DAData, error) {
if pos.Depth() <= topDepth {
return topProvider, nil
return topProvider, types.DAData{}, nil
}
if ref.Position.Depth() < topDepth {
return nil, fmt.Errorf("%w, claim depth: %v, depth required: %v", errRefClaimNotDeepEnough, ref.Position.Depth(), topDepth)
return nil, types.DAData{}, fmt.Errorf("%w, claim depth: %v, depth required: %v", errRefClaimNotDeepEnough, ref.Position.Depth(), topDepth)
}

// Find the ancestor claim at the (splitDepth + 1) level.
splitLeaf, err := trace.FindAncestorAtDepth(game, ref, types.Depth(topDepth+game.NBits()))
if err != nil {
return nil, err
return nil, types.DAData{}, err
}

// Find the ancestor claim at the leaf level splitDepth for the top game.
topLeaf, err := game.GetParent(splitLeaf)
if err != nil {
return nil, err
return nil, types.DAData{}, err
}

attackBranch := int64(splitLeaf.AttackBranch)
preTraceIdx := new(big.Int).Add(topLeaf.TraceIndex(topDepth), big.NewInt(attackBranch))
postTraceIdx := new(big.Int).Add(preTraceIdx, big.NewInt(1))
pre, err := findAncestorWithTraceIndex2(game, topLeaf, topDepth, preTraceIdx)

var outputRootDA = types.DAData{}
pre, preDA, err := findAncestorWithTraceIndex2(game, topLeaf, topDepth, preTraceIdx)
if err != nil {
return nil, fmt.Errorf("failed to find pre claim: %w", err)
return nil, outputRootDA, fmt.Errorf("failed to find pre claim: %w", err)
}
post, err := findAncestorWithTraceIndex2(game, topLeaf, topDepth, postTraceIdx)
post, postDA, err := findAncestorWithTraceIndex2(game, topLeaf, topDepth, postTraceIdx)
if err != nil {
return nil, fmt.Errorf("failed to find post claim: %w", err)
return nil, outputRootDA, fmt.Errorf("failed to find post claim: %w", err)
}

outputRootDA.PreDA = preDA
outputRootDA.PostDA = postDA

// The top game runs from depth 0 to split depth *inclusive*.
// The - 1 here accounts for the fact that the split depth is included in the top game.
bottomDepth := game.MaxDepth() - topDepth - game.NBits()
provider, err := bottomProviderCreator(ctx, bottomDepth, pre, post)
if err != nil {
return nil, err
return nil, outputRootDA, err
}

// Translate such that the root of the bottom game is the level below the top game leaf
return trace.Translate(provider, topDepth+game.NBits()), nil
return trace.Translate(provider, topDepth+game.NBits()), outputRootDA, nil
}
}
Loading

0 comments on commit 388bc3c

Please sign in to comment.