Commit edea36a7 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into 09-08-fix_Remove_fault_detector_from_version_tags

parents 214e0d82 7c9c00c4
......@@ -17,7 +17,7 @@ import (
type Responder interface {
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
Resolve(ctx context.Context) error
PerformAction(ctx context.Context, action solver.Action) error
PerformAction(ctx context.Context, action types.Action) error
}
type ClaimLoader interface {
......@@ -76,9 +76,9 @@ func (a *Agent) Act(ctx context.Context) error {
}
switch action.Type {
case solver.ActionTypeMove:
case types.ActionTypeMove:
a.metrics.RecordGameMove()
case solver.ActionTypeStep:
case types.ActionTypeStep:
a.metrics.RecordGameStep()
}
log.Info("Performing action")
......
......@@ -5,7 +5,6 @@ import (
"errors"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
......@@ -145,7 +144,7 @@ func (s *stubResponder) Resolve(ctx context.Context) error {
return s.resolveErr
}
func (s *stubResponder) PerformAction(ctx context.Context, response solver.Action) error {
func (s *stubResponder) PerformAction(ctx context.Context, response types.Action) error {
panic("Not implemented")
}
......
......@@ -5,7 +5,7 @@ import (
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
......@@ -94,17 +94,17 @@ func (r *FaultResponder) Resolve(ctx context.Context) error {
return r.sendTxAndWait(ctx, txData)
}
func (r *FaultResponder) PerformAction(ctx context.Context, action solver.Action) error {
func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) error {
var txData []byte
var err error
switch action.Type {
case solver.ActionTypeMove:
case types.ActionTypeMove:
if action.IsAttack {
txData, err = r.buildFaultAttackData(action.ParentIdx, action.Value)
} else {
txData, err = r.buildFaultDefendData(action.ParentIdx, action.Value)
}
case solver.ActionTypeStep:
case types.ActionTypeStep:
txData, err = r.buildStepTxData(uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData)
}
if err != nil {
......
......@@ -7,7 +7,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
......@@ -78,8 +78,8 @@ func TestPerformAction(t *testing.T) {
t.Run("send fails", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
mockTxMgr.sendFails = true
err := responder.PerformAction(context.Background(), solver.Action{
Type: solver.ActionTypeMove,
err := responder.PerformAction(context.Background(), types.Action{
Type: types.ActionTypeMove,
ParentIdx: 123,
IsAttack: true,
Value: common.Hash{0xaa},
......@@ -90,8 +90,8 @@ func TestPerformAction(t *testing.T) {
t.Run("sends response", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
err := responder.PerformAction(context.Background(), solver.Action{
Type: solver.ActionTypeMove,
err := responder.PerformAction(context.Background(), types.Action{
Type: types.ActionTypeMove,
ParentIdx: 123,
IsAttack: true,
Value: common.Hash{0xaa},
......@@ -102,8 +102,8 @@ func TestPerformAction(t *testing.T) {
t.Run("attack", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
action := solver.Action{
Type: solver.ActionTypeMove,
action := types.Action{
Type: types.ActionTypeMove,
ParentIdx: 123,
IsAttack: true,
Value: common.Hash{0xaa},
......@@ -123,8 +123,8 @@ func TestPerformAction(t *testing.T) {
t.Run("defend", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
action := solver.Action{
Type: solver.ActionTypeMove,
action := types.Action{
Type: types.ActionTypeMove,
ParentIdx: 123,
IsAttack: false,
Value: common.Hash{0xaa},
......@@ -144,8 +144,8 @@ func TestPerformAction(t *testing.T) {
t.Run("step", func(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t)
action := solver.Action{
Type: solver.ActionTypeStep,
action := types.Action{
Type: types.ActionTypeStep,
ParentIdx: 123,
IsAttack: true,
PreState: []byte{1, 2, 3},
......
......@@ -6,34 +6,8 @@ import (
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/common"
)
type ActionType string
const (
ActionTypeMove ActionType = "move"
ActionTypeStep ActionType = "step"
)
func (a ActionType) String() string {
return string(a)
}
type Action struct {
Type ActionType
ParentIdx int
IsAttack bool
// Moves
Value common.Hash
// Steps
PreState []byte
ProofData []byte
OracleData *types.PreimageOracleData
}
type GameSolver struct {
claimSolver *claimSolver
gameDepth int
......@@ -46,11 +20,11 @@ func NewGameSolver(gameDepth int, trace types.TraceProvider) *GameSolver {
}
}
func (s *GameSolver) CalculateNextActions(ctx context.Context, game types.Game) ([]Action, error) {
func (s *GameSolver) CalculateNextActions(ctx context.Context, game types.Game) ([]types.Action, error) {
var errs []error
var actions []Action
var actions []types.Action
for _, claim := range game.Claims() {
var action *Action
var action *types.Action
var err error
if claim.Depth() == s.gameDepth {
action, err = s.calculateStep(ctx, game, claim)
......@@ -69,7 +43,7 @@ func (s *GameSolver) CalculateNextActions(ctx context.Context, game types.Game)
return actions, errors.Join(errs...)
}
func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim types.Claim) (*Action, error) {
func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim types.Claim) (*types.Action, error) {
if claim.Countered {
return nil, nil
}
......@@ -80,8 +54,8 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim t
if err != nil {
return nil, err
}
return &Action{
Type: ActionTypeStep,
return &types.Action{
Type: types.ActionTypeStep,
ParentIdx: step.LeafClaim.ContractIndex,
IsAttack: step.IsAttack,
PreState: step.PreState,
......@@ -90,7 +64,7 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim t
}, nil
}
func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim types.Claim) (*Action, error) {
func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim types.Claim) (*types.Action, error) {
move, err := s.claimSolver.NextMove(ctx, claim, game.AgreeWithClaimLevel(claim))
if err != nil {
return nil, fmt.Errorf("failed to calculate next move for claim index %v: %w", claim.ContractIndex, err)
......@@ -98,8 +72,8 @@ func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim t
if move == nil || game.IsDuplicate(*move) {
return nil, nil
}
return &Action{
Type: ActionTypeMove,
return &types.Action{
Type: types.ActionTypeMove,
IsAttack: !move.DefendsParent(),
ParentIdx: move.ParentContractIndex,
Value: move.Value,
......
......@@ -6,88 +6,31 @@ import (
"testing"
faulttest "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
type actionMaker func(game types.Game) Action
func TestCalculateNextActions(t *testing.T) {
maxDepth := 4
claimBuilder := faulttest.NewAlphabetClaimBuilder(t, maxDepth)
attackClaim := func(parentIdx int) actionMaker {
return func(game types.Game) Action {
parentClaim := game.Claims()[parentIdx]
return Action{
Type: ActionTypeMove,
ParentIdx: parentIdx,
IsAttack: true,
Value: claimBuilder.CorrectClaimAtPosition(parentClaim.Position.Attack()),
}
}
}
defendClaim := func(parentIdx int) actionMaker {
return func(game types.Game) Action {
parentClaim := game.Claims()[parentIdx]
return Action{
Type: ActionTypeMove,
ParentIdx: parentIdx,
IsAttack: false,
Value: claimBuilder.CorrectClaimAtPosition(parentClaim.Position.Defend()),
}
}
}
stepAttack := func(parentIdx int) actionMaker {
return func(game types.Game) Action {
parentClaim := game.Claims()[parentIdx]
traceIdx := parentClaim.Position.TraceIndex(maxDepth)
return Action{
Type: ActionTypeStep,
ParentIdx: parentIdx,
IsAttack: true,
PreState: claimBuilder.CorrectPreState(traceIdx),
ProofData: claimBuilder.CorrectProofData(traceIdx),
OracleData: claimBuilder.CorrectOracleData(traceIdx),
}
}
}
stepDefend := func(parentIdx int) actionMaker {
return func(game types.Game) Action {
parentClaim := game.Claims()[parentIdx]
traceIdx := parentClaim.Position.TraceIndex(maxDepth) + 1
return Action{
Type: ActionTypeStep,
ParentIdx: parentIdx,
IsAttack: false,
PreState: claimBuilder.CorrectPreState(traceIdx),
ProofData: claimBuilder.CorrectProofData(traceIdx),
OracleData: claimBuilder.CorrectOracleData(traceIdx),
}
}
}
tests := []struct {
name string
agreeWithOutputRoot bool
rootClaimCorrect bool
setupGame func(builder *faulttest.GameBuilder)
expectedActions []actionMaker
}{
{
name: "AttackRootClaim",
agreeWithOutputRoot: true,
setupGame: func(builder *faulttest.GameBuilder) {},
expectedActions: []actionMaker{
attackClaim(0),
setupGame: func(builder *faulttest.GameBuilder) {
builder.Seq().ExpectAttack()
},
},
{
name: "DoNotAttackRootClaimWhenDisagreeWithOutputRoot",
agreeWithOutputRoot: false,
setupGame: func(builder *faulttest.GameBuilder) {},
expectedActions: nil,
},
{
// Note: The fault dispute game contract should prevent a correct root claim from actually being posted
......@@ -96,7 +39,6 @@ func TestCalculateNextActions(t *testing.T) {
agreeWithOutputRoot: true,
rootClaimCorrect: true,
setupGame: func(builder *faulttest.GameBuilder) {},
expectedActions: nil,
},
{
// Note: The fault dispute game contract should prevent a correct root claim from actually being posted
......@@ -105,7 +47,6 @@ func TestCalculateNextActions(t *testing.T) {
agreeWithOutputRoot: false,
rootClaimCorrect: true,
setupGame: func(builder *faulttest.GameBuilder) {},
expectedActions: nil,
},
{
......@@ -115,31 +56,19 @@ func TestCalculateNextActions(t *testing.T) {
// Expected move has already been made.
builder.Seq().AttackCorrect()
},
expectedActions: nil,
},
{
name: "RespondToAllClaimsAtDisagreeingLevel",
agreeWithOutputRoot: true,
setupGame: func(builder *faulttest.GameBuilder) {
honestClaim := builder.Seq().AttackCorrect() // 1
honestClaim.AttackCorrect() // 2
honestClaim.DefendCorrect() // 3
honestClaim.Attack(common.Hash{0xaa}) // 4
honestClaim.Attack(common.Hash{0xbb}) // 5
honestClaim.Defend(common.Hash{0xcc}) // 6
honestClaim.Defend(common.Hash{0xdd}) // 7
},
expectedActions: []actionMaker{
// Defend the correct claims
defendClaim(2),
defendClaim(3),
// Attack the incorrect claims
attackClaim(4),
attackClaim(5),
attackClaim(6),
attackClaim(7),
honestClaim := builder.Seq().AttackCorrect()
honestClaim.AttackCorrect().ExpectDefend()
honestClaim.DefendCorrect().ExpectDefend()
honestClaim.Attack(common.Hash{0xaa}).ExpectAttack()
honestClaim.Attack(common.Hash{0xbb}).ExpectAttack()
honestClaim.Defend(common.Hash{0xcc}).ExpectAttack()
honestClaim.Defend(common.Hash{0xdd}).ExpectAttack()
},
},
......@@ -148,15 +77,11 @@ func TestCalculateNextActions(t *testing.T) {
agreeWithOutputRoot: true,
setupGame: func(builder *faulttest.GameBuilder) {
lastHonestClaim := builder.Seq().
AttackCorrect(). // 1 - Honest
AttackCorrect(). // 2 - Dishonest
DefendCorrect() // 3 - Honest
lastHonestClaim.AttackCorrect() // 4 - Dishonest
lastHonestClaim.Attack(common.Hash{0xdd}) // 5 - Dishonest
},
expectedActions: []actionMaker{
stepDefend(4),
stepAttack(5),
AttackCorrect().
AttackCorrect().
DefendCorrect()
lastHonestClaim.AttackCorrect().ExpectStepDefend()
lastHonestClaim.Attack(common.Hash{0xdd}).ExpectStepAttack()
},
},
}
......@@ -178,10 +103,12 @@ func TestCalculateNextActions(t *testing.T) {
t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v",
i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData))
}
require.Len(t, actions, len(test.expectedActions))
for i, action := range test.expectedActions {
require.Containsf(t, actions, action(game), "Expected claim %v missing", i)
for i, action := range builder.ExpectedActions {
t.Logf("Expect %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v",
i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData))
require.Containsf(t, actions, action, "Expected claim %v missing", i)
}
require.Len(t, actions, len(builder.ExpectedActions), "Incorrect number of actions")
})
}
}
......@@ -8,6 +8,7 @@ import (
type GameBuilder struct {
builder *ClaimBuilder
Game types.Game
ExpectedActions []types.Action
}
func (c *ClaimBuilder) GameBuilder(agreeWithOutputRoot bool, rootCorrect bool) *GameBuilder {
......@@ -18,6 +19,7 @@ func (c *ClaimBuilder) GameBuilder(agreeWithOutputRoot bool, rootCorrect bool) *
}
type GameBuilderSeq struct {
gameBuilder *GameBuilder
builder *ClaimBuilder
lastClaim types.Claim
game types.Game
......@@ -25,6 +27,7 @@ type GameBuilderSeq struct {
func (g *GameBuilder) Seq() *GameBuilderSeq {
return &GameBuilderSeq{
gameBuilder: g,
builder: g.builder,
game: g.Game,
lastClaim: g.Game.Claims()[0],
......@@ -36,6 +39,7 @@ func (s *GameBuilderSeq) AttackCorrect() *GameBuilderSeq {
claim.ContractIndex = len(s.game.Claims())
s.builder.require.NoError(s.game.Put(claim))
return &GameBuilderSeq{
gameBuilder: s.gameBuilder,
builder: s.builder,
game: s.game,
lastClaim: claim,
......@@ -47,6 +51,7 @@ func (s *GameBuilderSeq) Attack(value common.Hash) *GameBuilderSeq {
claim.ContractIndex = len(s.game.Claims())
s.builder.require.NoError(s.game.Put(claim))
return &GameBuilderSeq{
gameBuilder: s.gameBuilder,
builder: s.builder,
game: s.game,
lastClaim: claim,
......@@ -58,6 +63,7 @@ func (s *GameBuilderSeq) DefendCorrect() *GameBuilderSeq {
claim.ContractIndex = len(s.game.Claims())
s.builder.require.NoError(s.game.Put(claim))
return &GameBuilderSeq{
gameBuilder: s.gameBuilder,
builder: s.builder,
game: s.game,
lastClaim: claim,
......@@ -69,8 +75,59 @@ func (s *GameBuilderSeq) Defend(value common.Hash) *GameBuilderSeq {
claim.ContractIndex = len(s.game.Claims())
s.builder.require.NoError(s.game.Put(claim))
return &GameBuilderSeq{
gameBuilder: s.gameBuilder,
builder: s.builder,
game: s.game,
lastClaim: claim,
}
}
func (s *GameBuilderSeq) ExpectAttack() *GameBuilderSeq {
newPos := s.lastClaim.Position.Attack()
value := s.builder.CorrectClaimAtPosition(newPos)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeMove,
ParentIdx: s.lastClaim.ContractIndex,
IsAttack: true,
Value: value,
})
return s
}
func (s *GameBuilderSeq) ExpectDefend() *GameBuilderSeq {
newPos := s.lastClaim.Position.Defend()
value := s.builder.CorrectClaimAtPosition(newPos)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeMove,
ParentIdx: s.lastClaim.ContractIndex,
IsAttack: false,
Value: value,
})
return s
}
func (s *GameBuilderSeq) ExpectStepAttack() *GameBuilderSeq {
traceIdx := s.lastClaim.TraceIndex(s.builder.maxDepth)
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeStep,
ParentIdx: s.lastClaim.ContractIndex,
IsAttack: true,
PreState: s.builder.CorrectPreState(traceIdx),
ProofData: s.builder.CorrectProofData(traceIdx),
OracleData: s.builder.CorrectOracleData(traceIdx),
})
return s
}
func (s *GameBuilderSeq) ExpectStepDefend() *GameBuilderSeq {
traceIdx := s.lastClaim.TraceIndex(s.builder.maxDepth) + 1
s.gameBuilder.ExpectedActions = append(s.gameBuilder.ExpectedActions, types.Action{
Type: types.ActionTypeStep,
ParentIdx: s.lastClaim.ContractIndex,
IsAttack: false,
PreState: s.builder.CorrectPreState(traceIdx),
ProofData: s.builder.CorrectProofData(traceIdx),
OracleData: s.builder.CorrectOracleData(traceIdx),
})
return s
}
package types
import "github.com/ethereum/go-ethereum/common"
type ActionType string
func (a ActionType) String() string {
return string(a)
}
const (
ActionTypeMove ActionType = "move"
ActionTypeStep ActionType = "step"
)
type Action struct {
Type ActionType
ParentIdx int
IsAttack bool
// Moves
Value common.Hash
// Steps
PreState []byte
ProofData []byte
OracleData *PreimageOracleData
}
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