Skip to content

Commit

Permalink
Merge pull request #6424 from ethereum-optimism/refcell/solver-module
Browse files Browse the repository at this point in the history
fix(op-challenger): Refactor Solver Component into its own Module
  • Loading branch information
OptimismBot committed Jul 24, 2023
2 parents 94ab156 + 18c4160 commit a19535e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 71 deletions.
7 changes: 4 additions & 3 deletions op-challenger/fault/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"

"github.com/ethereum-optimism/optimism/op-challenger/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/log"
)
Expand All @@ -19,7 +20,7 @@ type Responder interface {
}

type Agent struct {
solver *Solver
solver *solver.Solver
loader Loader
responder Responder
maxDepth int
Expand All @@ -29,7 +30,7 @@ type Agent struct {

func NewAgent(loader Loader, maxDepth int, trace types.TraceProvider, responder Responder, agreeWithProposedOutput bool, log log.Logger) *Agent {
return &Agent{
solver: NewSolver(maxDepth, trace),
solver: solver.NewSolver(maxDepth, trace),
loader: loader,
responder: responder,
maxDepth: maxDepth,
Expand All @@ -49,7 +50,7 @@ func (a *Agent) Act(ctx context.Context) error {
}
// Create counter claims
for _, claim := range game.Claims() {
if err := a.move(ctx, claim, game); err != nil && !errors.Is(err, ErrGameDepthReached) {
if err := a.move(ctx, claim, game); err != nil && !errors.Is(err, types.ErrGameDepthReached) {
log.Error("Failed to move", "err", err)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fault
package solver

import (
"errors"
Expand All @@ -9,9 +9,8 @@ import (
)

var (
ErrGameDepthReached = errors.New("game depth reached")
ErrStepNonLeafNode = errors.New("cannot step on non-leaf claims")
ErrStepAgreedClaim = errors.New("cannot step on claims we agree with")
ErrStepNonLeafNode = errors.New("cannot step on non-leaf claims")
ErrStepAgreedClaim = errors.New("cannot step on claims we agree with")
)

// Solver uses a [TraceProvider] to determine the moves to make in a dispute game.
Expand Down Expand Up @@ -62,7 +61,7 @@ func (s *Solver) handleMiddle(claim types.Claim) (*types.Claim, error) {
return nil, err
}
if claim.Depth() == s.gameDepth {
return nil, ErrGameDepthReached
return nil, types.ErrGameDepthReached
}
if claimCorrect {
return s.defend(claim)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package fault
package solver_test

import (
"fmt"
"testing"

"github.com/ethereum-optimism/optimism/op-challenger/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/stretchr/testify/require"
)

func TestNextMove(t *testing.T) {
maxDepth := 4
builder := NewClaimBuilder(t, maxDepth)
builder := test.NewAlphabetClaimBuilder(t, maxDepth)
tests := []struct {
name string
claim types.Claim
Expand Down Expand Up @@ -70,18 +72,18 @@ func TestNextMove(t *testing.T) {
{
name: "ErrorWhenClaimIsLeaf_Correct",
claim: builder.CreateLeafClaim(4, true),
expectedErr: ErrGameDepthReached,
expectedErr: types.ErrGameDepthReached,
},
{
name: "ErrorWhenClaimIsLeaf_Incorrect",
claim: builder.CreateLeafClaim(6, false),
expectedErr: ErrGameDepthReached,
expectedErr: types.ErrGameDepthReached,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
solver := NewSolver(maxDepth, builder.CorrectTraceProvider())
solver := solver.NewSolver(maxDepth, builder.CorrectTraceProvider())
move, err := solver.NextMove(test.claim, test.agreeWithLevel)
if test.expectedErr == nil {
require.NoError(t, err)
Expand All @@ -100,8 +102,8 @@ func TestNextMove(t *testing.T) {

func TestAttemptStep(t *testing.T) {
maxDepth := 3
builder := NewClaimBuilder(t, maxDepth)
solver := NewSolver(maxDepth, builder.CorrectTraceProvider())
builder := test.NewAlphabetClaimBuilder(t, maxDepth)
alphabetSolver := solver.NewSolver(maxDepth, builder.CorrectTraceProvider())

// Last accessible leaf is the second last trace index
// The root node is used for the last trace index and can only be attacked.
Expand Down Expand Up @@ -161,21 +163,21 @@ func TestAttemptStep(t *testing.T) {
{
name: "CannotStepNonLeaf",
claim: builder.Seq(false).Attack(false).Get(),
expectedErr: ErrStepNonLeafNode,
expectedErr: solver.ErrStepNonLeafNode,
},
{
name: "CannotStepAgreedNode",
claim: builder.Seq(false).Attack(false).Get(),
agreeWithLevel: true,
expectedErr: ErrStepNonLeafNode,
expectedErr: solver.ErrStepNonLeafNode,
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
fmt.Printf("%v\n", test.claim.Position.TraceIndex(maxDepth))
step, err := solver.AttemptStep(test.claim, test.agreeWithLevel)
step, err := alphabetSolver.AttemptStep(test.claim, test.agreeWithLevel)
if test.expectedErr == nil {
require.NoError(t, err)
require.Equal(t, test.claim, step.LeafClaim)
Expand All @@ -184,7 +186,7 @@ func TestAttemptStep(t *testing.T) {
require.Equal(t, test.expectProofData, step.ProofData)
} else {
require.ErrorIs(t, err, test.expectedErr)
require.Equal(t, StepData{}, step)
require.Equal(t, solver.StepData{}, step)
}
})
}
Expand Down
24 changes: 24 additions & 0 deletions op-challenger/fault/test/alphabet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package test

import (
"testing"

"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
)

func NewAlphabetClaimBuilder(t *testing.T, maxDepth int) *ClaimBuilder {
alphabetProvider := &alphabetWithProofProvider{alphabet.NewAlphabetProvider("abcdefghijklmnopqrstuvwxyz", uint64(maxDepth))}
return NewClaimBuilder(t, maxDepth, alphabetProvider)
}

type alphabetWithProofProvider struct {
*alphabet.AlphabetProvider
}

func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
preimage, _, err := a.AlphabetProvider.GetPreimage(i)
if err != nil {
return nil, nil, err
}
return preimage, []byte{byte(i)}, nil
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package fault
package test

import (
"math/big"
"testing"

"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
Expand All @@ -17,11 +16,12 @@ type ClaimBuilder struct {
correct types.TraceProvider
}

func NewClaimBuilder(t *testing.T, maxDepth int) *ClaimBuilder {
// NewClaimBuilder creates a new [ClaimBuilder].
func NewClaimBuilder(t *testing.T, maxDepth int, provider types.TraceProvider) *ClaimBuilder {
return &ClaimBuilder{
require: require.New(t),
maxDepth: maxDepth,
correct: &alphabetWithProofProvider{alphabet.NewAlphabetProvider("abcdefghijklmnopqrstuvwxyz", uint64(maxDepth))},
correct: provider,
}
}

Expand Down Expand Up @@ -109,51 +109,3 @@ func (c *ClaimBuilder) DefendClaim(claim types.Claim, correct bool) types.Claim
Parent: claim.ClaimData,
}
}

type SequenceBuilder struct {
builder *ClaimBuilder
lastClaim types.Claim
}

// Seq starts building a claim by following a sequence of attack and defend moves from the root
// The returned SequenceBuilder can be used to add additional moves. e.g:
// claim := Seq(true).Attack(false).Attack(true).Defend(true).Get()
func (c *ClaimBuilder) Seq(rootCorrect bool) *SequenceBuilder {
claim := c.CreateRootClaim(rootCorrect)
return &SequenceBuilder{
builder: c,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Attack(correct bool) *SequenceBuilder {
claim := s.builder.AttackClaim(s.lastClaim, correct)
return &SequenceBuilder{
builder: s.builder,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Defend(correct bool) *SequenceBuilder {
claim := s.builder.DefendClaim(s.lastClaim, correct)
return &SequenceBuilder{
builder: s.builder,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Get() types.Claim {
return s.lastClaim
}

type alphabetWithProofProvider struct {
*alphabet.AlphabetProvider
}

func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
preimage, _, err := a.AlphabetProvider.GetPreimage(i)
if err != nil {
return nil, nil, err
}
return preimage, []byte{byte(i)}, nil
}
41 changes: 41 additions & 0 deletions op-challenger/fault/test/seq_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package test

import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
)

type SequenceBuilder struct {
builder *ClaimBuilder
lastClaim types.Claim
}

// Seq starts building a claim by following a sequence of attack and defend moves from the root
// The returned SequenceBuilder can be used to add additional moves. e.g:
// claim := Seq(true).Attack(false).Attack(true).Defend(true).Get()
func (c *ClaimBuilder) Seq(rootCorrect bool) *SequenceBuilder {
claim := c.CreateRootClaim(rootCorrect)
return &SequenceBuilder{
builder: c,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Attack(correct bool) *SequenceBuilder {
claim := s.builder.AttackClaim(s.lastClaim, correct)
return &SequenceBuilder{
builder: s.builder,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Defend(correct bool) *SequenceBuilder {
claim := s.builder.DefendClaim(s.lastClaim, correct)
return &SequenceBuilder{
builder: s.builder,
lastClaim: claim,
}
}

func (s *SequenceBuilder) Get() types.Claim {
return s.lastClaim
}
6 changes: 6 additions & 0 deletions op-challenger/fault/types/types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package types

import (
"errors"

"github.com/ethereum/go-ethereum/common"
)

var (
ErrGameDepthReached = errors.New("game depth reached")
)

type GameStatus uint8

const (
Expand Down

0 comments on commit a19535e

Please sign in to comment.