@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,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
+ }