Commit a95bd8c2 authored by clabby's avatar clabby

Add modular VM interface + improve `OneVsOne` arena

parent cbae9e68
...@@ -32,12 +32,12 @@ DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_revert ...@@ -32,12 +32,12 @@ DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_revert
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243) DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44243)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642) DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 497198) FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 513436)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 499064) FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 515302)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot:test_resolvesCorrectly_succeeds() (gas: 489092) FaultDisputeGame_ResolvesCorrectly_CorrectRoot:test_resolvesCorrectly_succeeds() (gas: 502966)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 494067) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 510311)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 495933) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 512177)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot:test_resolvesCorrectly_succeeds() (gas: 485961) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot:test_resolvesCorrectly_succeeds() (gas: 499841)
FaultDisputeGame_Test:test_defendRoot_invalidMove_reverts() (gas: 13250) FaultDisputeGame_Test:test_defendRoot_invalidMove_reverts() (gas: 13250)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17409) FaultDisputeGame_Test:test_extraData_succeeds() (gas: 17409)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17834) FaultDisputeGame_Test:test_gameData_succeeds() (gas: 17834)
......
...@@ -6,6 +6,7 @@ import { IVersioned } from "./interfaces/IVersioned.sol"; ...@@ -6,6 +6,7 @@ import { IVersioned } from "./interfaces/IVersioned.sol";
import { IFaultDisputeGame } from "./interfaces/IFaultDisputeGame.sol"; import { IFaultDisputeGame } from "./interfaces/IFaultDisputeGame.sol";
import { IInitializable } from "./interfaces/IInitializable.sol"; import { IInitializable } from "./interfaces/IInitializable.sol";
import { IBondManager } from "./interfaces/IBondManager.sol"; import { IBondManager } from "./interfaces/IBondManager.sol";
import { IBigStepper } from "./interfaces/IBigStepper.sol";
import { Clone } from "../libraries/Clone.sol"; import { Clone } from "../libraries/Clone.sol";
import { LibHashing } from "./lib/LibHashing.sol"; import { LibHashing } from "./lib/LibHashing.sol";
...@@ -29,6 +30,10 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { ...@@ -29,6 +30,10 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
/// @notice The max depth of the game. /// @notice The max depth of the game.
uint256 public immutable MAX_GAME_DEPTH; uint256 public immutable MAX_GAME_DEPTH;
/// @notice A hypervisor that performs single instruction steps on a fault proof program trace.
/// @return vm_ The address of the hypervisor contract.
IBigStepper public immutable VM;
/// @notice The duration of the game. /// @notice The duration of the game.
/// @dev TODO: Account for resolution buffer. (?) /// @dev TODO: Account for resolution buffer. (?)
Duration internal constant GAME_DURATION = Duration.wrap(7 days); Duration internal constant GAME_DURATION = Duration.wrap(7 days);
...@@ -55,9 +60,14 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { ...@@ -55,9 +60,14 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
mapping(ClaimHash => bool) internal claims; mapping(ClaimHash => bool) internal claims;
/// @param _absolutePrestate The absolute prestate of the instruction trace. /// @param _absolutePrestate The absolute prestate of the instruction trace.
constructor(Claim _absolutePrestate, uint256 _maxGameDepth) { constructor(
Claim _absolutePrestate,
uint256 _maxGameDepth,
IBigStepper _vm
) {
ABSOLUTE_PRESTATE = _absolutePrestate; ABSOLUTE_PRESTATE = _absolutePrestate;
MAX_GAME_DEPTH = _maxGameDepth; MAX_GAME_DEPTH = _maxGameDepth;
VM = _vm;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
...@@ -79,8 +89,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { ...@@ -79,8 +89,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
uint256 _stateIndex, uint256 _stateIndex,
uint256 _claimIndex, uint256 _claimIndex,
bool _isAttack, bool _isAttack,
bytes calldata, bytes calldata _stateData,
bytes calldata bytes calldata _proof
) external { ) external {
// Steps cannot be made unless the game is currently in progress. // Steps cannot be made unless the game is currently in progress.
if (status != GameStatus.IN_PROGRESS) { if (status != GameStatus.IN_PROGRESS) {
...@@ -127,19 +137,19 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone { ...@@ -127,19 +137,19 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone {
postStateClaim = claimData[_stateIndex].claim; postStateClaim = claimData[_stateIndex].claim;
} }
// Assert that the given prestate commits to the instruction at `gindex - 1`. // Assert that the given prestate commits to the instruction at `gindex - 1` and
// that the `_stateData` is the preimage for the prestate claim digest.
if ( if (
Position.unwrap(preStatePos.rightIndex(MAX_GAME_DEPTH)) != Position.unwrap(preStatePos.rightIndex(MAX_GAME_DEPTH)) !=
Position.unwrap(postStatePos.rightIndex(MAX_GAME_DEPTH)) - 1 Position.unwrap(postStatePos.rightIndex(MAX_GAME_DEPTH)) - 1 ||
keccak256(_stateData) != Claim.unwrap(preStateClaim)
) { ) {
revert InvalidPrestate(); revert InvalidPrestate();
} }
} }
// TODO: Call `MIPS.sol#step` to verify the step. // Perform the VM step and check to see if it is valid.
// For now, we just use a simple state transition function that increments the prestate, if (VM.step(_stateData, _proof) == Claim.unwrap(postStateClaim)) {
// `s_p`, by 1.
if (uint256(Claim.unwrap(preStateClaim)) + 1 == uint256(Claim.unwrap(postStateClaim))) {
revert ValidStep(); revert ValidStep();
} }
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
/// @title IBigStepper
/// @notice An interface for a contract with a state transition function that
/// will accept a pre state and return a post state.
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⠶⢅⠒⢄⢔⣶⡦⣤⡤⠄⣀⠀⠀⠀⠀⠀⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⡏⠀⠀⠈⠢⣙⢯⣄⠀⢨⠯⡺⡘⢄⠀⠀⠀⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣶⡆⠀⠀⠀⠀⠈⠓⠬⡒⠡⣀⢙⡜⡀⠓⠄⠀⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡷⠿⣧⣀⡀⠀⠀⠀⠀⠀⠀⠉⠣⣞⠩⠥⠀⠼⢄⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠉⢹⣶⠒⠒⠂⠈⠉⠁⠘⡆⠀⣿⣿⠫⡄⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⢶⣤⣀⡀⠀⠀⢸⡿⠀⠀⠀⠀⠀⢀⠞⠀⠀⢡⢨⢀⡄⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡒⣿⢿⡤⠝⡣⠉⠁⠚⠛⠀⠤⠤⣄⡰⠁⠀⠀⠀⠉⠙⢸⠀⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⢯⡌⡿⡇⠘⡷⠀⠁⠀⠀⢀⣰⠢⠲⠛⣈⣸⠦⠤⠶⠴⢬⣐⣊⡂⠀
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⡪⡗⢫⠞⠀⠆⣀⠻⠤⠴⠐⠚⣉⢀⠦⠂⠋⠁⠀⠁⠀⠀⠀⠀⢋⠉⠇⠀
///⠀⠀⠀⠀⣀⡤⠐⠒⠘⡹⠉⢸⠇⠸⠀⠀⠀⠀⣀⣤⠴⠚⠉⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠀⣾⠀
///⠀⠀⠀⡰⠀⠉⠉⠀⠁⠀⠀⠈⢇⠈⠒⠒⠘⠈⢀⢡⡂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⢸⡄
///⠀⠀⠸⣿⣆⠤⢀⡀⠀⠀⠀⠀⢘⡌⠀⠀⣀⣀⣀⡈⣤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⢸⡇
///⠀⠀⢸⣀⠀⠉⠒⠐⠛⠋⠭⠭⠍⠉⠛⠒⠒⠒⠀⠒⠚⠛⠛⠛⠩⠭⠭⠭⠭⠤⠤⠤⠤⠤⠭⠭⠉⠓⡆
///⠀⠀⠘⠿⣷⣶⣤⣤⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇
///⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⢿⣿⣿⣷⣶⣶⣶⣤⣤⣀⣁⣛⣃⣒⠿⠿⠿⠤⠠⠄⠤⠤⢤⣛⣓⣂⣻⡇
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠙⠛⠻⠿⠿⠿⢿⣿⣿⣿⣷⣶⣶⣾⣿⣿⣿⣿⠿⠟⠁
///⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀
interface IBigStepper {
/// @notice Performs a single instruction step from a given prestate and returns the poststate
/// hash.
/// @param _stateData The preimage of the prestate hash.
/// @param _proof A proof for the inclusion of the prestate's memory in the merkle tree.
/// @return postState_ The poststate hash after the instruction step.
function step(bytes calldata _stateData, bytes calldata _proof)
external
returns (bytes32 postState_);
}
...@@ -11,6 +11,8 @@ import "../libraries/DisputeTypes.sol"; ...@@ -11,6 +11,8 @@ import "../libraries/DisputeTypes.sol";
import "../libraries/DisputeErrors.sol"; import "../libraries/DisputeErrors.sol";
import { LibClock } from "../dispute/lib/LibClock.sol"; import { LibClock } from "../dispute/lib/LibClock.sol";
import { LibPosition } from "../dispute/lib/LibPosition.sol"; import { LibPosition } from "../dispute/lib/LibPosition.sol";
import { Bytes } from "../libraries/Bytes.sol";
import { IBigStepper } from "../dispute/interfaces/IBigStepper.sol";
contract FaultDisputeGame_Init is DisputeGameFactory_Init { contract FaultDisputeGame_Init is DisputeGameFactory_Init {
/// @dev The extra data passed to the game for initialization. /// @dev The extra data passed to the game for initialization.
...@@ -28,7 +30,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { ...@@ -28,7 +30,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
function init(Claim rootClaim, Claim absolutePrestate) public { function init(Claim rootClaim, Claim absolutePrestate) public {
super.setUp(); super.setUp();
// Deploy an implementation of the fault game // Deploy an implementation of the fault game
gameImpl = new FaultDisputeGame(absolutePrestate, 4); gameImpl = new FaultDisputeGame(absolutePrestate, 4, new BigStepper(absolutePrestate));
// Register the game implementation with the factory. // Register the game implementation with the factory.
factory.setImplementation(GAME_TYPE, gameImpl); factory.setImplementation(GAME_TYPE, gameImpl);
// Create a new game. // Create a new game.
...@@ -296,10 +298,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -296,10 +298,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
contract GamePlayer { contract GamePlayer {
bool public failedToStep; bool public failedToStep;
FaultDisputeGame public gameProxy; FaultDisputeGame public gameProxy;
bytes public trace;
GamePlayer internal counterParty; GamePlayer internal counterParty;
Vm internal vm; Vm internal vm;
bytes internal trace;
uint256 internal maxDepth; uint256 internal maxDepth;
/// @notice Initializes the player /// @notice Initializes the player
...@@ -307,7 +309,7 @@ contract GamePlayer { ...@@ -307,7 +309,7 @@ contract GamePlayer {
FaultDisputeGame _gameProxy, FaultDisputeGame _gameProxy,
GamePlayer _counterParty, GamePlayer _counterParty,
Vm _vm Vm _vm
) public virtual { ) public {
gameProxy = _gameProxy; gameProxy = _gameProxy;
counterParty = _counterParty; counterParty = _counterParty;
vm = _vm; vm = _vm;
...@@ -366,8 +368,10 @@ contract GamePlayer { ...@@ -366,8 +368,10 @@ contract GamePlayer {
// If we are past the maximum depth, break the recursion and step. // If we are past the maximum depth, break the recursion and step.
if (movePos.depth() > maxDepth) { if (movePos.depth() > maxDepth) {
// Perform a step.
uint256 stateIndex; uint256 stateIndex;
Position statePos;
bytes memory preStateTrace;
// First, we need to find the pre/post state index depending on whether we // First, we need to find the pre/post state index depending on whether we
// are making an attack step or a defense step. If the index at depth of the // are making an attack step or a defense step. If the index at depth of the
// move position is 0, the prestate is the absolute prestate and we need to // move position is 0, the prestate is the absolute prestate and we need to
...@@ -376,7 +380,7 @@ contract GamePlayer { ...@@ -376,7 +380,7 @@ contract GamePlayer {
Position leafPos = isAttack Position leafPos = isAttack
? Position.wrap(Position.unwrap(parentPos) - 1) ? Position.wrap(Position.unwrap(parentPos) - 1)
: Position.wrap(Position.unwrap(parentPos) + 1); : Position.wrap(Position.unwrap(parentPos) + 1);
Position statePos = leafPos; statePos = leafPos;
// Walk up until the valid position that commits to the prestate's // Walk up until the valid position that commits to the prestate's
// trace index is found. // trace index is found.
...@@ -397,10 +401,13 @@ contract GamePlayer { ...@@ -397,10 +401,13 @@ contract GamePlayer {
break; break;
} }
} }
// Grab the trace up to the prestate's trace index.
preStateTrace = traceAt(isAttack ? statePos : parentPos);
} }
// Perform the step and halt recursion. // Perform the step and halt recursion.
try gameProxy.step(stateIndex, _parentIndex, isAttack, hex"", hex"") { try gameProxy.step(stateIndex, _parentIndex, isAttack, preStateTrace, hex"") {
// Do nothing, step succeeded. // Do nothing, step succeeded.
} catch { } catch {
failedToStep = true; failedToStep = true;
...@@ -439,14 +446,24 @@ contract GamePlayer { ...@@ -439,14 +446,24 @@ contract GamePlayer {
return uint256(vm.load(address(gameProxy), bytes32(uint256(1)))); return uint256(vm.load(address(gameProxy), bytes32(uint256(1))));
} }
/// @notice Returns the player's claim that commits to a given gindex. /// @notice Returns the preimage of a player's claim that commits to a given trace index.
function claimAt(Position _position) internal view returns (Claim claim_) { function traceAt(Position _position) public view returns (bytes memory trace_) {
return claimAt(_position.rightIndex(maxDepth).indexAtDepth()); return traceAt(_position.rightIndex(maxDepth).indexAtDepth());
}
/// @notice Returns the preimage of a player's claim that commits to a given trace index.
function traceAt(uint256 _traceIndex) public view returns (bytes memory trace_) {
return Bytes.slice(trace, 0, _traceIndex + 1);
} }
/// @notice Returns the player's claim that commits to a given trace index. /// @notice Returns the player's claim that commits to a given trace index.
function claimAt(uint256 _traceIndex) public view returns (Claim claim_) { function claimAt(uint256 _traceIndex) public view returns (Claim claim_) {
return Claim.wrap(bytes32(uint256(bytes32(trace[_traceIndex]) >> 248))); return Claim.wrap(keccak256(traceAt(_traceIndex)));
}
/// @notice Returns the player's claim that commits to a given trace index.
function claimAt(Position _position) public view returns (Claim claim_) {
return claimAt(_position.rightIndex(maxDepth).indexAtDepth());
} }
} }
...@@ -481,9 +498,9 @@ contract OneVsOne_Arena is FaultDisputeGame_Init { ...@@ -481,9 +498,9 @@ contract OneVsOne_Arena is FaultDisputeGame_Init {
contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new FullyDivergentPlayer(); GamePlayer dishonest = new FullyDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(30)))); super.init(honest, dishonest, Claim.wrap(keccak256(dishonest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -499,9 +516,9 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot is OneVsOne_Arena { ...@@ -499,9 +516,9 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot is OneVsOne_Arena {
contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new FullyDivergentPlayer(); GamePlayer dishonest = new FullyDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); super.init(honest, dishonest, Claim.wrap(keccak256(honest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -517,9 +534,9 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot is OneVsOne_Arena { ...@@ -517,9 +534,9 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot is OneVsOne_Arena {
contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2 is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2 is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new HalfDivergentPlayer(); GamePlayer dishonest = new HalfDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(15)))); super.init(honest, dishonest, Claim.wrap(keccak256(dishonest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -535,9 +552,9 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2 is OneVsOne_Arena { ...@@ -535,9 +552,9 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2 is OneVsOne_Arena {
contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot2 is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot2 is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new HalfDivergentPlayer(); GamePlayer dishonest = new HalfDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); super.init(honest, dishonest, Claim.wrap(keccak256(honest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -553,9 +570,9 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot2 is OneVsOne_Arena { ...@@ -553,9 +570,9 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot2 is OneVsOne_Arena {
contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3 is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3 is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new EarlyDivergentPlayer(); GamePlayer dishonest = new EarlyDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(15)))); super.init(honest, dishonest, Claim.wrap(keccak256(dishonest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -569,11 +586,11 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3 is OneVsOne_Arena { ...@@ -569,11 +586,11 @@ contract FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3 is OneVsOne_Arena {
} }
} }
contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot4 is OneVsOne_Arena { contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot3 is OneVsOne_Arena {
function setUp() public override { function setUp() public override {
GamePlayer honest = new HonestPlayer(); GamePlayer honest = new HonestPlayer(ABSOLUTE_PRESTATE);
GamePlayer dishonest = new EarlyDivergentPlayer(); GamePlayer dishonest = new EarlyDivergentPlayer(ABSOLUTE_PRESTATE);
super.init(honest, dishonest, Claim.wrap(bytes32(uint256(31)))); super.init(honest, dishonest, Claim.wrap(keccak256(honest.trace())));
} }
function test_resolvesCorrectly_succeeds() public { function test_resolvesCorrectly_succeeds() public {
...@@ -592,13 +609,8 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot4 is OneVsOne_Arena { ...@@ -592,13 +609,8 @@ contract FaultDisputeGame_ResolvesCorrectly_CorrectRoot4 is OneVsOne_Arena {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
contract HonestPlayer is GamePlayer { contract HonestPlayer is GamePlayer {
function init( constructor(Claim _absolutePrestate) {
FaultDisputeGame _gameProxy, uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_absolutePrestate)));
GamePlayer _counterParty,
Vm _vm
) public virtual override {
super.init(_gameProxy, _counterParty, _vm);
uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE())));
bytes memory honestTrace = new bytes(16); bytes memory honestTrace = new bytes(16);
for (uint8 i = 0; i < honestTrace.length; i++) { for (uint8 i = 0; i < honestTrace.length; i++) {
honestTrace[i] = bytes1(absolutePrestate + i + 1); honestTrace[i] = bytes1(absolutePrestate + i + 1);
...@@ -608,13 +620,8 @@ contract HonestPlayer is GamePlayer { ...@@ -608,13 +620,8 @@ contract HonestPlayer is GamePlayer {
} }
contract FullyDivergentPlayer is GamePlayer { contract FullyDivergentPlayer is GamePlayer {
function init( constructor(Claim _absolutePrestate) {
FaultDisputeGame _gameProxy, uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_absolutePrestate)));
GamePlayer _counterParty,
Vm _vm
) public virtual override {
super.init(_gameProxy, _counterParty, _vm);
uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE())));
bytes memory dishonestTrace = new bytes(16); bytes memory dishonestTrace = new bytes(16);
for (uint8 i = 0; i < dishonestTrace.length; i++) { for (uint8 i = 0; i < dishonestTrace.length; i++) {
// Offset the honest trace by 1. // Offset the honest trace by 1.
...@@ -625,13 +632,8 @@ contract FullyDivergentPlayer is GamePlayer { ...@@ -625,13 +632,8 @@ contract FullyDivergentPlayer is GamePlayer {
} }
contract HalfDivergentPlayer is GamePlayer { contract HalfDivergentPlayer is GamePlayer {
function init( constructor(Claim _absolutePrestate) {
FaultDisputeGame _gameProxy, uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_absolutePrestate)));
GamePlayer _counterParty,
Vm _vm
) public virtual override {
super.init(_gameProxy, _counterParty, _vm);
uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE())));
bytes memory dishonestTrace = new bytes(16); bytes memory dishonestTrace = new bytes(16);
for (uint8 i = 0; i < dishonestTrace.length; i++) { for (uint8 i = 0; i < dishonestTrace.length; i++) {
// Offset the trace after the first half. // Offset the trace after the first half.
...@@ -642,13 +644,8 @@ contract HalfDivergentPlayer is GamePlayer { ...@@ -642,13 +644,8 @@ contract HalfDivergentPlayer is GamePlayer {
} }
contract EarlyDivergentPlayer is GamePlayer { contract EarlyDivergentPlayer is GamePlayer {
function init( constructor(Claim _absolutePrestate) {
FaultDisputeGame _gameProxy, uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_absolutePrestate)));
GamePlayer _counterParty,
Vm _vm
) public virtual override {
super.init(_gameProxy, _counterParty, _vm);
uint8 absolutePrestate = uint8(uint256(Claim.unwrap(_gameProxy.ABSOLUTE_PRESTATE())));
bytes memory dishonestTrace = new bytes(16); bytes memory dishonestTrace = new bytes(16);
for (uint8 i = 0; i < dishonestTrace.length; i++) { for (uint8 i = 0; i < dishonestTrace.length; i++) {
// Offset the trace after the first half. // Offset the trace after the first half.
...@@ -657,3 +654,31 @@ contract EarlyDivergentPlayer is GamePlayer { ...@@ -657,3 +654,31 @@ contract EarlyDivergentPlayer is GamePlayer {
trace = dishonestTrace; trace = dishonestTrace;
} }
} }
////////////////////////////////////////////////////////////////
// MOCK VMS //
////////////////////////////////////////////////////////////////
contract BigStepper is IBigStepper {
Claim internal immutable ABSOLUTE_PRESTATE;
constructor(Claim _absolutePrestate) {
ABSOLUTE_PRESTATE = _absolutePrestate;
}
/// @inheritdoc IBigStepper
function step(bytes calldata _stateData, bytes calldata)
external
view
returns (bytes32 postState_)
{
// STF: n -> concat(n, n[n.len-1] + 1)
uint8 postState = (
_stateData.length == 0
? uint8(uint256(Claim.unwrap(ABSOLUTE_PRESTATE)))
: uint8(_stateData[_stateData.length - 1])
) + 1;
// Hash the trace for the claim.
postState_ = keccak256(bytes.concat(_stateData, bytes1(postState)));
}
}
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