@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,188 @@
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.4;
6
+
7
+ import "./IBridge.sol";
8
+ import "./IOutbox.sol";
9
+ import "../libraries/MerkleLib.sol";
10
+ import "../libraries/DelegateCallAware.sol";
11
+
12
+ contract Outbox is DelegateCallAware, IOutbox {
13
+ address public rollup; // the rollup contract
14
+ IBridge public bridge; // the bridge contract
15
+
16
+ mapping(uint256 => bool) public spent; // maps leaf number => if spent
17
+ mapping(bytes32 => bytes32) public roots; // maps root hashes => L2 block hash
18
+
19
+ struct L2ToL1Context {
20
+ uint128 l2Block;
21
+ uint128 l1Block;
22
+ uint128 timestamp;
23
+ bytes32 outputId;
24
+ address sender;
25
+ }
26
+ // Note, these variables are set and then wiped during a single transaction.
27
+ // Therefore their values don't need to be maintained, and their slots will
28
+ // be empty outside of transactions
29
+ L2ToL1Context internal context;
30
+ uint128 public constant OUTBOX_VERSION = 2;
31
+
32
+ function initialize(address _rollup, IBridge _bridge) external onlyDelegated {
33
+ if (rollup != address(0)) revert AlreadyInit();
34
+ rollup = _rollup;
35
+ bridge = _bridge;
36
+ }
37
+
38
+ function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external override {
39
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
40
+ roots[root] = l2BlockHash;
41
+ emit SendRootUpdated(root, l2BlockHash);
42
+ }
43
+
44
+ /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
45
+ /// When the return value is zero, that means this is a system message
46
+ /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
47
+ function l2ToL1Sender() external view override returns (address) {
48
+ return context.sender;
49
+ }
50
+
51
+ function l2ToL1Block() external view override returns (uint256) {
52
+ return uint256(context.l2Block);
53
+ }
54
+
55
+ function l2ToL1EthBlock() external view override returns (uint256) {
56
+ return uint256(context.l1Block);
57
+ }
58
+
59
+ function l2ToL1Timestamp() external view override returns (uint256) {
60
+ return uint256(context.timestamp);
61
+ }
62
+
63
+ // @deprecated batch number is now always 0
64
+ function l2ToL1BatchNum() external pure override returns (uint256) {
65
+ return 0;
66
+ }
67
+
68
+ function l2ToL1OutputId() external view override returns (bytes32) {
69
+ return context.outputId;
70
+ }
71
+
72
+ /**
73
+ * @notice Executes a messages in an Outbox entry.
74
+ * @dev Reverts if dispute period hasn't expired, since the outbox entry
75
+ * is only created once the rollup confirms the respective assertion.
76
+ * @param proof Merkle proof of message inclusion in send root
77
+ * @param index Merkle path to message
78
+ * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
79
+ * @param to destination address for L1 contract call
80
+ * @param l2Block l2 block number at which sendTxToL1 call was made
81
+ * @param l1Block l1 block number at which sendTxToL1 call was made
82
+ * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
83
+ * @param value wei in L1 message
84
+ * @param data abi-encoded L1 message data
85
+ */
86
+ function executeTransaction(
87
+ bytes32[] calldata proof,
88
+ uint256 index,
89
+ address l2Sender,
90
+ address to,
91
+ uint256 l2Block,
92
+ uint256 l1Block,
93
+ uint256 l2Timestamp,
94
+ uint256 value,
95
+ bytes calldata data
96
+ ) external virtual {
97
+ bytes32 outputId;
98
+ {
99
+ bytes32 userTx = calculateItemHash(
100
+ l2Sender,
101
+ to,
102
+ l2Block,
103
+ l1Block,
104
+ l2Timestamp,
105
+ value,
106
+ data
107
+ );
108
+
109
+ outputId = recordOutputAsSpent(proof, index, userTx);
110
+ emit OutBoxTransactionExecuted(to, l2Sender, 0, index);
111
+ }
112
+
113
+ // we temporarily store the previous values so the outbox can naturally
114
+ // unwind itself when there are nested calls to `executeTransaction`
115
+ L2ToL1Context memory prevContext = context;
116
+
117
+ context = L2ToL1Context({
118
+ sender: l2Sender,
119
+ l2Block: uint128(l2Block),
120
+ l1Block: uint128(l1Block),
121
+ timestamp: uint128(l2Timestamp),
122
+ outputId: outputId
123
+ });
124
+
125
+ // set and reset vars around execution so they remain valid during call
126
+ executeBridgeCall(to, value, data);
127
+
128
+ context = prevContext;
129
+ }
130
+
131
+ function recordOutputAsSpent(
132
+ bytes32[] memory proof,
133
+ uint256 index,
134
+ bytes32 item
135
+ ) internal returns (bytes32) {
136
+ if (proof.length >= 256) revert ProofTooLong(proof.length);
137
+ if (index >= 2**proof.length) revert PathNotMinimal(index, 2**proof.length);
138
+
139
+ // Hash the leaf an extra time to prove it's a leaf
140
+ bytes32 calcRoot = calculateMerkleRoot(proof, index, item);
141
+ if (roots[calcRoot] == bytes32(0)) revert UnknownRoot(calcRoot);
142
+
143
+ if (spent[index]) revert AlreadySpent(index);
144
+ spent[index] = true;
145
+
146
+ return bytes32(index);
147
+ }
148
+
149
+ function executeBridgeCall(
150
+ address to,
151
+ uint256 value,
152
+ bytes memory data
153
+ ) internal {
154
+ (bool success, bytes memory returndata) = bridge.executeCall(to, value, data);
155
+ if (!success) {
156
+ if (returndata.length > 0) {
157
+ // solhint-disable-next-line no-inline-assembly
158
+ assembly {
159
+ let returndata_size := mload(returndata)
160
+ revert(add(32, returndata), returndata_size)
161
+ }
162
+ } else {
163
+ revert BridgeCallFailed();
164
+ }
165
+ }
166
+ }
167
+
168
+ function calculateItemHash(
169
+ address l2Sender,
170
+ address to,
171
+ uint256 l2Block,
172
+ uint256 l1Block,
173
+ uint256 l2Timestamp,
174
+ uint256 value,
175
+ bytes calldata data
176
+ ) public pure returns (bytes32) {
177
+ return
178
+ keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
179
+ }
180
+
181
+ function calculateMerkleRoot(
182
+ bytes32[] memory proof,
183
+ uint256 path,
184
+ bytes32 item
185
+ ) public pure returns (bytes32) {
186
+ return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
187
+ }
188
+ }
@@ -0,0 +1,274 @@
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 "./IBridge.sol";
8
+ import "./ISequencerInbox.sol";
9
+ import "./Messages.sol";
10
+
11
+ import {GasRefundEnabled, IGasRefunder} from "../libraries/IGasRefunder.sol";
12
+ import "../libraries/DelegateCallAware.sol";
13
+ import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
14
+
15
+ /**
16
+ * @title Accepts batches from the sequencer and adds them to the rollup inbox.
17
+ * @notice Contains the inbox accumulator which is the ordering of all data and transactions to be processed by the rollup.
18
+ * As part of submitting a batch the sequencer is also expected to include items enqueued
19
+ * in the delayed inbox (Bridge.sol). If items in the delayed inbox are not included by a
20
+ * sequencer within a time limit they can be force included into the rollup inbox by anyone.
21
+ */
22
+ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox {
23
+ bytes32[] public override inboxAccs;
24
+ uint256 public totalDelayedMessagesRead;
25
+
26
+ IBridge public delayedBridge;
27
+
28
+ /// @dev The size of the batch header
29
+ uint256 public constant HEADER_LENGTH = 40;
30
+ /// @dev If the first batch data byte after the header has this bit set,
31
+ /// the sequencer inbox has authenticated the data. Currently not used.
32
+ bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
33
+
34
+ address public rollup;
35
+ mapping(address => bool) public isBatchPoster;
36
+ ISequencerInbox.MaxTimeVariation public maxTimeVariation;
37
+
38
+ function initialize(
39
+ IBridge delayedBridge_,
40
+ address rollup_,
41
+ ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
42
+ ) external onlyDelegated {
43
+ if (delayedBridge != IBridge(address(0))) revert AlreadyInit();
44
+ if (delayedBridge_ == IBridge(address(0))) revert HadZeroInit();
45
+ delayedBridge = delayedBridge_;
46
+ rollup = rollup_;
47
+ maxTimeVariation = maxTimeVariation_;
48
+ }
49
+
50
+ function getTimeBounds() internal view virtual returns (TimeBounds memory) {
51
+ TimeBounds memory bounds;
52
+ if (block.timestamp > maxTimeVariation.delaySeconds) {
53
+ bounds.minTimestamp = uint64(block.timestamp - maxTimeVariation.delaySeconds);
54
+ }
55
+ bounds.maxTimestamp = uint64(block.timestamp + maxTimeVariation.futureSeconds);
56
+ if (block.number > maxTimeVariation.delayBlocks) {
57
+ bounds.minBlockNumber = uint64(block.number - maxTimeVariation.delayBlocks);
58
+ }
59
+ bounds.maxBlockNumber = uint64(block.number + maxTimeVariation.futureBlocks);
60
+ return bounds;
61
+ }
62
+
63
+ /// @notice Force messages from the delayed inbox to be included in the chain
64
+ /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and maxTimeVariation.delaySeconds
65
+ /// has elapsed. As part of normal behaviour the sequencer will include these messages
66
+ /// so it's only necessary to call this if the sequencer is down, or not including
67
+ /// any delayed messages.
68
+ /// @param _totalDelayedMessagesRead The total number of messages to read up to
69
+ /// @param kind The kind of the last message to be included
70
+ /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
71
+ /// @param baseFeeL1 The l1 gas price of the last message to be included
72
+ /// @param sender The sender of the last message to be included
73
+ /// @param messageDataHash The messageDataHash of the last message to be included
74
+ function forceInclusion(
75
+ uint256 _totalDelayedMessagesRead,
76
+ uint8 kind,
77
+ uint64[2] calldata l1BlockAndTime,
78
+ uint256 baseFeeL1,
79
+ address sender,
80
+ bytes32 messageDataHash
81
+ ) external {
82
+ if (_totalDelayedMessagesRead <= totalDelayedMessagesRead) revert DelayedBackwards();
83
+ bytes32 messageHash = Messages.messageHash(
84
+ kind,
85
+ sender,
86
+ l1BlockAndTime[0],
87
+ l1BlockAndTime[1],
88
+ _totalDelayedMessagesRead - 1,
89
+ baseFeeL1,
90
+ messageDataHash
91
+ );
92
+ // Can only force-include after the Sequencer-only window has expired.
93
+ if (l1BlockAndTime[0] + maxTimeVariation.delayBlocks >= block.number)
94
+ revert ForceIncludeBlockTooSoon();
95
+ if (l1BlockAndTime[1] + maxTimeVariation.delaySeconds >= block.timestamp)
96
+ revert ForceIncludeTimeTooSoon();
97
+
98
+ // Verify that message hash represents the last message sequence of delayed message to be included
99
+ bytes32 prevDelayedAcc = 0;
100
+ if (_totalDelayedMessagesRead > 1) {
101
+ prevDelayedAcc = delayedBridge.inboxAccs(_totalDelayedMessagesRead - 2);
102
+ }
103
+ if (
104
+ delayedBridge.inboxAccs(_totalDelayedMessagesRead - 1) !=
105
+ Messages.accumulateInboxMessage(prevDelayedAcc, messageHash)
106
+ ) revert IncorrectMessagePreimage();
107
+
108
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
109
+ _totalDelayedMessagesRead
110
+ );
111
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
112
+ dataHash,
113
+ _totalDelayedMessagesRead
114
+ );
115
+ emit SequencerBatchDelivered(
116
+ inboxAccs.length - 1,
117
+ beforeAcc,
118
+ afterAcc,
119
+ delayedAcc,
120
+ totalDelayedMessagesRead,
121
+ timeBounds,
122
+ BatchDataLocation.NoData
123
+ );
124
+ }
125
+
126
+ function addSequencerL2BatchFromOrigin(
127
+ uint256 sequenceNumber,
128
+ bytes calldata data,
129
+ uint256 afterDelayedMessagesRead,
130
+ IGasRefunder gasRefunder
131
+ ) external refundsGasWithCalldata(gasRefunder, payable(msg.sender)) {
132
+ // solhint-disable-next-line avoid-tx-origin
133
+ if (msg.sender != tx.origin) revert NotOrigin();
134
+ if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
135
+ if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
136
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
137
+ data,
138
+ afterDelayedMessagesRead
139
+ );
140
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
141
+ dataHash,
142
+ afterDelayedMessagesRead
143
+ );
144
+ emit SequencerBatchDelivered(
145
+ inboxAccs.length - 1,
146
+ beforeAcc,
147
+ afterAcc,
148
+ delayedAcc,
149
+ totalDelayedMessagesRead,
150
+ timeBounds,
151
+ BatchDataLocation.TxInput
152
+ );
153
+ }
154
+
155
+ function addSequencerL2Batch(
156
+ uint256 sequenceNumber,
157
+ bytes calldata data,
158
+ uint256 afterDelayedMessagesRead,
159
+ IGasRefunder gasRefunder
160
+ ) external override refundsGasNoCalldata(gasRefunder, payable(msg.sender)) {
161
+ if (!isBatchPoster[msg.sender] && msg.sender != rollup) revert NotBatchPoster();
162
+ if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
163
+
164
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
165
+ data,
166
+ afterDelayedMessagesRead
167
+ );
168
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
169
+ dataHash,
170
+ afterDelayedMessagesRead
171
+ );
172
+ emit SequencerBatchDelivered(
173
+ sequenceNumber,
174
+ beforeAcc,
175
+ afterAcc,
176
+ delayedAcc,
177
+ afterDelayedMessagesRead,
178
+ timeBounds,
179
+ BatchDataLocation.SeparateBatchEvent
180
+ );
181
+ emit SequencerBatchData(sequenceNumber, data);
182
+ }
183
+
184
+ function packHeader(uint256 afterDelayedMessagesRead)
185
+ internal
186
+ view
187
+ returns (bytes memory, TimeBounds memory)
188
+ {
189
+ TimeBounds memory timeBounds = getTimeBounds();
190
+ bytes memory header = abi.encodePacked(
191
+ timeBounds.minTimestamp,
192
+ timeBounds.maxTimestamp,
193
+ timeBounds.minBlockNumber,
194
+ timeBounds.maxBlockNumber,
195
+ uint64(afterDelayedMessagesRead)
196
+ );
197
+ // This must always be true from the packed encoding
198
+ assert(header.length == HEADER_LENGTH);
199
+ return (header, timeBounds);
200
+ }
201
+
202
+ function formDataHash(bytes calldata data, uint256 afterDelayedMessagesRead)
203
+ internal
204
+ view
205
+ returns (bytes32, TimeBounds memory)
206
+ {
207
+ uint256 fullDataLen = HEADER_LENGTH + data.length;
208
+ if (fullDataLen < HEADER_LENGTH) revert DataLengthOverflow();
209
+ if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
210
+ bytes memory fullData = new bytes(fullDataLen);
211
+ (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
212
+
213
+ for (uint256 i = 0; i < HEADER_LENGTH; i++) {
214
+ fullData[i] = header[i];
215
+ }
216
+ if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
217
+ revert DataNotAuthenticated();
218
+ }
219
+ // copy data into fullData at offset of HEADER_LENGTH (the extra 32 offset is because solidity puts the array len first)
220
+ assembly {
221
+ calldatacopy(add(fullData, add(HEADER_LENGTH, 32)), data.offset, data.length)
222
+ }
223
+ return (keccak256(fullData), timeBounds);
224
+ }
225
+
226
+ function formEmptyDataHash(uint256 afterDelayedMessagesRead)
227
+ internal
228
+ view
229
+ returns (bytes32, TimeBounds memory)
230
+ {
231
+ (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
232
+ return (keccak256(header), timeBounds);
233
+ }
234
+
235
+ function addSequencerL2BatchImpl(bytes32 dataHash, uint256 afterDelayedMessagesRead)
236
+ internal
237
+ returns (
238
+ bytes32 beforeAcc,
239
+ bytes32 delayedAcc,
240
+ bytes32 acc
241
+ )
242
+ {
243
+ if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards();
244
+ if (afterDelayedMessagesRead > delayedBridge.messageCount()) revert DelayedTooFar();
245
+
246
+ if (inboxAccs.length > 0) {
247
+ beforeAcc = inboxAccs[inboxAccs.length - 1];
248
+ }
249
+ if (afterDelayedMessagesRead > 0) {
250
+ delayedAcc = delayedBridge.inboxAccs(afterDelayedMessagesRead - 1);
251
+ }
252
+
253
+ acc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc));
254
+ inboxAccs.push(acc);
255
+ totalDelayedMessagesRead = afterDelayedMessagesRead;
256
+ }
257
+
258
+ function batchCount() external view override returns (uint256) {
259
+ return inboxAccs.length;
260
+ }
261
+
262
+ function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
263
+ external
264
+ override
265
+ {
266
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
267
+ maxTimeVariation = maxTimeVariation_;
268
+ }
269
+
270
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external override {
271
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
272
+ isBatchPoster[addr] = isBatchPoster_;
273
+ }
274
+ }
@@ -0,0 +1,135 @@
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/Machine.sol";
8
+ import "../state/GlobalState.sol";
9
+
10
+ library ChallengeLib {
11
+ using MachineLib for Machine;
12
+ using ChallengeLib for Challenge;
13
+
14
+ /// @dev It's assumed that that uninitialzed challenges have mode NONE
15
+ enum ChallengeMode {
16
+ NONE,
17
+ BLOCK,
18
+ EXECUTION
19
+ }
20
+
21
+ struct Participant {
22
+ address addr;
23
+ uint256 timeLeft;
24
+ }
25
+
26
+ struct Challenge {
27
+ Participant current;
28
+ Participant next;
29
+ uint256 lastMoveTimestamp;
30
+ bytes32 wasmModuleRoot;
31
+ bytes32 challengeStateHash;
32
+ uint64 maxInboxMessages;
33
+ ChallengeMode mode;
34
+ }
35
+
36
+ struct SegmentSelection {
37
+ uint256 oldSegmentsStart;
38
+ uint256 oldSegmentsLength;
39
+ bytes32[] oldSegments;
40
+ uint256 challengePosition;
41
+ }
42
+
43
+ function timeUsedSinceLastMove(Challenge storage challenge) internal view returns (uint256) {
44
+ return block.timestamp - challenge.lastMoveTimestamp;
45
+ }
46
+
47
+ function isTimedOut(Challenge storage challenge) internal view returns (bool) {
48
+ return challenge.timeUsedSinceLastMove() > challenge.current.timeLeft;
49
+ }
50
+
51
+ function getStartMachineHash(bytes32 globalStateHash, bytes32 wasmModuleRoot)
52
+ internal
53
+ pure
54
+ returns (bytes32)
55
+ {
56
+ // Start the value stack with the function call ABI for the entrypoint
57
+ Value[] memory startingValues = new Value[](3);
58
+ startingValues[0] = ValueLib.newRefNull();
59
+ startingValues[1] = ValueLib.newI32(0);
60
+ startingValues[2] = ValueLib.newI32(0);
61
+ ValueArray memory valuesArray = ValueArray({inner: startingValues});
62
+ ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0});
63
+ ValueStack memory internalStack;
64
+ PcStack memory blocks;
65
+ StackFrameWindow memory frameStack;
66
+
67
+ Machine memory mach = Machine({
68
+ status: MachineStatus.RUNNING,
69
+ valueStack: values,
70
+ internalStack: internalStack,
71
+ blockStack: blocks,
72
+ frameStack: frameStack,
73
+ globalStateHash: globalStateHash,
74
+ moduleIdx: 0,
75
+ functionIdx: 0,
76
+ functionPc: 0,
77
+ modulesRoot: wasmModuleRoot
78
+ });
79
+ return mach.hash();
80
+ }
81
+
82
+ function getEndMachineHash(MachineStatus status, bytes32 globalStateHash)
83
+ internal
84
+ pure
85
+ returns (bytes32)
86
+ {
87
+ if (status == MachineStatus.FINISHED) {
88
+ return keccak256(abi.encodePacked("Machine finished:", globalStateHash));
89
+ } else if (status == MachineStatus.ERRORED) {
90
+ return keccak256(abi.encodePacked("Machine errored:"));
91
+ } else if (status == MachineStatus.TOO_FAR) {
92
+ return keccak256(abi.encodePacked("Machine too far:"));
93
+ } else {
94
+ revert("BAD_BLOCK_STATUS");
95
+ }
96
+ }
97
+
98
+ function extractChallengeSegment(SegmentSelection calldata selection)
99
+ internal
100
+ pure
101
+ returns (uint256 segmentStart, uint256 segmentLength)
102
+ {
103
+ uint256 oldChallengeDegree = selection.oldSegments.length - 1;
104
+ segmentLength = selection.oldSegmentsLength / oldChallengeDegree;
105
+ // Intentionally done before challengeLength is potentially added to for the final segment
106
+ segmentStart = selection.oldSegmentsStart + segmentLength * selection.challengePosition;
107
+ if (selection.challengePosition == selection.oldSegments.length - 2) {
108
+ segmentLength += selection.oldSegmentsLength % oldChallengeDegree;
109
+ }
110
+ }
111
+
112
+ function hashChallengeState(
113
+ uint256 segmentsStart,
114
+ uint256 segmentsLength,
115
+ bytes32[] memory segments
116
+ ) internal pure returns (bytes32) {
117
+ return keccak256(abi.encodePacked(segmentsStart, segmentsLength, segments));
118
+ }
119
+
120
+ function blockStateHash(MachineStatus status, bytes32 globalStateHash)
121
+ internal
122
+ pure
123
+ returns (bytes32)
124
+ {
125
+ if (status == MachineStatus.FINISHED) {
126
+ return keccak256(abi.encodePacked("Block state:", globalStateHash));
127
+ } else if (status == MachineStatus.ERRORED) {
128
+ return keccak256(abi.encodePacked("Block state, errored:", globalStateHash));
129
+ } else if (status == MachineStatus.TOO_FAR) {
130
+ return keccak256(abi.encodePacked("Block state, too far:"));
131
+ } else {
132
+ revert("BAD_BLOCK_STATUS");
133
+ }
134
+ }
135
+ }