@arbitrum/nitro-contracts 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|