@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,115 @@
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 "./InboxStub.sol";
8
+
9
+ import "../bridge/IBridge.sol";
10
+
11
+ contract BridgeStub is IBridge {
12
+ struct InOutInfo {
13
+ uint256 index;
14
+ bool allowed;
15
+ }
16
+
17
+ mapping(address => InOutInfo) private allowedInboxesMap;
18
+ //mapping(address => InOutInfo) private allowedOutboxesMap;
19
+
20
+ address[] public allowedInboxList;
21
+ address[] public allowedOutboxList;
22
+
23
+ address public override activeOutbox;
24
+
25
+ // Accumulator for delayed inbox; tail represents hash of the current state; each element represents the inclusion of a new message.
26
+ bytes32[] public override inboxAccs;
27
+
28
+ function allowedInboxes(address inbox) external view override returns (bool) {
29
+ return allowedInboxesMap[inbox].allowed;
30
+ }
31
+
32
+ function allowedOutboxes(address) external pure override returns (bool) {
33
+ revert("NOT_IMPLEMENTED");
34
+ }
35
+
36
+ function enqueueDelayedMessage(
37
+ uint8 kind,
38
+ address sender,
39
+ bytes32 messageDataHash
40
+ ) external payable override returns (uint256) {
41
+ require(allowedInboxesMap[msg.sender].allowed, "NOT_FROM_INBOX");
42
+ return
43
+ addMessageToAccumulator(
44
+ kind,
45
+ sender,
46
+ block.number,
47
+ block.timestamp, // solhint-disable-line not-rely-on-time
48
+ block.basefee,
49
+ messageDataHash
50
+ );
51
+ }
52
+
53
+ function addMessageToAccumulator(
54
+ uint8,
55
+ address,
56
+ uint256,
57
+ uint256,
58
+ uint256,
59
+ bytes32 messageDataHash
60
+ ) internal returns (uint256) {
61
+ uint256 count = inboxAccs.length;
62
+ bytes32 messageHash = Messages.messageHash(
63
+ 0,
64
+ address(uint160(0)),
65
+ 0,
66
+ 0,
67
+ 0,
68
+ 0,
69
+ messageDataHash
70
+ );
71
+ bytes32 prevAcc = 0;
72
+ if (count > 0) {
73
+ prevAcc = inboxAccs[count - 1];
74
+ }
75
+ inboxAccs.push(Messages.accumulateInboxMessage(prevAcc, messageHash));
76
+ return count;
77
+ }
78
+
79
+ function executeCall(
80
+ address,
81
+ uint256,
82
+ bytes calldata
83
+ ) external pure override returns (bool, bytes memory) {
84
+ revert("NOT_IMPLEMENTED");
85
+ }
86
+
87
+ function setInbox(address inbox, bool enabled) external override {
88
+ InOutInfo storage info = allowedInboxesMap[inbox];
89
+ bool alreadyEnabled = info.allowed;
90
+ emit InboxToggle(inbox, enabled);
91
+ if ((alreadyEnabled && enabled) || (!alreadyEnabled && !enabled)) {
92
+ return;
93
+ }
94
+ if (enabled) {
95
+ allowedInboxesMap[inbox] = InOutInfo(allowedInboxList.length, true);
96
+ allowedInboxList.push(inbox);
97
+ } else {
98
+ allowedInboxList[info.index] = allowedInboxList[allowedInboxList.length - 1];
99
+ allowedInboxesMap[allowedInboxList[info.index]].index = info.index;
100
+ allowedInboxList.pop();
101
+ delete allowedInboxesMap[inbox];
102
+ }
103
+ }
104
+
105
+ function setOutbox(
106
+ address, /* outbox */
107
+ bool /* enabled*/
108
+ ) external pure override {
109
+ revert("NOT_IMPLEMENTED");
110
+ }
111
+
112
+ function messageCount() external view override returns (uint256) {
113
+ return inboxAccs.length;
114
+ }
115
+ }
@@ -0,0 +1,13 @@
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
+ contract Simple {
8
+ uint64 public counter;
9
+
10
+ function increment() external {
11
+ counter++;
12
+ }
13
+ }
@@ -0,0 +1,41 @@
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 "../challenge/ChallengeManager.sol";
8
+
9
+ contract SingleExecutionChallenge is ChallengeManager {
10
+ constructor(
11
+ IOneStepProofEntry osp_,
12
+ IChallengeResultReceiver resultReceiver_,
13
+ uint64 maxInboxMessagesRead_,
14
+ bytes32[2] memory startAndEndHashes,
15
+ uint256 numSteps_,
16
+ address asserter_,
17
+ address challenger_,
18
+ uint256 asserterTimeLeft_,
19
+ uint256 challengerTimeLeft_
20
+ ) {
21
+ osp = osp_;
22
+ resultReceiver = resultReceiver_;
23
+ uint64 challengeIndex = ++totalChallengesCreated;
24
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
25
+ challenge.maxInboxMessages = maxInboxMessagesRead_;
26
+ bytes32[] memory segments = new bytes32[](2);
27
+ segments[0] = startAndEndHashes[0];
28
+ segments[1] = startAndEndHashes[1];
29
+ bytes32 challengeStateHash = ChallengeLib.hashChallengeState(0, numSteps_, segments);
30
+ challenge.challengeStateHash = challengeStateHash;
31
+ challenge.next = ChallengeLib.Participant({addr: asserter_, timeLeft: asserterTimeLeft_});
32
+ challenge.current = ChallengeLib.Participant({
33
+ addr: challenger_,
34
+ timeLeft: challengerTimeLeft_
35
+ });
36
+ challenge.lastMoveTimestamp = block.timestamp;
37
+ challenge.mode = ChallengeLib.ChallengeMode.EXECUTION;
38
+
39
+ emit Bisected(challengeIndex, challengeStateHash, 0, numSteps_, segments);
40
+ }
41
+ }
@@ -0,0 +1,131 @@
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 "../bridge/IInbox.sol";
8
+ import "../bridge/IBridge.sol";
9
+
10
+ import "../bridge/Messages.sol";
11
+ import "./BridgeStub.sol";
12
+ import {
13
+ L2_MSG,
14
+ L1MessageType_L2FundedByL1,
15
+ L1MessageType_submitRetryableTx,
16
+ L2MessageType_unsignedEOATx,
17
+ L2MessageType_unsignedContractTx
18
+ } from "../libraries/MessageTypes.sol";
19
+
20
+ contract InboxStub is IInbox {
21
+ IBridge public override bridge;
22
+
23
+ bool public paused;
24
+
25
+ function initialize(IBridge _bridge) external {
26
+ require(address(bridge) == address(0), "ALREADY_INIT");
27
+ bridge = _bridge;
28
+ }
29
+
30
+ /**
31
+ * @notice Send a generic L2 message to the chain
32
+ * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
33
+ * @param messageData Data of the message being sent
34
+ */
35
+ function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256) {
36
+ // solhint-disable-next-line avoid-tx-origin
37
+ require(msg.sender == tx.origin, "origin only");
38
+ uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
39
+ emit InboxMessageDeliveredFromOrigin(msgNum);
40
+ return msgNum;
41
+ }
42
+
43
+ /**
44
+ * @notice Send a generic L2 message to the chain
45
+ * @dev This method can be used to send any type of message that doesn't require L1 validation
46
+ * @param messageData Data of the message being sent
47
+ */
48
+ function sendL2Message(bytes calldata messageData) external override returns (uint256) {
49
+ uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
50
+ emit InboxMessageDelivered(msgNum, messageData);
51
+ return msgNum;
52
+ }
53
+
54
+ function deliverToBridge(
55
+ uint8 kind,
56
+ address sender,
57
+ bytes32 messageDataHash
58
+ ) internal returns (uint256) {
59
+ return bridge.enqueueDelayedMessage{value: msg.value}(kind, sender, messageDataHash);
60
+ }
61
+
62
+ function sendUnsignedTransaction(
63
+ uint256,
64
+ uint256,
65
+ uint256,
66
+ address,
67
+ uint256,
68
+ bytes calldata
69
+ ) external pure override returns (uint256) {
70
+ revert("NOT_IMPLEMENTED");
71
+ }
72
+
73
+ function sendContractTransaction(
74
+ uint256,
75
+ uint256,
76
+ address,
77
+ uint256,
78
+ bytes calldata
79
+ ) external pure override returns (uint256) {
80
+ revert("NOT_IMPLEMENTED");
81
+ }
82
+
83
+ function sendL1FundedUnsignedTransaction(
84
+ uint256,
85
+ uint256,
86
+ uint256,
87
+ address,
88
+ bytes calldata
89
+ ) external payable override returns (uint256) {
90
+ revert("NOT_IMPLEMENTED");
91
+ }
92
+
93
+ function sendL1FundedContractTransaction(
94
+ uint256,
95
+ uint256,
96
+ address,
97
+ bytes calldata
98
+ ) external payable override returns (uint256) {
99
+ revert("NOT_IMPLEMENTED");
100
+ }
101
+
102
+ function createRetryableTicket(
103
+ address,
104
+ uint256,
105
+ uint256,
106
+ address,
107
+ address,
108
+ uint256,
109
+ uint256,
110
+ bytes calldata
111
+ ) external payable override returns (uint256) {
112
+ revert("NOT_IMPLEMENTED");
113
+ }
114
+
115
+ function unsafeCreateRetryableTicket(
116
+ address,
117
+ uint256,
118
+ uint256,
119
+ address,
120
+ address,
121
+ uint256,
122
+ uint256,
123
+ bytes calldata
124
+ ) external payable override returns (uint256) {
125
+ revert("NOT_IMPLEMENTED");
126
+ }
127
+
128
+ function depositEth(uint256) external payable override returns (uint256) {
129
+ revert("NOT_IMPLEMENTED");
130
+ }
131
+ }
@@ -0,0 +1,59 @@
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 "../challenge/IChallengeResultReceiver.sol";
8
+ import "../challenge/IChallengeManager.sol";
9
+
10
+ contract MockResultReceiver is IChallengeResultReceiver {
11
+ IChallengeManager public manager;
12
+ address public winner;
13
+ address public loser;
14
+ uint256 public challengeIndex;
15
+
16
+ event ChallengeCompleted(
17
+ uint256 indexed challengeIndex,
18
+ address indexed winner,
19
+ address indexed loser
20
+ );
21
+
22
+ constructor(IChallengeManager manager_) {
23
+ manager = manager_;
24
+ }
25
+
26
+ function createChallenge(
27
+ bytes32 wasmModuleRoot_,
28
+ MachineStatus[2] calldata startAndEndMachineStatuses_,
29
+ GlobalState[2] calldata startAndEndGlobalStates_,
30
+ uint64 numBlocks,
31
+ address asserter_,
32
+ address challenger_,
33
+ uint256 asserterTimeLeft_,
34
+ uint256 challengerTimeLeft_
35
+ ) external returns (uint64) {
36
+ return
37
+ manager.createChallenge(
38
+ wasmModuleRoot_,
39
+ startAndEndMachineStatuses_,
40
+ startAndEndGlobalStates_,
41
+ numBlocks,
42
+ asserter_,
43
+ challenger_,
44
+ asserterTimeLeft_,
45
+ challengerTimeLeft_
46
+ );
47
+ }
48
+
49
+ function completeChallenge(
50
+ uint256 challengeIndex_,
51
+ address winner_,
52
+ address loser_
53
+ ) external override {
54
+ winner = winner_;
55
+ loser = loser_;
56
+ challengeIndex = challengeIndex_;
57
+ emit ChallengeCompleted(challengeIndex, winner_, loser_);
58
+ }
59
+ }
@@ -0,0 +1,42 @@
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 "../bridge/SequencerInbox.sol";
8
+
9
+ contract SequencerInboxStub is SequencerInbox {
10
+ constructor(
11
+ IBridge delayedBridge_,
12
+ address sequencer_,
13
+ ISequencerInbox.MaxTimeVariation memory maxTimeVariation_
14
+ ) {
15
+ delayedBridge = delayedBridge_;
16
+ rollup = msg.sender;
17
+ maxTimeVariation = maxTimeVariation_;
18
+ isBatchPoster[sequencer_] = true;
19
+ }
20
+
21
+ function addInitMessage() external {
22
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(0);
23
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
24
+ dataHash,
25
+ 0
26
+ );
27
+ emit SequencerBatchDelivered(
28
+ inboxAccs.length - 1,
29
+ beforeAcc,
30
+ afterAcc,
31
+ delayedAcc,
32
+ totalDelayedMessagesRead,
33
+ timeBounds,
34
+ BatchDataLocation.NoData
35
+ );
36
+ }
37
+
38
+ function getTimeBounds() internal view override returns (TimeBounds memory bounds) {
39
+ this; // silence warning about function not being view
40
+ return bounds;
41
+ }
42
+ }
@@ -0,0 +1,19 @@
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/Proxy.sol";
8
+
9
+ contract SimpleProxy is Proxy {
10
+ address private immutable impl;
11
+
12
+ constructor(address impl_) {
13
+ impl = impl_;
14
+ }
15
+
16
+ function _implementation() internal view override returns (address) {
17
+ return impl;
18
+ }
19
+ }
@@ -0,0 +1,50 @@
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.4.21 <0.9.0;
6
+
7
+ /** @title Interface for providing gas estimation for retryable auto-redeems and constructing outbox proofs
8
+ * @notice This contract doesn't exist on-chain. Instead it is a virtual interface accessible at
9
+ * 0x00000000000000000000000000000000000000C8
10
+ * This is a cute trick to allow an Arbitrum node to provide data without us having to implement additional RPCs
11
+ */
12
+
13
+ interface NodeInterface {
14
+ /**
15
+ * @notice Estimate the cost of putting a message in the L2 inbox that is reexecuted
16
+ * @param sender sender of the L1 and L2 transaction
17
+ * @param deposit amount to deposit to sender in L2
18
+ * @param to destination L2 contract address
19
+ * @param l2CallValue call value for retryable L2 message
20
+ * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
21
+ * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
22
+ * @param data ABI encoded data of L2 message
23
+ */
24
+ function estimateRetryableTicket(
25
+ address sender,
26
+ uint256 deposit,
27
+ address to,
28
+ uint256 l2CallValue,
29
+ address excessFeeRefundAddress,
30
+ address callValueRefundAddress,
31
+ bytes calldata data
32
+ ) external;
33
+
34
+ /**
35
+ * @notice Constructs an outbox proof of an l2->l1 send's existence in the outbox accumulator
36
+ * @param size the number of elements in the accumulator
37
+ * @param leaf the position of the send in the accumulator
38
+ * @return send the l2->l1 send's hash
39
+ * @return root the root of the outbox accumulator
40
+ * @return proof level-by-level branch hashes constituting a proof of the send's membership at the given size
41
+ */
42
+ function constructOutboxProof(uint64 size, uint64 leaf)
43
+ external
44
+ view
45
+ returns (
46
+ bytes32 send,
47
+ bytes32 root,
48
+ bytes32[] memory proof
49
+ );
50
+ }
@@ -0,0 +1,154 @@
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 "../libraries/CryptographyPrimitives.sol";
8
+
9
+ /// @dev The requested hash preimage at the given offset has not been proven yet
10
+ error NotProven(bytes32 fullHash, uint64 offset);
11
+
12
+ contract HashProofHelper {
13
+ struct KeccakState {
14
+ uint64 offset;
15
+ bytes part;
16
+ uint64[25] state;
17
+ uint256 length;
18
+ }
19
+
20
+ struct PreimagePart {
21
+ bool proven;
22
+ bytes part;
23
+ }
24
+
25
+ mapping(bytes32 => mapping(uint64 => PreimagePart)) private preimageParts;
26
+ mapping(address => KeccakState) public keccakStates;
27
+
28
+ event PreimagePartProven(bytes32 indexed fullHash, uint64 indexed offset, bytes part);
29
+
30
+ uint256 private constant MAX_PART_LENGTH = 32;
31
+ uint256 private constant KECCAK_ROUND_INPUT = 136;
32
+
33
+ function proveWithFullPreimage(bytes calldata data, uint64 offset)
34
+ external
35
+ returns (bytes32 fullHash)
36
+ {
37
+ fullHash = keccak256(data);
38
+ bytes memory part;
39
+ if (data.length > offset) {
40
+ uint256 partLength = data.length - offset;
41
+ if (partLength > 32) {
42
+ partLength = 32;
43
+ }
44
+ part = data[offset:(offset + partLength)];
45
+ }
46
+ preimageParts[fullHash][offset] = PreimagePart({proven: true, part: part});
47
+ emit PreimagePartProven(fullHash, offset, part);
48
+ }
49
+
50
+ // Flags: a bitset signaling various things about the proof, ordered from least to most significant bits.
51
+ // 0th bit: indicates that this data is the final chunk of preimage data.
52
+ // 1st bit: indicates that the preimage part currently being built should be cleared before this.
53
+ function proveWithSplitPreimage(
54
+ bytes calldata data,
55
+ uint64 offset,
56
+ uint256 flags
57
+ ) external returns (bytes32 fullHash) {
58
+ bool isFinal = (flags & (1 << 0)) != 0;
59
+ if ((flags & (1 << 1)) != 0) {
60
+ delete keccakStates[msg.sender];
61
+ }
62
+ require(isFinal || data.length % KECCAK_ROUND_INPUT == 0, "NOT_BLOCK_ALIGNED");
63
+ KeccakState storage state = keccakStates[msg.sender];
64
+ uint256 startLength = state.length;
65
+ if (startLength == 0) {
66
+ state.offset = offset;
67
+ } else {
68
+ require(state.offset == offset, "DIFF_OFFSET");
69
+ }
70
+ keccakUpdate(state, data, isFinal);
71
+ if (uint256(offset) + MAX_PART_LENGTH > startLength && offset < state.length) {
72
+ uint256 startIdx = 0;
73
+ if (offset > startLength) {
74
+ startIdx = offset - startLength;
75
+ }
76
+ uint256 endIdx = uint256(offset) + MAX_PART_LENGTH - startLength;
77
+ if (endIdx > data.length) {
78
+ endIdx = data.length;
79
+ }
80
+ for (uint256 i = startIdx; i < endIdx; i++) {
81
+ state.part.push(data[i]);
82
+ }
83
+ }
84
+ if (!isFinal) {
85
+ return bytes32(0);
86
+ }
87
+ for (uint256 i = 0; i < 32; i++) {
88
+ uint256 stateIdx = i / 8;
89
+ // work around our weird keccakF function state ordering
90
+ stateIdx = 5 * (stateIdx % 5) + stateIdx / 5;
91
+ uint8 b = uint8(state.state[stateIdx] >> ((i % 8) * 8));
92
+ fullHash |= bytes32(uint256(b) << (248 - (i * 8)));
93
+ }
94
+ preimageParts[fullHash][state.offset] = PreimagePart({proven: true, part: state.part});
95
+ emit PreimagePartProven(fullHash, state.offset, state.part);
96
+ delete keccakStates[msg.sender];
97
+ }
98
+
99
+ function keccakUpdate(
100
+ KeccakState storage state,
101
+ bytes calldata data,
102
+ bool isFinal
103
+ ) internal {
104
+ state.length += data.length;
105
+ while (true) {
106
+ if (data.length == 0 && !isFinal) {
107
+ break;
108
+ }
109
+ for (uint256 i = 0; i < KECCAK_ROUND_INPUT; i++) {
110
+ uint8 b = 0;
111
+ if (i < data.length) {
112
+ b = uint8(data[i]);
113
+ } else {
114
+ // Padding
115
+ if (i == data.length) {
116
+ b |= uint8(0x01);
117
+ }
118
+ if (i == KECCAK_ROUND_INPUT - 1) {
119
+ b |= uint8(0x80);
120
+ }
121
+ }
122
+ uint256 stateIdx = i / 8;
123
+ // work around our weird keccakF function state ordering
124
+ stateIdx = 5 * (stateIdx % 5) + stateIdx / 5;
125
+ state.state[stateIdx] ^= uint64(b) << uint64((i % 8) * 8);
126
+ }
127
+ uint256[25] memory state256;
128
+ for (uint256 i = 0; i < 25; i++) {
129
+ state256[i] = state.state[i];
130
+ }
131
+ state256 = CryptographyPrimitives.keccakF(state256);
132
+ for (uint256 i = 0; i < 25; i++) {
133
+ state.state[i] = uint64(state256[i]);
134
+ }
135
+ if (data.length < KECCAK_ROUND_INPUT) {
136
+ break;
137
+ }
138
+ data = data[KECCAK_ROUND_INPUT:];
139
+ }
140
+ }
141
+
142
+ function clearSplitProof() external {
143
+ delete keccakStates[msg.sender];
144
+ }
145
+
146
+ /// Retrieves up to 32 bytes of the preimage of fullHash at the given offset, reverting if it hasn't been proven yet.
147
+ function getPreimagePart(bytes32 fullHash, uint64 offset) external view returns (bytes memory) {
148
+ PreimagePart storage part = preimageParts[fullHash][offset];
149
+ if (!part.proven) {
150
+ revert NotProven(fullHash, offset);
151
+ }
152
+ return part.part;
153
+ }
154
+ }
@@ -0,0 +1,20 @@
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 "./IOneStepProver.sol";
8
+
9
+ library OneStepProofEntryLib {
10
+ uint256 internal constant MAX_STEPS = 1 << 43;
11
+ }
12
+
13
+ interface IOneStepProofEntry {
14
+ function proveOneStep(
15
+ ExecutionContext calldata execCtx,
16
+ uint256 machineStep,
17
+ bytes32 beforeHash,
18
+ bytes calldata proof
19
+ ) external view returns (bytes32 afterHash);
20
+ }
@@ -0,0 +1,27 @@
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/Module.sol";
9
+ import "../state/Instructions.sol";
10
+ import "../bridge/ISequencerInbox.sol";
11
+ import "../bridge/IBridge.sol";
12
+
13
+ struct ExecutionContext {
14
+ uint256 maxInboxMessagesRead;
15
+ ISequencerInbox sequencerInbox;
16
+ IBridge delayedBridge;
17
+ }
18
+
19
+ abstract contract IOneStepProver {
20
+ function executeOneStep(
21
+ ExecutionContext memory execCtx,
22
+ Machine calldata mach,
23
+ Module calldata mod,
24
+ Instruction calldata instruction,
25
+ bytes calldata proof
26
+ ) external view virtual returns (Machine memory result, Module memory resultMod);
27
+ }