Commit 57f9bf9e authored by George Hotz's avatar George Hotz

challenge contract compiles

parent eb1f6050
Two oracles:
Implement as three MIPS instructions
One oracle:
Implement as a MIPS instruction?
InputOracle -- Preagreed upon inputs
InputOracle -- Preagreed upon inputs (TODO: replace with memory reads from given address range)
$a0 = input choice
0 -- StateRoot(n)
1 -- Transactions(n+1)
......@@ -40,21 +40,21 @@ C: InitiateChallenge(uint blockNumberN, bytes blockHeaderN, bytes blockHeaderNp1
* confirm assertionProof[8] proves the final state of $pc in finalSystemHash is 0xDEADDEAD
* L = 0, R = stepCount # we agree at L=0, we disagree at R=stepCount
* return new challengeId
* assertedRiscState[0] = GlobalStartSystemHash
* defendedRiscState[0] = GlobalStartSystemHash
* assertedRiscState[stepCount] = finalSystemHash
* assertedState[0] = GlobalStartSystemHash + inputOracleMutations
* defendedState[0] = GlobalStartSystemHash + inputOracleMutations
* assertedState[stepCount] = finalSystemHash
........
if it's one step, we are done. considering it's not, we binary search
........
C: ProposeRiscState(uint256 challengeId, uint256 riscState)
C: ProposeState(uint256 challengeId, uint256 riscState)
* stepNumber = GetStepNumber(uint256 challengeId) returns floor((L + R) / 2)
* assert assertedRiscState[stepNumber] == 0
* assertedRiscState[stepNumber] = riscState
D: RespondRiscState(uint256 challengeId, uint256 riscState) onlyOwner
* assert assertedState[stepNumber] == 0
* assertedState[stepNumber] = riscState
D: RespondState(uint256 challengeId, uint256 riscState) onlyOwner
* off-chain: run to step = stepNumber, get state hash, check if it matches
* stepNumber = GetStepNumber(uint256 challengeId) returns floor((L + R) / 2)
* defendedRiscState[stepNumber] = riscState
* if assertedRiscState[stepNumber] == defendedRiscState[stepNumber]:
* defendedState[stepNumber] = riscState
* if assertedState[stepNumber] == defendedState[stepNumber]:
L = stepNumber # we agree at stepNumber
else:
R = stepNumber # we disagree at stepNumber
......@@ -62,14 +62,14 @@ D: RespondRiscState(uint256 challengeId, uint256 riscState) onlyOwner
........
binary search until L+1 == R
the issue is with the L->R transition
aka assertedRiscState[L] -> assertedRiscState[R]
aka assertedState[L] -> assertedState[R]
........
# call this at any time (global), adds them to a preimage lookup for PreimageOracle
# put these on the MIPS contract
C: ProposePreimage(bytes anything)
C: AddPreimage(bytes anything)
* preimageLookup[keccak256(anything)] = anything
C: AddMerkleState(uint256 stateHash, uint32 addr, uint32 value, string proof)
* validate proof in assertedRiscState[stepNumber]
* validate proof in assertedState[stepNumber]
* riscMemory[stepNumber][address] = value
* Final
......@@ -77,12 +77,12 @@ C: ConfirmStateTransition(uint256 challengeId)
* assert L+1 == R
* do the state transition
* if any needed pieces of start state are missing in riscMemory, challenge fails (it can try again)
* reconstruct the riscState after transition -> newRiscState
* assert assertedRiscState[R] == newRiscState
* reconstruct the riscState after transition -> newState
* assert assertedState[R] == newState
* pay out bounty
# optional claim for the defender
# prove the defendedRiscState[L] -> defendedRiscState[R]
# NOTE, if it's the last step, defendedRiscState[R] might not exist.
# prove the defendedState[L] -> defendedState[R]
# NOTE, if it's the last step, defendedState[R] might not exist.
TODO: ensure the state merklization is canonical. if it doesn't match perfectly you can lose
\ No newline at end of file
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
interface IMIPS {
function Step(bytes32 stateHash) external view returns (bytes32);
}
contract Challenge {
address payable immutable owner;
IMIPS immutable mips;
struct Chal {
uint256 L;
uint256 R;
mapping(uint256 => bytes32) assertedState;
mapping(uint256 => bytes32) defendedState;
address payable challenger;
}
Chal[] challenges;
constructor(IMIPS imips) {
owner = msg.sender;
mips = imips;
}
// allow getting money
fallback() external payable {}
receive() external payable {}
function withdraw() external {
require(msg.sender == owner);
owner.transfer(address(this).balance);
}
function InitiateChallenge(uint blockNumberN,
bytes calldata blockHeaderN, bytes calldata blockHeaderNp1,
bytes32 assertionHash, bytes32 finalSystemHash, uint256 stepCount) external {
// is this new?
Chal storage c = challenges[challenges.length];
c.challenger = msg.sender;
// TODO: this is the function with the complexity
}
function getStepNumber(uint256 challengeId) view public returns (uint256) {
Chal storage c = challenges[challengeId];
return (c.L+c.R)/2;
}
function ProposeState(uint256 challengeId, bytes32 riscState) external {
Chal storage c = challenges[challengeId];
require(c.challenger == msg.sender, "must be challenger");
uint256 stepNumber = getStepNumber(challengeId);
require(c.assertedState[stepNumber] == bytes32(0), "state already proposed");
c.assertedState[stepNumber] = riscState;
}
function RespondState(uint256 challengeId, bytes32 riscState) external {
Chal storage c = challenges[challengeId];
require(msg.sender == owner, "must be owner");
uint256 stepNumber = getStepNumber(challengeId);
require(c.defendedState[stepNumber] == bytes32(0), "state already proposed");
// technically, we don't have to save these states
// but if we want to prove us right and not just the attacker wrong, we do
c.defendedState[stepNumber] = riscState;
if (c.assertedState[stepNumber] == c.defendedState[stepNumber]) {
// agree
c.L = stepNumber;
} else {
// disagree
c.R = stepNumber;
}
}
function ConfirmStateTransition(uint256 challengeId) external {
Chal storage c = challenges[challengeId];
require(c.challenger == msg.sender, "must be challenger");
require(c.L + 1 == c.R, "binary search not finished");
bytes32 newState = mips.Step(c.assertedState[c.L]);
require(newState == c.assertedState[c.R], "wrong asserted state");
// pay out bounty!!
msg.sender.transfer(address(this).balance);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.3;
// https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf
// https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdf
// This is a separate contract from the challenge contract
// Anyone can use it to validate a MIPS state transition
// First, to prepare, you call AddMerkleState, which adds valid state nodes in the stateHash.
// If you are using the Preimage oracle, you call AddPreimage
// Then, you call Step. Step will revert if state is missing. If all state is present, it will return the next hash
contract MIPS {
// This state is global
mapping(bytes32 => mapping (uint32 => uint64)) public state;
......@@ -33,7 +41,7 @@ contract MIPS {
// compute the next state
// will revert if any input state is missing
function Step(bytes32 stateHash) public view returns (uint64[] memory) {
function Step(bytes32 stateHash) public view returns (bytes32) {
// instruction fetch
uint32 pc = getState(stateHash, REG_PC);
uint32 insn = getState(stateHash, pc);
......
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