@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,243 @@
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
+ pragma experimental ABIEncoderV2;
8
+
9
+ import "../rollup/IRollupCore.sol";
10
+ import "../rollup/IRollupLogic.sol";
11
+ import "../challenge/IChallengeManager.sol";
12
+
13
+ import {NO_CHAL_INDEX} from "../libraries/Constants.sol";
14
+
15
+ contract ValidatorUtils {
16
+ using NodeLib for Node;
17
+
18
+ enum ConfirmType {
19
+ NONE,
20
+ VALID,
21
+ INVALID
22
+ }
23
+
24
+ enum NodeConflictType {
25
+ NONE,
26
+ FOUND,
27
+ INDETERMINATE,
28
+ INCOMPLETE
29
+ }
30
+
31
+ struct NodeConflict {
32
+ NodeConflictType ty;
33
+ uint64 node1;
34
+ uint64 node2;
35
+ }
36
+
37
+ function findStakerConflict(
38
+ IRollupCore rollup,
39
+ address staker1,
40
+ address staker2,
41
+ uint256 maxDepth
42
+ ) external view returns (NodeConflict memory) {
43
+ uint64 staker1NodeNum = rollup.latestStakedNode(staker1);
44
+ uint64 staker2NodeNum = rollup.latestStakedNode(staker2);
45
+ return findNodeConflict(rollup, staker1NodeNum, staker2NodeNum, maxDepth);
46
+ }
47
+
48
+ function checkDecidableNextNode(IRollupUserAbs rollup) external view returns (ConfirmType) {
49
+ try ValidatorUtils(address(this)).requireConfirmable(rollup) {
50
+ return ConfirmType.VALID;
51
+ } catch {}
52
+
53
+ try ValidatorUtils(address(this)).requireRejectable(rollup) {
54
+ return ConfirmType.INVALID;
55
+ } catch {
56
+ return ConfirmType.NONE;
57
+ }
58
+ }
59
+
60
+ function requireRejectable(IRollupCore rollup) external view {
61
+ IRollupUser(address(rollup)).requireUnresolvedExists();
62
+ uint64 firstUnresolvedNode = rollup.firstUnresolvedNode();
63
+ Node memory node = rollup.getNode(firstUnresolvedNode);
64
+ if (node.prevNum == rollup.latestConfirmed()) {
65
+ // Verify the block's deadline has passed
66
+ require(block.number >= node.deadlineBlock, "BEFORE_DEADLINE");
67
+ rollup.getNode(node.prevNum).requirePastChildConfirmDeadline();
68
+
69
+ // Verify that no staker is staked on this node
70
+ require(
71
+ node.stakerCount ==
72
+ IRollupUser(address(rollup)).countStakedZombies(firstUnresolvedNode),
73
+ "HAS_STAKERS"
74
+ );
75
+ }
76
+ }
77
+
78
+ function requireConfirmable(IRollupUserAbs rollup) external view {
79
+ rollup.requireUnresolvedExists();
80
+
81
+ uint256 stakerCount = rollup.stakerCount();
82
+ // There is at least one non-zombie staker
83
+ require(stakerCount > 0, "NO_STAKERS");
84
+
85
+ uint64 firstUnresolved = rollup.firstUnresolvedNode();
86
+ Node memory node = rollup.getNode(firstUnresolved);
87
+
88
+ // Verify the block's deadline has passed
89
+ node.requirePastDeadline();
90
+
91
+ // Check that prev is latest confirmed
92
+ assert(node.prevNum == rollup.latestConfirmed());
93
+
94
+ Node memory prevNode = rollup.getNode(node.prevNum);
95
+ prevNode.requirePastChildConfirmDeadline();
96
+
97
+ uint256 zombiesStakedOnOtherChildren = rollup.countZombiesStakedOnChildren(node.prevNum) -
98
+ rollup.countStakedZombies(firstUnresolved);
99
+ require(
100
+ prevNode.childStakerCount == node.stakerCount + zombiesStakedOnOtherChildren,
101
+ "NOT_ALL_STAKED"
102
+ );
103
+ }
104
+
105
+ function refundableStakers(IRollupCore rollup) external view returns (address[] memory) {
106
+ uint256 stakerCount = rollup.stakerCount();
107
+ address[] memory stakers = new address[](stakerCount);
108
+ uint256 latestConfirmed = rollup.latestConfirmed();
109
+ uint256 index = 0;
110
+ for (uint64 i = 0; i < stakerCount; i++) {
111
+ address staker = rollup.getStakerAddress(i);
112
+ uint256 latestStakedNode = rollup.latestStakedNode(staker);
113
+ if (latestStakedNode <= latestConfirmed && rollup.currentChallenge(staker) == 0) {
114
+ stakers[index] = staker;
115
+ index++;
116
+ }
117
+ }
118
+ assembly {
119
+ mstore(stakers, index)
120
+ }
121
+ return stakers;
122
+ }
123
+
124
+ function latestStaked(IRollupCore rollup, address staker)
125
+ external
126
+ view
127
+ returns (uint64, Node memory)
128
+ {
129
+ uint64 num = rollup.latestStakedNode(staker);
130
+ if (num == 0) {
131
+ num = rollup.latestConfirmed();
132
+ }
133
+ Node memory node = rollup.getNode(num);
134
+ return (num, node);
135
+ }
136
+
137
+ function stakedNodes(IRollupCore rollup, address staker)
138
+ external
139
+ view
140
+ returns (uint64[] memory)
141
+ {
142
+ uint64[] memory nodes = new uint64[](100000);
143
+ uint256 index = 0;
144
+ for (uint64 i = rollup.latestConfirmed(); i <= rollup.latestNodeCreated(); i++) {
145
+ if (rollup.nodeHasStaker(i, staker)) {
146
+ nodes[index] = i;
147
+ index++;
148
+ }
149
+ }
150
+ // Shrink array down to real size
151
+ assembly {
152
+ mstore(nodes, index)
153
+ }
154
+ return nodes;
155
+ }
156
+
157
+ function findNodeConflict(
158
+ IRollupCore rollup,
159
+ uint64 node1,
160
+ uint64 node2,
161
+ uint256 maxDepth
162
+ ) public view returns (NodeConflict memory) {
163
+ uint64 firstUnresolvedNode = rollup.firstUnresolvedNode();
164
+ uint64 node1Prev = rollup.getNode(node1).prevNum;
165
+ uint64 node2Prev = rollup.getNode(node2).prevNum;
166
+
167
+ for (uint256 i = 0; i < maxDepth; i++) {
168
+ if (node1 == node2) {
169
+ return NodeConflict(NodeConflictType.NONE, node1, node2);
170
+ }
171
+ if (node1Prev == node2Prev) {
172
+ return NodeConflict(NodeConflictType.FOUND, node1, node2);
173
+ }
174
+ if (node1Prev < firstUnresolvedNode && node2Prev < firstUnresolvedNode) {
175
+ return NodeConflict(NodeConflictType.INDETERMINATE, 0, 0);
176
+ }
177
+ if (node1Prev < node2Prev) {
178
+ node2 = node2Prev;
179
+ node2Prev = rollup.getNode(node2).prevNum;
180
+ } else {
181
+ node1 = node1Prev;
182
+ node1Prev = rollup.getNode(node1).prevNum;
183
+ }
184
+ }
185
+ return NodeConflict(NodeConflictType.INCOMPLETE, 0, 0);
186
+ }
187
+
188
+ function getStakers(
189
+ IRollupCore rollup,
190
+ uint64 startIndex,
191
+ uint64 max
192
+ ) public view returns (address[] memory, bool hasMore) {
193
+ uint256 maxStakers = rollup.stakerCount();
194
+ if (startIndex + max <= maxStakers) {
195
+ maxStakers = startIndex + max;
196
+ hasMore = true;
197
+ }
198
+
199
+ address[] memory stakers = new address[](maxStakers);
200
+ for (uint64 i = 0; i < maxStakers; i++) {
201
+ stakers[i] = rollup.getStakerAddress(startIndex + i);
202
+ }
203
+ return (stakers, hasMore);
204
+ }
205
+
206
+ function timedOutChallenges(
207
+ IRollupCore rollup,
208
+ uint64 startIndex,
209
+ uint64 max
210
+ ) external view returns (uint64[] memory, bool hasMore) {
211
+ (address[] memory stakers, bool hasMoreStakers) = getStakers(rollup, startIndex, max);
212
+ uint64[] memory challenges = new uint64[](stakers.length);
213
+ uint256 index = 0;
214
+ IChallengeManager challengeManager = rollup.challengeManager();
215
+ for (uint256 i = 0; i < stakers.length; i++) {
216
+ address staker = stakers[i];
217
+ uint64 challengeIndex = rollup.currentChallenge(staker);
218
+ if (
219
+ challengeIndex != NO_CHAL_INDEX &&
220
+ challengeManager.isTimedOut(challengeIndex) &&
221
+ challengeManager.currentResponder(challengeIndex) == staker
222
+ ) {
223
+ challenges[index++] = challengeIndex;
224
+ }
225
+ }
226
+ // Shrink array down to real size
227
+ assembly {
228
+ mstore(challenges, index)
229
+ }
230
+ return (challenges, hasMoreStakers);
231
+ }
232
+
233
+ // Worst case runtime of O(depth), as it terminates if it switches paths.
234
+ function areUnresolvedNodesLinear(IRollupCore rollup) external view returns (bool) {
235
+ uint256 end = rollup.latestNodeCreated();
236
+ for (uint64 i = rollup.firstUnresolvedNode(); i <= end; i++) {
237
+ if (i > 0 && rollup.getNode(i).prevNum != i - 1) {
238
+ return false;
239
+ }
240
+ }
241
+ return true;
242
+ }
243
+ }
@@ -0,0 +1,76 @@
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 "./IRollupLogic.sol";
8
+ import "../challenge/IChallengeManager.sol";
9
+ import "../libraries/DelegateCallAware.sol";
10
+ import "@openzeppelin/contracts/utils/Address.sol";
11
+ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
12
+
13
+ contract ValidatorWallet is OwnableUpgradeable, DelegateCallAware {
14
+ using Address for address;
15
+
16
+ function initialize() external initializer onlyDelegated {
17
+ __Ownable_init();
18
+ }
19
+
20
+ function executeTransactions(
21
+ bytes[] calldata data,
22
+ address[] calldata destination,
23
+ uint256[] calldata amount
24
+ ) external payable onlyOwner {
25
+ uint256 numTxes = data.length;
26
+ for (uint256 i = 0; i < numTxes; i++) {
27
+ if (data[i].length > 0) require(destination[i].isContract(), "NO_CODE_AT_ADDR");
28
+ // We use a low level call here to allow for contract and non-contract calls
29
+ // solhint-disable-next-line avoid-low-level-calls
30
+ (bool success, ) = address(destination[i]).call{value: amount[i]}(data[i]);
31
+ if (!success) {
32
+ assembly {
33
+ let ptr := mload(0x40)
34
+ let size := returndatasize()
35
+ returndatacopy(ptr, 0, size)
36
+ revert(ptr, size)
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ function executeTransaction(
43
+ bytes calldata data,
44
+ address destination,
45
+ uint256 amount
46
+ ) external payable onlyOwner {
47
+ if (data.length > 0) require(destination.isContract(), "NO_CODE_AT_ADDR");
48
+ // We use a low level call here to allow for contract and non-contract calls
49
+ // solhint-disable-next-line avoid-low-level-calls
50
+ (bool success, ) = destination.call{value: amount}(data);
51
+ if (!success) {
52
+ assembly {
53
+ let ptr := mload(0x40)
54
+ let size := returndatasize()
55
+ returndatacopy(ptr, 0, size)
56
+ revert(ptr, size)
57
+ }
58
+ }
59
+ }
60
+
61
+ function timeoutChallenges(IChallengeManager manager, uint64[] calldata challenges)
62
+ external
63
+ onlyOwner
64
+ {
65
+ uint256 challengesCount = challenges.length;
66
+ for (uint256 i = 0; i < challengesCount; i++) {
67
+ try manager.timeout(challenges[i]) {} catch (bytes memory error) {
68
+ if (error.length == 0) {
69
+ // Assume out of gas
70
+ // We need to revert here so gas estimation works
71
+ require(false, "GAS");
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,43 @@
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 "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
8
+ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
9
+ import "@openzeppelin/contracts/access/Ownable.sol";
10
+
11
+ import "./ValidatorWallet.sol";
12
+
13
+ contract ValidatorWalletCreator is Ownable {
14
+ event WalletCreated(
15
+ address indexed walletAddress,
16
+ address indexed userAddress,
17
+ address adminProxy
18
+ );
19
+ event TemplateUpdated();
20
+
21
+ address public template;
22
+
23
+ constructor() Ownable() {
24
+ template = address(new ValidatorWallet());
25
+ }
26
+
27
+ function setTemplate(address _template) external onlyOwner {
28
+ template = _template;
29
+ emit TemplateUpdated();
30
+ }
31
+
32
+ function createWallet() external returns (address) {
33
+ ProxyAdmin admin = new ProxyAdmin();
34
+ address proxy = address(
35
+ new TransparentUpgradeableProxy(address(template), address(admin), "")
36
+ );
37
+ admin.transferOwnership(msg.sender);
38
+ ValidatorWallet(proxy).initialize();
39
+ ValidatorWallet(proxy).transferOwnership(msg.sender);
40
+ emit WalletCreated(proxy, msg.sender, address(admin));
41
+ return proxy;
42
+ }
43
+ }
@@ -0,0 +1,321 @@
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 "./Value.sol";
8
+ import "./ValueStack.sol";
9
+ import "./PcStack.sol";
10
+ import "./Machine.sol";
11
+ import "./Instructions.sol";
12
+ import "./StackFrame.sol";
13
+ import "./MerkleProof.sol";
14
+ import "./ModuleMemory.sol";
15
+ import "./Module.sol";
16
+ import "./GlobalState.sol";
17
+
18
+ library Deserialize {
19
+ function u8(bytes calldata proof, uint256 startOffset)
20
+ internal
21
+ pure
22
+ returns (uint8 ret, uint256 offset)
23
+ {
24
+ offset = startOffset;
25
+ ret = uint8(proof[offset]);
26
+ offset++;
27
+ }
28
+
29
+ function u16(bytes calldata proof, uint256 startOffset)
30
+ internal
31
+ pure
32
+ returns (uint16 ret, uint256 offset)
33
+ {
34
+ offset = startOffset;
35
+ for (uint256 i = 0; i < 16 / 8; i++) {
36
+ ret <<= 8;
37
+ ret |= uint8(proof[offset]);
38
+ offset++;
39
+ }
40
+ }
41
+
42
+ function u32(bytes calldata proof, uint256 startOffset)
43
+ internal
44
+ pure
45
+ returns (uint32 ret, uint256 offset)
46
+ {
47
+ offset = startOffset;
48
+ for (uint256 i = 0; i < 32 / 8; i++) {
49
+ ret <<= 8;
50
+ ret |= uint8(proof[offset]);
51
+ offset++;
52
+ }
53
+ }
54
+
55
+ function u64(bytes calldata proof, uint256 startOffset)
56
+ internal
57
+ pure
58
+ returns (uint64 ret, uint256 offset)
59
+ {
60
+ offset = startOffset;
61
+ for (uint256 i = 0; i < 64 / 8; i++) {
62
+ ret <<= 8;
63
+ ret |= uint8(proof[offset]);
64
+ offset++;
65
+ }
66
+ }
67
+
68
+ function u256(bytes calldata proof, uint256 startOffset)
69
+ internal
70
+ pure
71
+ returns (uint256 ret, uint256 offset)
72
+ {
73
+ offset = startOffset;
74
+ for (uint256 i = 0; i < 256 / 8; i++) {
75
+ ret <<= 8;
76
+ ret |= uint8(proof[offset]);
77
+ offset++;
78
+ }
79
+ }
80
+
81
+ function b32(bytes calldata proof, uint256 startOffset)
82
+ internal
83
+ pure
84
+ returns (bytes32 ret, uint256 offset)
85
+ {
86
+ offset = startOffset;
87
+ uint256 retInt;
88
+ (retInt, offset) = u256(proof, offset);
89
+ ret = bytes32(retInt);
90
+ }
91
+
92
+ function value(bytes calldata proof, uint256 startOffset)
93
+ internal
94
+ pure
95
+ returns (Value memory val, uint256 offset)
96
+ {
97
+ offset = startOffset;
98
+ uint8 typeInt = uint8(proof[offset]);
99
+ offset++;
100
+ require(typeInt <= uint8(ValueLib.maxValueType()), "BAD_VALUE_TYPE");
101
+ uint256 contents;
102
+ (contents, offset) = u256(proof, offset);
103
+ val = Value({valueType: ValueType(typeInt), contents: contents});
104
+ }
105
+
106
+ function valueStack(bytes calldata proof, uint256 startOffset)
107
+ internal
108
+ pure
109
+ returns (ValueStack memory stack, uint256 offset)
110
+ {
111
+ offset = startOffset;
112
+ bytes32 remainingHash;
113
+ (remainingHash, offset) = b32(proof, offset);
114
+ uint256 provedLength;
115
+ (provedLength, offset) = u256(proof, offset);
116
+ Value[] memory proved = new Value[](provedLength);
117
+ for (uint256 i = 0; i < proved.length; i++) {
118
+ (proved[i], offset) = value(proof, offset);
119
+ }
120
+ stack = ValueStack({proved: ValueArray(proved), remainingHash: remainingHash});
121
+ }
122
+
123
+ function pcStack(bytes calldata proof, uint256 startOffset)
124
+ internal
125
+ pure
126
+ returns (PcStack memory stack, uint256 offset)
127
+ {
128
+ offset = startOffset;
129
+ bytes32 remainingHash;
130
+ (remainingHash, offset) = b32(proof, offset);
131
+ uint256 provedLength;
132
+ (provedLength, offset) = u256(proof, offset);
133
+ uint32[] memory proved = new uint32[](provedLength);
134
+ for (uint256 i = 0; i < proved.length; i++) {
135
+ (proved[i], offset) = u32(proof, offset);
136
+ }
137
+ stack = PcStack({proved: PcArray(proved), remainingHash: remainingHash});
138
+ }
139
+
140
+ function instruction(bytes calldata proof, uint256 startOffset)
141
+ internal
142
+ pure
143
+ returns (Instruction memory inst, uint256 offset)
144
+ {
145
+ offset = startOffset;
146
+ uint16 opcode;
147
+ uint256 data;
148
+ (opcode, offset) = u16(proof, offset);
149
+ (data, offset) = u256(proof, offset);
150
+ inst = Instruction({opcode: opcode, argumentData: data});
151
+ }
152
+
153
+ function stackFrame(bytes calldata proof, uint256 startOffset)
154
+ internal
155
+ pure
156
+ returns (StackFrame memory window, uint256 offset)
157
+ {
158
+ offset = startOffset;
159
+ Value memory returnPc;
160
+ bytes32 localsMerkleRoot;
161
+ uint32 callerModule;
162
+ uint32 callerModuleInternals;
163
+ (returnPc, offset) = value(proof, offset);
164
+ (localsMerkleRoot, offset) = b32(proof, offset);
165
+ (callerModule, offset) = u32(proof, offset);
166
+ (callerModuleInternals, offset) = u32(proof, offset);
167
+ window = StackFrame({
168
+ returnPc: returnPc,
169
+ localsMerkleRoot: localsMerkleRoot,
170
+ callerModule: callerModule,
171
+ callerModuleInternals: callerModuleInternals
172
+ });
173
+ }
174
+
175
+ function stackFrameWindow(bytes calldata proof, uint256 startOffset)
176
+ internal
177
+ pure
178
+ returns (StackFrameWindow memory window, uint256 offset)
179
+ {
180
+ offset = startOffset;
181
+ bytes32 remainingHash;
182
+ (remainingHash, offset) = b32(proof, offset);
183
+ StackFrame[] memory proved;
184
+ if (proof[offset] != 0) {
185
+ offset++;
186
+ proved = new StackFrame[](1);
187
+ (proved[0], offset) = stackFrame(proof, offset);
188
+ } else {
189
+ offset++;
190
+ proved = new StackFrame[](0);
191
+ }
192
+ window = StackFrameWindow({proved: proved, remainingHash: remainingHash});
193
+ }
194
+
195
+ function moduleMemory(bytes calldata proof, uint256 startOffset)
196
+ internal
197
+ pure
198
+ returns (ModuleMemory memory mem, uint256 offset)
199
+ {
200
+ offset = startOffset;
201
+ uint64 size;
202
+ bytes32 root;
203
+ (size, offset) = u64(proof, offset);
204
+ (root, offset) = b32(proof, offset);
205
+ mem = ModuleMemory({size: size, merkleRoot: root});
206
+ }
207
+
208
+ function module(bytes calldata proof, uint256 startOffset)
209
+ internal
210
+ pure
211
+ returns (Module memory mod, uint256 offset)
212
+ {
213
+ offset = startOffset;
214
+ bytes32 globalsMerkleRoot;
215
+ ModuleMemory memory mem;
216
+ bytes32 tablesMerkleRoot;
217
+ bytes32 functionsMerkleRoot;
218
+ uint32 internalsOffset;
219
+ (globalsMerkleRoot, offset) = b32(proof, offset);
220
+ (mem, offset) = moduleMemory(proof, offset);
221
+ (tablesMerkleRoot, offset) = b32(proof, offset);
222
+ (functionsMerkleRoot, offset) = b32(proof, offset);
223
+ (internalsOffset, offset) = u32(proof, offset);
224
+ mod = Module({
225
+ globalsMerkleRoot: globalsMerkleRoot,
226
+ moduleMemory: mem,
227
+ tablesMerkleRoot: tablesMerkleRoot,
228
+ functionsMerkleRoot: functionsMerkleRoot,
229
+ internalsOffset: internalsOffset
230
+ });
231
+ }
232
+
233
+ function globalState(bytes calldata proof, uint256 startOffset)
234
+ internal
235
+ pure
236
+ returns (GlobalState memory state, uint256 offset)
237
+ {
238
+ offset = startOffset;
239
+
240
+ // using constant ints for array size requires newer solidity
241
+ bytes32[2] memory bytes32Vals;
242
+ uint64[2] memory u64Vals;
243
+
244
+ for (uint8 i = 0; i < GlobalStateLib.BYTES32_VALS_NUM; i++) {
245
+ (bytes32Vals[i], offset) = b32(proof, offset);
246
+ }
247
+ for (uint8 i = 0; i < GlobalStateLib.U64_VALS_NUM; i++) {
248
+ (u64Vals[i], offset) = u64(proof, offset);
249
+ }
250
+ state = GlobalState({bytes32Vals: bytes32Vals, u64Vals: u64Vals});
251
+ }
252
+
253
+ function machine(bytes calldata proof, uint256 startOffset)
254
+ internal
255
+ pure
256
+ returns (Machine memory mach, uint256 offset)
257
+ {
258
+ offset = startOffset;
259
+ MachineStatus status;
260
+ {
261
+ uint8 statusU8;
262
+ (statusU8, offset) = u8(proof, offset);
263
+ if (statusU8 == 0) {
264
+ status = MachineStatus.RUNNING;
265
+ } else if (statusU8 == 1) {
266
+ status = MachineStatus.FINISHED;
267
+ } else if (statusU8 == 2) {
268
+ status = MachineStatus.ERRORED;
269
+ } else if (statusU8 == 3) {
270
+ status = MachineStatus.TOO_FAR;
271
+ } else {
272
+ revert("UNKNOWN_MACH_STATUS");
273
+ }
274
+ }
275
+ ValueStack memory values;
276
+ ValueStack memory internalStack;
277
+ PcStack memory blocks;
278
+ bytes32 globalStateHash;
279
+ uint32 moduleIdx;
280
+ uint32 functionIdx;
281
+ uint32 functionPc;
282
+ StackFrameWindow memory frameStack;
283
+ bytes32 modulesRoot;
284
+ (values, offset) = valueStack(proof, offset);
285
+ (internalStack, offset) = valueStack(proof, offset);
286
+ (blocks, offset) = pcStack(proof, offset);
287
+ (frameStack, offset) = stackFrameWindow(proof, offset);
288
+ (globalStateHash, offset) = b32(proof, offset);
289
+ (moduleIdx, offset) = u32(proof, offset);
290
+ (functionIdx, offset) = u32(proof, offset);
291
+ (functionPc, offset) = u32(proof, offset);
292
+ (modulesRoot, offset) = b32(proof, offset);
293
+ mach = Machine({
294
+ status: status,
295
+ valueStack: values,
296
+ internalStack: internalStack,
297
+ blockStack: blocks,
298
+ frameStack: frameStack,
299
+ globalStateHash: globalStateHash,
300
+ moduleIdx: moduleIdx,
301
+ functionIdx: functionIdx,
302
+ functionPc: functionPc,
303
+ modulesRoot: modulesRoot
304
+ });
305
+ }
306
+
307
+ function merkleProof(bytes calldata proof, uint256 startOffset)
308
+ internal
309
+ pure
310
+ returns (MerkleProof memory merkle, uint256 offset)
311
+ {
312
+ offset = startOffset;
313
+ uint8 length;
314
+ (length, offset) = u8(proof, offset);
315
+ bytes32[] memory counterparts = new bytes32[](length);
316
+ for (uint8 i = 0; i < length; i++) {
317
+ (counterparts[i], offset) = b32(proof, offset);
318
+ }
319
+ merkle = MerkleProof(counterparts);
320
+ }
321
+ }