Commit d3d0dfe5 authored by Inphi's avatar Inphi Committed by GitHub

op-e2e: Add Freeloader dispute tests (#9377)

* op-e2e: Add Freeloader dispute tests

The test is skipped for now until the challenger responds
to freeloaders correctly.

* Update op-e2e/faultproofs/output_alphabet_test.go
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>

---------
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
parent f7c50027
......@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......@@ -98,11 +99,21 @@ func (c *ClaimHelper) Attack(ctx context.Context, value common.Hash) *ClaimHelpe
return c.WaitForCounterClaim(ctx)
}
func (c *ClaimHelper) AttackWithTransactOpts(ctx context.Context, value common.Hash, opts *bind.TransactOpts) *ClaimHelper {
c.game.AttackWithTransactOpts(ctx, c.index, value, opts)
return c.WaitForCounterClaim(ctx)
}
func (c *ClaimHelper) Defend(ctx context.Context, value common.Hash) *ClaimHelper {
c.game.Defend(ctx, c.index, value)
return c.WaitForCounterClaim(ctx)
}
func (c *ClaimHelper) DefendWithTransactOpts(ctx context.Context, value common.Hash, opts *bind.TransactOpts) *ClaimHelper {
c.game.DefendWithTransactOpts(ctx, c.index, value, opts)
return c.WaitForCounterClaim(ctx)
}
func (c *ClaimHelper) RequireDifferentClaimValue(other *ClaimHelper) {
c.require.NotEqual(c.claim, other.claim, "should have posted different claims")
}
......
......@@ -446,9 +446,9 @@ func (g *OutputGameHelper) waitForNewClaim(ctx context.Context, checkPoint int64
return newClaimLen, err
}
func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash) {
func (g *OutputGameHelper) AttackWithTransactOpts(ctx context.Context, claimIdx int64, claim common.Hash, opts *bind.TransactOpts) {
g.t.Logf("Attacking claim %v with value %v", claimIdx, claim)
tx, err := g.game.Attack(g.opts, big.NewInt(claimIdx), claim)
tx, err := g.game.Attack(opts, big.NewInt(claimIdx), claim)
if err != nil {
g.require.NoErrorf(err, "Attack transaction did not send. Game state: \n%v", g.gameData(ctx))
}
......@@ -458,7 +458,11 @@ func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim com
}
}
func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim common.Hash) {
func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash) {
g.AttackWithTransactOpts(ctx, claimIdx, claim, g.opts)
}
func (g *OutputGameHelper) DefendWithTransactOpts(ctx context.Context, claimIdx int64, claim common.Hash, opts *bind.TransactOpts) {
g.t.Logf("Defending claim %v with value %v", claimIdx, claim)
tx, err := g.game.Defend(g.opts, big.NewInt(claimIdx), claim)
if err != nil {
......@@ -470,6 +474,10 @@ func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim com
}
}
func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim common.Hash) {
g.DefendWithTransactOpts(ctx, claimIdx, claim, g.opts)
}
type ErrWithData interface {
ErrorData() interface{}
}
......@@ -583,8 +591,8 @@ func (g *OutputGameHelper) gameData(ctx context.Context) string {
extra = fmt.Sprintf("Block num: %v", blockNum)
}
}
info = info + fmt.Sprintf("%v - Position: %v, Depth: %v, IndexAtDepth: %v Trace Index: %v, Value: %v, Countered By: %v, ParentIndex: %v %v\n",
i, claim.Position.Int64(), pos.Depth(), pos.IndexAtDepth(), pos.TraceIndex(maxDepth), common.Hash(claim.Claim).Hex(), claim.CounteredBy, claim.ParentIndex, extra)
info = info + fmt.Sprintf("%v - Position: %v, Depth: %v, IndexAtDepth: %v Trace Index: %v, ClaimHash: %v, Countered By: %v, ParentIndex: %v Claimant: %v Bond: %v %v\n",
i, claim.Position.Int64(), pos.Depth(), pos.IndexAtDepth(), pos.TraceIndex(maxDepth), common.Hash(claim.Claim).Hex(), claim.CounteredBy, claim.ParentIndex, claim.Claimant, claim.Bond, extra)
}
l2BlockNum := g.L2BlockNum(ctx)
status, err := g.game.Status(opts)
......@@ -596,3 +604,10 @@ func (g *OutputGameHelper) gameData(ctx context.Context) string {
func (g *OutputGameHelper) LogGameData(ctx context.Context) {
g.t.Log(g.gameData(ctx))
}
func (g *OutputGameHelper) Credit(ctx context.Context, addr common.Address) *big.Int {
opts := &bind.CallOpts{Context: ctx}
amt, err := g.game.Credit(opts, addr)
g.require.NoError(err)
return amt
}
......@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/stretchr/testify/require"
)
......@@ -23,12 +24,21 @@ func (h *OutputHonestHelper) AttackClaim(ctx context.Context, claim *ClaimHelper
return claim.WaitForCounterClaim(ctx)
}
func (h *OutputHonestHelper) AttackClaimWithTransactOpts(ctx context.Context, claim *ClaimHelper, opts *bind.TransactOpts) *ClaimHelper {
h.AttackWithTransactOpts(ctx, claim.index, opts)
return claim.WaitForCounterClaim(ctx)
}
func (h *OutputHonestHelper) DefendClaim(ctx context.Context, claim *ClaimHelper) *ClaimHelper {
h.Defend(ctx, claim.index)
return claim.WaitForCounterClaim(ctx)
}
func (h *OutputHonestHelper) Attack(ctx context.Context, claimIdx int64) {
h.AttackWithTransactOpts(ctx, claimIdx, h.game.opts)
}
func (h *OutputHonestHelper) AttackWithTransactOpts(ctx context.Context, claimIdx int64, opts *bind.TransactOpts) {
// Ensure the claim exists
h.game.WaitForClaimCount(ctx, claimIdx+1)
......@@ -41,7 +51,7 @@ func (h *OutputHonestHelper) Attack(ctx context.Context, claimIdx int64) {
value, err := h.correctTrace.Get(ctx, game, claim, attackPos)
h.require.NoErrorf(err, "Get correct claim at position %v with g index %v", attackPos, attackPos.ToGIndex())
h.t.Log("Performing attack")
h.game.Attack(ctx, claimIdx, value)
h.game.AttackWithTransactOpts(ctx, claimIdx, value, opts)
h.t.Log("Attack complete")
}
......
......@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......@@ -167,3 +168,64 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) {
testCase(t, false)
})
}
func TestOutputAlphabetGame_FreeloaderEarnsNothing(t *testing.T) {
t.Skip("CLI-103")
op_e2e.InitParallel(t)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
freeloaderOpts, err := bind.NewKeyedTransactorWithChainID(sys.Cfg.Secrets.Mallory, sys.Cfg.L1ChainIDBig())
require.Nil(t, err)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
game := disputeGameFactory.StartOutputAlphabetGameWithCorrectRoot(ctx, "sequencer", 2)
correctTrace := game.CreateHonestActor(ctx, "sequencer")
game.LogGameData(ctx)
claim := game.DisputeLastBlock(ctx)
// Invalid root claim of the alphabet game
claim = claim.Attack(ctx, common.Hash{0x01})
// Chronology of claims:
// dishonest root claim:
// - honest counter
// - dishonest
// - freeloader
// - honest
// - freeloader
// The freeloader must be positioned leftmost (gindex positioning) or at the same position as honest claims.
// honest counter
claim = correctTrace.AttackClaim(ctx, claim)
var freeloaders []*disputegame.ClaimHelper
// dishonest
dishonest := correctTrace.AttackClaim(ctx, claim)
freeloaders = append(freeloaders, correctTrace.AttackClaimWithTransactOpts(ctx, dishonest, freeloaderOpts))
freeloaders = append(freeloaders, dishonest.AttackWithTransactOpts(ctx, common.Hash{0x02}, freeloaderOpts))
freeloaders = append(freeloaders, dishonest.DefendWithTransactOpts(ctx, common.Hash{0x03}, freeloaderOpts))
// Ensure freeloaders respond before the honest challenger
game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
dishonest.WaitForCounterClaim(ctx, freeloaders...)
// Freeloaders after the honest challenger
freeloaders = append(freeloaders, dishonest.AttackWithTransactOpts(ctx, common.Hash{0x04}, freeloaderOpts))
freeloaders = append(freeloaders, dishonest.DefendWithTransactOpts(ctx, common.Hash{0x05}, freeloaderOpts))
for _, freeloader := range freeloaders {
freeloader.WaitForCounterClaim(ctx)
}
game.LogGameData(ctx)
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins)
amt := game.Credit(ctx, freeloaderOpts.From)
require.True(t, amt.BitLen() == 0, "freeloaders should not be rewarded")
}
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