Commit 6e174ae2 authored by Adrian Sutton's avatar Adrian Sutton

fpa: Add docs that point to the e2e test for invalid proposals

parent 8d8597a2
......@@ -14,3 +14,4 @@ finalized and may change without notice.
* [Manual Usage](./manual.md)
* [Creating Traces with Cannon](./cannon.md)
* [Automation with `op-challenger`](./run-challenger.md)
* [Challenging Invalid Output Proposals](./invalid-proposals.md)
## Challenging Invalid Output Proposals
The dispute game factory deployed to Goerli reads from the permissioned L2 Output Oracle contract. This restricts games
to challenging valid output proposals and an honest challenger should win every game. To test creating games that
challenge an invalid output proposal, a custom chain is required. The simplest way to do this is using the end-to-end
test utilities in [`op-e2e`](https://github.com/ethereum-optimism/optimism/tree/develop/op-e2e).
A simple starting point has been provided in the `TestCannonProposedOutputRootInvalid` test case
in [`faultproof_test.go`](https://github.com/ethereum-optimism/optimism/blob/5e93c1696c28402c54ef0dab9d98f41680e3c0c3/op-e2e/faultproof_test.go#L334).
This is a table test that takes the output root to propose, plus functions for move and step to counter the honest
claims. The test asserts that the defender always wins and thus the output root is found to be invalid.
......@@ -333,22 +333,32 @@ func TestCannonDefendStep(t *testing.T) {
func TestCannonProposedOutputRootInvalid(t *testing.T) {
InitParallel(t)
honestStepsFail := func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
// honestStepsFail attempts to perform both an attack and defend step using the correct trace.
honestStepsFail := func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
// Attack step should fail
correctTrace.StepFails(ctx, parentClaimIdx, true)
// Defending should fail too
correctTrace.StepFails(ctx, parentClaimIdx, false)
}
tests := []struct {
name string
outputRoot common.Hash
performMove func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64)
performStep func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64)
// name is the name of the test
name string
// outputRoot is the invalid output root to propose
outputRoot common.Hash
// performMove is called to respond to each claim posted by the honest op-challenger.
// It should either attack or defend the claim at parentClaimIdx
performMove func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64)
// performStep is called once the maximum game depth is reached. It should perform a step to counter the
// claim at parentClaimIdx. Since the proposed output root is invalid, the step call should always revert.
performStep func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64)
}{
{
name: "AttackWithCorrectTrace",
outputRoot: common.Hash{0xab},
performMove: func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
performMove: func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
// Attack everything but oddly using the correct hash.
correctTrace.Attack(ctx, parentClaimIdx)
},
......@@ -357,7 +367,7 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) {
{
name: "DefendWithCorrectTrace",
outputRoot: common.Hash{0xab},
performMove: func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
performMove: func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) {
// Can only attack the root claim
if parentClaimIdx == 0 {
correctTrace.Attack(ctx, parentClaimIdx)
......@@ -376,16 +386,16 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) {
InitParallel(t)
ctx := context.Background()
sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0xab})
sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, test.outputRoot)
t.Cleanup(sys.Close)
// Now maliciously play the game and it should be impossible to win
game.ChallengeRootClaim(ctx,
func(parentClaimIdx int64) {
test.performMove(ctx, correctTrace, parentClaimIdx)
test.performMove(ctx, game, correctTrace, parentClaimIdx)
},
func(parentClaimIdx int64) {
test.performStep(ctx, correctTrace, parentClaimIdx)
test.performStep(ctx, game, correctTrace, parentClaimIdx)
})
// Time travel past when the game will be resolvable.
......
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