@arbitrum/nitro-contracts 1.0.0-beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. package/.prettierrc +5 -0
  2. package/.solhint.json +18 -0
  3. package/deploy/BridgeStubCreator.js +10 -0
  4. package/deploy/HashProofHelper.js +13 -0
  5. package/deploy/InboxStubCreator.js +17 -0
  6. package/deploy/OneStepProofEntryCreator.js +19 -0
  7. package/deploy/OneStepProver0Creator.js +14 -0
  8. package/deploy/OneStepProverHostIoCreator.js +14 -0
  9. package/deploy/OneStepProverMathCreator.js +14 -0
  10. package/deploy/OneStepProverMemoryCreator.js +14 -0
  11. package/deploy/SequencerInboxStubCreator.js +13 -0
  12. package/deploy/ValueArrayTesterCreator.js +13 -0
  13. package/hardhat.config.ts +47 -0
  14. package/hardhat.prod-config.js +18 -0
  15. package/package.json +49 -0
  16. package/scripts/build.bash +5 -0
  17. package/src/bridge/Bridge.sol +168 -0
  18. package/src/bridge/IBridge.sol +68 -0
  19. package/src/bridge/IInbox.sol +80 -0
  20. package/src/bridge/IMessageProvider.sol +11 -0
  21. package/src/bridge/IOutbox.sol +52 -0
  22. package/src/bridge/ISequencerInbox.sol +85 -0
  23. package/src/bridge/Inbox.sol +414 -0
  24. package/src/bridge/Messages.sol +38 -0
  25. package/src/bridge/Outbox.sol +188 -0
  26. package/src/bridge/SequencerInbox.sol +274 -0
  27. package/src/challenge/ChallengeLib.sol +135 -0
  28. package/src/challenge/ChallengeManager.sol +367 -0
  29. package/src/challenge/IChallengeManager.sol +75 -0
  30. package/src/challenge/IChallengeResultReceiver.sol +13 -0
  31. package/src/libraries/AddressAliasHelper.sol +29 -0
  32. package/src/libraries/AdminFallbackProxy.sol +153 -0
  33. package/src/libraries/ArbitrumProxy.sol +20 -0
  34. package/src/libraries/Constants.sol +10 -0
  35. package/src/libraries/CryptographyPrimitives.sol +323 -0
  36. package/src/libraries/DelegateCallAware.sol +44 -0
  37. package/src/libraries/Error.sol +38 -0
  38. package/src/libraries/IGasRefunder.sol +35 -0
  39. package/src/libraries/MerkleLib.sol +46 -0
  40. package/src/libraries/MessageTypes.sol +14 -0
  41. package/src/libraries/SecondaryLogicUUPSUpgradeable.sol +58 -0
  42. package/src/libraries/UUPSNotUpgradeable.sol +56 -0
  43. package/src/mocks/BridgeStub.sol +115 -0
  44. package/src/mocks/Counter.sol +13 -0
  45. package/src/mocks/ExecutionManager.sol +41 -0
  46. package/src/mocks/InboxStub.sol +131 -0
  47. package/src/mocks/MockResultReceiver.sol +59 -0
  48. package/src/mocks/SequencerInboxStub.sol +42 -0
  49. package/src/mocks/SimpleProxy.sol +19 -0
  50. package/src/node-interface/NodeInterface.sol +50 -0
  51. package/src/osp/HashProofHelper.sol +154 -0
  52. package/src/osp/IOneStepProofEntry.sol +20 -0
  53. package/src/osp/IOneStepProver.sol +27 -0
  54. package/src/osp/OneStepProofEntry.sol +129 -0
  55. package/src/osp/OneStepProver0.sol +566 -0
  56. package/src/osp/OneStepProverHostIo.sol +357 -0
  57. package/src/osp/OneStepProverMath.sol +514 -0
  58. package/src/osp/OneStepProverMemory.sol +313 -0
  59. package/src/precompiles/ArbAddressTable.sol +60 -0
  60. package/src/precompiles/ArbAggregator.sol +62 -0
  61. package/src/precompiles/ArbBLS.sol +53 -0
  62. package/src/precompiles/ArbDebug.sol +39 -0
  63. package/src/precompiles/ArbFunctionTable.sol +29 -0
  64. package/src/precompiles/ArbGasInfo.sol +121 -0
  65. package/src/precompiles/ArbInfo.sol +15 -0
  66. package/src/precompiles/ArbOwner.sol +65 -0
  67. package/src/precompiles/ArbOwnerPublic.sol +18 -0
  68. package/src/precompiles/ArbRetryableTx.sol +89 -0
  69. package/src/precompiles/ArbStatistics.sol +29 -0
  70. package/src/precompiles/ArbSys.sol +134 -0
  71. package/src/precompiles/ArbosActs.sol +41 -0
  72. package/src/precompiles/ArbosTest.sol +14 -0
  73. package/src/rollup/BridgeCreator.sol +120 -0
  74. package/src/rollup/IRollupCore.sol +152 -0
  75. package/src/rollup/IRollupLogic.sol +183 -0
  76. package/src/rollup/Node.sol +99 -0
  77. package/src/rollup/RollupAdminLogic.sol +322 -0
  78. package/src/rollup/RollupCore.sol +627 -0
  79. package/src/rollup/RollupCreator.sol +133 -0
  80. package/src/rollup/RollupEventBridge.sol +46 -0
  81. package/src/rollup/RollupLib.sol +135 -0
  82. package/src/rollup/RollupUserLogic.sol +712 -0
  83. package/src/rollup/ValidatorUtils.sol +243 -0
  84. package/src/rollup/ValidatorWallet.sol +76 -0
  85. package/src/rollup/ValidatorWalletCreator.sol +43 -0
  86. package/src/state/Deserialize.sol +321 -0
  87. package/src/state/GlobalState.sol +44 -0
  88. package/src/state/Instructions.sol +159 -0
  89. package/src/state/Machine.sol +65 -0
  90. package/src/state/MerkleProof.sol +99 -0
  91. package/src/state/Module.sol +33 -0
  92. package/src/state/ModuleMemory.sol +42 -0
  93. package/src/state/PcArray.sol +45 -0
  94. package/src/state/PcStack.sol +32 -0
  95. package/src/state/StackFrame.sol +63 -0
  96. package/src/state/Value.sol +65 -0
  97. package/src/state/ValueArray.sol +47 -0
  98. package/src/state/ValueStack.sol +39 -0
  99. package/src/test-helpers/CryptographyPrimitivesTester.sol +27 -0
  100. package/src/test-helpers/MessageTester.sol +34 -0
  101. package/src/test-helpers/ValueArrayTester.sol +34 -0
  102. package/test/contract/arbRollup.spec.ts +869 -0
  103. package/test/contract/common/challengeLib.ts +43 -0
  104. package/test/contract/common/globalStateLib.ts +17 -0
  105. package/test/contract/common/rolluplib.ts +259 -0
  106. package/test/contract/cryptographyPrimitives.spec.ts +82 -0
  107. package/test/contract/sequencerInboxForceInclude.spec.ts +516 -0
  108. package/test/contract/utils.ts +40 -0
  109. package/test/prover/hash-proofs.ts +75 -0
  110. package/test/prover/one-step-proof.ts +93 -0
  111. package/test/prover/proofs/.gitkeep +0 -0
  112. package/test/prover/value-arrays.ts +11 -0
  113. package/tsconfig.json +13 -0
@@ -0,0 +1,129 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ import "../state/Deserialize.sol";
8
+ import "../state/Machine.sol";
9
+ import "../state/MerkleProof.sol";
10
+ import "./IOneStepProver.sol";
11
+ import "./IOneStepProofEntry.sol";
12
+
13
+ contract OneStepProofEntry is IOneStepProofEntry {
14
+ using MerkleProofLib for MerkleProof;
15
+ using MachineLib for Machine;
16
+
17
+ IOneStepProver public prover0;
18
+ IOneStepProver public proverMem;
19
+ IOneStepProver public proverMath;
20
+ IOneStepProver public proverHostIo;
21
+
22
+ constructor(
23
+ IOneStepProver prover0_,
24
+ IOneStepProver proverMem_,
25
+ IOneStepProver proverMath_,
26
+ IOneStepProver proverHostIo_
27
+ ) {
28
+ prover0 = prover0_;
29
+ proverMem = proverMem_;
30
+ proverMath = proverMath_;
31
+ proverHostIo = proverHostIo_;
32
+ }
33
+
34
+ function proveOneStep(
35
+ ExecutionContext calldata execCtx,
36
+ uint256 machineStep,
37
+ bytes32 beforeHash,
38
+ bytes calldata proof
39
+ ) external view override returns (bytes32 afterHash) {
40
+ Machine memory mach;
41
+ Module memory mod;
42
+ MerkleProof memory modProof;
43
+ Instruction memory inst;
44
+
45
+ {
46
+ uint256 offset = 0;
47
+ (mach, offset) = Deserialize.machine(proof, offset);
48
+ require(mach.hash() == beforeHash, "MACHINE_BEFORE_HASH");
49
+ if (mach.status != MachineStatus.RUNNING) {
50
+ // Machine is halted.
51
+ // WARNING: at this point, most machine fields are unconstrained.
52
+ return mach.hash();
53
+ }
54
+
55
+ if (machineStep + 1 == OneStepProofEntryLib.MAX_STEPS) {
56
+ mach.status = MachineStatus.ERRORED;
57
+ return mach.hash();
58
+ }
59
+
60
+ (mod, offset) = Deserialize.module(proof, offset);
61
+ (modProof, offset) = Deserialize.merkleProof(proof, offset);
62
+ require(
63
+ modProof.computeRootFromModule(mach.moduleIdx, mod) == mach.modulesRoot,
64
+ "MODULES_ROOT"
65
+ );
66
+
67
+ {
68
+ MerkleProof memory instProof;
69
+ MerkleProof memory funcProof;
70
+ (inst, offset) = Deserialize.instruction(proof, offset);
71
+ (instProof, offset) = Deserialize.merkleProof(proof, offset);
72
+ (funcProof, offset) = Deserialize.merkleProof(proof, offset);
73
+ bytes32 codeHash = instProof.computeRootFromInstruction(mach.functionPc, inst);
74
+ bytes32 recomputedRoot = funcProof.computeRootFromFunction(
75
+ mach.functionIdx,
76
+ codeHash
77
+ );
78
+ require(recomputedRoot == mod.functionsMerkleRoot, "BAD_FUNCTIONS_ROOT");
79
+ }
80
+ proof = proof[offset:];
81
+ }
82
+
83
+ uint256 oldModIdx = mach.moduleIdx;
84
+ mach.functionPc += 1;
85
+ uint16 opcode = inst.opcode;
86
+ IOneStepProver prover;
87
+ if (
88
+ (opcode >= Instructions.I32_LOAD && opcode <= Instructions.I64_LOAD32_U) ||
89
+ (opcode >= Instructions.I32_STORE && opcode <= Instructions.I64_STORE32) ||
90
+ opcode == Instructions.MEMORY_SIZE ||
91
+ opcode == Instructions.MEMORY_GROW
92
+ ) {
93
+ prover = proverMem;
94
+ } else if (
95
+ (opcode == Instructions.I32_EQZ || opcode == Instructions.I64_EQZ) ||
96
+ (opcode >= Instructions.I32_RELOP_BASE &&
97
+ opcode <= Instructions.I32_RELOP_BASE + Instructions.IRELOP_LAST) ||
98
+ (opcode >= Instructions.I32_UNOP_BASE &&
99
+ opcode <= Instructions.I32_UNOP_BASE + Instructions.IUNOP_LAST) ||
100
+ (opcode >= Instructions.I32_ADD && opcode <= Instructions.I32_ROTR) ||
101
+ (opcode >= Instructions.I64_RELOP_BASE &&
102
+ opcode <= Instructions.I64_RELOP_BASE + Instructions.IRELOP_LAST) ||
103
+ (opcode >= Instructions.I64_UNOP_BASE &&
104
+ opcode <= Instructions.I64_UNOP_BASE + Instructions.IUNOP_LAST) ||
105
+ (opcode >= Instructions.I64_ADD && opcode <= Instructions.I64_ROTR) ||
106
+ (opcode == Instructions.I32_WRAP_I64) ||
107
+ (opcode == Instructions.I64_EXTEND_I32_S || opcode == Instructions.I64_EXTEND_I32_U) ||
108
+ (opcode >= Instructions.I32_EXTEND_8S && opcode <= Instructions.I64_EXTEND_32S) ||
109
+ (opcode >= Instructions.I32_REINTERPRET_F32 &&
110
+ opcode <= Instructions.F64_REINTERPRET_I64)
111
+ ) {
112
+ prover = proverMath;
113
+ } else if (
114
+ (opcode >= Instructions.GET_GLOBAL_STATE_BYTES32 &&
115
+ opcode <= Instructions.SET_GLOBAL_STATE_U64) ||
116
+ (opcode >= Instructions.READ_PRE_IMAGE && opcode <= Instructions.HALT_AND_SET_FINISHED)
117
+ ) {
118
+ prover = proverHostIo;
119
+ } else {
120
+ prover = prover0;
121
+ }
122
+
123
+ (mach, mod) = prover.executeOneStep(execCtx, mach, mod, inst, proof);
124
+
125
+ mach.modulesRoot = modProof.computeRootFromModule(oldModIdx, mod);
126
+
127
+ return mach.hash();
128
+ }
129
+ }
@@ -0,0 +1,566 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ import "../state/Value.sol";
8
+ import "../state/Machine.sol";
9
+ import "../state/Module.sol";
10
+ import "../state/Deserialize.sol";
11
+ import "./IOneStepProver.sol";
12
+
13
+ contract OneStepProver0 is IOneStepProver {
14
+ using MerkleProofLib for MerkleProof;
15
+ using PcStackLib for PcStack;
16
+ using StackFrameLib for StackFrameWindow;
17
+ using ValueLib for Value;
18
+ using ValueStackLib for ValueStack;
19
+
20
+ function executeUnreachable(
21
+ Machine memory mach,
22
+ Module memory,
23
+ Instruction calldata,
24
+ bytes calldata
25
+ ) internal pure {
26
+ mach.status = MachineStatus.ERRORED;
27
+ }
28
+
29
+ function executeNop(
30
+ Machine memory mach,
31
+ Module memory,
32
+ Instruction calldata,
33
+ bytes calldata
34
+ ) internal pure {
35
+ // :)
36
+ }
37
+
38
+ function executeConstPush(
39
+ Machine memory mach,
40
+ Module memory,
41
+ Instruction calldata inst,
42
+ bytes calldata
43
+ ) internal pure {
44
+ uint16 opcode = inst.opcode;
45
+ ValueType ty;
46
+ if (opcode == Instructions.I32_CONST) {
47
+ ty = ValueType.I32;
48
+ } else if (opcode == Instructions.I64_CONST) {
49
+ ty = ValueType.I64;
50
+ } else if (opcode == Instructions.F32_CONST) {
51
+ ty = ValueType.F32;
52
+ } else if (opcode == Instructions.F64_CONST) {
53
+ ty = ValueType.F64;
54
+ } else if (opcode == Instructions.PUSH_STACK_BOUNDARY) {
55
+ ty = ValueType.STACK_BOUNDARY;
56
+ } else {
57
+ revert("CONST_PUSH_INVALID_OPCODE");
58
+ }
59
+
60
+ mach.valueStack.push(Value({valueType: ty, contents: uint64(inst.argumentData)}));
61
+ }
62
+
63
+ function executeDrop(
64
+ Machine memory mach,
65
+ Module memory,
66
+ Instruction calldata,
67
+ bytes calldata
68
+ ) internal pure {
69
+ mach.valueStack.pop();
70
+ }
71
+
72
+ function executeSelect(
73
+ Machine memory mach,
74
+ Module memory,
75
+ Instruction calldata,
76
+ bytes calldata
77
+ ) internal pure {
78
+ uint32 selector = mach.valueStack.pop().assumeI32();
79
+ Value memory b = mach.valueStack.pop();
80
+ Value memory a = mach.valueStack.pop();
81
+
82
+ if (selector != 0) {
83
+ mach.valueStack.push(a);
84
+ } else {
85
+ mach.valueStack.push(b);
86
+ }
87
+ }
88
+
89
+ function executeBlock(
90
+ Machine memory mach,
91
+ Module memory,
92
+ Instruction calldata inst,
93
+ bytes calldata
94
+ ) internal pure {
95
+ uint32 targetPc = uint32(inst.argumentData);
96
+ require(targetPc == inst.argumentData, "BAD_BLOCK_PC");
97
+ mach.blockStack.push(targetPc);
98
+ }
99
+
100
+ function executeBranch(
101
+ Machine memory mach,
102
+ Module memory,
103
+ Instruction calldata,
104
+ bytes calldata
105
+ ) internal pure {
106
+ mach.functionPc = mach.blockStack.pop();
107
+ }
108
+
109
+ function executeBranchIf(
110
+ Machine memory mach,
111
+ Module memory,
112
+ Instruction calldata,
113
+ bytes calldata
114
+ ) internal pure {
115
+ uint32 cond = mach.valueStack.pop().assumeI32();
116
+ if (cond != 0) {
117
+ // Jump to target
118
+ mach.functionPc = mach.blockStack.pop();
119
+ }
120
+ }
121
+
122
+ function executeReturn(
123
+ Machine memory mach,
124
+ Module memory,
125
+ Instruction calldata,
126
+ bytes calldata
127
+ ) internal pure {
128
+ StackFrame memory frame = mach.frameStack.pop();
129
+ if (frame.returnPc.valueType == ValueType.REF_NULL) {
130
+ mach.status = MachineStatus.ERRORED;
131
+ return;
132
+ } else if (frame.returnPc.valueType != ValueType.INTERNAL_REF) {
133
+ revert("INVALID_RETURN_PC_TYPE");
134
+ }
135
+ uint256 data = frame.returnPc.contents;
136
+ uint32 pc = uint32(data);
137
+ uint32 func = uint32(data >> 32);
138
+ uint32 mod = uint32(data >> 64);
139
+ require(data >> 96 == 0, "INVALID_RETURN_PC_DATA");
140
+ mach.functionPc = pc;
141
+ mach.functionIdx = func;
142
+ mach.moduleIdx = mod;
143
+ }
144
+
145
+ function createReturnValue(Machine memory mach) internal pure returns (Value memory) {
146
+ uint256 returnData = 0;
147
+ returnData |= mach.functionPc;
148
+ returnData |= uint256(mach.functionIdx) << 32;
149
+ returnData |= uint256(mach.moduleIdx) << 64;
150
+ return Value({valueType: ValueType.INTERNAL_REF, contents: returnData});
151
+ }
152
+
153
+ function executeCall(
154
+ Machine memory mach,
155
+ Module memory,
156
+ Instruction calldata inst,
157
+ bytes calldata
158
+ ) internal pure {
159
+ // Push the return pc to the stack
160
+ mach.valueStack.push(createReturnValue(mach));
161
+
162
+ // Push caller module info to the stack
163
+ StackFrame memory frame = mach.frameStack.peek();
164
+ mach.valueStack.push(ValueLib.newI32(frame.callerModule));
165
+ mach.valueStack.push(ValueLib.newI32(frame.callerModuleInternals));
166
+
167
+ // Jump to the target
168
+ uint32 idx = uint32(inst.argumentData);
169
+ require(idx == inst.argumentData, "BAD_CALL_DATA");
170
+ mach.functionIdx = idx;
171
+ mach.functionPc = 0;
172
+ }
173
+
174
+ function executeCrossModuleCall(
175
+ Machine memory mach,
176
+ Module memory mod,
177
+ Instruction calldata inst,
178
+ bytes calldata
179
+ ) internal pure {
180
+ // Push the return pc to the stack
181
+ mach.valueStack.push(createReturnValue(mach));
182
+
183
+ // Push caller module info to the stack
184
+ mach.valueStack.push(ValueLib.newI32(mach.moduleIdx));
185
+ mach.valueStack.push(ValueLib.newI32(mod.internalsOffset));
186
+
187
+ // Jump to the target
188
+ uint32 func = uint32(inst.argumentData);
189
+ uint32 module = uint32(inst.argumentData >> 32);
190
+ require(inst.argumentData >> 64 == 0, "BAD_CROSS_MODULE_CALL_DATA");
191
+ mach.moduleIdx = module;
192
+ mach.functionIdx = func;
193
+ mach.functionPc = 0;
194
+ }
195
+
196
+ function executeCallerModuleInternalCall(
197
+ Machine memory mach,
198
+ Module memory mod,
199
+ Instruction calldata inst,
200
+ bytes calldata
201
+ ) internal pure {
202
+ // Push the return pc to the stack
203
+ mach.valueStack.push(createReturnValue(mach));
204
+
205
+ // Push caller module info to the stack
206
+ mach.valueStack.push(ValueLib.newI32(mach.moduleIdx));
207
+ mach.valueStack.push(ValueLib.newI32(mod.internalsOffset));
208
+
209
+ StackFrame memory frame = mach.frameStack.peek();
210
+ if (frame.callerModuleInternals == 0) {
211
+ // The caller module has no internals
212
+ mach.status = MachineStatus.ERRORED;
213
+ return;
214
+ }
215
+
216
+ // Jump to the target
217
+ uint32 offset = uint32(inst.argumentData);
218
+ require(offset == inst.argumentData, "BAD_CALLER_INTERNAL_CALL_DATA");
219
+ mach.moduleIdx = frame.callerModule;
220
+ mach.functionIdx = frame.callerModuleInternals + offset;
221
+ mach.functionPc = 0;
222
+ }
223
+
224
+ function executeCallIndirect(
225
+ Machine memory mach,
226
+ Module memory mod,
227
+ Instruction calldata inst,
228
+ bytes calldata proof
229
+ ) internal pure {
230
+ uint32 funcIdx;
231
+ {
232
+ uint32 elementIdx = mach.valueStack.pop().assumeI32();
233
+
234
+ // Prove metadata about the instruction and tables
235
+ bytes32 elemsRoot;
236
+ bytes32 wantedFuncTypeHash;
237
+ uint256 offset = 0;
238
+ {
239
+ uint64 tableIdx;
240
+ uint8 tableType;
241
+ uint64 tableSize;
242
+ MerkleProof memory tableMerkleProof;
243
+ (tableIdx, offset) = Deserialize.u64(proof, offset);
244
+ (wantedFuncTypeHash, offset) = Deserialize.b32(proof, offset);
245
+ (tableType, offset) = Deserialize.u8(proof, offset);
246
+ (tableSize, offset) = Deserialize.u64(proof, offset);
247
+ (elemsRoot, offset) = Deserialize.b32(proof, offset);
248
+ (tableMerkleProof, offset) = Deserialize.merkleProof(proof, offset);
249
+
250
+ // Validate the information by recomputing known hashes
251
+ bytes32 recomputed = keccak256(
252
+ abi.encodePacked("Call indirect:", tableIdx, wantedFuncTypeHash)
253
+ );
254
+ require(recomputed == bytes32(inst.argumentData), "BAD_CALL_INDIRECT_DATA");
255
+ recomputed = tableMerkleProof.computeRootFromTable(
256
+ tableIdx,
257
+ tableType,
258
+ tableSize,
259
+ elemsRoot
260
+ );
261
+ require(recomputed == mod.tablesMerkleRoot, "BAD_TABLES_ROOT");
262
+
263
+ // Check if the table access is out of bounds
264
+ if (elementIdx >= tableSize) {
265
+ mach.status = MachineStatus.ERRORED;
266
+ return;
267
+ }
268
+ }
269
+
270
+ bytes32 elemFuncTypeHash;
271
+ Value memory functionPointer;
272
+ MerkleProof memory elementMerkleProof;
273
+ (elemFuncTypeHash, offset) = Deserialize.b32(proof, offset);
274
+ (functionPointer, offset) = Deserialize.value(proof, offset);
275
+ (elementMerkleProof, offset) = Deserialize.merkleProof(proof, offset);
276
+ bytes32 recomputedElemRoot = elementMerkleProof.computeRootFromElement(
277
+ elementIdx,
278
+ elemFuncTypeHash,
279
+ functionPointer
280
+ );
281
+ require(recomputedElemRoot == elemsRoot, "BAD_ELEMENTS_ROOT");
282
+
283
+ if (elemFuncTypeHash != wantedFuncTypeHash) {
284
+ mach.status = MachineStatus.ERRORED;
285
+ return;
286
+ }
287
+
288
+ if (functionPointer.valueType == ValueType.REF_NULL) {
289
+ mach.status = MachineStatus.ERRORED;
290
+ return;
291
+ } else if (functionPointer.valueType == ValueType.FUNC_REF) {
292
+ funcIdx = uint32(functionPointer.contents);
293
+ require(funcIdx == functionPointer.contents, "BAD_FUNC_REF_CONTENTS");
294
+ } else {
295
+ revert("BAD_ELEM_TYPE");
296
+ }
297
+ }
298
+
299
+ // Push the return pc to the stack
300
+ mach.valueStack.push(createReturnValue(mach));
301
+
302
+ // Push caller module info to the stack
303
+ StackFrame memory frame = mach.frameStack.peek();
304
+ mach.valueStack.push(ValueLib.newI32(frame.callerModule));
305
+ mach.valueStack.push(ValueLib.newI32(frame.callerModuleInternals));
306
+
307
+ // Jump to the target
308
+ mach.functionIdx = funcIdx;
309
+ mach.functionPc = 0;
310
+ }
311
+
312
+ function executeArbitraryJumpIf(
313
+ Machine memory mach,
314
+ Module memory,
315
+ Instruction calldata inst,
316
+ bytes calldata
317
+ ) internal pure {
318
+ uint32 cond = mach.valueStack.pop().assumeI32();
319
+ if (cond != 0) {
320
+ // Jump to target
321
+ uint32 pc = uint32(inst.argumentData);
322
+ require(pc == inst.argumentData, "BAD_CALL_DATA");
323
+ mach.functionPc = pc;
324
+ }
325
+ }
326
+
327
+ function merkleProveGetValue(
328
+ bytes32 merkleRoot,
329
+ uint256 index,
330
+ bytes calldata proof
331
+ ) internal pure returns (Value memory) {
332
+ uint256 offset = 0;
333
+ Value memory proposedVal;
334
+ MerkleProof memory merkle;
335
+ (proposedVal, offset) = Deserialize.value(proof, offset);
336
+ (merkle, offset) = Deserialize.merkleProof(proof, offset);
337
+ bytes32 recomputedRoot = merkle.computeRootFromValue(index, proposedVal);
338
+ require(recomputedRoot == merkleRoot, "WRONG_MERKLE_ROOT");
339
+ return proposedVal;
340
+ }
341
+
342
+ function merkleProveSetValue(
343
+ bytes32 merkleRoot,
344
+ uint256 index,
345
+ Value memory newVal,
346
+ bytes calldata proof
347
+ ) internal pure returns (bytes32) {
348
+ Value memory oldVal;
349
+ uint256 offset = 0;
350
+ MerkleProof memory merkle;
351
+ (oldVal, offset) = Deserialize.value(proof, offset);
352
+ (merkle, offset) = Deserialize.merkleProof(proof, offset);
353
+ bytes32 recomputedRoot = merkle.computeRootFromValue(index, oldVal);
354
+ require(recomputedRoot == merkleRoot, "WRONG_MERKLE_ROOT");
355
+ return merkle.computeRootFromValue(index, newVal);
356
+ }
357
+
358
+ function executeLocalGet(
359
+ Machine memory mach,
360
+ Module memory,
361
+ Instruction calldata inst,
362
+ bytes calldata proof
363
+ ) internal pure {
364
+ StackFrame memory frame = mach.frameStack.peek();
365
+ Value memory val = merkleProveGetValue(frame.localsMerkleRoot, inst.argumentData, proof);
366
+ mach.valueStack.push(val);
367
+ }
368
+
369
+ function executeLocalSet(
370
+ Machine memory mach,
371
+ Module memory,
372
+ Instruction calldata inst,
373
+ bytes calldata proof
374
+ ) internal pure {
375
+ Value memory newVal = mach.valueStack.pop();
376
+ StackFrame memory frame = mach.frameStack.peek();
377
+ frame.localsMerkleRoot = merkleProveSetValue(
378
+ frame.localsMerkleRoot,
379
+ inst.argumentData,
380
+ newVal,
381
+ proof
382
+ );
383
+ }
384
+
385
+ function executeGlobalGet(
386
+ Machine memory mach,
387
+ Module memory mod,
388
+ Instruction calldata inst,
389
+ bytes calldata proof
390
+ ) internal pure {
391
+ Value memory val = merkleProveGetValue(mod.globalsMerkleRoot, inst.argumentData, proof);
392
+ mach.valueStack.push(val);
393
+ }
394
+
395
+ function executeGlobalSet(
396
+ Machine memory mach,
397
+ Module memory mod,
398
+ Instruction calldata inst,
399
+ bytes calldata proof
400
+ ) internal pure {
401
+ Value memory newVal = mach.valueStack.pop();
402
+ mod.globalsMerkleRoot = merkleProveSetValue(
403
+ mod.globalsMerkleRoot,
404
+ inst.argumentData,
405
+ newVal,
406
+ proof
407
+ );
408
+ }
409
+
410
+ function executeEndBlock(
411
+ Machine memory mach,
412
+ Module memory,
413
+ Instruction calldata,
414
+ bytes calldata
415
+ ) internal pure {
416
+ mach.blockStack.pop();
417
+ }
418
+
419
+ function executeEndBlockIf(
420
+ Machine memory mach,
421
+ Module memory,
422
+ Instruction calldata,
423
+ bytes calldata
424
+ ) internal pure {
425
+ uint32 cond = mach.valueStack.peek().assumeI32();
426
+ if (cond != 0) {
427
+ mach.blockStack.pop();
428
+ }
429
+ }
430
+
431
+ function executeInitFrame(
432
+ Machine memory mach,
433
+ Module memory,
434
+ Instruction calldata inst,
435
+ bytes calldata
436
+ ) internal pure {
437
+ Value memory callerModuleInternals = mach.valueStack.pop();
438
+ Value memory callerModule = mach.valueStack.pop();
439
+ Value memory returnPc = mach.valueStack.pop();
440
+ StackFrame memory newFrame = StackFrame({
441
+ returnPc: returnPc,
442
+ localsMerkleRoot: bytes32(inst.argumentData),
443
+ callerModule: callerModule.assumeI32(),
444
+ callerModuleInternals: callerModuleInternals.assumeI32()
445
+ });
446
+ mach.frameStack.push(newFrame);
447
+ }
448
+
449
+ function executeMoveInternal(
450
+ Machine memory mach,
451
+ Module memory,
452
+ Instruction calldata inst,
453
+ bytes calldata
454
+ ) internal pure {
455
+ Value memory val;
456
+ if (inst.opcode == Instructions.MOVE_FROM_STACK_TO_INTERNAL) {
457
+ val = mach.valueStack.pop();
458
+ mach.internalStack.push(val);
459
+ } else if (inst.opcode == Instructions.MOVE_FROM_INTERNAL_TO_STACK) {
460
+ val = mach.internalStack.pop();
461
+ mach.valueStack.push(val);
462
+ } else {
463
+ revert("MOVE_INTERNAL_INVALID_OPCODE");
464
+ }
465
+ }
466
+
467
+ function executeIsStackBoundary(
468
+ Machine memory mach,
469
+ Module memory,
470
+ Instruction calldata,
471
+ bytes calldata
472
+ ) internal pure {
473
+ Value memory val = mach.valueStack.pop();
474
+ uint32 newContents = 0;
475
+ if (val.valueType == ValueType.STACK_BOUNDARY) {
476
+ newContents = 1;
477
+ }
478
+ mach.valueStack.push(ValueLib.newI32(newContents));
479
+ }
480
+
481
+ function executeDup(
482
+ Machine memory mach,
483
+ Module memory,
484
+ Instruction calldata,
485
+ bytes calldata
486
+ ) internal pure {
487
+ Value memory val = mach.valueStack.peek();
488
+ mach.valueStack.push(val);
489
+ }
490
+
491
+ function executeOneStep(
492
+ ExecutionContext calldata,
493
+ Machine calldata startMach,
494
+ Module calldata startMod,
495
+ Instruction calldata inst,
496
+ bytes calldata proof
497
+ ) external pure override returns (Machine memory mach, Module memory mod) {
498
+ mach = startMach;
499
+ mod = startMod;
500
+
501
+ uint16 opcode = inst.opcode;
502
+
503
+ function(Machine memory, Module memory, Instruction calldata, bytes calldata)
504
+ internal
505
+ pure impl;
506
+ if (opcode == Instructions.UNREACHABLE) {
507
+ impl = executeUnreachable;
508
+ } else if (opcode == Instructions.NOP) {
509
+ impl = executeNop;
510
+ } else if (opcode == Instructions.BLOCK) {
511
+ impl = executeBlock;
512
+ } else if (opcode == Instructions.BRANCH) {
513
+ impl = executeBranch;
514
+ } else if (opcode == Instructions.BRANCH_IF) {
515
+ impl = executeBranchIf;
516
+ } else if (opcode == Instructions.RETURN) {
517
+ impl = executeReturn;
518
+ } else if (opcode == Instructions.CALL) {
519
+ impl = executeCall;
520
+ } else if (opcode == Instructions.CROSS_MODULE_CALL) {
521
+ impl = executeCrossModuleCall;
522
+ } else if (opcode == Instructions.CALLER_MODULE_INTERNAL_CALL) {
523
+ impl = executeCallerModuleInternalCall;
524
+ } else if (opcode == Instructions.CALL_INDIRECT) {
525
+ impl = executeCallIndirect;
526
+ } else if (opcode == Instructions.END_BLOCK) {
527
+ impl = executeEndBlock;
528
+ } else if (opcode == Instructions.END_BLOCK_IF) {
529
+ impl = executeEndBlockIf;
530
+ } else if (opcode == Instructions.ARBITRARY_JUMP_IF) {
531
+ impl = executeArbitraryJumpIf;
532
+ } else if (opcode == Instructions.LOCAL_GET) {
533
+ impl = executeLocalGet;
534
+ } else if (opcode == Instructions.LOCAL_SET) {
535
+ impl = executeLocalSet;
536
+ } else if (opcode == Instructions.GLOBAL_GET) {
537
+ impl = executeGlobalGet;
538
+ } else if (opcode == Instructions.GLOBAL_SET) {
539
+ impl = executeGlobalSet;
540
+ } else if (opcode == Instructions.INIT_FRAME) {
541
+ impl = executeInitFrame;
542
+ } else if (opcode == Instructions.DROP) {
543
+ impl = executeDrop;
544
+ } else if (opcode == Instructions.SELECT) {
545
+ impl = executeSelect;
546
+ } else if (
547
+ (opcode >= Instructions.I32_CONST && opcode <= Instructions.F64_CONST) ||
548
+ opcode == Instructions.PUSH_STACK_BOUNDARY
549
+ ) {
550
+ impl = executeConstPush;
551
+ } else if (
552
+ opcode == Instructions.MOVE_FROM_STACK_TO_INTERNAL ||
553
+ opcode == Instructions.MOVE_FROM_INTERNAL_TO_STACK
554
+ ) {
555
+ impl = executeMoveInternal;
556
+ } else if (opcode == Instructions.IS_STACK_BOUNDARY) {
557
+ impl = executeIsStackBoundary;
558
+ } else if (opcode == Instructions.DUP) {
559
+ impl = executeDup;
560
+ } else {
561
+ revert("INVALID_OPCODE");
562
+ }
563
+
564
+ impl(mach, mod, inst, proof);
565
+ }
566
+ }