Commit e13fe02b authored by clabby's avatar clabby

Ignore high byte in Alphabet game

parent f6c7fa5b
...@@ -75,19 +75,10 @@ func BuildAlphabetPreimage(i uint64, letter string) []byte { ...@@ -75,19 +75,10 @@ func BuildAlphabetPreimage(i uint64, letter string) []byte {
return append(IndexToBytes(i), LetterToBytes(letter)...) return append(IndexToBytes(i), LetterToBytes(letter)...)
} }
const maxAlphabet = 26
func alphabetStateHash(state []byte) common.Hash { func alphabetStateHash(state []byte) common.Hash {
h := crypto.Keccak256Hash(state) h := crypto.Keccak256Hash(state)
// instead of the state containing an "exited" boolean, we just check if the index reached the end // In the alphabet game, we ignore the VM status code and always set it to 1.
i := new(big.Int).SetBytes(state[:32]) h[0] = 1
if !i.IsUint64() || i.Uint64() > maxAlphabet {
h[0] = types.VMStatusPanic // this state should never be reached, if we increment by 1 per step
} else if i.Uint64() == maxAlphabet {
h[0] = types.VMStatusValid
} else {
h[0] = types.VMStatusUnfinished
}
return h return h
} }
......
This diff is collapsed.
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"src/L2/L2StandardBridge.sol": "0xe025dcccbf21d48828ecf588941c9ba04c91b87bdd177a653d3f1b265b0b02a8", "src/L2/L2StandardBridge.sol": "0xe025dcccbf21d48828ecf588941c9ba04c91b87bdd177a653d3f1b265b0b02a8",
"src/L2/L2ToL1MessagePasser.sol": "0xda56ba2e5b2c28fa8ca2df24077d49e96155a00ecc99cd0778d681be6ed166fe", "src/L2/L2ToL1MessagePasser.sol": "0xda56ba2e5b2c28fa8ca2df24077d49e96155a00ecc99cd0778d681be6ed166fe",
"src/L2/SequencerFeeVault.sol": "0x37816035c992d38cf7e3d5a1846b02d017dd7bdca46abe6e5c5171b9ee6225ab", "src/L2/SequencerFeeVault.sol": "0x37816035c992d38cf7e3d5a1846b02d017dd7bdca46abe6e5c5171b9ee6225ab",
"src/dispute/FaultDisputeGame.sol": "0x72c917e8513d17f274753a391bdbddc1f4daeca1a392f79492df29a1107c3525", "src/dispute/FaultDisputeGame.sol": "0x1ee46e383f6017c8a381c54ff26958659d54995c97144879586a0d827f4a82c8",
"src/legacy/DeployerWhitelist.sol": "0xf2129ec3da75307ba8e21bc943c332bb04704642e6e263149b5c8ee92dbcb7a8", "src/legacy/DeployerWhitelist.sol": "0xf2129ec3da75307ba8e21bc943c332bb04704642e6e263149b5c8ee92dbcb7a8",
"src/legacy/L1BlockNumber.sol": "0x30aae1fc85103476af0226b6e98c71c01feebbdc35d93401390b1ad438a37be6", "src/legacy/L1BlockNumber.sol": "0x30aae1fc85103476af0226b6e98c71c01feebbdc35d93401390b1ad438a37be6",
"src/legacy/LegacyMessagePasser.sol": "0x5c08b0a663cc49d30e4e38540f6aefab19ef287c3ecd31c8d8c3decd5f5bd497", "src/legacy/LegacyMessagePasser.sol": "0x5c08b0a663cc49d30e4e38540f6aefab19ef287c3ecd31c8d8c3decd5f5bd497",
......
...@@ -85,7 +85,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -85,7 +85,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @param _blockOracle The block oracle, used for loading block hashes further back /// @param _blockOracle The block oracle, used for loading block hashes further back
/// than the `BLOCKHASH` opcode allows as well as their estimated /// than the `BLOCKHASH` opcode allows as well as their estimated
/// timestamps. /// timestamps.
/// @custom:semver 0.0.7 /// @custom:semver 0.0.8
constructor( constructor(
GameType _gameType, GameType _gameType,
Claim _absolutePrestate, Claim _absolutePrestate,
...@@ -149,7 +149,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -149,7 +149,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// INVARIANT: The prestate is always invalid if the passed `_stateData` is not the // INVARIANT: The prestate is always invalid if the passed `_stateData` is not the
// preimage of the prestate claim hash. // preimage of the prestate claim hash.
if (keccak256(_stateData) != Claim.unwrap(preStateClaim)) revert InvalidPrestate(); // We ignore the highest order byte of the digest because it is used to
// indicate the VM Status.
if (cleanHighByte(keccak256(_stateData)) != cleanHighByte(Claim.unwrap(preStateClaim))) {
revert InvalidPrestate();
}
// INVARIANT: If a step is an attack, the poststate is valid if the step produces // INVARIANT: If a step is an attack, the poststate is valid if the step produces
// the same poststate hash as the parent claim's value. // the same poststate hash as the parent claim's value.
...@@ -434,11 +438,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -434,11 +438,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
function initialize() external { function initialize() external {
// SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and
// prevent the game from being created. // prevent the game from being created.
//
// Implicit assumptions: // Implicit assumptions:
// - The `gameStatus` state variable defaults to 0, which is `GameStatus.IN_PROGRESS` // - The `gameStatus` state variable defaults to 0, which is `GameStatus.IN_PROGRESS`
// The VMStatus must indicate (1) 'invalid', to argue that disputed thing is invalid. // The VMStatus must indicate (1) 'invalid', to argue that disputed thing is invalid.
// Games that agree with the existing outcome are not allowed. // Games that agree with the existing outcome are not allowed.
// NOTE(clabby): This assumption will change in Alpha Chad.
if (uint8(Claim.unwrap(rootClaim())[0]) != 1) revert UnexpectedRootClaim(rootClaim()); if (uint8(Claim.unwrap(rootClaim())[0]) != 1) revert UnexpectedRootClaim(rootClaim());
// Set the game's starting timestamp // Set the game's starting timestamp
...@@ -535,4 +541,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -535,4 +541,13 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
ancestor_ = claimData[ancestor_.parentIndex]; ancestor_ = claimData[ancestor_.parentIndex];
} }
} }
/// @notice Cleans the highest order byte of a given fixed bytes value.
/// @param _in The bytes32 value to clean.
/// @return out_ The cleaned bytes32 value.
function cleanHighByte(bytes32 _in) internal pure returns (bytes32 out_) {
assembly {
out_ := and(not(shl(248, 0xFF)), _in)
}
}
} }
...@@ -77,7 +77,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { ...@@ -77,7 +77,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
contract FaultDisputeGame_Test is FaultDisputeGame_Init { contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev The root claim of the game. /// @dev The root claim of the game.
Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32((uint256(1) << 248) + uint256(10))); Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32((uint256(1) << 248) | uint256(10)));
/// @dev The absolute prestate of the trace. /// @dev The absolute prestate of the trace.
Claim internal constant ABSOLUTE_PRESTATE = Claim.wrap(bytes32(uint256(0))); Claim internal constant ABSOLUTE_PRESTATE = Claim.wrap(bytes32(uint256(0)));
...@@ -609,9 +609,11 @@ contract GamePlayer { ...@@ -609,9 +609,11 @@ contract GamePlayer {
/// @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 hash =
keccak256(abi.encode(_traceIndex >= trace.length ? trace.length - 1 : _traceIndex, traceAt(_traceIndex))) keccak256(abi.encode(_traceIndex >= trace.length ? trace.length - 1 : _traceIndex, traceAt(_traceIndex)));
); assembly {
claim_ := or(and(hash, not(shl(248, 0xFF))), shl(248, 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.
...@@ -631,7 +633,7 @@ contract OneVsOne_Arena is FaultDisputeGame_Init { ...@@ -631,7 +633,7 @@ contract OneVsOne_Arena is FaultDisputeGame_Init {
GamePlayer internal challenger; GamePlayer internal challenger;
function init(GamePlayer _defender, GamePlayer _challenger, uint256 _finalTraceIndex) public { function init(GamePlayer _defender, GamePlayer _challenger, uint256 _finalTraceIndex) public {
Claim rootClaim = Claim.wrap(keccak256(abi.encode(_finalTraceIndex, _defender.traceAt(_finalTraceIndex)))); Claim rootClaim = _defender.claimAt(_finalTraceIndex);
super.init(rootClaim, ABSOLUTE_PRESTATE_CLAIM); super.init(rootClaim, ABSOLUTE_PRESTATE_CLAIM);
defender = _defender; defender = _defender;
challenger = _challenger; challenger = _challenger;
...@@ -995,5 +997,8 @@ contract AlphabetVM is IBigStepper { ...@@ -995,5 +997,8 @@ contract AlphabetVM is IBigStepper {
} }
// STF: n -> n + 1 // STF: n -> n + 1
postState_ = keccak256(abi.encode(traceIndex, claim + 1)); postState_ = keccak256(abi.encode(traceIndex, claim + 1));
assembly {
postState_ := or(and(postState_, not(shl(248, 0xFF))), shl(248, 1))
}
} }
} }
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