Commit 12a46911 authored by clabby's avatar clabby Committed by GitHub

feat(ctb): Support variable length traces in `FaultDisputeGame` (#6316)

* init: Variable trace length support

* Support variable trace lengths

* chore: gas-snapshot

* chore: bindings

* chore: lint

* chore: Bump Semver + :broom:

* chore: resolve conflicts
parent cfac6f24
This diff is collapsed.
...@@ -83,12 +83,16 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520) ...@@ -83,12 +83,16 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520)
FaucetTest:test_receive_succeeds() (gas: 17401) FaucetTest:test_receive_succeeds() (gas: 17401)
FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145) FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145)
FaucetTest:test_withdraw_succeeds() (gas: 78359) FaucetTest:test_withdraw_succeeds() (gas: 78359)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 491839) FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 498900)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 495751) FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 503381)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 495049) FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 502679)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 490600) FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 505608)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 494512) FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 504939)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 493810) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 497692)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 502173)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 501471)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 502373)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 501731)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17426) FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17426)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17917) FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17917)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10315) FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10315)
......
...@@ -59,7 +59,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -59,7 +59,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
Claim _absolutePrestate, Claim _absolutePrestate,
uint256 _maxGameDepth, uint256 _maxGameDepth,
IBigStepper _vm IBigStepper _vm
) Semver(0, 0, 2) { ) Semver(0, 0, 3) {
ABSOLUTE_PRESTATE = _absolutePrestate; ABSOLUTE_PRESTATE = _absolutePrestate;
MAX_GAME_DEPTH = _maxGameDepth; MAX_GAME_DEPTH = _maxGameDepth;
VM = _vm; VM = _vm;
...@@ -92,7 +92,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -92,7 +92,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// Determine the expected pre & post states of the step. // Determine the expected pre & post states of the step.
Claim preStateClaim; Claim preStateClaim;
Claim postStateClaim; ClaimData storage postState;
if (_isAttack) { if (_isAttack) {
if (stepPos.indexAtDepth() == 0) { if (stepPos.indexAtDepth() == 0) {
// If the step position's index at depth is 0, the prestate is the absolute // If the step position's index at depth is 0, the prestate is the absolute
...@@ -104,16 +104,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -104,16 +104,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
preStateClaim = findTraceAncestor( preStateClaim = findTraceAncestor(
Position.wrap(Position.unwrap(parentPos) - 1), Position.wrap(Position.unwrap(parentPos) - 1),
parent.parentIndex parent.parentIndex
); ).claim;
} }
// For all attacks, the poststate is the parent claim. // For all attacks, the poststate is the parent claim.
postStateClaim = parent.claim; postState = parent;
} else { } else {
// If the step is a defense, the poststate exists elsewhere in the game state, // If the step is a defense, the poststate exists elsewhere in the game state,
// and the parent claim is the expected pre-state. // and the parent claim is the expected pre-state.
preStateClaim = parent.claim; preStateClaim = parent.claim;
postStateClaim = findTraceAncestor( postState = findTraceAncestor(
Position.wrap(Position.unwrap(parentPos) + 1), Position.wrap(Position.unwrap(parentPos) + 1),
parent.parentIndex parent.parentIndex
); );
...@@ -123,10 +123,21 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -123,10 +123,21 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// preimage of the prestate claim hash. // preimage of the prestate claim hash.
if (keccak256(_stateData) != Claim.unwrap(preStateClaim)) revert InvalidPrestate(); if (keccak256(_stateData) != Claim.unwrap(preStateClaim)) revert InvalidPrestate();
// INVARIANT: A VM step can never counter a parent claim unless it produces a poststate // INVARIANT: If a step is an attack, the poststate is valid if the step produces
// that is not equal to the claim at `_parentIndex` if the step is an attack, // the same poststate hash as the parent claim's value.
// or the claim at `_stateIndex` if the step is a defense. // If a step is a defense:
if (VM.step(_stateData, _proof) == Claim.unwrap(postStateClaim)) revert ValidStep(); // 1. If the parent claim and the found post state agree with each other
// (depth diff % 2 == 0), the step is valid if it produces the same
// state hash as the post state's claim.
// 2. If the parent claim and the found post state disagree with each other
// (depth diff % 2 != 0), the parent cannot be countered unless the step
// produces the same state hash as `postState.claim`.
// SAFETY: While the `attack` path does not need an extra check for the post
// state's depth in relation to the parent, we don't need another
// branch because (n - n) % 2 == 0.
bool validStep = VM.step(_stateData, _proof) == Claim.unwrap(postState.claim);
bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0;
if ((parentPostAgree && validStep) || (!parentPostAgree && !validStep)) revert ValidStep();
// Set the parent claim as countered. We do not need to append a new claim to the game; // Set the parent claim as countered. We do not need to append a new claim to the game;
// instead, we can just set the existing parent as countered. // instead, we can just set the existing parent as countered.
...@@ -384,17 +395,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -384,17 +395,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
function findTraceAncestor(Position _pos, uint256 _start) function findTraceAncestor(Position _pos, uint256 _start)
internal internal
view view
returns (Claim ancestor_) returns (ClaimData storage ancestor_)
{ {
// Grab the trace ancestor's expected position. // Grab the trace ancestor's expected position.
Position preStateTraceAncestor = _pos.traceAncestor(); Position preStateTraceAncestor = _pos.traceAncestor();
// Walk up the DAG to find a claim that commits to the same trace index as `_pos`. It is // Walk up the DAG to find a claim that commits to the same trace index as `_pos`. It is
// guaranteed that such a claim exists. // guaranteed that such a claim exists.
ClaimData storage ancestor = claimData[_start]; ancestor_ = claimData[_start];
while (Position.unwrap(ancestor.position) != Position.unwrap(preStateTraceAncestor)) { while (Position.unwrap(ancestor_.position) != Position.unwrap(preStateTraceAncestor)) {
ancestor = claimData[ancestor.parentIndex]; ancestor_ = claimData[ancestor_.parentIndex];
} }
ancestor_ = ancestor.claim;
} }
} }
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