@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.
- package/.prettierrc +5 -0
- package/.solhint.json +18 -0
- package/deploy/BridgeStubCreator.js +10 -0
- package/deploy/HashProofHelper.js +13 -0
- package/deploy/InboxStubCreator.js +17 -0
- package/deploy/OneStepProofEntryCreator.js +19 -0
- package/deploy/OneStepProver0Creator.js +14 -0
- package/deploy/OneStepProverHostIoCreator.js +14 -0
- package/deploy/OneStepProverMathCreator.js +14 -0
- package/deploy/OneStepProverMemoryCreator.js +14 -0
- package/deploy/SequencerInboxStubCreator.js +13 -0
- package/deploy/ValueArrayTesterCreator.js +13 -0
- package/hardhat.config.ts +47 -0
- package/hardhat.prod-config.js +18 -0
- package/package.json +49 -0
- package/scripts/build.bash +5 -0
- package/src/bridge/Bridge.sol +168 -0
- package/src/bridge/IBridge.sol +68 -0
- package/src/bridge/IInbox.sol +80 -0
- package/src/bridge/IMessageProvider.sol +11 -0
- package/src/bridge/IOutbox.sol +52 -0
- package/src/bridge/ISequencerInbox.sol +85 -0
- package/src/bridge/Inbox.sol +414 -0
- package/src/bridge/Messages.sol +38 -0
- package/src/bridge/Outbox.sol +188 -0
- package/src/bridge/SequencerInbox.sol +274 -0
- package/src/challenge/ChallengeLib.sol +135 -0
- package/src/challenge/ChallengeManager.sol +367 -0
- package/src/challenge/IChallengeManager.sol +75 -0
- package/src/challenge/IChallengeResultReceiver.sol +13 -0
- package/src/libraries/AddressAliasHelper.sol +29 -0
- package/src/libraries/AdminFallbackProxy.sol +153 -0
- package/src/libraries/ArbitrumProxy.sol +20 -0
- package/src/libraries/Constants.sol +10 -0
- package/src/libraries/CryptographyPrimitives.sol +323 -0
- package/src/libraries/DelegateCallAware.sol +44 -0
- package/src/libraries/Error.sol +38 -0
- package/src/libraries/IGasRefunder.sol +35 -0
- package/src/libraries/MerkleLib.sol +46 -0
- package/src/libraries/MessageTypes.sol +14 -0
- package/src/libraries/SecondaryLogicUUPSUpgradeable.sol +58 -0
- package/src/libraries/UUPSNotUpgradeable.sol +56 -0
- package/src/mocks/BridgeStub.sol +115 -0
- package/src/mocks/Counter.sol +13 -0
- package/src/mocks/ExecutionManager.sol +41 -0
- package/src/mocks/InboxStub.sol +131 -0
- package/src/mocks/MockResultReceiver.sol +59 -0
- package/src/mocks/SequencerInboxStub.sol +42 -0
- package/src/mocks/SimpleProxy.sol +19 -0
- package/src/node-interface/NodeInterface.sol +50 -0
- package/src/osp/HashProofHelper.sol +154 -0
- package/src/osp/IOneStepProofEntry.sol +20 -0
- package/src/osp/IOneStepProver.sol +27 -0
- package/src/osp/OneStepProofEntry.sol +129 -0
- package/src/osp/OneStepProver0.sol +566 -0
- package/src/osp/OneStepProverHostIo.sol +357 -0
- package/src/osp/OneStepProverMath.sol +514 -0
- package/src/osp/OneStepProverMemory.sol +313 -0
- package/src/precompiles/ArbAddressTable.sol +60 -0
- package/src/precompiles/ArbAggregator.sol +62 -0
- package/src/precompiles/ArbBLS.sol +53 -0
- package/src/precompiles/ArbDebug.sol +39 -0
- package/src/precompiles/ArbFunctionTable.sol +29 -0
- package/src/precompiles/ArbGasInfo.sol +121 -0
- package/src/precompiles/ArbInfo.sol +15 -0
- package/src/precompiles/ArbOwner.sol +65 -0
- package/src/precompiles/ArbOwnerPublic.sol +18 -0
- package/src/precompiles/ArbRetryableTx.sol +89 -0
- package/src/precompiles/ArbStatistics.sol +29 -0
- package/src/precompiles/ArbSys.sol +134 -0
- package/src/precompiles/ArbosActs.sol +41 -0
- package/src/precompiles/ArbosTest.sol +14 -0
- package/src/rollup/BridgeCreator.sol +120 -0
- package/src/rollup/IRollupCore.sol +152 -0
- package/src/rollup/IRollupLogic.sol +183 -0
- package/src/rollup/Node.sol +99 -0
- package/src/rollup/RollupAdminLogic.sol +322 -0
- package/src/rollup/RollupCore.sol +627 -0
- package/src/rollup/RollupCreator.sol +133 -0
- package/src/rollup/RollupEventBridge.sol +46 -0
- package/src/rollup/RollupLib.sol +135 -0
- package/src/rollup/RollupUserLogic.sol +712 -0
- package/src/rollup/ValidatorUtils.sol +243 -0
- package/src/rollup/ValidatorWallet.sol +76 -0
- package/src/rollup/ValidatorWalletCreator.sol +43 -0
- package/src/state/Deserialize.sol +321 -0
- package/src/state/GlobalState.sol +44 -0
- package/src/state/Instructions.sol +159 -0
- package/src/state/Machine.sol +65 -0
- package/src/state/MerkleProof.sol +99 -0
- package/src/state/Module.sol +33 -0
- package/src/state/ModuleMemory.sol +42 -0
- package/src/state/PcArray.sol +45 -0
- package/src/state/PcStack.sol +32 -0
- package/src/state/StackFrame.sol +63 -0
- package/src/state/Value.sol +65 -0
- package/src/state/ValueArray.sol +47 -0
- package/src/state/ValueStack.sol +39 -0
- package/src/test-helpers/CryptographyPrimitivesTester.sol +27 -0
- package/src/test-helpers/MessageTester.sol +34 -0
- package/src/test-helpers/ValueArrayTester.sol +34 -0
- package/test/contract/arbRollup.spec.ts +869 -0
- package/test/contract/common/challengeLib.ts +43 -0
- package/test/contract/common/globalStateLib.ts +17 -0
- package/test/contract/common/rolluplib.ts +259 -0
- package/test/contract/cryptographyPrimitives.spec.ts +82 -0
- package/test/contract/sequencerInboxForceInclude.spec.ts +516 -0
- package/test/contract/utils.ts +40 -0
- package/test/prover/hash-proofs.ts +75 -0
- package/test/prover/one-step-proof.ts +93 -0
- package/test/prover/proofs/.gitkeep +0 -0
- package/test/prover/value-arrays.ts +11 -0
- 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
|
+
}
|