Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
2e4de94b
Unverified
Commit
2e4de94b
authored
Nov 09, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-challenger: Add a provider selector function for split output games.
parent
6c4a9ac4
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
373 additions
and
202 deletions
+373
-202
game_builder.go
op-challenger/game/fault/test/game_builder.go
+5
-1
access.go
op-challenger/game/fault/trace/access.go
+3
-3
provider.go
op-challenger/game/fault/trace/alphabet/provider.go
+3
-0
provider_test.go
op-challenger/game/fault/trace/alphabet/provider_test.go
+8
-0
split.go
op-challenger/game/fault/trace/outputs/split.go
+86
-0
split_test.go
op-challenger/game/fault/trace/outputs/split_test.go
+268
-0
provider.go
op-challenger/game/fault/trace/split/provider.go
+0
-67
provider_test.go
op-challenger/game/fault/trace/split/provider_test.go
+0
-131
No files found.
op-challenger/game/fault/test/game_builder.go
View file @
2e4de94b
...
@@ -29,10 +29,14 @@ type GameBuilderSeq struct {
...
@@ -29,10 +29,14 @@ type GameBuilderSeq struct {
}
}
func
(
g
*
GameBuilder
)
Seq
()
*
GameBuilderSeq
{
func
(
g
*
GameBuilder
)
Seq
()
*
GameBuilderSeq
{
return
g
.
SeqFrom
(
g
.
Game
.
Claims
()[
0
])
}
func
(
g
*
GameBuilder
)
SeqFrom
(
claim
types
.
Claim
)
*
GameBuilderSeq
{
return
&
GameBuilderSeq
{
return
&
GameBuilderSeq
{
gameBuilder
:
g
,
gameBuilder
:
g
,
builder
:
g
.
builder
,
builder
:
g
.
builder
,
lastClaim
:
g
.
Game
.
Claims
()[
0
]
,
lastClaim
:
claim
,
}
}
}
}
...
...
op-challenger/game/fault/trace/access.go
View file @
2e4de94b
...
@@ -7,8 +7,6 @@ import (
...
@@ -7,8 +7,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
)
)
type
ProviderCreator
func
(
ctx
context
.
Context
,
pre
types
.
Claim
,
post
types
.
Claim
)
(
types
.
TraceProvider
,
error
)
func
NewSimpleTraceAccessor
(
trace
types
.
TraceProvider
)
*
Accessor
{
func
NewSimpleTraceAccessor
(
trace
types
.
TraceProvider
)
*
Accessor
{
selector
:=
func
(
_
context
.
Context
,
_
types
.
Game
,
_
types
.
Claim
,
_
types
.
Position
)
(
types
.
TraceProvider
,
error
)
{
selector
:=
func
(
_
context
.
Context
,
_
types
.
Game
,
_
types
.
Claim
,
_
types
.
Position
)
(
types
.
TraceProvider
,
error
)
{
return
trace
,
nil
return
trace
,
nil
...
@@ -16,8 +14,10 @@ func NewSimpleTraceAccessor(trace types.TraceProvider) *Accessor {
...
@@ -16,8 +14,10 @@ func NewSimpleTraceAccessor(trace types.TraceProvider) *Accessor {
return
&
Accessor
{
selector
}
return
&
Accessor
{
selector
}
}
}
type
ProviderSelector
func
(
ctx
context
.
Context
,
game
types
.
Game
,
ref
types
.
Claim
,
pos
types
.
Position
)
(
types
.
TraceProvider
,
error
)
type
Accessor
struct
{
type
Accessor
struct
{
selector
func
(
ctx
context
.
Context
,
game
types
.
Game
,
ref
types
.
Claim
,
pos
types
.
Position
)
(
types
.
TraceProvider
,
error
)
selector
ProviderSelector
}
}
func
(
t
*
Accessor
)
Get
(
ctx
context
.
Context
,
game
types
.
Game
,
ref
types
.
Claim
,
pos
types
.
Position
)
(
common
.
Hash
,
error
)
{
func
(
t
*
Accessor
)
Get
(
ctx
context
.
Context
,
game
types
.
Game
,
ref
types
.
Claim
,
pos
types
.
Position
)
(
common
.
Hash
,
error
)
{
...
...
op-challenger/game/fault/trace/alphabet/provider.go
View file @
2e4de94b
...
@@ -54,6 +54,9 @@ func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, i types.Positi
...
@@ -54,6 +54,9 @@ func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, i types.Positi
// Get returns the claim value at the given index in the trace.
// Get returns the claim value at the given index in the trace.
func
(
ap
*
AlphabetTraceProvider
)
Get
(
ctx
context
.
Context
,
i
types
.
Position
)
(
common
.
Hash
,
error
)
{
func
(
ap
*
AlphabetTraceProvider
)
Get
(
ctx
context
.
Context
,
i
types
.
Position
)
(
common
.
Hash
,
error
)
{
if
uint64
(
i
.
Depth
())
>
ap
.
depth
{
return
common
.
Hash
{},
ErrIndexTooLarge
}
// Step data returns the pre-state, so add 1 to get the state for index i
// Step data returns the pre-state, so add 1 to get the state for index i
ti
:=
i
.
TraceIndex
(
int
(
ap
.
depth
))
ti
:=
i
.
TraceIndex
(
int
(
ap
.
depth
))
postPosition
:=
types
.
NewPosition
(
int
(
ap
.
depth
),
new
(
big
.
Int
)
.
Add
(
ti
,
big
.
NewInt
(
1
)))
postPosition
:=
types
.
NewPosition
(
int
(
ap
.
depth
),
new
(
big
.
Int
)
.
Add
(
ti
,
big
.
NewInt
(
1
)))
...
...
op-challenger/game/fault/trace/alphabet/provider_test.go
View file @
2e4de94b
...
@@ -92,6 +92,14 @@ func TestGet_IndexTooLarge(t *testing.T) {
...
@@ -92,6 +92,14 @@ func TestGet_IndexTooLarge(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
ErrIndexTooLarge
)
require
.
ErrorIs
(
t
,
err
,
ErrIndexTooLarge
)
}
}
func
TestGet_DepthTooLarge
(
t
*
testing
.
T
)
{
depth
:=
2
ap
:=
NewTraceProvider
(
"abc"
,
uint64
(
depth
))
pos
:=
types
.
NewPosition
(
depth
+
1
,
big
.
NewInt
(
0
))
_
,
err
:=
ap
.
Get
(
context
.
Background
(),
pos
)
require
.
ErrorIs
(
t
,
err
,
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
// than the trace, but smaller than the maximum depth.
// than the trace, but smaller than the maximum depth.
func
TestGet_Extends
(
t
*
testing
.
T
)
{
func
TestGet_Extends
(
t
*
testing
.
T
)
{
...
...
op-challenger/game/fault/trace/outputs/split.go
0 → 100644
View file @
2e4de94b
package
outputs
import
(
"context"
"errors"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
)
var
(
errRefClaimNotDeepEnough
=
errors
.
New
(
"reference claim is not deep enough"
)
)
type
ProviderCreator
func
(
ctx
context
.
Context
,
pre
types
.
Claim
,
post
types
.
Claim
)
(
types
.
TraceProvider
,
error
)
func
newSplitProviderSelector
(
topProvider
types
.
TraceProvider
,
topDepth
int
,
bottomProviderCreator
ProviderCreator
)
trace
.
ProviderSelector
{
return
func
(
ctx
context
.
Context
,
game
types
.
Game
,
ref
types
.
Claim
,
pos
types
.
Position
)
(
types
.
TraceProvider
,
error
)
{
if
pos
.
Depth
()
<=
topDepth
{
return
topProvider
,
nil
}
if
ref
.
Position
.
Depth
()
<
topDepth
{
return
nil
,
fmt
.
Errorf
(
"%w, claim depth: %v, depth required: %v"
,
errRefClaimNotDeepEnough
,
ref
.
Position
.
Depth
(),
topDepth
)
}
// Find the ancestor claim at the leaf level for the top game.
topLeaf
,
err
:=
findAncestorAtDepth
(
game
,
ref
,
topDepth
)
if
err
!=
nil
{
return
nil
,
err
}
var
pre
,
post
types
.
Claim
// If pos is to the right of the leaf from the top game, we must be defending that output root
// otherwise, we're attacking it.
if
pos
.
TraceIndex
(
pos
.
Depth
())
.
Cmp
(
topLeaf
.
TraceIndex
(
pos
.
Depth
()))
>
0
{
// Defending the top leaf claim, so use it as the pre-claim and find the post
pre
=
topLeaf
postTraceIdx
:=
new
(
big
.
Int
)
.
Add
(
pre
.
TraceIndex
(
topDepth
),
big
.
NewInt
(
1
))
post
,
err
=
findAncestorWithTraceIndex
(
game
,
topLeaf
,
topDepth
,
postTraceIdx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to find post claim: %w"
,
err
)
}
}
else
{
// Attacking the top leaf claim, so use it as the post-claim and find the pre
post
=
topLeaf
postTraceIdx
:=
post
.
TraceIndex
(
topDepth
)
if
postTraceIdx
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
pre
=
types
.
Claim
{}
}
else
{
preTraceIdx
:=
new
(
big
.
Int
)
.
Sub
(
postTraceIdx
,
big
.
NewInt
(
1
))
pre
,
err
=
findAncestorWithTraceIndex
(
game
,
topLeaf
,
topDepth
,
preTraceIdx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to find pre claim: %w"
,
err
)
}
}
}
provider
,
err
:=
bottomProviderCreator
(
ctx
,
pre
,
post
)
// TODO: Translate the bottom provider
return
provider
,
err
}
}
func
findAncestorAtDepth
(
game
types
.
Game
,
claim
types
.
Claim
,
depth
int
)
(
types
.
Claim
,
error
)
{
for
claim
.
Depth
()
>
depth
{
parent
,
err
:=
game
.
GetParent
(
claim
)
if
err
!=
nil
{
return
types
.
Claim
{},
fmt
.
Errorf
(
"failed to find ancestor at depth %v: %w"
,
depth
,
err
)
}
claim
=
parent
}
return
claim
,
nil
}
func
findAncestorWithTraceIndex
(
game
types
.
Game
,
ref
types
.
Claim
,
depth
int
,
traceIdx
*
big
.
Int
)
(
types
.
Claim
,
error
)
{
candidate
:=
ref
for
candidate
.
TraceIndex
(
depth
)
.
Cmp
(
traceIdx
)
!=
0
{
parent
,
err
:=
game
.
GetParent
(
candidate
)
if
err
!=
nil
{
return
types
.
Claim
{},
fmt
.
Errorf
(
"failed to get parent of claim %v: %w"
,
candidate
.
ContractIndex
,
err
)
}
candidate
=
parent
}
return
candidate
,
nil
}
op-challenger/game/fault/trace/outputs/split_test.go
0 → 100644
View file @
2e4de94b
package
outputs
import
(
"context"
"fmt"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/stretchr/testify/require"
)
const
(
topDepth
=
3
bottomDepth
=
4
)
func
TestUseTopProvider
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
topProvider
,
selector
,
gameBuilder
:=
setupAlphabetSplitSelector
(
t
)
ref
:=
gameBuilder
.
Game
.
Claims
()[
0
]
pos
:=
ref
.
Position
for
pos
.
Depth
()
<=
topDepth
{
provider
,
err
:=
selector
(
ctx
,
gameBuilder
.
Game
,
ref
,
ref
.
Position
)
require
.
NoError
(
t
,
err
)
require
.
Same
(
t
,
topProvider
,
provider
)
_
,
err
=
topProvider
.
Get
(
ctx
,
pos
)
require
.
NoError
(
t
,
err
,
"should be able to use provider for position"
)
pos
=
pos
.
Attack
()
}
}
func
TestErrorWhenRefAboveTopGameLeafButPositionInBottom
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
_
,
selector
,
gameBuilder
:=
setupAlphabetSplitSelector
(
t
)
// Generate claims at depths up to but not including the leaf of the top providers
createClaimsToDepth
(
gameBuilder
,
topDepth
-
1
)
for
_
,
ref
:=
range
gameBuilder
.
Game
.
Claims
()
{
pos
:=
types
.
NewPosition
(
topDepth
+
1
,
big
.
NewInt
(
0
))
provider
,
err
:=
selector
(
ctx
,
gameBuilder
.
Game
,
ref
,
pos
)
require
.
ErrorIsf
(
t
,
err
,
errRefClaimNotDeepEnough
,
"should not get provider with ref claim at depth: %v"
,
ref
.
Depth
())
require
.
Nil
(
t
,
provider
)
}
}
func
TestBottomProviderAttackingTopLeaf
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
setup
func
(
t
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
}{
// There are 4 leaf nodes that can be accessed in the top tree of depth 3: 8, 10, 12, 14
// Then you can attack and defend any of those to challenge all blocks
// We can then use these setups to test any other reference claim descending from what these setup since
// that whole subtree should have the same pre and post claim from the top provider.
{
"attackTopLeafGIndex8"
,
attackTopLeafGIndex8
},
{
"defendTopLeafGIndex8"
,
defendTopLeafGIndex8
},
{
"attackTopLeafGIndex10"
,
attackTopLeafGIndex10
},
{
"defendTopLeafGIndex10"
,
defendTopLeafGIndex10
},
{
"attackTopLeafGIndex12"
,
attackTopLeafGIndex12
},
{
"defendTopLeafGIndex12"
,
defendTopLeafGIndex12
},
{
"attackTopLeafGIndex14"
,
attackTopLeafGIndex14
},
{
"attackTopLeafGIndex14"
,
defendTopLeafGIndex14
},
}
for
_
,
tCase
:=
range
tests
{
tCase
:=
tCase
t
.
Run
(
tCase
.
name
,
func
(
t
*
testing
.
T
)
{
_
,
selector
,
gameBuilder
:=
setupAlphabetSplitSelector
(
t
)
ref
,
pos
,
expectedPre
,
expectedPost
:=
tCase
.
setup
(
t
,
gameBuilder
)
runTest
:=
func
(
ref
types
.
Claim
,
pos
types
.
Position
)
{
t
.
Run
(
fmt
.
Sprintf
(
"Ref-d%vi%v_Pos-d%vi%v"
,
ref
.
Depth
(),
ref
.
IndexAtDepth
(),
pos
.
Depth
(),
pos
.
IndexAtDepth
()),
func
(
t
*
testing
.
T
)
{
provider
,
err
:=
selector
(
context
.
Background
(),
gameBuilder
.
Game
,
ref
,
pos
)
require
.
NoError
(
t
,
err
)
requireBottomProviderForClaims
(
t
,
provider
,
expectedPre
,
expectedPost
)
})
}
// Check we get the same pre and post for any reference claim lower in the game
var
testDescendantClaims
func
(
ref
types
.
Claim
,
pos
types
.
Position
)
testDescendantClaims
=
func
(
ref
types
.
Claim
,
pos
types
.
Position
)
{
// For each reference, check it works with the same position or attack or defend positions
// from there.
runTest
(
ref
,
pos
)
runTest
(
ref
,
pos
.
Attack
())
runTest
(
ref
,
pos
.
Defend
())
if
pos
.
Depth
()
>=
topDepth
+
bottomDepth
{
return
}
gameBuilder
.
SeqFrom
(
ref
)
.
AttackCorrect
()
attackRef
:=
latestClaim
(
gameBuilder
)
gameBuilder
.
SeqFrom
(
ref
)
.
DefendCorrect
()
defendRef
:=
latestClaim
(
gameBuilder
)
// If the ref is the leaf of the top claim, ensure we respect whether the test is setup
// to attack or defend the top leaf claim.
if
ref
.
Depth
()
!=
topDepth
||
pos
.
ToGIndex
()
.
Cmp
(
attackRef
.
Position
.
ToGIndex
())
==
0
{
testDescendantClaims
(
attackRef
,
attackRef
.
Position
)
}
if
ref
.
Depth
()
!=
topDepth
||
pos
.
ToGIndex
()
.
Cmp
(
defendRef
.
Position
.
ToGIndex
())
==
0
{
testDescendantClaims
(
defendRef
,
defendRef
.
Position
)
}
}
testDescendantClaims
(
ref
,
pos
)
})
}
}
func
attackTopLeafGIndex8
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
// Generate claims down to the top provider's leaf
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
AttackCorrect
()
// gindex 4, trace 1
seq
.
AttackCorrect
()
// gindex 8, trace 0
expectPost
=
latestClaim
(
gameBuilder
)
// No pre-claim as the first output root is being challenged.
expectPre
=
types
.
Claim
{}
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Attack
()
return
}
func
defendTopLeafGIndex8
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
// Generate claims down to the top provider's leaf
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
AttackCorrect
()
// gindex 4, trace 1
expectPost
=
latestClaim
(
gameBuilder
)
seq
.
AttackCorrect
()
// gindex 8, trace 0
expectPre
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Defend
()
return
}
func
attackTopLeafGIndex10
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
AttackCorrect
()
// gindex 4, trace 1
expectPre
=
latestClaim
(
gameBuilder
)
seq
.
DefendCorrect
()
// gindex 10, trace 2
expectPost
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Attack
()
return
}
func
defendTopLeafGIndex10
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
expectPost
=
latestClaim
(
gameBuilder
)
seq
=
seq
.
AttackCorrect
()
// gindex 4, trace 1
seq
.
DefendCorrect
()
// gindex 10, trace 2
expectPre
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Defend
()
return
}
func
attackTopLeafGIndex12
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
expectPre
=
latestClaim
(
gameBuilder
)
seq
=
seq
.
DefendCorrect
()
// gindex 6, trace 5
seq
.
AttackCorrect
()
// gindex 12, trace 4
expectPost
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Attack
()
return
}
func
defendTopLeafGIndex12
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
DefendCorrect
()
// gindex 6, trace 5
expectPost
=
latestClaim
(
gameBuilder
)
seq
.
AttackCorrect
()
// gindex 12, trace 4
expectPre
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Defend
()
return
}
func
attackTopLeafGIndex14
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
DefendCorrect
()
// gindex 6, trace 5
expectPre
=
latestClaim
(
gameBuilder
)
seq
.
DefendCorrect
()
// gindex 14, trace 6
expectPost
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Attack
()
return
}
func
defendTopLeafGIndex14
(
_
*
testing
.
T
,
gameBuilder
*
test
.
GameBuilder
)
(
ref
types
.
Claim
,
pos
types
.
Position
,
expectPre
types
.
Claim
,
expectPost
types
.
Claim
)
{
seq
:=
gameBuilder
.
Seq
()
// gindex 1, trace 7
expectPost
=
latestClaim
(
gameBuilder
)
seq
=
seq
.
AttackCorrect
()
// gindex 2, trace 3
seq
=
seq
.
DefendCorrect
()
// gindex 6, trace 5
seq
.
DefendCorrect
()
// gindex 14, trace 6
expectPre
=
latestClaim
(
gameBuilder
)
ref
=
latestClaim
(
gameBuilder
)
pos
=
ref
.
Position
.
Defend
()
return
}
func
latestClaim
(
gameBuilder
*
test
.
GameBuilder
)
types
.
Claim
{
return
gameBuilder
.
Game
.
Claims
()[
len
(
gameBuilder
.
Game
.
Claims
())
-
1
]
}
func
createClaimsToDepth
(
gameBuilder
*
test
.
GameBuilder
,
depth
int
)
{
seq
:=
gameBuilder
.
Seq
()
for
i
:=
0
;
i
<
depth
;
i
++
{
seq
=
seq
.
AttackCorrect
()
}
}
func
requireBottomProviderForClaims
(
t
*
testing
.
T
,
actual
types
.
TraceProvider
,
expectedPre
types
.
Claim
,
expectedPost
types
.
Claim
)
{
if
expectedPre
!=
(
types
.
Claim
{})
{
require
.
Equal
(
t
,
new
(
big
.
Int
)
.
Add
(
expectedPre
.
TraceIndex
(
topDepth
),
big
.
NewInt
(
1
)),
expectedPost
.
TraceIndex
(
topDepth
),
"should expect adjacent top level trace indices"
)
}
bottomProvider
,
ok
:=
actual
.
(
*
bottomTraceProvider
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
expectedPre
,
bottomProvider
.
pre
,
"Incorrect pre claim"
)
require
.
Equal
(
t
,
expectedPost
,
bottomProvider
.
post
,
"Incorrect post claim"
)
}
func
setupAlphabetSplitSelector
(
t
*
testing
.
T
)
(
*
alphabet
.
AlphabetTraceProvider
,
trace
.
ProviderSelector
,
*
test
.
GameBuilder
)
{
top
:=
alphabet
.
NewTraceProvider
(
"abcdef"
,
topDepth
)
bottomCreator
:=
func
(
ctx
context
.
Context
,
pre
types
.
Claim
,
post
types
.
Claim
)
(
types
.
TraceProvider
,
error
)
{
return
&
bottomTraceProvider
{
pre
:
pre
,
post
:
post
,
AlphabetTraceProvider
:
alphabet
.
NewTraceProvider
(
post
.
Value
.
Hex
(),
bottomDepth
),
},
nil
}
selector
:=
newSplitProviderSelector
(
top
,
topDepth
,
bottomCreator
)
claimBuilder
:=
test
.
NewAlphabetClaimBuilder
(
t
,
topDepth
+
bottomDepth
)
gameBuilder
:=
claimBuilder
.
GameBuilder
(
true
,
true
)
return
top
,
selector
,
gameBuilder
}
type
bottomTraceProvider
struct
{
pre
types
.
Claim
post
types
.
Claim
*
alphabet
.
AlphabetTraceProvider
}
op-challenger/game/fault/trace/split/provider.go
deleted
100644 → 0
View file @
6c4a9ac4
package
split
import
(
"context"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
var
_
types
.
TraceProvider
=
(
*
SplitTraceProvider
)(
nil
)
// SplitTraceProvider is a [types.TraceProvider] implementation that
// routes requests to the correct internal trace provider based on the
// depth of the requested trace.
type
SplitTraceProvider
struct
{
logger
log
.
Logger
topProvider
types
.
TraceProvider
bottomProvider
types
.
TraceProvider
topDepth
uint64
}
// NewTraceProvider creates a new [SplitTraceProvider] instance.
// The [topDepth] parameter specifies the depth at which the internal
// [types.TraceProvider] should be switched.
func
NewTraceProvider
(
logger
log
.
Logger
,
topProvider
types
.
TraceProvider
,
bottomProvider
types
.
TraceProvider
,
topDepth
uint64
)
*
SplitTraceProvider
{
return
&
SplitTraceProvider
{
logger
:
logger
,
topProvider
:
topProvider
,
bottomProvider
:
bottomProvider
,
topDepth
:
topDepth
,
}
}
func
(
s
*
SplitTraceProvider
)
providerForDepth
(
depth
uint64
)
(
uint64
,
types
.
TraceProvider
)
{
if
depth
<=
s
.
topDepth
{
return
0
,
s
.
topProvider
}
return
s
.
topDepth
,
s
.
bottomProvider
}
// Get routes the Get request to the internal [types.TraceProvider] that
// that serves the trace index at the depth.
func
(
s
*
SplitTraceProvider
)
Get
(
ctx
context
.
Context
,
pos
types
.
Position
)
(
common
.
Hash
,
error
)
{
ancestorDepth
,
provider
:=
s
.
providerForDepth
(
uint64
(
pos
.
Depth
()))
relativePosition
,
err
:=
pos
.
RelativeToAncestorAtDepth
(
ancestorDepth
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
return
provider
.
Get
(
ctx
,
relativePosition
)
}
// AbsolutePreStateCommitment returns the absolute prestate from the lowest internal [types.TraceProvider]
func
(
s
*
SplitTraceProvider
)
AbsolutePreStateCommitment
(
ctx
context
.
Context
)
(
hash
common
.
Hash
,
err
error
)
{
return
s
.
bottomProvider
.
AbsolutePreStateCommitment
(
ctx
)
}
// GetStepData routes the GetStepData request to the lowest internal [types.TraceProvider].
func
(
s
*
SplitTraceProvider
)
GetStepData
(
ctx
context
.
Context
,
pos
types
.
Position
)
(
prestate
[]
byte
,
proofData
[]
byte
,
preimageData
*
types
.
PreimageOracleData
,
err
error
)
{
ancestorDepth
,
provider
:=
s
.
providerForDepth
(
uint64
(
pos
.
Depth
()))
relativePosition
,
err
:=
pos
.
RelativeToAncestorAtDepth
(
ancestorDepth
)
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
return
provider
.
GetStepData
(
ctx
,
relativePosition
)
}
op-challenger/game/fault/trace/split/provider_test.go
deleted
100644 → 0
View file @
6c4a9ac4
package
split
import
(
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
var
(
mockGetError
=
errors
.
New
(
"mock get error"
)
mockOutput
=
common
.
HexToHash
(
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
)
mockCommitment
=
common
.
HexToHash
(
"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
)
)
func
TestGet
(
t
*
testing
.
T
)
{
t
.
Run
(
"ErrorBubblesUp"
,
func
(
t
*
testing
.
T
)
{
mockOutputProvider
:=
mockTraceProvider
{
getError
:
mockGetError
}
splitProvider
:=
newSplitTraceProvider
(
t
,
&
mockOutputProvider
,
nil
,
40
)
_
,
err
:=
splitProvider
.
Get
(
context
.
Background
(),
types
.
NewPosition
(
1
,
common
.
Big0
))
require
.
ErrorIs
(
t
,
err
,
mockGetError
)
})
t
.
Run
(
"ReturnsCorrectOutputFromTopProvider"
,
func
(
t
*
testing
.
T
)
{
mockOutputProvider
:=
mockTraceProvider
{
getOutput
:
mockOutput
}
splitProvider
:=
newSplitTraceProvider
(
t
,
&
mockOutputProvider
,
&
mockTraceProvider
{},
40
)
output
,
err
:=
splitProvider
.
Get
(
context
.
Background
(),
types
.
NewPosition
(
6
,
big
.
NewInt
(
3
)))
require
.
NoError
(
t
,
err
)
expectedGIndex
:=
types
.
NewPosition
(
6
,
big
.
NewInt
(
3
))
.
ToGIndex
()
require
.
Equal
(
t
,
common
.
BigToHash
(
expectedGIndex
),
output
)
})
t
.
Run
(
"ReturnsCorrectOutputWithMultipleProviders"
,
func
(
t
*
testing
.
T
)
{
bottomProvider
:=
mockTraceProvider
{
getOutput
:
mockOutput
}
splitProvider
:=
newSplitTraceProvider
(
t
,
&
mockTraceProvider
{},
&
bottomProvider
,
40
)
output
,
err
:=
splitProvider
.
Get
(
context
.
Background
(),
types
.
NewPosition
(
42
,
big
.
NewInt
(
17
)))
require
.
NoError
(
t
,
err
)
expectedGIndex
:=
types
.
NewPosition
(
2
,
big
.
NewInt
(
1
))
.
ToGIndex
()
require
.
Equal
(
t
,
common
.
BigToHash
(
expectedGIndex
),
output
)
})
}
func
TestAbsolutePreStateCommitment
(
t
*
testing
.
T
)
{
t
.
Run
(
"ErrorBubblesUp"
,
func
(
t
*
testing
.
T
)
{
mockOutputProvider
:=
mockTraceProvider
{
absolutePreStateCommitmentError
:
mockGetError
}
splitProvider
:=
newSplitTraceProvider
(
t
,
nil
,
&
mockOutputProvider
,
40
)
_
,
err
:=
splitProvider
.
AbsolutePreStateCommitment
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockGetError
)
})
t
.
Run
(
"ReturnsCorrectOutput"
,
func
(
t
*
testing
.
T
)
{
mockOutputProvider
:=
mockTraceProvider
{
absolutePreStateCommitment
:
mockCommitment
}
splitProvider
:=
newSplitTraceProvider
(
t
,
nil
,
&
mockOutputProvider
,
40
)
output
,
err
:=
splitProvider
.
AbsolutePreStateCommitment
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
mockCommitment
,
output
)
})
}
func
TestGetStepData
(
t
*
testing
.
T
)
{
t
.
Run
(
"ErrorBubblesUp"
,
func
(
t
*
testing
.
T
)
{
mockOutputProvider
:=
mockTraceProvider
{
getStepDataError
:
mockGetError
}
splitProvider
:=
newSplitTraceProvider
(
t
,
&
mockOutputProvider
,
nil
,
40
)
_
,
_
,
_
,
err
:=
splitProvider
.
GetStepData
(
context
.
Background
(),
types
.
NewPosition
(
0
,
common
.
Big0
))
require
.
ErrorIs
(
t
,
err
,
mockGetError
)
})
t
.
Run
(
"ReturnsCorrectStepData"
,
func
(
t
*
testing
.
T
)
{
expectedStepData
:=
[]
byte
{
1
,
2
,
3
,
4
}
mockOutputProvider
:=
mockTraceProvider
{
stepPrestateData
:
expectedStepData
}
splitProvider
:=
newSplitTraceProvider
(
t
,
nil
,
&
mockOutputProvider
,
40
)
output
,
_
,
_
,
err
:=
splitProvider
.
GetStepData
(
context
.
Background
(),
types
.
NewPosition
(
41
,
common
.
Big0
))
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
expectedStepData
,
output
)
})
}
type
mockTraceProvider
struct
{
getOutput
common
.
Hash
getError
error
absolutePreStateCommitmentError
error
absolutePreStateCommitment
common
.
Hash
absolutePreStateError
error
preImageData
[]
byte
getStepDataError
error
stepPrestateData
[]
byte
}
func
newSplitTraceProvider
(
t
*
testing
.
T
,
tp
*
mockTraceProvider
,
bp
*
mockTraceProvider
,
topDepth
uint64
)
SplitTraceProvider
{
return
SplitTraceProvider
{
logger
:
testlog
.
Logger
(
t
,
log
.
LvlInfo
),
topProvider
:
tp
,
bottomProvider
:
bp
,
topDepth
:
topDepth
,
}
}
func
(
m
*
mockTraceProvider
)
Get
(
ctx
context
.
Context
,
pos
types
.
Position
)
(
common
.
Hash
,
error
)
{
if
m
.
getError
!=
nil
{
return
common
.
Hash
{},
m
.
getError
}
return
common
.
BigToHash
(
pos
.
ToGIndex
()),
nil
}
func
(
m
*
mockTraceProvider
)
AbsolutePreStateCommitment
(
ctx
context
.
Context
)
(
hash
common
.
Hash
,
err
error
)
{
if
m
.
absolutePreStateCommitmentError
!=
nil
{
return
common
.
Hash
{},
m
.
absolutePreStateCommitmentError
}
return
m
.
absolutePreStateCommitment
,
nil
}
func
(
m
*
mockTraceProvider
)
AbsolutePreState
(
ctx
context
.
Context
)
(
preimage
[]
byte
,
err
error
)
{
if
m
.
absolutePreStateError
!=
nil
{
return
[]
byte
{},
m
.
absolutePreStateError
}
return
m
.
preImageData
,
nil
}
func
(
m
*
mockTraceProvider
)
GetStepData
(
ctx
context
.
Context
,
pos
types
.
Position
)
([]
byte
,
[]
byte
,
*
types
.
PreimageOracleData
,
error
)
{
if
m
.
getStepDataError
!=
nil
{
return
nil
,
nil
,
nil
,
m
.
getStepDataError
}
return
m
.
stepPrestateData
,
nil
,
nil
,
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment