forked from ethereum-optimism/cannon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCHALLENGE
90 lines (81 loc) · 3.46 KB
/
CHALLENGE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
One oracle:
Implement as a MIPS instruction?
InputOracle -- Preagreed upon inputs (TODO: replace with memory reads from given address range)
$a0 = input choice
0 -- BlockHash(n)
1 -- Transactions(n+1)
2 -- Coinbase(n+1)
3 -- Uncles(n+1)
$a1 = shift amount
returns
$v0 = inputs[$a0] >> $a1
This has been changed to an MMIO oracle
hash at 0x30001000 loads len at 0x31000000 and data at 0x31000004
PreimageOracle -- key value store
$a0 = dword index in value
$t0 = hash[31:0]
$t1 = hash[63:32]
$t2 = hash[95:64]
$t3 = hash[127:96]
$t4 = hash[159:128]
$t5 = hash[191:160]
$t6 = hash[223:192]
$t7 = hash[255:224]
returns
$v0 = preimage[$t7...$t0] >> ($a0 * 32)
Program returns a hash in mem(0x30000800) and exits(jump to 0x5EAD0000) with the hash in the state
Challenge Flow:
C is challenger, D is defender
Super nice, the defender barely needs to spend gas!
C: InitiateChallenge(uint blockNumberN, bytes blockHeaderN, bytes blockHeaderNp1,
bytes32 assertionHash, bytes32 finalSystemHash, string[] assertionProof, uint256 stepCount)
* checks hashes of the block headers
* saves inputs for input oracle
* confirms assertionHash != blockHeaderNp1.Hash
* confirm assertionProof[0..7] proves the final state of [$t7...$t0] in finalSystemHash is assertionHash
* confirm assertionProof[8] proves the final state of $pc in finalSystemHash is 0x5EAD0000
* L = 0, R = stepCount # we agree at L=0, we disagree at R=stepCount
* return new challengeId
* 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: ProposeState(uint256 challengeId, uint256 riscState)
* stepNumber = GetStepNumber(uint256 challengeId) returns floor((L + R) / 2)
* 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)
* defendedState[stepNumber] = riscState
* if assertedState[stepNumber] == defendedState[stepNumber]:
L = stepNumber # we agree at stepNumber
else:
R = stepNumber # we disagree at stepNumber
# issue is between [L...R]
........
binary search until L+1 == R
the issue is with the L->R transition
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: AddPreimage(bytes anything)
* preimageLookup[keccak256(anything)] = anything
C: AddMerkleState(uint256 stateHash, uint32 addr, uint32 value, string proof)
* validate proof in assertedState[stepNumber]
* riscMemory[stepNumber][address] = value
* Final
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 -> newState
* assert assertedState[R] == newState
* pay out bounty
# optional claim for the defender
# 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