@arbitrum/nitro-contracts 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }