Commit 6b50a465 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-e2e: Add tests to check behaviour within the extended trace of the output root bisection (#8808)

* op-e2e: Add tests to check behaviour within the extended trace of the output root bisection.

* op-e2e: Add test that explicitly changes the claimed output root for the root block.
parent 848f7928
...@@ -119,7 +119,7 @@ func (a *Agent) tryResolveClaims(ctx context.Context) error { ...@@ -119,7 +119,7 @@ func (a *Agent) tryResolveClaims(ctx context.Context) error {
var resolvableClaims []int64 var resolvableClaims []int64
for _, claim := range claims { for _, claim := range claims {
a.log.Debug("checking if claim is resolvable", "claimIdx", claim.ContractIndex) a.log.Trace("Checking if claim is resolvable", "claimIdx", claim.ContractIndex)
if err := a.responder.CallResolveClaim(ctx, uint64(claim.ContractIndex)); err == nil { if err := a.responder.CallResolveClaim(ctx, uint64(claim.ContractIndex)); err == nil {
a.log.Info("Resolving claim", "claimIdx", claim.ContractIndex) a.log.Info("Resolving claim", "claimIdx", claim.ContractIndex)
resolvableClaims = append(resolvableClaims, int64(claim.ContractIndex)) resolvableClaims = append(resolvableClaims, int64(claim.ContractIndex))
......
...@@ -58,6 +58,10 @@ func (h *OutputHonestHelper) Defend(ctx context.Context, claimIdx int64) { ...@@ -58,6 +58,10 @@ func (h *OutputHonestHelper) Defend(ctx context.Context, claimIdx int64) {
h.game.Defend(ctx, claimIdx, value) h.game.Defend(ctx, claimIdx, value)
} }
func (h *OutputHonestHelper) StepClaimFails(ctx context.Context, claim *ClaimHelper, isAttack bool) {
h.StepFails(ctx, claim.index, isAttack)
}
func (h *OutputHonestHelper) StepFails(ctx context.Context, claimIdx int64, isAttack bool) { func (h *OutputHonestHelper) StepFails(ctx context.Context, claimIdx int64, isAttack bool) {
// Ensure the claim exists // Ensure the claim exists
h.game.WaitForClaimCount(ctx, claimIdx+1) h.game.WaitForClaimCount(ctx, claimIdx+1)
......
...@@ -370,3 +370,164 @@ func TestOutputCannonPoisonedPostState(t *testing.T) { ...@@ -370,3 +370,164 @@ func TestOutputCannonPoisonedPostState(t *testing.T) {
game.LogGameData(ctx) game.LogGameData(ctx)
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins) game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
} }
func TestDisputeOutputRootBeyondProposedBlock_ValidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor))
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
// Root claim is dishonest
game := disputeGameFactory.StartOutputCannonGameWithCorrectRoot(ctx, "sequencer", 1)
correctTrace := game.CreateHonestActor(ctx, "sequencer", challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
// Start the honest challenger
game.StartChallenger(ctx, "sequencer", "Honest", challenger.WithPrivKey(sys.Cfg.Secrets.Bob))
claim := game.RootClaim(ctx)
// Attack the output root
claim = correctTrace.AttackClaim(ctx, claim)
// Wait for the challenger to respond
claim = claim.WaitForCounterClaim(ctx)
// Then defend until the split depth to force the game into the extension part of the output root bisection
// ie. the output root we wind up disputing is theoretically for a block after block number 1
for !claim.IsOutputRootLeaf(ctx) {
claim = correctTrace.DefendClaim(ctx, claim)
claim = claim.WaitForCounterClaim(ctx)
}
game.LogGameData(ctx)
// At this point we've reached the bottom of the output root bisection and every claim
// will have the same, valid, output root. We now need to post a cannon trace root that claims its invalid.
claim = claim.Defend(ctx, common.Hash{0x01, 0xaa})
// Now defend with the correct trace
for {
game.LogGameData(ctx)
claim = claim.WaitForCounterClaim(ctx)
if claim.IsMaxDepth(ctx) {
break
}
claim = correctTrace.DefendClaim(ctx, claim)
}
// Should not be able to step either attacking or defending
correctTrace.StepClaimFails(ctx, claim, true)
correctTrace.StepClaimFails(ctx, claim, false)
// Time travel past when the game will be resolvable.
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins)
game.LogGameData(ctx)
}
func TestDisputeOutputRootBeyondProposedBlock_InvalidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor))
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
// Root claim is dishonest
game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", 1, common.Hash{0xaa})
correctTrace := game.CreateHonestActor(ctx, "sequencer", challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
// Start the honest challenger
game.StartChallenger(ctx, "sequencer", "Honest", challenger.WithPrivKey(sys.Cfg.Secrets.Bob))
claim := game.RootClaim(ctx)
// Wait for the honest challenger to counter the root
claim = claim.WaitForCounterClaim(ctx)
// Then defend until the split depth to force the game into the extension part of the output root bisection
// ie. the output root we wind up disputing is theoretically for a block after block number 1
// The dishonest actor challenges with the correct roots
for claim.IsOutputRoot(ctx) {
claim = correctTrace.DefendClaim(ctx, claim)
claim = claim.WaitForCounterClaim(ctx)
}
game.LogGameData(ctx)
// Now defend with the correct trace
for !claim.IsMaxDepth(ctx) {
game.LogGameData(ctx)
if claim.IsBottomGameRoot(ctx) {
claim = correctTrace.AttackClaim(ctx, claim)
} else {
claim = correctTrace.DefendClaim(ctx, claim)
}
if !claim.IsMaxDepth(ctx) {
// Have to attack the root of the cannon trace
claim = claim.WaitForCounterClaim(ctx)
}
}
// Wait for our final claim to be countered by the challenger calling step
claim.WaitForCountered(ctx)
// Time travel past when the game will be resolvable.
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
game.LogGameData(ctx)
}
func TestDisputeOutputRoot_ChangeClaimedOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor))
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
// Root claim is dishonest
game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", 1, common.Hash{0xaa})
correctTrace := game.CreateHonestActor(ctx, "sequencer", challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
// Start the honest challenger
game.StartChallenger(ctx, "sequencer", "Honest", challenger.WithPrivKey(sys.Cfg.Secrets.Bob))
claim := game.RootClaim(ctx)
// Wait for the honest challenger to counter the root
claim = claim.WaitForCounterClaim(ctx)
// Then attack every claim until the leaf of output root bisection
for {
claim = claim.Attack(ctx, common.Hash{0xbb})
claim = claim.WaitForCounterClaim(ctx)
if claim.Depth() == game.SplitDepth(ctx)-1 {
// Post the correct output root as the leaf.
// This is for block 1 which is what the original output root was for too
claim = correctTrace.AttackClaim(ctx, claim)
// Challenger should post the first cannon trace
claim = claim.WaitForCounterClaim(ctx)
break
}
}
game.LogGameData(ctx)
// Now defend with the correct trace
for !claim.IsMaxDepth(ctx) {
game.LogGameData(ctx)
if claim.IsBottomGameRoot(ctx) {
claim = correctTrace.AttackClaim(ctx, claim)
} else {
claim = correctTrace.DefendClaim(ctx, claim)
}
if !claim.IsMaxDepth(ctx) {
// Have to attack the root of the cannon trace
claim = claim.WaitForCounterClaim(ctx)
}
}
// Wait for our final claim to be countered by the challenger calling step
claim.WaitForCountered(ctx)
// Time travel past when the game will be resolvable.
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, wait.ForNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
game.LogGameData(ctx)
}
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