Commit f28b7f23 authored by Adrian Sutton's avatar Adrian Sutton

op-e2e: Use helper to create dishonest helper.

Reduces the amount of boilerplate required in the actual test.
parent bd7e7965
...@@ -35,7 +35,7 @@ func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint str ...@@ -35,7 +35,7 @@ func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint str
return c return c
} }
func (g *AlphabetGameHelper) CreateHonestActor(ctx context.Context, alphabetTrace string, depth uint64) *HonestHelper { func (g *AlphabetGameHelper) CreateHonestActor(alphabetTrace string, depth uint64) *HonestHelper {
return &HonestHelper{ return &HonestHelper{
t: g.t, t: g.t,
require: g.require, require: g.require,
...@@ -43,3 +43,7 @@ func (g *AlphabetGameHelper) CreateHonestActor(ctx context.Context, alphabetTrac ...@@ -43,3 +43,7 @@ func (g *AlphabetGameHelper) CreateHonestActor(ctx context.Context, alphabetTrac
correctTrace: alphabet.NewTraceProvider(alphabetTrace, depth), correctTrace: alphabet.NewTraceProvider(alphabetTrace, depth),
} }
} }
func (g *AlphabetGameHelper) CreateDishonestHelper(alphabetTrace string, depth uint64, defender bool) *DishonestHelper {
return newDishonestHelper(&g.FaultGameHelper, g.CreateHonestActor(alphabetTrace, depth), defender)
}
package disputegame
import (
"context"
"errors"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/common"
)
type dishonestClaim struct {
ParentIndex int64
IsAttack bool
Valid bool
}
type DishonestHelper struct {
*FaultGameHelper
*HonestHelper
claims map[dishonestClaim]bool
defender bool
}
func newDishonestHelper(g *FaultGameHelper, correctTrace *HonestHelper, defender bool) *DishonestHelper {
return &DishonestHelper{g, correctTrace, make(map[dishonestClaim]bool), defender}
}
func (t *DishonestHelper) Attack(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, true, false}
if t.claims[c] {
return
}
t.claims[c] = true
t.FaultGameHelper.Attack(ctx, claimIndex, common.Hash{byte(claimIndex)})
}
func (t *DishonestHelper) Defend(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, false, false}
if t.claims[c] {
return
}
t.claims[c] = true
t.FaultGameHelper.Defend(ctx, claimIndex, common.Hash{byte(claimIndex)})
}
func (t *DishonestHelper) AttackCorrect(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, true, true}
if t.claims[c] {
return
}
t.claims[c] = true
t.HonestHelper.Attack(ctx, claimIndex)
}
func (t *DishonestHelper) DefendCorrect(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, false, true}
if t.claims[c] {
return
}
t.claims[c] = true
t.HonestHelper.Defend(ctx, claimIndex)
}
// ExhaustDishonestClaims makes all possible significant moves (mod honest challenger's) in a game.
// It is very inefficient and should NOT be used on games with large depths
func (d *DishonestHelper) ExhaustDishonestClaims(ctx context.Context) {
depth := d.MaxDepth(ctx)
move := func(claimIndex int64, claimData ContractClaim) {
// dishonest level, valid attack
// dishonest level, invalid attack
// dishonest level, valid defense
// dishonest level, invalid defense
// honest level, invalid attack
// honest level, invalid defense
pos := types.NewPositionFromGIndex(claimData.Position.Uint64())
if int64(pos.Depth()) == depth {
return
}
d.LogGameData(ctx)
d.FaultGameHelper.t.Logf("Dishonest moves against claimIndex %d", claimIndex)
agreeWithLevel := d.defender == (pos.Depth()%2 == 0)
if !agreeWithLevel {
d.AttackCorrect(ctx, claimIndex)
if claimIndex != 0 {
d.DefendCorrect(ctx, claimIndex)
}
}
d.Attack(ctx, claimIndex)
if claimIndex != 0 {
d.Defend(ctx, claimIndex)
}
}
var numClaimsSeen int64
for {
newCount, err := d.WaitForNewClaim(ctx, numClaimsSeen)
if errors.Is(err, context.DeadlineExceeded) {
// we assume that the honest challenger has stopped responding
// There's nothing to respond to.
break
}
d.FaultGameHelper.require.NoError(err)
for i := numClaimsSeen; i < newCount; i++ {
claimData := d.getClaim(ctx, numClaimsSeen)
move(numClaimsSeen, claimData)
numClaimsSeen++
}
}
}
...@@ -2,7 +2,6 @@ package disputegame ...@@ -2,7 +2,6 @@ package disputegame
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"math/big" "math/big"
"testing" "testing"
...@@ -383,106 +382,3 @@ func (g *FaultGameHelper) gameData(ctx context.Context) string { ...@@ -383,106 +382,3 @@ func (g *FaultGameHelper) gameData(ctx context.Context) string {
func (g *FaultGameHelper) LogGameData(ctx context.Context) { func (g *FaultGameHelper) LogGameData(ctx context.Context) {
g.t.Log(g.gameData(ctx)) g.t.Log(g.gameData(ctx))
} }
type dishonestClaim struct {
ParentIndex int64
IsAttack bool
Valid bool
}
type DishonestHelper struct {
*FaultGameHelper
*HonestHelper
claims map[dishonestClaim]bool
defender bool
}
func NewDishonestHelper(g *FaultGameHelper, correctTrace *HonestHelper, defender bool) *DishonestHelper {
return &DishonestHelper{g, correctTrace, make(map[dishonestClaim]bool), defender}
}
func (t *DishonestHelper) Attack(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, true, false}
if t.claims[c] {
return
}
t.claims[c] = true
t.FaultGameHelper.Attack(ctx, claimIndex, common.Hash{byte(claimIndex)})
}
func (t *DishonestHelper) Defend(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, false, false}
if t.claims[c] {
return
}
t.claims[c] = true
t.FaultGameHelper.Defend(ctx, claimIndex, common.Hash{byte(claimIndex)})
}
func (t *DishonestHelper) AttackCorrect(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, true, true}
if t.claims[c] {
return
}
t.claims[c] = true
t.HonestHelper.Attack(ctx, claimIndex)
}
func (t *DishonestHelper) DefendCorrect(ctx context.Context, claimIndex int64) {
c := dishonestClaim{claimIndex, false, true}
if t.claims[c] {
return
}
t.claims[c] = true
t.HonestHelper.Defend(ctx, claimIndex)
}
// ExhaustDishonestClaims makes all possible significant moves (mod honest challenger's) in a game.
// It is very inefficient and should NOT be used on games with large depths
func (d *DishonestHelper) ExhaustDishonestClaims(ctx context.Context) {
depth := d.MaxDepth(ctx)
move := func(claimIndex int64, claimData ContractClaim) {
// dishonest level, valid attack
// dishonest level, invalid attack
// dishonest level, valid defense
// dishonest level, invalid defense
// honest level, invalid attack
// honest level, invalid defense
pos := types.NewPositionFromGIndex(claimData.Position.Uint64())
if int64(pos.Depth()) == depth {
return
}
d.LogGameData(ctx)
d.FaultGameHelper.t.Logf("Dishonest moves against claimIndex %d", claimIndex)
agreeWithLevel := d.defender == (pos.Depth()%2 == 0)
if !agreeWithLevel {
d.AttackCorrect(ctx, claimIndex)
if claimIndex != 0 {
d.DefendCorrect(ctx, claimIndex)
}
}
d.Attack(ctx, claimIndex)
if claimIndex != 0 {
d.Defend(ctx, claimIndex)
}
}
var numClaimsSeen int64
for {
newCount, err := d.WaitForNewClaim(ctx, numClaimsSeen)
if errors.Is(err, context.DeadlineExceeded) {
// we assume that the honest challenger has stopped responding
// There's nothing to respond to.
break
}
d.FaultGameHelper.require.NoError(err)
for i := numClaimsSeen; i < newCount; i++ {
claimData := d.getClaim(ctx, numClaimsSeen)
move(numClaimsSeen, claimData)
numClaimsSeen++
}
}
}
...@@ -208,8 +208,7 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) { ...@@ -208,8 +208,7 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) {
) )
// Start dishonest challenger // Start dishonest challenger
correctTrace := game.CreateHonestActor(ctx, disputegame.CorrectAlphabet, 4) dishonestHelper := game.CreateDishonestHelper(disputegame.CorrectAlphabet, 4, !isRootCorrect)
dishonestHelper := disputegame.NewDishonestHelper(&game.FaultGameHelper, correctTrace, !isRootCorrect)
dishonestHelper.ExhaustDishonestClaims(ctx) dishonestHelper.ExhaustDishonestClaims(ctx)
// Wait until we've reached max depth before checking for inactivity // Wait until we've reached max depth before checking for inactivity
......
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