diff --git a/.github/workflows/contract-tests.yml b/.github/workflows/contract-tests.yml index f8636ed3..28090d00 100644 --- a/.github/workflows/contract-tests.yml +++ b/.github/workflows/contract-tests.yml @@ -12,7 +12,7 @@ on: jobs: test-unit: name: Test unit - runs-on: ubuntu-latest + runs-on: linux-2xl steps: - uses: actions/checkout@v3 with: @@ -34,10 +34,10 @@ jobs: run: yarn - name: Build - run: forge test + run: forge test --fork-url https://rpc.holesky.ethpandaops.io/ tests: name: Contract tests - runs-on: ubuntu-8 + runs-on: linux-2xl defaults: run: shell: bash @@ -106,7 +106,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} test-4844: name: 4844 tests - runs-on: ubuntu-latest + runs-on: linux-2xl steps: - uses: actions/checkout@v3 with: diff --git a/.gitmodules b/.gitmodules index 21bc9153..a22a2b5d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/foundry-rs/forge-std [submodule "lib/eigenda"] path = lib/eigenda - url = https://github.com/Layr-Labs/eigenda \ No newline at end of file + url = https://github.com/Layr-Labs/eigenda diff --git a/deploy/EigenDARollupManagerStubCreator.js b/deploy/EigenDARollupManagerStubCreator.js new file mode 100644 index 00000000..ef109419 --- /dev/null +++ b/deploy/EigenDARollupManagerStubCreator.js @@ -0,0 +1,11 @@ +module.exports = async hre => { + const { deployments, getNamedAccounts, ethers } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + + await deploy('EigenDADummyManager', { from: deployer, args: [] }) + } + + module.exports.tags = ['EigenDADummyManager'] + module.exports.dependencies = [] + \ No newline at end of file diff --git a/deploy/EigenDAServiceManagerStubCreator.js b/deploy/EigenDAServiceManagerStubCreator.js new file mode 100644 index 00000000..31b1182c --- /dev/null +++ b/deploy/EigenDAServiceManagerStubCreator.js @@ -0,0 +1,10 @@ +module.exports = async hre => { + const { deployments, getNamedAccounts, ethers } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + + await deploy('EigenDAServiceManagerStub', { from: deployer, args: [] }) +} + +module.exports.tags = ['EigenDAServiceManagerStub', 'test'] +module.exports.dependencies = [] diff --git a/deploy/SequencerInbox.js b/deploy/SequencerInbox.js index d90135a9..0aeebb60 100644 --- a/deploy/SequencerInbox.js +++ b/deploy/SequencerInbox.js @@ -6,8 +6,12 @@ module.exports = async hre => { const blobBasefeeReader = await ethers.getContract('BlobBasefeeReader') const dataHashReader = await ethers.getContract('DataHashReader') - await deploy('SequencerInbox', { from: deployer, args: [117964] }) + const EigenDARollupUtils = await ethers.getContract('EigenDARollupUtils') + + + + await deploy('SequencerInbox', { from: deployer, args: [117964], libraries: { EigenDARollupUtils: EigenDARollupUtils.address } }) } module.exports.tags = ['SequencerInbox'] -module.exports.dependencies = [] +module.exports.dependencies = ['EigenDARollupUtils'] diff --git a/deploy/SequencerInboxStubCreator.js b/deploy/SequencerInboxStubCreator.js index e61a227c..495263c9 100644 --- a/deploy/SequencerInboxStubCreator.js +++ b/deploy/SequencerInboxStubCreator.js @@ -15,6 +15,7 @@ module.exports = async hre => { delaySeconds: 10000, futureSeconds: 10000, } + await deploy('SequencerInboxStub', { from: deployer, args: [ diff --git a/hello.txt b/hello.txt new file mode 100644 index 00000000..e69de29b diff --git a/package.json b/package.json index c81d3f32..9237eaa0 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,13 @@ "deploy-cachemanager-testnode": "hardhat run scripts/local-deployment/deployCacheManager.ts" }, "dependencies": { + "@eigenda/eigenda-utils": "2.0.0", + "@grpc/grpc-js": "^1.8.22", + "@grpc/proto-loader": "^0.7.13", "@offchainlabs/upgrade-executor": "1.1.0-beta.0", - "@openzeppelin/contracts": "4.5.0", - "@openzeppelin/contracts-upgradeable": "4.5.2", + "@openzeppelin/contracts": "4.7.0", + "@openzeppelin-upgrades/contracts": "npm:@openzeppelin/contracts-upgradeable@4.7", + "@openzeppelin/contracts-upgradeable": "4.7.2", "patch-package": "^6.4.7", "solady": "0.0.182" }, @@ -64,6 +68,7 @@ "@typechain/ethers-v5": "^10.0.0", "@typechain/hardhat": "^6.0.0", "@types/chai": "^4.3.0", + "@types/google-protobuf": "^3.15.12", "@types/mocha": "^9.0.0", "@types/node": "^17.0.5", "@typescript-eslint/eslint-plugin": "^5.14.0", diff --git a/scripts/deploymentUtils.ts b/scripts/deploymentUtils.ts index 582ae67d..ae4ea53b 100644 --- a/scripts/deploymentUtils.ts +++ b/scripts/deploymentUtils.ts @@ -63,6 +63,7 @@ export async function deployContract( verify: boolean = true, overrides?: Overrides ): Promise { + console.log("Deploying contract EigenDA x Arbitrum", contractName) const factory: ContractFactory = await ethers.getContractFactory(contractName) const connectedFactory: ContractFactory = factory.connect(signer) @@ -100,6 +101,8 @@ export async function deployAllContracts( ): Promise> { const isOnArb = await _isRunningOnArbitrum(signer) + const eigenDARollupManager = await deployContract('EigenDADummyManager', signer, [], verify) + const ethBridge = await deployContract('Bridge', signer, [], verify) const reader4844 = isOnArb ? ethers.constants.AddressZero @@ -227,6 +230,7 @@ export async function deployAllContracts( ) const deployHelper = await deployContract('DeployHelper', signer, [], verify) return { + ethSequencerInbox, bridgeCreator, prover0, proverMem, @@ -241,6 +245,7 @@ export async function deployAllContracts( validatorWalletCreator, rollupCreator, deployHelper, + eigenDARollupManager, } } diff --git a/scripts/local-deployment/deployCreatorAndCreateRollup.ts b/scripts/local-deployment/deployCreatorAndCreateRollup.ts index 1a63b2f7..c814aa27 100644 --- a/scripts/local-deployment/deployCreatorAndCreateRollup.ts +++ b/scripts/local-deployment/deployCreatorAndCreateRollup.ts @@ -74,7 +74,8 @@ async function main() { deployerWallet, true, contracts.rollupCreator.address, - feeToken + feeToken, + contracts.eigenDARollupManager.address, ) if (!result) { diff --git a/scripts/rollupCreation.ts b/scripts/rollupCreation.ts index e70b82dc..66632835 100644 --- a/scripts/rollupCreation.ts +++ b/scripts/rollupCreation.ts @@ -61,7 +61,8 @@ export async function createRollup( signer: Signer, isDevDeployment: boolean, rollupCreatorAddress: string, - feeToken: string + feeToken: string, + eigenDARollupManager: string, ): Promise<{ rollupCreationResult: RollupCreationResult chainInfo: ChainInfo @@ -101,7 +102,7 @@ export async function createRollup( // Call the createRollup function console.log('Calling createRollup to generate a new rollup ...') const deployParams = isDevDeployment - ? await _getDevRollupConfig(feeToken, validatorWalletCreator) + ? await _getDevRollupConfig(eigenDARollupManager, feeToken, validatorWalletCreator) : { config: config.rollupConfig, validators: config.validators, @@ -111,6 +112,7 @@ export async function createRollup( maxFeePerGasForRetryables: MAX_FER_PER_GAS, batchPosters: config.batchPosters, batchPosterManager: config.batchPosterManager, + eigenDARollupManager: eigenDARollupManager } const createRollupTx = await rollupCreator.createRollup(deployParams, { @@ -229,6 +231,7 @@ export async function createRollup( } async function _getDevRollupConfig( + rollupManager: string, feeToken: string, validatorWalletCreator: string ) { @@ -329,6 +332,7 @@ async function _getDevRollupConfig( maxFeePerGasForRetryables: MAX_FER_PER_GAS, batchPosters: batchPosters, batchPosterManager: batchPosterManager, + eigenDARollupManager: rollupManager } function _createValidatorAddress( diff --git a/src/bridge/IBridge.sol b/src/bridge/IBridge.sol index 1137fcd3..3c55a811 100644 --- a/src/bridge/IBridge.sol +++ b/src/bridge/IBridge.sol @@ -20,7 +20,9 @@ interface IBridge { /// @notice This batch contains no data NoData, /// @notice The data can be found in the 4844 data blobs on this transaction - Blob + Blob, + /// @notice The data can be found in the EigenDA blob associated with this batch + EigenDA } struct TimeBounds { @@ -42,10 +44,7 @@ interface IBridge { ); event BridgeCallTriggered( - address indexed outbox, - address indexed to, - uint256 value, - bytes data + address indexed outbox, address indexed to, uint256 value, bytes data ); event InboxToggle(address indexed inbox, bool enabled); @@ -78,11 +77,9 @@ interface IBridge { function sequencerReportedSubMessageCount() external view returns (uint256); - function executeCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success, bytes memory returnData); + function executeCall(address to, uint256 value, bytes calldata data) + external + returns (bool success, bytes memory returnData); function delayedMessageCount() external view returns (uint256); @@ -97,12 +94,7 @@ interface IBridge { uint256 newMessageCount ) external - returns ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 acc - ); + returns (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 acc); /** * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type diff --git a/src/bridge/ISequencerInbox.sol b/src/bridge/ISequencerInbox.sol index 47db30f0..2883139d 100644 --- a/src/bridge/ISequencerInbox.sol +++ b/src/bridge/ISequencerInbox.sol @@ -10,6 +10,9 @@ import "../libraries/IGasRefunder.sol"; import "./IDelayedMessageProvider.sol"; import "./IBridge.sol"; +import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; + interface ISequencerInbox is IDelayedMessageProvider { struct MaxTimeVariation { uint256 delayBlocks; @@ -83,6 +86,12 @@ interface ISequencerInbox is IDelayedMessageProvider { // solhint-disable-next-line func-name-mixedcase function ZERO_HEAVY_MESSAGE_HEADER_FLAG() external view returns (bytes1); + /// @dev If the first data byte after the header has this bit set, + /// then the batch data is an eigenDA message + /// See: https://github.com/Layr-Labs/nitro/blob/2ad088cb5943ec50ed8b521c4681561817a602c5/das/eigenda/eigenda.go + // solhint-disable-next-line func-name-mixedcase + function EIGENDA_MESSAGE_HEADER_FLAG() external view returns (bytes1); + function rollup() external view returns (IOwnable); function isBatchPoster(address) external view returns (bool); @@ -179,8 +188,29 @@ interface ISequencerInbox is IDelayedMessageProvider { uint256 newMessageCount ) external; + function addSequencerL2BatchFromEigenDA( + uint256 sequenceNumber, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof, + IEigenDAServiceManager.BlobHeader calldata blobHeader, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount + ) external; + // ---------- onlyRollupOrOwner functions ---------- + /** + * @notice Set the rollup manager contract address + * @param newRollupManager the new rollup manager contract address + */ + function setEigenDARollupManager(address newRollupManager) external; + + /** + * @notice Set the new rollup contract address + */ + function setRollupAddress() external; + + /** * @notice Set max delay for sequencer inbox * @param maxTimeVariation_ the maximum time variation parameters @@ -223,6 +253,7 @@ interface ISequencerInbox is IDelayedMessageProvider { /// @notice Allows the rollup owner to sync the rollup address function updateRollupAddress() external; + // ---------- initializer ---------- function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external; diff --git a/src/bridge/RollupManager.sol b/src/bridge/RollupManager.sol new file mode 100644 index 00000000..7e8a4a39 --- /dev/null +++ b/src/bridge/RollupManager.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.9; + +import {Merkle} from "@eigenda/eigenda-utils/libraries/Merkle.sol"; +import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; +import {EigenDAHasher} from "@eigenda/eigenda-utils/libraries/EigenDAHasher.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; +import {BitmapUtils} from "@eigenda/eigenda-utils/libraries/BitmapUtils.sol"; +import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; +import {IBLSSignatureChecker} from "@eigenda/eigenda-utils/interfaces/IBLSSignatureChecker.sol"; +import {IPaymentCoordinator} from "@eigenda/eigenda-utils/interfaces/IPaymentCoordinator.sol"; +import {ISignatureUtils} from "@eigenda/eigenda-utils/interfaces/ISignatureUtils.sol"; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +interface IRollupManager { + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view; + + function openCommitment( + uint256 point, + uint256 evaluation, + BN254.G1Point memory tau, + BN254.G1Point memory commitment, + BN254.G2Point memory proof + ) external view returns(bool); + +} + +// EigenDADummyManager is a dummy implementation of IRollupManager +// and is used in nitro-testnode to avoid the overhead of deploying core EigenDA contracts +// to simplify the testing process. +contract EigenDADummyManager { + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata, + EigenDARollupUtils.BlobVerificationProof calldata + ) external view { + return ; + } + + function openCommitment( + uint256 point, + uint256 evaluation, + BN254.G1Point memory tau, + BN254.G1Point memory commitment, + BN254.G2Point memory proof + ) internal view returns(bool) { + + return EigenDARollupUtils.openCommitment(point, evaluation, tau, commitment, proof); + } +} + +contract EigenDARollupManager is Ownable, IRollupManager { + using BN254 for BN254.G1Point; + + address public eigenDAServiceManager; + + function verifyBlob( + IEigenDAServiceManager.BlobHeader calldata blobHeader, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof + ) external view { + return EigenDARollupUtils.verifyBlob(blobHeader, IEigenDAServiceManager(eigenDAServiceManager), blobVerificationProof); + } + + function openCommitment( + uint256 point, + uint256 evaluation, + BN254.G1Point memory tau, + BN254.G1Point memory commitment, + BN254.G2Point memory proof + ) external view returns(bool) { + + return EigenDARollupUtils.openCommitment(point, evaluation, tau, commitment, proof); + } + + function setEigenDAServiceManager(address _eigenDAServiceManager) external onlyOwner { + eigenDAServiceManager = _eigenDAServiceManager; + } +} diff --git a/src/bridge/SequencerInbox.sol b/src/bridge/SequencerInbox.sol index 16a65e77..c196c4c7 100644 --- a/src/bridge/SequencerInbox.sol +++ b/src/bridge/SequencerInbox.sol @@ -47,6 +47,10 @@ import {GasRefundEnabled} from "../libraries/GasRefundEnabled.sol"; import "../libraries/ArbitrumChecker.sol"; import {IERC20Bridge} from "./IERC20Bridge.sol"; +import {IRollupManager} from "./RollupManager.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; + + /** * @title Accepts batches from the sequencer and adds them to the rollup inbox. * @notice Contains the inbox accumulator which is the ordering of all data and transactions to be processed by the rollup. @@ -59,6 +63,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox IBridge public bridge; + address public eigenDARollupManager; + /// @inheritdoc ISequencerInbox uint256 public constant HEADER_LENGTH = 40; @@ -80,9 +86,14 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox /// @inheritdoc ISequencerInbox bytes1 public constant ZERO_HEAVY_MESSAGE_HEADER_FLAG = 0x20; + /// @inheritdoc ISequencerInbox + bytes1 public constant EIGENDA_MESSAGE_HEADER_FLAG = 0xed; + // GAS_PER_BLOB from EIP-4844 uint256 internal constant GAS_PER_BLOB = 1 << 17; + uint256 internal constant GAS_PER_SYMBOL_EIGENDA = 1; + IOwnable public rollup; mapping(address => bool) public isBatchPoster; @@ -148,19 +159,19 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox // Assuming we would not upgrade from a version that have MaxTimeVariation all set to zero // If that is the case, postUpgradeInit do not need to be called if ( - __LEGACY_MAX_TIME_VARIATION.delayBlocks == 0 && - __LEGACY_MAX_TIME_VARIATION.futureBlocks == 0 && - __LEGACY_MAX_TIME_VARIATION.delaySeconds == 0 && - __LEGACY_MAX_TIME_VARIATION.futureSeconds == 0 + __LEGACY_MAX_TIME_VARIATION.delayBlocks == 0 + && __LEGACY_MAX_TIME_VARIATION.futureBlocks == 0 + && __LEGACY_MAX_TIME_VARIATION.delaySeconds == 0 + && __LEGACY_MAX_TIME_VARIATION.futureSeconds == 0 ) { revert AlreadyInit(); } if ( - __LEGACY_MAX_TIME_VARIATION.delayBlocks > type(uint64).max || - __LEGACY_MAX_TIME_VARIATION.futureBlocks > type(uint64).max || - __LEGACY_MAX_TIME_VARIATION.delaySeconds > type(uint64).max || - __LEGACY_MAX_TIME_VARIATION.futureSeconds > type(uint64).max + __LEGACY_MAX_TIME_VARIATION.delayBlocks > type(uint64).max + || __LEGACY_MAX_TIME_VARIATION.futureBlocks > type(uint64).max + || __LEGACY_MAX_TIME_VARIATION.delaySeconds > type(uint64).max + || __LEGACY_MAX_TIME_VARIATION.futureSeconds > type(uint64).max ) { revert BadPostUpgradeInit(); } @@ -201,23 +212,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox _setMaxTimeVariation(maxTimeVariation_); } - /// @notice Allows the rollup owner to sync the rollup address - function updateRollupAddress() external { - if (msg.sender != IOwnable(rollup).owner()) - revert NotOwner(msg.sender, IOwnable(rollup).owner()); - IOwnable newRollup = bridge.rollup(); - if (rollup == newRollup) revert RollupNotChanged(); - rollup = newRollup; - } - function getTimeBounds() internal view virtual returns (IBridge.TimeBounds memory) { IBridge.TimeBounds memory bounds; - ( - uint64 delayBlocks_, - uint64 futureBlocks_, - uint64 delaySeconds_, - uint64 futureSeconds_ - ) = maxTimeVariationInternal(); + (uint64 delayBlocks_, uint64 futureBlocks_, uint64 delaySeconds_, uint64 futureSeconds_) = + maxTimeVariationInternal(); if (block.timestamp > delaySeconds_) { bounds.minTimestamp = uint64(block.timestamp) - delaySeconds_; } @@ -238,22 +236,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox futureSeconds = 1; } - function maxTimeVariation() - external - view - returns ( - uint256, - uint256, - uint256, - uint256 - ) - { - ( - uint64 delayBlocks_, - uint64 futureBlocks_, - uint64 delaySeconds_, - uint64 futureSeconds_ - ) = maxTimeVariationInternal(); + function maxTimeVariation() external view returns (uint256, uint256, uint256, uint256) { + (uint64 delayBlocks_, uint64 futureBlocks_, uint64 delaySeconds_, uint64 futureSeconds_) = + maxTimeVariationInternal(); return ( uint256(delayBlocks_), @@ -263,16 +248,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox ); } - function maxTimeVariationInternal() - internal - view - returns ( - uint64, - uint64, - uint64, - uint64 - ) - { + function maxTimeVariationInternal() internal view returns (uint64, uint64, uint64, uint64) { if (_chainIdChanged()) { return (1, 1, 1, 1); } else { @@ -309,28 +285,19 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox prevDelayedAcc = bridge.delayedInboxAccs(_totalDelayedMessagesRead - 2); } if ( - bridge.delayedInboxAccs(_totalDelayedMessagesRead - 1) != - Messages.accumulateInboxMessage(prevDelayedAcc, messageHash) + bridge.delayedInboxAccs(_totalDelayedMessagesRead - 1) + != Messages.accumulateInboxMessage(prevDelayedAcc, messageHash) ) revert IncorrectMessagePreimage(); - (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formEmptyDataHash( - _totalDelayedMessagesRead - ); + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = + formEmptyDataHash(_totalDelayedMessagesRead); uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead; uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount(); uint256 newSeqMsgCount = prevSeqMsgCount; // force inclusion should not modify sequencer message count - ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 afterAcc - ) = addSequencerL2BatchImpl( - dataHash, - __totalDelayedMessagesRead, - 0, - prevSeqMsgCount, - newSeqMsgCount - ); + (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl( + dataHash, __totalDelayedMessagesRead, 0, prevSeqMsgCount, newSeqMsgCount + ); emit SequencerBatchDelivered( seqMessageIndex, beforeAcc, @@ -343,12 +310,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox } /// @dev Deprecated, kept for abi generation and will be removed in the future - function addSequencerL2BatchFromOrigin( - uint256, - bytes calldata, - uint256, - IGasRefunder - ) external pure { + function addSequencerL2BatchFromOrigin(uint256, bytes calldata, uint256, IGasRefunder) + external + pure + { revert Deprecated(); } @@ -363,10 +328,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox // solhint-disable-next-line avoid-tx-origin if (msg.sender != tx.origin) revert NotOrigin(); if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); - (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formCallDataHash( - data, - afterDelayedMessagesRead - ); + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = + formCallDataHash(data, afterDelayedMessagesRead); // Reformat the stack to prevent "Stack too deep" uint256 sequenceNumber_ = sequenceNumber; IBridge.TimeBounds memory timeBounds_ = timeBounds; @@ -375,18 +338,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead; uint256 prevMessageCount_ = prevMessageCount; uint256 newMessageCount_ = newMessageCount; - ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 afterAcc - ) = addSequencerL2BatchImpl( - dataHash_, - afterDelayedMessagesRead_, - dataLength, - prevMessageCount_, - newMessageCount_ - ); + (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl( + dataHash_, afterDelayedMessagesRead_, dataLength, prevMessageCount_, newMessageCount_ + ); // ~uint256(0) is type(uint256).max, but ever so slightly cheaper if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0)) { @@ -412,27 +367,16 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 newMessageCount ) external refundsGas(gasRefunder, reader4844) { if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); - ( - bytes32 dataHash, - IBridge.TimeBounds memory timeBounds, - uint256 blobGas - ) = formBlobDataHash(afterDelayedMessagesRead); + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds, uint256 blobGas) = + formBlobDataHash(afterDelayedMessagesRead); // we use addSequencerL2BatchImpl for submitting the message // normally this would also submit a batch spending report but that is skipped if we pass // an empty call data size, then we submit a separate batch spending report later - ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 afterAcc - ) = addSequencerL2BatchImpl( - dataHash, - afterDelayedMessagesRead, - 0, - prevMessageCount, - newMessageCount - ); + (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl( + dataHash, afterDelayedMessagesRead, 0, prevMessageCount, newMessageCount + ); uint256 _sequenceNumber = sequenceNumber; // stack workaround @@ -464,6 +408,59 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox submitBatchSpendingReport(dataHash, seqMessageIndex, block.basefee, blobGas); } } + + + + function addSequencerL2BatchFromEigenDA( + uint256 sequenceNumber, + EigenDARollupUtils.BlobVerificationProof calldata blobVerificationProof, + IEigenDAServiceManager.BlobHeader calldata blobHeader, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount + ) external { + if (!isBatchPoster[msg.sender]) revert NotBatchPoster(); + + // verify that the blob was actually included before continuing + IRollupManager(eigenDARollupManager).verifyBlob(blobHeader, blobVerificationProof); + + + // NOTE: to retrieve need the following + // see: https://github.com/Layr-Labs/eigenda/blob/master/api/docs/retriever.md#blobrequest + // batch header hash -> can get by computing hash(blobVerificationproof.batchMetadata.batchheader) + // blob index -> included in blobVerificationproof.blobIndex + // reference block number -> included in blobVerificationproof.batchMetadata.BatchHeaderreferenceBlockNumber + // quorum id -> included in blobHeader.QuorumBlobParam[0].quorumNumber + // todo: what do to for dual quorum? + ( + bytes32 dataHash, + IBridge.TimeBounds memory timeBounds, + uint256 eigenDABatchCost //set as 0 rn + ) = formEigenDADataHash(blobHeader, afterDelayedMessagesRead); + + (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl( + dataHash, afterDelayedMessagesRead, 0, prevMessageCount, newMessageCount + ); + + uint256 _sequenceNumber = sequenceNumber; // stack workaround + + // ~uint256(0) is type(uint256).max, but ever so slightly cheaper + if (seqMessageIndex != _sequenceNumber && _sequenceNumber != ~uint256(0)) { + revert BadSequencerNumber(seqMessageIndex, _sequenceNumber); + } + + emit SequencerBatchDelivered( + _sequenceNumber, + beforeAcc, + afterAcc, + delayedAcc, + totalDelayedMessagesRead, + timeBounds, + IBridge.BatchDataLocation.EigenDA + + ); + } function addSequencerL2Batch( uint256 sequenceNumber, @@ -474,10 +471,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 newMessageCount ) external override refundsGas(gasRefunder, IReader4844(address(0))) { if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster(); - (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formCallDataHash( - data, - afterDelayedMessagesRead - ); + (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = + formCallDataHash(data, afterDelayedMessagesRead); uint256 seqMessageIndex; { // Reformat the stack to prevent "Stack too deep" @@ -493,11 +488,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox bytes32 delayedAcc; bytes32 afterAcc; (seqMessageIndex, beforeAcc, delayedAcc, afterAcc) = addSequencerL2BatchImpl( - dataHash_, - afterDelayedMessagesRead_, - 0, - prevMessageCount_, - newMessageCount_ + dataHash_, afterDelayedMessagesRead_, 0, prevMessageCount_, newMessageCount_ ); // ~uint256(0) is type(uint256).max, but ever so slightly cheaper @@ -545,9 +536,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox view returns (bytes32, IBridge.TimeBounds memory) { - (bytes memory header, IBridge.TimeBounds memory timeBounds) = packHeader( - afterDelayedMessagesRead - ); + (bytes memory header, IBridge.TimeBounds memory timeBounds) = + packHeader(afterDelayedMessagesRead); return (keccak256(header), timeBounds); } @@ -557,11 +547,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox /// This also safe guards unused flags for future use, as we know they would have been disallowed up until this point /// @param headerByte The first byte in the calldata function isValidCallDataFlag(bytes1 headerByte) internal pure returns (bool) { - return - headerByte == BROTLI_MESSAGE_HEADER_FLAG || - headerByte == DAS_MESSAGE_HEADER_FLAG || - (headerByte == (DAS_MESSAGE_HEADER_FLAG | TREE_DAS_MESSAGE_HEADER_FLAG)) || - headerByte == ZERO_HEAVY_MESSAGE_HEADER_FLAG; + return headerByte == BROTLI_MESSAGE_HEADER_FLAG || headerByte == DAS_MESSAGE_HEADER_FLAG + || (headerByte == (DAS_MESSAGE_HEADER_FLAG | TREE_DAS_MESSAGE_HEADER_FLAG)) + || headerByte == ZERO_HEAVY_MESSAGE_HEADER_FLAG || headerByte == EIGENDA_MESSAGE_HEADER_FLAG; } /// @dev Form a hash of the data taken from the calldata @@ -577,9 +565,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 fullDataLen = HEADER_LENGTH + data.length; if (fullDataLen > maxDataSize) revert DataTooLarge(fullDataLen, maxDataSize); - (bytes memory header, IBridge.TimeBounds memory timeBounds) = packHeader( - afterDelayedMessagesRead - ); + (bytes memory header, IBridge.TimeBounds memory timeBounds) = + packHeader(afterDelayedMessagesRead); // the batch poster is allowed to submit an empty batch, they can use this to progress the // delayed inbox without providing extra batch data @@ -592,7 +579,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox // das batches expect to have the type byte set, followed by the keyset (so they should have at least 33 bytes) // if invalid data is supplied here the state transition function will process it as an empty block // however we can provide a nice additional check here for the batch poster - if (data[0] & DAS_MESSAGE_HEADER_FLAG != 0 && data.length >= 33) { + // ignore if the first byte is 0xed, as that is the eigenDA message flag + if (data[0] != EIGENDA_MESSAGE_HEADER_FLAG && (data[0] & DAS_MESSAGE_HEADER_FLAG != 0) && data.length >= 33) { // we skip the first byte, then read the next 32 bytes for the keyset bytes32 dasKeysetHash = bytes32(data[1:33]); if (!dasKeySetInfo[dasKeysetHash].isValidKeyset) revert NoSuchKeyset(dasKeysetHash); @@ -609,18 +597,13 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox function formBlobDataHash(uint256 afterDelayedMessagesRead) internal view - returns ( - bytes32, - IBridge.TimeBounds memory, - uint256 - ) + returns (bytes32, IBridge.TimeBounds memory, uint256) { bytes32[] memory dataHashes = reader4844.getDataHashes(); if (dataHashes.length == 0) revert MissingDataHashes(); - (bytes memory header, IBridge.TimeBounds memory timeBounds) = packHeader( - afterDelayedMessagesRead - ); + (bytes memory header, IBridge.TimeBounds memory timeBounds) = + packHeader(afterDelayedMessagesRead); uint256 blobCost = reader4844.getBlobBaseFee() * GAS_PER_BLOB * dataHashes.length; return ( @@ -630,6 +613,32 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox ); } + function formEigenDADataHash( + IEigenDAServiceManager.BlobHeader memory blobHeader, + uint256 afterDelayedMessagesRead + ) internal view returns (bytes32, IBridge.TimeBounds memory, uint256) { + // we can't get the full data preimage onchain, so we hash the commitment to the blobdata and the datalength + + uint256 eigenDABlobCost = GAS_PER_SYMBOL_EIGENDA * blobHeader.dataLength; // set as some cost equal to some multiple of the length of the length of the blobs + + (bytes memory header, IBridge.TimeBounds memory timeBounds) = + packHeader(afterDelayedMessagesRead); + + return ( + keccak256( + bytes.concat( + header, + EIGENDA_MESSAGE_HEADER_FLAG, + abi.encodePacked( + blobHeader.commitment.X, blobHeader.commitment.Y, blobHeader.dataLength + ) + ) + ), + timeBounds, + block.basefee > 0 ? eigenDABlobCost / block.basefee : 0 + ); + } + /// @dev Submit a batch spending report message so that the batch poster can be reimbursed on the rollup /// This function expect msg.sender is tx.origin, and will always record tx.origin as the spender /// @param dataHash The hash of the message the spending report is being submitted for @@ -655,18 +664,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox } require(extraGas <= type(uint64).max, "EXTRA_GAS_NOT_UINT64"); bytes memory spendingReportMsg = abi.encodePacked( - block.timestamp, - batchPoster, - dataHash, - seqMessageIndex, - gasPrice, - uint64(extraGas) + block.timestamp, batchPoster, dataHash, seqMessageIndex, gasPrice, uint64(extraGas) ); - uint256 msgNum = bridge.submitBatchSpendingReport( - batchPoster, - keccak256(spendingReportMsg) - ); + uint256 msgNum = bridge.submitBatchSpendingReport(batchPoster, keccak256(spendingReportMsg)); // this is the same event used by Inbox.sol after including a message to the delayed message accumulator emit InboxMessageDelivered(msgNum, spendingReportMsg); } @@ -679,21 +680,13 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox uint256 newMessageCount ) internal - returns ( - uint256 seqMessageIndex, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 acc - ) + returns (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 acc) { if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards(); if (afterDelayedMessagesRead > bridge.delayedMessageCount()) revert DelayedTooFar(); (seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage( - dataHash, - afterDelayedMessagesRead, - prevMessageCount, - newMessageCount + dataHash, afterDelayedMessagesRead, prevMessageCount, newMessageCount ); totalDelayedMessagesRead = afterDelayedMessagesRead; @@ -716,10 +709,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox internal { if ( - maxTimeVariation_.delayBlocks > type(uint64).max || - maxTimeVariation_.futureBlocks > type(uint64).max || - maxTimeVariation_.delaySeconds > type(uint64).max || - maxTimeVariation_.futureSeconds > type(uint64).max + maxTimeVariation_.delayBlocks > type(uint64).max + || maxTimeVariation_.futureBlocks > type(uint64).max + || maxTimeVariation_.delaySeconds > type(uint64).max + || maxTimeVariation_.futureSeconds > type(uint64).max ) { revert BadMaxTimeVariation(); } @@ -758,10 +751,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox if (hostChainIsArbitrum) { creationBlock = ArbSys(address(100)).arbBlockNumber(); } - dasKeySetInfo[ksHash] = DasKeySetInfo({ - isValidKeyset: true, - creationBlock: uint64(creationBlock) - }); + dasKeySetInfo[ksHash] = + DasKeySetInfo({isValidKeyset: true, creationBlock: uint64(creationBlock)}); emit SetValidKeyset(ksHash, keysetBytes); emit OwnerFunctionCalled(2); } @@ -792,6 +783,29 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox emit OwnerFunctionCalled(5); } + /// @inheritdoc ISequencerInbox + function setRollupAddress() external onlyRollupOwner { + IOwnable newRollup = bridge.rollup(); + if (rollup == newRollup) revert RollupNotChanged(); + rollup = newRollup; + emit OwnerFunctionCalled(6); + } + + /// @inheritdoc ISequencerInbox + function setEigenDARollupManager(address newRollupManager) external onlyRollupOwner { + eigenDARollupManager = newRollupManager; + emit OwnerFunctionCalled(7); + } + + /// @notice Allows the rollup owner to sync the rollup address + function updateRollupAddress() external { + if (msg.sender != IOwnable(rollup).owner()) + revert NotOwner(msg.sender, IOwnable(rollup).owner()); + IOwnable newRollup = bridge.rollup(); + if (rollup == newRollup) revert RollupNotChanged(); + rollup = newRollup; + } + function isValidKeysetHash(bytes32 ksHash) external view returns (bool) { return dasKeySetInfo[ksHash].isValidKeyset; } @@ -802,4 +816,4 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash); return uint256(ksInfo.creationBlock); } -} +} \ No newline at end of file diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 9b41159f..e3577063 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -194,6 +194,9 @@ error MissingDataHashes(); /// @dev Thrown when rollup is not updated with updateRollupAddress error RollupNotChanged(); +/// @dev Thrown when the eigenDAServiceManager address is not changed +error EigenDAServiceManagerNotChanged(); + /// @dev Unsupported header flag was provided error InvalidHeaderFlag(bytes1); diff --git a/src/mocks/AvsDirectoryStub.sol b/src/mocks/AvsDirectoryStub.sol new file mode 100644 index 00000000..e69de29b diff --git a/src/mocks/EigenDAServiceManagerStub.sol b/src/mocks/EigenDAServiceManagerStub.sol new file mode 100644 index 00000000..6a459d96 --- /dev/null +++ b/src/mocks/EigenDAServiceManagerStub.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +import {EigenDAServiceManager} from "@eigenda/eigenda-utils/contracts/eigenda/EigenDAServiceManager.sol"; +import {IAVSDirectory} from "@eigenda/eigenda-utils/interfaces/IAVSDirectory.sol"; +import {IPaymentCoordinator} from "@eigenda/eigenda-utils/interfaces/IPaymentCoordinator.sol"; +import {IRegistryCoordinator} from "@eigenda/eigenda-utils/interfaces/IRegistryCoordinator.sol"; +import {IStakeRegistry} from "@eigenda/eigenda-utils/interfaces/IStakeRegistry.sol"; +import {IPauserRegistry} from "@eigenda/eigenda-utils/interfaces/IPauserRegistry.sol"; + +contract EigenDAServiceManagerStub is EigenDAServiceManager { + + constructor( + IAVSDirectory __avsDirectory, + IPaymentCoordinator __paymentCoordinator, + IRegistryCoordinator __registryCoordinator, + IStakeRegistry __stakeRegistry, + IPauserRegistry _pauserRegistry, + uint256 _initialPausedStatus, + address _initialOwner, + address[] memory _batchConfirmers + ) EigenDAServiceManager( + __avsDirectory, + __paymentCoordinator, + __registryCoordinator, + __stakeRegistry + ) { + } +} diff --git a/src/mocks/PaymentCoordinatorStub.sol b/src/mocks/PaymentCoordinatorStub.sol new file mode 100644 index 00000000..e69de29b diff --git a/src/mocks/SequencerInboxStub.sol b/src/mocks/SequencerInboxStub.sol index 49b31702..bf24ab9f 100644 --- a/src/mocks/SequencerInboxStub.sol +++ b/src/mocks/SequencerInboxStub.sol @@ -8,6 +8,9 @@ import "../bridge/SequencerInbox.sol"; import "../bridge/IEthBridge.sol"; import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; +import {IRollupManager} from "../bridge/RollupManager.sol"; + contract SequencerInboxStub is SequencerInbox { constructor( IBridge bridge_, @@ -15,6 +18,7 @@ contract SequencerInboxStub is SequencerInbox { ISequencerInbox.MaxTimeVariation memory maxTimeVariation_, uint256 maxDataSize_, IReader4844 reader4844_, + bool isUsingFeeToken_ ) SequencerInbox(maxDataSize_, reader4844_, isUsingFeeToken_) { bridge = bridge_; @@ -29,19 +33,13 @@ contract SequencerInboxStub is SequencerInbox { function addInitMessage(uint256 chainId) external { bytes memory initMsg = abi.encodePacked(chainId); uint256 num = IEthBridge(address(bridge)).enqueueDelayedMessage( - INITIALIZATION_MSG_TYPE, - address(0), - keccak256(initMsg) + INITIALIZATION_MSG_TYPE, address(0), keccak256(initMsg) ); require(num == 0, "ALREADY_DELAYED_INIT"); emit InboxMessageDelivered(num, initMsg); (bytes32 dataHash, IBridge.TimeBounds memory timeBounds) = formEmptyDataHash(1); - ( - uint256 sequencerMessageCount, - bytes32 beforeAcc, - bytes32 delayedAcc, - bytes32 afterAcc - ) = addSequencerL2BatchImpl(dataHash, 1, 0, 0, 1); + (uint256 sequencerMessageCount, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = + addSequencerL2BatchImpl(dataHash, 1, 0, 0, 1); require(sequencerMessageCount == 0, "ALREADY_SEQ_INIT"); emit SequencerBatchDelivered( sequencerMessageCount, diff --git a/src/osp/OneStepProverHostIo.sol b/src/osp/OneStepProverHostIo.sol index f5f124d2..9bd8ad15 100644 --- a/src/osp/OneStepProverHostIo.sol +++ b/src/osp/OneStepProverHostIo.sol @@ -14,6 +14,8 @@ import "./IOneStepProver.sol"; import "../bridge/Messages.sol"; import "../bridge/IBridge.sol"; +import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; + contract OneStepProverHostIo is IOneStepProver { using GlobalStateLib for GlobalState; using MachineLib for Machine; @@ -125,6 +127,13 @@ contract OneStepProverHostIo is IOneStepProver { return uint256(bytes32(modExpOutput)); } + + uint256 internal constant BN_254_PRIMITIVE_ROOT_OF_UNITY = + 19103219067921713944291392827692070036145651957329286315305642004821462161904; + + // see: https://github.com/Layr-Labs/eigenda/blob/master/disperser/apiserver/server.go#L35 + uint256 internal constant eigenDAMaxFieldElementsPerBlob = (2 * 1024 * 1024) / 32; + function executeReadPreImage( ExecutionContext calldata, Machine memory mach, @@ -236,6 +245,79 @@ contract OneStepProverHostIo is IOneStepProver { extracted = kzgProof[64:96]; } + } else if (inst.argumentData == 3) { + // The machine is asking for a EigenDA versioned hash preimage + + require(proofType == 0, "UNKNOWN_EIGENDA_PREIMAGE_PROOF"); + + bytes calldata kzgProof = proof[proofOffset:]; + + // NOTE we are expecting the following layout for our proof data, similar + // to that expected for the point evaluation precompile + // [:32] - versionhash (eigenlayer) + // [32:64] - evaluation point + // [64:96] - expected output + // [96:224] - g2TauMinusG2z + // [224:288] - kzg commitment (g1 point) + // [288:352] - proof (g1 point) + + // expect first 32 bytes of proof to be the expected version hash + require(bytes32(kzgProof[:32]) == leafContents, "KZG_PROOF_WRONG_HASH"); + + { + // evaluation point + uint256 evaluationPoint = uint256(bytes32(kzgProof[32:64])); + + // expected output + uint256 expectedOutput = uint256(bytes32(kzgProof[64:96])); + + BN254.G2Point memory g2TauMinusG2z = BN254.G2Point({ + X: [uint256(bytes32(kzgProof[96:128])), uint256(bytes32(kzgProof[128:160]))], + Y: [uint256(bytes32(kzgProof[160:192])), uint256(bytes32(kzgProof[192:224]))] + }); + + BN254.G1Point memory kzgCommitment = + BN254.G1Point(uint256(bytes32(kzgProof[224:256])), uint256(bytes32(kzgProof[256:288]))); + + BN254.G1Point memory eigenDAKZGProof = + BN254.G1Point(uint256(bytes32(kzgProof[288:320])), uint256(bytes32(kzgProof[320:352]))); + + // must be valid proof + require(verifyEigenDACommitment(kzgCommitment, eigenDAKZGProof, g2TauMinusG2z, evaluationPoint, expectedOutput), "INVALID_KZG_PROOF"); + } + + + // If preimageOffset is greater than or equal to the blob size, leave extracted empty and call it here. + if (preimageOffset < eigenDAMaxFieldElementsPerBlob * 32) { + // We need to compute what point the polynomial should be evaluated at to get the right part of the preimage. + // KZG commitments use a bit reversal permutation to order the roots of unity. + // To account for that, we reverse the bit order of the index. + uint256 bitReversedIndex = 0; + // preimageOffset was required to be 32 byte aligned above + uint256 tmp = preimageOffset / 32; + // instead of eigenDAMaxFieldElementsPerBlob should be number of field elements in OUR blob + for (uint256 i = 1; i < eigenDAMaxFieldElementsPerBlob; i <<= 1) { + bitReversedIndex <<= 1; + if (tmp & 1 == 1) { + bitReversedIndex |= 1; + } + tmp >>= 1; + } + + // First, we get the root of unity of order 2**fieldElementsPerBlob. + // We start with a root of unity of order 2**32 and then raise it to + // the power of (2**32)/fieldElementsPerBlob to get root of unity we need. + uint256 rootOfUnityPower = (1 << 32) / eigenDAMaxFieldElementsPerBlob; + // Then, we raise the root of unity to the power of bitReversedIndex, + // to retrieve this word of the KZG commitment. + rootOfUnityPower *= bitReversedIndex; + // z is the point the polynomial is evaluated at to retrieve this word of data + uint256 z = modExp256(BN_254_PRIMITIVE_ROOT_OF_UNITY, rootOfUnityPower, BN254.FR_MODULUS); + require(bytes32(kzgProof[32:64]) == bytes32(z), "KZG_PROOF_WRONG_Z"); + + extracted = kzgProof[64:96]; + } + } else { revert("UNKNOWN_PREIMAGE_TYPE"); } @@ -646,4 +728,90 @@ contract OneStepProverHostIo is IOneStepProver { impl(execCtx, mach, mod, inst, proof); } + + + // G2_SRS_1 + + //note might be useful to give back to the bn library + uint256 internal constant G2Taux1 = 21039730876973405969844107393779063362038454413254731404052240341412356318284; + uint256 internal constant G2Taux0 = 7912312892787135728292535536655271843828059318189722219035249994421084560563; + uint256 internal constant G2Tauy1 = 7586489485579523767759120334904353546627445333297951253230866312564920951171; + uint256 internal constant G2Tauy0 = 18697407556011630376420900106252341752488547575648825575049647403852275261247; + + function g2Tau() internal view returns (BN254.G2Point memory) { + return BN254.G2Point({ + X: [G2Taux1, G2Taux0], + Y: [G2Tauy1, G2Tauy0] + }); + } + + //TODO: move this toa eigenDA utils thing + function verifyEigenDACommitment( + BN254.G1Point memory _commitment, + BN254.G1Point memory _proof, + BN254.G2Point memory _g2TauMinusZCommitG2, + uint256 _index, + uint256 _value + ) public view returns (bool) { + // need to have each element less than modulus for underlying F_r field + require(_commitment.X < BN254.FR_MODULUS, "COMMIT_X_LARGER_THAN_FIELD"); + require(_commitment.Y < BN254.FR_MODULUS, "COMMIT_Y_LARGER_THAN_FIELD"); + + require(_proof.X < BN254.FR_MODULUS, "PROOF_X_LARGER_THAN_FIELD"); + require(_proof.Y < BN254.FR_MODULUS, "PROOF_Y_LARGER_THAN_FIELD"); + + // see: https://github.com/bxue-l2/eigenda/blob/a88ad0662a18f2139f9d288d5e667d00a89e26b9/encoding/utils/openCommitment/open_commitment.go#L63 + // and https://ethresear.ch/t/a-minimum-viable-kzg-polynomial-commitment-scheme-implementation/7675 + + // var valueG1 bn254.G1Affine + // var valueBig big.Int + // valueG1.ScalarMultiplication(&G1Gen, valueFr.BigInt(&valueBig)) + BN254.G1Point memory valueG1 = BN254.scalar_mul(BN254.generatorG1(), _value); + + // var commitMinusValue bn254.G1Affine + // commitMinusValue.Sub(&commitment, &valueG1) + + BN254.G1Point memory commitmentMinusValue = BN254.plus(_commitment, BN254.negate(valueG1)); + + //console.log("commitmentMinusValue: %s", commitmentMinusValue); + + // var zG2 bn254.G2Affine + // zG2.ScalarMultiplication(&G2Gen, zFr.BigInt(&valueBig)) + + // var xMinusZ bn254.G2Affine + // xMinusZ.Sub(&G2tau, &zG2) + + return BN254.pairing( + commitmentMinusValue, + BN254.generatorG2(), + BN254.negate(_proof), + _g2TauMinusZCommitG2 + ); + + + + // return PairingsVerify(&commitMinusValue, &G2Gen, &proof, &xMinusZ) + + // BN254.G1Point memory commitmentMinusA = BN254.plus( + // _commitment, + // BN254.negate( + // BN254.scalar_mul(BN254.generatorG1(), _value) + // ) + // ); + + // // Negate the proof + // BN254.G1Point memory negProof = BN254.negate(_proof); + + // // Compute index * proof + // BN254.G1Point memory indexMulProof = BN254.scalar_mul(_proof, _index); + + // // Returns true if and only if + // // e((index * proof) + (commitment - aCommitment), G2.g) * e(-proof, xCommit) == 1 + // return BN254.pairing( + // BN254.plus(indexMulProof, commitmentMinusA), + // BN254.generatorG2(), + // negProof, + // g2Tau() + // ); + } } diff --git a/src/rollup/RollupCreator.sol b/src/rollup/RollupCreator.sol index 61351cfe..01256e63 100644 --- a/src/rollup/RollupCreator.sol +++ b/src/rollup/RollupCreator.sol @@ -43,6 +43,7 @@ contract RollupCreator is Ownable { //// @dev The address of the batch poster, not used when set to zero address address[] batchPosters; address batchPosterManager; + address eigenDARollupManager; } BridgeCreator public bridgeCreator; @@ -196,6 +197,9 @@ contract RollupCreator is Ownable { bridgeContracts.sequencerInbox.setBatchPosterManager(deployParams.batchPosterManager); } + // Setting EigenDAServiceManager and EigenDARollupManager + bridgeContracts.sequencerInbox.setEigenDARollupManager(deployParams.eigenDARollupManager); + // Call setValidator on the newly created rollup contract just if validator set is not empty if (deployParams.validators.length != 0) { bool[] memory _vals = new bool[](deployParams.validators.length); diff --git a/test/contract/sequencerInboxForceInclude.spec.ts b/test/contract/sequencerInboxForceInclude.spec.ts index fcaf2055..1a240814 100644 --- a/test/contract/sequencerInboxForceInclude.spec.ts +++ b/test/contract/sequencerInboxForceInclude.spec.ts @@ -27,6 +27,7 @@ import { Inbox__factory, MessageTester, RollupMock__factory, + EigenDAServiceManagerStub__factory, SequencerInbox, SequencerInbox__factory, TransparentUpgradeableProxy__factory, @@ -224,19 +225,42 @@ describe('SequencerInboxForceInclude', async () => { const rollupOwner = accounts[3] const batchPoster = accounts[4] // const batchPosterManager = accounts[5] + const dummyAVSContract= accounts[6] + const dummyAVSContractAddress = await dummyAVSContract.getAddress() const rollupMockFac = (await ethers.getContractFactory( 'RollupMock' )) as RollupMock__factory const rollup = await rollupMockFac.deploy(await rollupOwner.getAddress()) + const EigenDARollupUtils = await ethers.getContractFactory("EigenDARollupUtils"); + const eigenDARollupUtils = await EigenDARollupUtils.deploy(); + await eigenDARollupUtils.deployed(); + + const EigenDAServiceManagerStub = await ethers.getContractFactory("EigenDAServiceManagerStub"); + + const eigenDAServiceManagerStub = await EigenDAServiceManagerStub.deploy( + dummyAVSContractAddress, + dummyAVSContractAddress, + dummyAVSContractAddress, + dummyAVSContractAddress, + dummyAVSContractAddress, + 0, + adminAddr, + [adminAddr] + ); + await eigenDAServiceManagerStub.deployed(); + const reader4844 = await Toolkit4844.deployReader4844(admin) - const sequencerInboxFac = (await ethers.getContractFactory( - 'SequencerInbox' - )) as SequencerInbox__factory + const sequencerInboxFac = await ethers.getContractFactory("SequencerInbox", { + libraries: { + EigenDARollupUtils: eigenDARollupUtils.address + } + }) as SequencerInbox__factory const seqInboxTemplate = await sequencerInboxFac.deploy( 117964, reader4844.address, + eigenDAServiceManagerStub.address, false ) const inboxFac = (await ethers.getContractFactory( diff --git a/test/foundry/BridgeCreator.t.sol b/test/foundry/BridgeCreator.t.sol index f6178d76..0f270034 100644 --- a/test/foundry/BridgeCreator.t.sol +++ b/test/foundry/BridgeCreator.t.sol @@ -14,6 +14,8 @@ contract BridgeCreatorTest is Test { address public owner = address(100); uint256 public constant MAX_DATA_SIZE = 117_964; IReader4844 dummyReader4844 = IReader4844(address(137)); + IEigenDAServiceManager dummyEigenDAServiceManager = IEigenDAServiceManager(address(138)); + IRollupManager rollupManager = IRollupManager(address(139)); BridgeCreator.BridgeContracts ethBasedTemplates = BridgeCreator.BridgeContracts({ diff --git a/test/foundry/ERC20Outbox.t.sol b/test/foundry/ERC20Outbox.t.sol index 4c385a56..914ad874 100644 --- a/test/foundry/ERC20Outbox.t.sol +++ b/test/foundry/ERC20Outbox.t.sol @@ -17,7 +17,13 @@ contract ERC20OutboxTest is AbsOutboxTest { function setUp() public { // deploy token, bridge and outbox - nativeToken = new ERC20PresetFixedSupply("Appchain Token", "App", 1_000_000, address(this)); + + // hardcoded proof in tests assume that this contract is deployed at the repsective address + IERC20 nativeTokenCode = new ERC20PresetFixedSupply("Appchain Token", "App", 1_000_000, address(this)); + nativeToken = IERC20(0xFEfC6BAF87cF3684058D62Da40Ff3A795946Ab06); + vm.etch(address(nativeToken), address(nativeTokenCode).code); + deal(address(nativeToken), address(this), 1_000_000); + bridge = IBridge(TestUtil.deployProxy(address(new ERC20Bridge()))); erc20Bridge = ERC20Bridge(address(bridge)); outbox = IOutbox(TestUtil.deployProxy(address(new ERC20Outbox()))); @@ -52,7 +58,10 @@ contract ERC20OutboxTest is AbsOutboxTest { vm.stopPrank(); // create msg receiver on L1 - ERC20L2ToL1Target target = new ERC20L2ToL1Target(); + // hardcoded proof in tests assume that this contract is deployed at the repsective address + ERC20L2ToL1Target targetCode = new ERC20L2ToL1Target(); + ERC20L2ToL1Target target = ERC20L2ToL1Target(0x87B2d08110B7D50861141D7bBDd49326af3Ecb31); + vm.etch(address(target), address(targetCode).code); target.setOutbox(address(outbox)); //// execute transaction diff --git a/test/foundry/KZGbn254.t.sol b/test/foundry/KZGbn254.t.sol new file mode 100644 index 00000000..9beee339 --- /dev/null +++ b/test/foundry/KZGbn254.t.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.12; + +import "../../src/osp/OneStepProverHostIo.sol"; +import "forge-std/Test.sol"; + +import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; + +contract VerifyCommitentTest is Test { + OneStepProverHostIo public osp; + + BN254.G1Point public commitment; + BN254.G1Point public proof; + + uint256 public value; + uint256 public evaluationPoint; + + // all commitments generated by eigenDA open commitment utils + + function setUp() public { + osp = new OneStepProverHostIo(); + } + + uint256 internal constant G2TauMinusZCommitG2x0 = + 18661601381049519024519089189471291422853092365704516815915072048157194827561; + uint256 internal constant G2TauMinusZCommitG2x1 = + 13438494147988583567753250571691619913302076853362981785635918286557069251073; + uint256 internal constant G2TauMinusZCommitG2y0 = + 21334762444346340210567460488634776100469500639295693474545191705712497478514; + uint256 internal constant G2TauMinusZCommitG2y1 = + 14745907799873989757051972255056064218237282162891110568940978756126201824118; + + function testVerifyCommitmentG2TauMinusZCommitG2() + internal + view + returns (BN254.G2Point memory) + { + return BN254.G2Point({ + X: [G2TauMinusZCommitG2x1, G2TauMinusZCommitG2x0], + Y: [G2TauMinusZCommitG2y1, G2TauMinusZCommitG2y0] + }); + } + + function testVerifyCommitment() public { + BN254.G2Point memory g2TauMinusZCommitG2 = testVerifyCommitmentG2TauMinusZCommitG2(); + commitment = BN254.G1Point( + 2961155957874067312593973807786254905069537311739090798303675273531563528369, + 159565752702690920280451512738307422982252330088949702406468210607852362941 + ); + proof = BN254.G1Point( + 3140275006105214616398887911734375818851847806994540943016311942563097259100, + 1901335408387077094777259997775410691226053037507541656866982737926032745825 + ); + value = + 207508779162842735480548510602597324319082308236775252882533101718680401000; + evaluationPoint = 1; + + assertTrue( + osp.verifyEigenDACommitment( + commitment, proof, g2TauMinusZCommitG2, evaluationPoint, value + ) + ); + } + + function testSanityPairing() public { + // sanity pairing works + BN254.G1Point memory g1Gen = BN254.generatorG1(); + BN254.G2Point memory g2Gen = BN254.generatorG2(); + + BN254.G1Point memory g1GenNeg = BN254.negate(g1Gen); + + assertTrue(BN254.pairing(g1Gen, g2Gen, g1GenNeg, g2Gen)); + } + + function testVerifyIllegalCommitmentFails() public { + commitment = BN254.G1Point( + 2961155957874067312593973807786254905069537311739090798303675273531563528369, + 159565752702690920280451512738307422982252330088949702406468210607852362941 + ); + proof = BN254.G1Point( + 20889584344688264775152566886162369109335964682277058078504426815999095925704, + 216054499853810563509078220646136944393866292849931571513515988346637933611 + ); + value = + 400194862503576342918173310331854693478403117005444701857659884415883371564; + evaluationPoint = 10; + + //assertFalse(osp.verifyEigenDACommitment(commitment, proof, value, evaluationPoint)); + } + + function testDecodeAndVerifyProof() public { + + // hash = bytes32(0) + // evaluation point = bytes32(1) + // expected output = 207508779162842735480548510602597324319082308236775252882533101718680401000 + // g2TauMinusG2z = 13438494147988583567753250571691619913302076853362981785635918286557069251073186616013810495190245190891894712914228530923657045168159150720481571948275611474590779987398975705197225505606421823728216289111056894097875612620182411821334762444346340210567460488634776100469500639295693474545191705712497478514 + // kzgCommitment = 2961155957874067312593973807786254905069537311739090798303675273531563528369159565752702690920280451512738307422982252330088949702406468210607852362941 + // eigenDAKZGProof = 31402750061052146163988879117343758188518478069945409430163119425630972591001901335408387077094777259997775410691226053037507541656866982737926032745825 + bytes memory proofBytes = abi.encode(bytes32(uint256(0)), bytes32(uint256(1)), bytes32(uint256(207508779162842735480548510602597324319082308236775252882533101718680401000)), bytes32(uint256(13438494147988583567753250571691619913302076853362981785635918286557069251073)), bytes32(uint256(18661601381049519024519089189471291422853092365704516815915072048157194827561)), bytes32(uint256(14745907799873989757051972255056064218237282162891110568940978756126201824118)), bytes32(uint256(21334762444346340210567460488634776100469500639295693474545191705712497478514)), bytes32(uint256(2961155957874067312593973807786254905069537311739090798303675273531563528369)), bytes32(uint256(159565752702690920280451512738307422982252330088949702406468210607852362941)), bytes32(uint256(3140275006105214616398887911734375818851847806994540943016311942563097259100)), bytes32(uint256(1901335408387077094777259997775410691226053037507541656866982737926032745825))); + + + assertTrue(this.decodeAndVerifyProof(proofBytes)); + } + + function decodeAndVerifyProof(bytes calldata kzgProof) public returns (bool) { + + // evaluation point + uint256 evaluationPoint = uint256(bytes32(kzgProof[32:64])); + + // expected output + uint256 expectedOutput = uint256(bytes32(kzgProof[64:96])); + + console.log("g2TauMinusG2z"); + + BN254.G2Point memory g2TauMinusG2z = BN254.G2Point({ + X: [uint256(bytes32(kzgProof[96:128])), uint256(bytes32(kzgProof[128:160]))], + Y: [uint256(bytes32(kzgProof[160:192])), uint256(bytes32(kzgProof[192:224]))] + }); + + assertTrue(g2TauMinusG2z.X[0] == testVerifyCommitmentG2TauMinusZCommitG2().X[0]); + assertTrue(g2TauMinusG2z.Y[0] == testVerifyCommitmentG2TauMinusZCommitG2().Y[0]); + assertTrue(g2TauMinusG2z.X[1] == testVerifyCommitmentG2TauMinusZCommitG2().X[1]); + assertTrue(g2TauMinusG2z.Y[1] == testVerifyCommitmentG2TauMinusZCommitG2().Y[1]); + + BN254.G1Point memory kzgCommitment = + BN254.G1Point(uint256(bytes32(kzgProof[224:256])), uint256(bytes32(kzgProof[256:288]))); + + assertTrue(kzgCommitment.X == 2961155957874067312593973807786254905069537311739090798303675273531563528369); + assertTrue(kzgCommitment.Y == 159565752702690920280451512738307422982252330088949702406468210607852362941); + + BN254.G1Point memory eigenDAKZGProof = + BN254.G1Point(uint256(bytes32(kzgProof[288:320])), uint256(bytes32(kzgProof[320:352]))); + + assertTrue(eigenDAKZGProof.X == 3140275006105214616398887911734375818851847806994540943016311942563097259100); + assertTrue(eigenDAKZGProof.Y == 1901335408387077094777259997775410691226053037507541656866982737926032745825); + + return osp.verifyEigenDACommitment(kzgCommitment, eigenDAKZGProof, g2TauMinusG2z, evaluationPoint, expectedOutput); + } +} diff --git a/test/foundry/RollupCreator.t.sol b/test/foundry/RollupCreator.t.sol index 68b8ebe2..c24d6f6c 100644 --- a/test/foundry/RollupCreator.t.sol +++ b/test/foundry/RollupCreator.t.sol @@ -28,6 +28,8 @@ contract RollupCreatorTest is Test { IRollupUser public rollupUser; DeployHelper public deployHelper; IReader4844 dummyReader4844 = IReader4844(address(137)); + IEigenDAServiceManager dummyEigenDAServiceManager = IEigenDAServiceManager(address(138)); + IRollupManager rollupManager = IRollupManager(address(139)); // 1 gwei uint256 public constant MAX_FEE_PER_GAS = 1_000_000_000; @@ -124,18 +126,22 @@ contract RollupCreatorTest is Test { address[] memory validators = new address[](2); validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); - - RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator - .RollupDeploymentParams({ - config: config, - batchPosters: batchPosters, - validators: validators, - maxDataSize: MAX_DATA_SIZE, - nativeToken: address(0), - deployFactoriesToL2: true, - maxFeePerGasForRetryables: MAX_FEE_PER_GAS, - batchPosterManager: batchPosterManager - }); + + address eigenDASvcManager = makeAddr("eigenDASvcManager"); + address eigenDARollupManager = makeAddr("rollupManager"); + + RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator.RollupDeploymentParams({ + config: config, + batchPosters: batchPosters, + validators: validators, + maxDataSize: MAX_DATA_SIZE, + nativeToken: address(0), + deployFactoriesToL2: true, + maxFeePerGasForRetryables: MAX_FEE_PER_GAS, + batchPosterManager: batchPosterManager, + eigenDARollupManager: eigenDARollupManager + }); + address rollupAddress = rollupCreator.createRollup{value: factoryDeploymentFunds}( deployParams ); @@ -281,6 +287,9 @@ contract RollupCreatorTest is Test { validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); + address eigenDASvcManager = makeAddr("eigenDASvcManager"); + address eigenDARollupManager = makeAddr("rollupManager"); + RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator .RollupDeploymentParams({ config: config, @@ -290,7 +299,8 @@ contract RollupCreatorTest is Test { nativeToken: nativeToken, deployFactoriesToL2: true, maxFeePerGasForRetryables: MAX_FEE_PER_GAS, - batchPosterManager: batchPosterManager + batchPosterManager: batchPosterManager, + eigenDARollupManager: eigenDARollupManager }); address rollupAddress = rollupCreator.createRollup(deployParams); @@ -433,6 +443,8 @@ contract RollupCreatorTest is Test { address[] memory validators = new address[](2); validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); + address eigenDASvcManager = makeAddr("eigenDASvcManager"); + address eigenDARollupManager = makeAddr("rollupManager"); RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator .RollupDeploymentParams({ @@ -443,7 +455,8 @@ contract RollupCreatorTest is Test { nativeToken: address(0), deployFactoriesToL2: true, maxFeePerGasForRetryables: MAX_FEE_PER_GAS, - batchPosterManager: batchPosterManager + batchPosterManager: batchPosterManager, + eigenDARollupManager: eigenDARollupManager }); address rollupAddress = rollupCreator.createRollup{value: factoryDeploymentFunds}( deployParams diff --git a/test/foundry/SequencerInbox.t.sol b/test/foundry/SequencerInbox.t.sol index 92902d68..e85e1ae7 100644 --- a/test/foundry/SequencerInbox.t.sol +++ b/test/foundry/SequencerInbox.t.sol @@ -8,6 +8,11 @@ import "../../src/bridge/SequencerInbox.sol"; import {ERC20Bridge} from "../../src/bridge/ERC20Bridge.sol"; import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; +import {EigenDARollupUtils} from "@eigenda/eigenda-utils/libraries/EigenDARollupUtils.sol"; +import {IEigenDAServiceManager} from "@eigenda/eigenda-utils/interfaces/IEigenDAServiceManager.sol"; +import {IRollupManager, EigenDADummyManager} from "../../src/bridge/RollupManager.sol"; +import {BN254} from "@eigenda/eigenda-utils/libraries/BN254.sol"; + contract RollupMock { address public immutable owner; @@ -42,26 +47,26 @@ contract SequencerInboxTest is Test { Random RAND = new Random(); address rollupOwner = address(137); - uint256 maxDataSize = 10000; - ISequencerInbox.MaxTimeVariation maxTimeVariation = - ISequencerInbox.MaxTimeVariation({ - delayBlocks: 10, - futureBlocks: 10, - delaySeconds: 100, - futureSeconds: 100 - }); + uint256 maxDataSize = 10_000; + ISequencerInbox.MaxTimeVariation maxTimeVariation = ISequencerInbox.MaxTimeVariation({ + delayBlocks: 10, + futureBlocks: 10, + delaySeconds: 100, + futureSeconds: 100 + }); address dummyInbox = address(139); address proxyAdmin = address(140); IReader4844 dummyReader4844 = IReader4844(address(137)); + IEigenDAServiceManager dummyEigenDAServiceManager = IEigenDAServiceManager(address(138)); + IRollupManager rollupManager = IRollupManager(address(139)); - uint256 public constant MAX_DATA_SIZE = 117964; + uint256 public constant MAX_DATA_SIZE = 117_964; function deployRollup(bool isArbHosted) internal returns (SequencerInbox, Bridge) { RollupMock rollupMock = new RollupMock(rollupOwner); Bridge bridgeImpl = new Bridge(); - Bridge bridge = Bridge( - address(new TransparentUpgradeableProxy(address(bridgeImpl), proxyAdmin, "")) - ); + Bridge bridge = + Bridge(address(new TransparentUpgradeableProxy(address(bridgeImpl), proxyAdmin, ""))); bridge.initialize(IOwnable(address(rollupMock))); vm.prank(rollupOwner); @@ -105,9 +110,7 @@ contract SequencerInboxTest is Test { abi.encode(uint256(11)) ); SequencerInbox seqInboxImpl = new SequencerInbox( - maxDataSize, - IReader4844(address(0)), - true + maxDataSize, IReader4844(address(0)), true ); SequencerInbox seqInbox = SequencerInbox( address(new TransparentUpgradeableProxy(address(seqInboxImpl), proxyAdmin, "")) @@ -123,15 +126,65 @@ contract SequencerInboxTest is Test { return (seqInbox, bridge); } + // Split the logic that deals with calculating and emitting the spending report into a separate function because of stack too deep limits + function _handleSpendingReport( + IBridge bridge, + SequencerInbox seqInbox, + uint256 delayedMessagesRead, + bytes32 dataHash, + uint256 sequenceNumber, + bool hostChainIsArbitrum + ) internal { + if (!hostChainIsArbitrum) return; // If not Arbitrum, no need to process this part + + // set 0.1 gwei basefee + uint256 basefee = 100_000_000; + vm.fee(basefee); + // 30 gwei TX L1 fees + uint256 l1Fees = 30_000_000_000; + vm.mockCall( + address(0x6c), abi.encodeWithSignature("getCurrentTxL1GasFees()"), abi.encode(l1Fees) + ); + uint256 expectedReportedExtraGas = l1Fees / basefee; + + bytes memory spendingReportMsg = abi.encodePacked( + block.timestamp, + msg.sender, + dataHash, + sequenceNumber, + block.basefee, + uint64(expectedReportedExtraGas) + ); + + // spending report + vm.expectEmit(); + emit MessageDelivered( + delayedMessagesRead, + bridge.delayedInboxAccs(delayedMessagesRead - 1), // directly use the call here to reduce a variable + address(seqInbox), + L1MessageType_batchPostingReport, + tx.origin, + keccak256(spendingReportMsg), + block.basefee, + uint64(block.timestamp) + ); + + // spending report event in seq inbox + vm.expectEmit(); + emit InboxMessageDelivered(delayedMessagesRead, spendingReportMsg); + } + function expectEvents( IBridge bridge, SequencerInbox seqInbox, bytes memory data, bool hostChainIsArbitrum, - bool isUsingFeeToken + bool isUsingFeeToken, + bool isUsingEigenDA ) internal { uint256 delayedMessagesRead = bridge.delayedMessageCount(); uint256 sequenceNumber = bridge.sequencerMessageCount(); + IBridge.TimeBounds memory timeBounds; if (block.timestamp > maxTimeVariation.delaySeconds) { timeBounds.minTimestamp = uint64(block.timestamp - maxTimeVariation.delaySeconds); @@ -141,67 +194,49 @@ contract SequencerInboxTest is Test { timeBounds.minBlockNumber = uint64(block.number - maxTimeVariation.delayBlocks); } timeBounds.maxBlockNumber = uint64(block.number + maxTimeVariation.futureBlocks); - bytes32 dataHash = keccak256( - bytes.concat( - abi.encodePacked( - timeBounds.minTimestamp, - timeBounds.maxTimestamp, - timeBounds.minBlockNumber, - timeBounds.maxBlockNumber, - uint64(delayedMessagesRead) - ), - data - ) - ); + + bytes32 dataHash; + + if (isUsingEigenDA) { + dataHash = keccak256( + bytes.concat( + abi.encodePacked( + timeBounds.minTimestamp, + timeBounds.maxTimestamp, + timeBounds.minBlockNumber, + timeBounds.maxBlockNumber, + uint64(delayedMessagesRead) + ), + data + ) + ); + } else { + dataHash = keccak256( + bytes.concat( + abi.encodePacked( + timeBounds.minTimestamp, + timeBounds.maxTimestamp, + timeBounds.minBlockNumber, + timeBounds.maxBlockNumber, + uint64(delayedMessagesRead) + ), + data + ) + ); + } bytes32 beforeAcc = bytes32(0); bytes32 delayedAcc = bridge.delayedInboxAccs(delayedMessagesRead - 1); bytes32 afterAcc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc)); - if (!isUsingFeeToken) { - uint256 expectedReportedExtraGas = 0; - if (hostChainIsArbitrum) { - // set 0.1 gwei basefee - uint256 basefee = 100000000; - vm.fee(basefee); - // 30 gwei TX L1 fees - uint256 l1Fees = 30000000000; - vm.mockCall( - address(0x6c), - abi.encodeWithSignature("getCurrentTxL1GasFees()"), - abi.encode(l1Fees) - ); - expectedReportedExtraGas = l1Fees / basefee; - } - - bytes memory spendingReportMsg = abi.encodePacked( - block.timestamp, - msg.sender, - dataHash, - sequenceNumber, - block.basefee, - uint64(expectedReportedExtraGas) + if (!isUsingFeeToken && !isUsingEigenDA) { + _handleSpendingReport( + bridge, seqInbox, delayedMessagesRead, dataHash, sequenceNumber, hostChainIsArbitrum ); - - // spending report - vm.expectEmit(); - emit MessageDelivered( - delayedMessagesRead, - delayedAcc, - address(seqInbox), - L1MessageType_batchPostingReport, - tx.origin, - keccak256(spendingReportMsg), - block.basefee, - uint64(block.timestamp) - ); - - // spending report event in seq inbox - vm.expectEmit(); - emit InboxMessageDelivered(delayedMessagesRead, spendingReportMsg); } // sequencer batch delivered + vm.expectEmit(); emit SequencerBatchDelivered( sequenceNumber, @@ -210,10 +245,80 @@ contract SequencerInboxTest is Test { delayedAcc, delayedMessagesRead, timeBounds, - IBridge.BatchDataLocation.TxInput + !isUsingEigenDA ? IBridge.BatchDataLocation.TxInput : IBridge.BatchDataLocation.EigenDA + ); + } + + bytes eigenDAData = + hex"ed4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a"; + + // note that this test is for continuted compatibility with the m0 arbitrum integration. + function testAddSequencerL2BatchFromOrigin_EigenDaHeader() public { + (SequencerInbox seqInbox, Bridge bridge) = deployRollup(false); + address delayedInboxSender = address(140); + uint8 delayedInboxKind = 3; + bytes32 messageDataHash = RAND.Bytes32(); + bytes memory data = eigenDAData; // ed is EIGENDA_MESSAGE_HEADER_FLAG + + vm.prank(dummyInbox); + bridge.enqueueDelayedMessage(delayedInboxKind, delayedInboxSender, messageDataHash); + + uint256 subMessageCount = bridge.sequencerReportedSubMessageCount(); + uint256 sequenceNumber = bridge.sequencerMessageCount(); + uint256 delayedMessagesRead = bridge.delayedMessageCount(); + + // set 60 gwei basefee + uint256 basefee = 60000000000; + vm.fee(basefee); + expectEvents(bridge, seqInbox, data, false, false, false); + + vm.prank(tx.origin); + seqInbox.addSequencerL2BatchFromOrigin( + sequenceNumber, + data, + delayedMessagesRead, + IGasRefunder(address(0)), + subMessageCount, + subMessageCount + 1 ); + } + bytes invalidHeaderData = + hex"ab4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a"; + + function testAddSequencerL2BatchFromOrigin_InvalidHeader() public { + (SequencerInbox seqInbox, Bridge bridge) = deployRollup(false); + address delayedInboxSender = address(140); + uint8 delayedInboxKind = 3; + bytes32 messageDataHash = RAND.Bytes32(); + bytes memory data = invalidHeaderData; // ab is not any valid header flag + + vm.prank(dummyInbox); + bridge.enqueueDelayedMessage(delayedInboxKind, delayedInboxSender, messageDataHash); + + uint256 subMessageCount = bridge.sequencerReportedSubMessageCount(); + uint256 sequenceNumber = bridge.sequencerMessageCount(); + uint256 delayedMessagesRead = bridge.delayedMessageCount(); + + // set 60 gwei basefee + uint256 basefee = 60000000000; + vm.fee(basefee); + + vm.prank(tx.origin); + vm.expectRevert(abi.encodeWithSignature("InvalidHeaderFlag(bytes1)", 0xab00000000000000000000000000000000000000000000000000000000000000)); + seqInbox.addSequencerL2BatchFromOrigin( + sequenceNumber, + data, + delayedMessagesRead, + IGasRefunder(address(0)), + subMessageCount, + subMessageCount + 1 + ); + + } + + bytes biggerData = hex"00a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890a4567890"; @@ -232,9 +337,9 @@ contract SequencerInboxTest is Test { uint256 delayedMessagesRead = bridge.delayedMessageCount(); // set 60 gwei basefee - uint256 basefee = 60000000000; + uint256 basefee = 60_000_000_000; vm.fee(basefee); - expectEvents(bridge, seqInbox, data, false, false); + expectEvents(bridge, seqInbox, data, false, false, false); vm.prank(tx.origin); seqInbox.addSequencerL2BatchFromOrigin( @@ -249,7 +354,8 @@ contract SequencerInboxTest is Test { /* solhint-disable func-name-mixedcase */ function testConstructor() public { - SequencerInbox seqInboxLogic = new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false); + SequencerInbox seqInboxLogic = + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false); assertEq(seqInboxLogic.maxDataSize(), MAX_DATA_SIZE, "Invalid MAX_DATA_SIZE"); assertEq(seqInboxLogic.isUsingFeeToken(), false, "Invalid isUsingFeeToken"); @@ -257,28 +363,25 @@ contract SequencerInboxTest is Test { assertEq(seqInboxProxy.maxDataSize(), MAX_DATA_SIZE, "Invalid MAX_DATA_SIZE"); assertEq(seqInboxProxy.isUsingFeeToken(), false, "Invalid isUsingFeeToken"); - SequencerInbox seqInboxLogicFeeToken = new SequencerInbox( - MAX_DATA_SIZE, - dummyReader4844, - true - ); + SequencerInbox seqInboxLogicFeeToken = + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, true); assertEq(seqInboxLogicFeeToken.maxDataSize(), MAX_DATA_SIZE, "Invalid MAX_DATA_SIZE"); assertEq(seqInboxLogicFeeToken.isUsingFeeToken(), true, "Invalid isUsingFeeToken"); - SequencerInbox seqInboxProxyFeeToken = SequencerInbox( - TestUtil.deployProxy(address(seqInboxLogicFeeToken)) - ); + SequencerInbox seqInboxProxyFeeToken = + SequencerInbox(TestUtil.deployProxy(address(seqInboxLogicFeeToken))); assertEq(seqInboxProxyFeeToken.maxDataSize(), MAX_DATA_SIZE, "Invalid MAX_DATA_SIZE"); assertEq(seqInboxProxyFeeToken.isUsingFeeToken(), true, "Invalid isUsingFeeToken"); } function testInitialize() public { - Bridge _bridge = Bridge( - address(new TransparentUpgradeableProxy(address(new Bridge()), proxyAdmin, "")) - ); + Bridge _bridge = + Bridge(address(new TransparentUpgradeableProxy(address(new Bridge()), proxyAdmin, ""))); _bridge.initialize(IOwnable(address(new RollupMock(rollupOwner)))); - address seqInboxLogic = address(new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false)); + address seqInboxLogic = address( + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false) + ); SequencerInbox seqInboxProxy = SequencerInbox(TestUtil.deployProxy(seqInboxLogic)); seqInboxProxy.initialize(IBridge(_bridge), maxTimeVariation); @@ -294,7 +397,9 @@ contract SequencerInboxTest is Test { address nativeToken = address(new ERC20PresetMinterPauser("Appchain Token", "App")); _bridge.initialize(IOwnable(address(new RollupMock(rollupOwner))), nativeToken); - address seqInboxLogic = address(new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, true)); + address seqInboxLogic = address( + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, true) + ); SequencerInbox seqInboxProxy = SequencerInbox(TestUtil.deployProxy(seqInboxLogic)); seqInboxProxy.initialize(IBridge(_bridge), maxTimeVariation); @@ -304,12 +409,13 @@ contract SequencerInboxTest is Test { } function testInitialize_revert_NativeTokenMismatch_EthFeeToken() public { - Bridge _bridge = Bridge( - address(new TransparentUpgradeableProxy(address(new Bridge()), proxyAdmin, "")) - ); + Bridge _bridge = + Bridge(address(new TransparentUpgradeableProxy(address(new Bridge()), proxyAdmin, ""))); _bridge.initialize(IOwnable(address(new RollupMock(rollupOwner)))); - address seqInboxLogic = address(new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, true)); + address seqInboxLogic = address( + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, true) + ); SequencerInbox seqInboxProxy = SequencerInbox(TestUtil.deployProxy(seqInboxLogic)); vm.expectRevert(abi.encodeWithSelector(NativeTokenMismatch.selector)); @@ -323,7 +429,9 @@ contract SequencerInboxTest is Test { address nativeToken = address(new ERC20PresetMinterPauser("Appchain Token", "App")); _bridge.initialize(IOwnable(address(new RollupMock(rollupOwner))), nativeToken); - address seqInboxLogic = address(new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false)); + address seqInboxLogic = address( + new SequencerInbox(MAX_DATA_SIZE, dummyReader4844, false) + ); SequencerInbox seqInboxProxy = SequencerInbox(TestUtil.deployProxy(seqInboxLogic)); vm.expectRevert(abi.encodeWithSelector(NativeTokenMismatch.selector)); @@ -351,7 +459,7 @@ contract SequencerInboxTest is Test { uint256 sequenceNumber = bridge.sequencerMessageCount(); uint256 delayedMessagesRead = bridge.delayedMessageCount(); - expectEvents(bridge, seqInbox, data, true, false); + expectEvents(bridge, seqInbox, data, true, false, false); vm.prank(tx.origin); seqInbox.addSequencerL2BatchFromOrigin( @@ -379,10 +487,10 @@ contract SequencerInboxTest is Test { uint256 delayedMessagesRead = bridge.delayedMessageCount(); // set 40 gwei basefee - uint256 basefee = 40000000000; + uint256 basefee = 40_000_000_000; vm.fee(basefee); - expectEvents(IBridge(address(bridge)), seqInbox, data, true, true); + expectEvents(IBridge(address(bridge)), seqInbox, data, true, true, false); vm.prank(tx.origin); seqInbox.addSequencerL2BatchFromOrigin( @@ -442,9 +550,7 @@ contract SequencerInboxTest is Test { ); vm.expectRevert( abi.encodeWithSelector( - DataTooLarge.selector, - bigData.length + seqInbox.HEADER_LENGTH(), - maxDataSize + DataTooLarge.selector, bigData.length + seqInbox.HEADER_LENGTH(), maxDataSize ) ); vm.prank(tx.origin); @@ -483,15 +589,129 @@ contract SequencerInboxTest is Test { ); } + + function testAddSequencerL2BatchFromEigenDA() public { + + EigenDADummyManager rollupManagerImpl = new EigenDADummyManager(); + (SequencerInbox seqInbox, Bridge bridge) = deployRollup(false); + // update the dummyEigenDAServiceManager to use the holesky serviceManager contract + + vm.startPrank(rollupOwner); + // deploy rollup + seqInbox.setEigenDARollupManager(address(rollupManagerImpl)); + vm.stopPrank(); + + address delayedInboxSender = address(140); + uint8 delayedInboxKind = 3; + bytes32 messageDataHash = RAND.Bytes32(); + + vm.prank(dummyInbox); + bridge.enqueueDelayedMessage(delayedInboxKind, delayedInboxSender, messageDataHash); + + (IEigenDAServiceManager.BlobHeader memory blobHeader, EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof) = readAndParseBlobInfo(); + + // ed is EIGEN_DA_MESSAGE_HEADER_FLAG rest is abi.encodePacked(blobHeader.commitment.X, blobHeader.commitment.Y, blobHeader.dataLength) + bytes memory data = + abi.encodePacked(hex"ed", blobHeader.commitment.X, blobHeader.commitment.Y, blobHeader.dataLength); + + uint256 subMessageCount = bridge.sequencerReportedSubMessageCount(); + uint256 sequenceNumber = bridge.sequencerMessageCount(); + uint256 delayedMessagesRead = bridge.delayedMessageCount(); + + expectEvents(bridge, seqInbox, data, false, false, true); + + vm.prank(tx.origin); + + seqInbox.addSequencerL2BatchFromEigenDA( + sequenceNumber, + blobVerificationProof, + blobHeader, + delayedMessagesRead, + subMessageCount, + subMessageCount + 1 + ); + } + + // TODO: put these in jsons later + // create illegal commitment + BN254.G1Point illegalCommitment = BN254.G1Point({ + X: 11151623676041303181597631684634074376466382703418354161831688442589830350329, + Y: 4222041728992406478862708226745479381252734858741080790666424175645694456140 + }); + + IEigenDAServiceManager.BlobHeader illegalBlobHeader; + + IEigenDAServiceManager.BatchHeader illegalBatchHeader = IEigenDAServiceManager.BatchHeader({ + blobHeadersRoot: bytes32(0), + quorumNumbers: bytes(""), + signedStakeForQuorums: bytes(""), + referenceBlockNumber: 1 + }); + + IEigenDAServiceManager.BatchMetadata illegalBatchMetadata = IEigenDAServiceManager.BatchMetadata({ + batchHeader: illegalBatchHeader, + signatoryRecordHash: bytes32(0), + confirmationBlockNumber: 1 + }); + + EigenDARollupUtils.BlobVerificationProof illegalBlobVerificationProof = EigenDARollupUtils + .BlobVerificationProof({ + batchId: 1, + blobIndex: 1, + batchMetadata: illegalBatchMetadata, + inclusionProof: bytes(""), + quorumIndices: bytes("") + }); + + function testAddSequencerL2BatchFrom() public { + // finish filling out the illegalBlobHeader + illegalBlobHeader.commitment = illegalCommitment; + illegalBlobHeader.dataLength = 20; + illegalBlobHeader.quorumBlobParams.push( + IEigenDAServiceManager.QuorumBlobParam({ + quorumNumber: uint8(1), + adversaryThresholdPercentage: uint8(1), + confirmationThresholdPercentage: uint8(1), + chunkLength: uint32(1) + }) + ); + + // change the eigenDAServiceManager to use the holesky testnet contract + (SequencerInbox seqInbox, Bridge bridge) = deployRollup(false); + address delayedInboxSender = address(140); + uint8 delayedInboxKind = 3; + bytes32 messageDataHash = RAND.Bytes32(); + bytes memory data = biggerData; // 00 is BROTLI_MESSAGE_HEADER_FLAG + + vm.prank(dummyInbox); + bridge.enqueueDelayedMessage(delayedInboxKind, delayedInboxSender, messageDataHash); + + uint256 subMessageCount = bridge.sequencerReportedSubMessageCount(); + uint256 sequenceNumber = bridge.sequencerMessageCount(); + uint256 delayedMessagesRead = bridge.delayedMessageCount(); + + vm.prank(tx.origin); + + vm.expectRevert(); + seqInbox.addSequencerL2BatchFromEigenDA( + sequenceNumber, + illegalBlobVerificationProof, + illegalBlobHeader, + delayedMessagesRead, + subMessageCount, + subMessageCount + 1 + ); + } + function testPostUpgradeInitAlreadyInit() public returns (SequencerInbox, SequencerInbox) { - (SequencerInbox seqInbox, ) = deployRollup(false); - SequencerInbox seqInboxImpl = new SequencerInbox(maxDataSize, dummyReader4844, false); + (SequencerInbox seqInbox,) = deployRollup(false); + SequencerInbox seqInboxImpl = + new SequencerInbox(maxDataSize, dummyReader4844, false); vm.expectRevert(abi.encodeWithSelector(AlreadyInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), - abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); return (seqInbox, seqInboxImpl); } @@ -509,26 +729,21 @@ contract SequencerInboxTest is Test { vm.expectRevert(abi.encodeWithSelector(AlreadyInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), - abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); - vm.store(address(seqInbox), bytes32(uint256(4)), bytes32(uint256(delayBlocks))); // slot 4: delayBlocks - vm.store(address(seqInbox), bytes32(uint256(5)), bytes32(uint256(futureBlocks))); // slot 5: futureBlocks - vm.store(address(seqInbox), bytes32(uint256(6)), bytes32(uint256(delaySeconds))); // slot 6: delaySeconds - vm.store(address(seqInbox), bytes32(uint256(7)), bytes32(uint256(futureSeconds))); // slot 7: futureSeconds + // IMPORTANT: slots have moved down by one because we have added additional variables for eigenDA + vm.store(address(seqInbox), bytes32(uint256(6)), bytes32(uint256(delayBlocks))); // slot 6: delayBlocks + vm.store(address(seqInbox), bytes32(uint256(7)), bytes32(uint256(futureBlocks))); // slot 7: futureBlocks + vm.store(address(seqInbox), bytes32(uint256(8)), bytes32(uint256(delaySeconds))); // slot 8: delaySeconds + vm.store(address(seqInbox), bytes32(uint256(9)), bytes32(uint256(futureSeconds))); // slot 9: futureSeconds vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), - abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); - ( - uint256 delayBlocks_, - uint256 futureBlocks_, - uint256 delaySeconds_, - uint256 futureSeconds_ - ) = seqInbox.maxTimeVariation(); + (uint256 delayBlocks_, uint256 futureBlocks_, uint256 delaySeconds_, uint256 futureSeconds_) + = seqInbox.maxTimeVariation(); assertEq(delayBlocks_, delayBlocks); assertEq(futureBlocks_, futureBlocks); assertEq(delaySeconds_, delaySeconds); @@ -537,8 +752,7 @@ contract SequencerInboxTest is Test { vm.expectRevert(abi.encodeWithSelector(AlreadyInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), - abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); } @@ -562,8 +776,7 @@ contract SequencerInboxTest is Test { vm.expectRevert(abi.encodeWithSelector(BadPostUpgradeInit.selector)); vm.prank(proxyAdmin); TransparentUpgradeableProxy(payable(address(seqInbox))).upgradeToAndCall( - address(seqInboxImpl), - abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) + address(seqInboxImpl), abi.encodeWithSelector(SequencerInbox.postUpgradeInit.selector) ); } @@ -577,7 +790,7 @@ contract SequencerInboxTest is Test { vm.assume(futureBlocks <= uint256(type(uint64).max)); vm.assume(delaySeconds <= uint256(type(uint64).max)); vm.assume(futureSeconds <= uint256(type(uint64).max)); - (SequencerInbox seqInbox, ) = deployRollup(false); + (SequencerInbox seqInbox,) = deployRollup(false); vm.prank(rollupOwner); seqInbox.setMaxTimeVariation( ISequencerInbox.MaxTimeVariation({ @@ -599,7 +812,7 @@ contract SequencerInboxTest is Test { vm.assume(futureBlocks > uint256(type(uint64).max)); vm.assume(delaySeconds > uint256(type(uint64).max)); vm.assume(futureSeconds > uint256(type(uint64).max)); - (SequencerInbox seqInbox, ) = deployRollup(false); + (SequencerInbox seqInbox,) = deployRollup(false); vm.expectRevert(abi.encodeWithSelector(BadMaxTimeVariation.selector)); vm.prank(rollupOwner); seqInbox.setMaxTimeVariation( @@ -611,4 +824,67 @@ contract SequencerInboxTest is Test { }) ); } + + function readAndParseBlobInfo() public returns (IEigenDAServiceManager.BlobHeader memory, EigenDARollupUtils.BlobVerificationProof memory) { + string memory json = vm.readFile("test/foundry/blobInfo/blobInfo.json"); + + // parse the blob header + + IEigenDAServiceManager.BlobHeader memory blobHeader; + + BN254.G1Point memory commitment = BN254.G1Point({ + X: uint256(vm.parseJsonInt(json, ".blob_info.blob_header.commitment.x")), + Y: uint256(vm.parseJsonInt(json, ".blob_info.blob_header.commitment.y")) + }); + + blobHeader.commitment = commitment; + blobHeader.dataLength = uint32(uint256(vm.parseJsonInt(json, ".blob_info.blob_header.data_length"))); + + //bytes memory quorumParamsBytes = vm.parseJson(json, ".blob_info.blob_header.blob_quorum_params"); + + // TODO: Parse these from the array, for some reason parsing them reads in the wrong order + IEigenDAServiceManager.QuorumBlobParam[] memory quorumParams = new IEigenDAServiceManager.QuorumBlobParam[](2); + + quorumParams[0].quorumNumber = 0; + quorumParams[0].adversaryThresholdPercentage = 33; + quorumParams[0].confirmationThresholdPercentage = 55; + quorumParams[0].chunkLength = 1; + + quorumParams[1].quorumNumber = 1; + quorumParams[1].adversaryThresholdPercentage = 33; + quorumParams[1].confirmationThresholdPercentage = 55; + quorumParams[1].chunkLength = 1; + + blobHeader.quorumBlobParams = quorumParams; + + + // parse the blob verification proof + + IEigenDAServiceManager.BatchHeader memory batchHeader = IEigenDAServiceManager.BatchHeader({ + blobHeadersRoot: vm.parseJsonBytes32(json, ".blob_info.blob_verification_proof.batch_metadata.batch_header.batch_root"), + quorumNumbers: vm.parseJsonBytes(json, ".blob_info.blob_verification_proof.batch_metadata.batch_header.quorum_numbers"), + signedStakeForQuorums: vm.parseJsonBytes(json, ".blob_info.blob_verification_proof.batch_metadata.batch_header.quorum_signed_percentages"), + referenceBlockNumber: uint32(uint256(vm.parseJsonUint(json, ".blob_info.blob_verification_proof.batch_metadata.batch_header.reference_block_number"))) + }); + + IEigenDAServiceManager.BatchMetadata memory batchMetadata = IEigenDAServiceManager.BatchMetadata({ + batchHeader: batchHeader, + signatoryRecordHash: vm.parseJsonBytes32(json, ".blob_info.blob_verification_proof.batch_metadata.signatory_record_hash"), + confirmationBlockNumber: uint32(uint256(vm.parseJsonUint(json, ".blob_info.blob_verification_proof.batch_metadata.confirmation_block_number"))) + }); + + EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof = EigenDARollupUtils + .BlobVerificationProof({ + batchId: uint32(uint256(vm.parseJsonUint(json, ".blob_info.blob_verification_proof.batch_id"))), + blobIndex: uint32(uint256(vm.parseJsonUint(json, ".blob_info.blob_verification_proof.blob_index"))), + batchMetadata: batchMetadata, + inclusionProof: vm.parseJsonBytes(json, ".blob_info.blob_verification_proof.inclusion_proof"), + quorumIndices: vm.parseJsonBytes(json, ".blob_info.blob_verification_proof.quorum_indexes") + }); + console.logBytes32(keccak256(abi.encode(blobHeader))); + return (blobHeader, blobVerificationProof); + + } + + } diff --git a/test/foundry/blobInfo/blobInfo.json b/test/foundry/blobInfo/blobInfo.json new file mode 100644 index 00000000..e45fdd28 --- /dev/null +++ b/test/foundry/blobInfo/blobInfo.json @@ -0,0 +1,44 @@ +{ + "request_id": "316638323561613266303032306566376366393164666133306461343636386437393163356434383234666338653431333534623839656330353739356162332d33313337333133393335333233373333333633303336333133363333333533303330333133363266333032663333333332663331326633333333326665336230633434323938666331633134396166626634633839393666623932343237616534316534363439623933346361343935393931623738353262383535", + "blob_info": { + "blob_header": { + "commitment": { + "x": "0x2569a1994232d43b210e860d876c0bbc8d7f22dc0b8ae17d4c369ce7c2d33c26", + "y": "0x14f8198412fea43aaeb4a5355600d0fe3f175ea2f5d7246a7c6472c453fcde53" + }, + "data_length": 1, + "blob_quorum_params": [ + { + "quorum_number": 0, + "adversary_threshold_percentage": 33, + "confirmation_threshold_percentage": 55, + "chunk_length": 1 + }, + { + "quorum_number": 1, + "adversary_threshold_percentage": 33, + "confirmation_threshold_percentage": 55, + "chunk_length": 1 + } + ] + }, + "blob_verification_proof": { + "batch_id": 21103, + "blob_index": 1905, + "batch_metadata": { + "batch_header": { + "batch_root": "d627b55c1f307c37d0543562cdb2e1faf907dd98c1e5f94be62785ac30cca851", + "quorum_numbers": "0001", + "quorum_signed_percentages": "6362", + "reference_block_number": 1820787 + }, + "signatory_record_hash": "390703dea190bab4fc41037a72055dfe8ad3df2cf359a15dca3ebe601c4a0bd9", + "fee": "00", + "confirmation_block_number": 1820926, + "batch_header_hash": "f38003c8fed893238c3e8712efe1149333ed86a163fffdb77c98595fa76454aa" + }, + "inclusion_proof": "75ad90fbbde05f97f78dd7908f85a45c4e851cc29b796b70f78cf704a6e32815089c0d4db7fafbb64881a16d7f85e0e8c87129295a31a33e496cde48b1d08c8355754e58189833af2acd177159cd5f433420f335089f657643b85bef9d5701972354f1d752a9d31fce3ca7773c341b8aa729c88a2b3a2bb678c166f563b33f622c587b69c2ec92c998385010f08dc4170a08747c42e23ef429b67cf505a471d0eed3f79adb6a4d781e242ff800c29214f8fbf4f57d7d57ea48082f54e52d7f759afd178572e6986ba7ef6e9050184332eebd04cec473279188ae2a0f780d2ed69a0b17cfa3962bc09162db8b469ae8a38e3db31042338457f765c77f6b28cdd7e14df7b2c40f27f32bd7d4907816fb2655e06414a5b180ade4ebe295662c007428e2141faccaee62f177305df72d1f3b0f8dfc90235272f9a741af4eae6af6dc7bce2ce5f9c820c78fe436beaeef9b6734702cfc3d7863fac39ed52dc3061a1cf4f895c0797e6aff0a6076044102b00663e5e74f5ec53e4621312b98f4c74a7e", + "quorum_indexes": "0001" + } + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 00d8467d..a5ec8fa4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -46,6 +46,11 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@eigenda/eigenda-utils@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@eigenda/eigenda-utils/-/eigenda-utils-2.0.0.tgz#4a2b179d2b41cc7d4ccfbff4aef210b5fa23d1ca" + integrity sha512-aijRWVPZWw3WA7sZHu1lmYRwQxWqK51YcZPq/QkyyfVsVqHJQdW3zUpuyKLesH1jVkfcQ3f1LdFPZTonvj8oIg== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -628,6 +633,24 @@ optionalDependencies: "@trufflesuite/bigint-buffer" "1.1.9" +"@grpc/grpc-js@^1.8.22": + version "1.8.22" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.22.tgz#847930c9af46e14df05b57fc12325db140ceff1d" + integrity sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA== + dependencies: + "@grpc/proto-loader" "^0.7.0" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.7.0", "@grpc/proto-loader@^0.7.13": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -893,26 +916,84 @@ "@openzeppelin/contracts" "4.7.3" "@openzeppelin/contracts-upgradeable" "4.7.3" -"@openzeppelin/contracts-upgradeable@4.5.2": - version "4.5.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" - integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== +"@openzeppelin-upgrades/contracts@npm:@openzeppelin/contracts-upgradeable@4.7": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" + integrity sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A== + +"@openzeppelin/contracts-upgradeable@4.7.2": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.2.tgz#414096e21f048200cbb7ad4fe4c6de2e822513bf" + integrity sha512-3dgc6qVmFch/uOmlmKnw5/v3JxwXcZD4T10/9CI1OUbX8AqjoZrBGKfxN1z3QxnIXRU/X31/BItJezJSDDTe7Q== "@openzeppelin/contracts-upgradeable@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" integrity sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A== -"@openzeppelin/contracts@4.5.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" - integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== +"@openzeppelin/contracts@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.0.tgz#3092d70ea60e3d1835466266b1d68ad47035a2d5" + integrity sha512-52Qb+A1DdOss8QvJrijYYPSf32GUg2pGaG/yCxtaA3cu4jduouTdg4XZSMLW9op54m1jH7J8hoajhHKOPsoJFw== "@openzeppelin/contracts@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@resolver-engine/core@^0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" @@ -1191,6 +1272,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/google-protobuf@^3.15.12": + version "3.15.12" + resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.12.tgz#eb2ba0eddd65712211a2b455dc6071d665ccf49b" + integrity sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ== + "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -1271,6 +1357,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== +"@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "20.14.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" + integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== + dependencies: + undici-types "~5.26.4" + "@types/node@^10.0.3": version "10.17.60" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" @@ -1740,7 +1833,7 @@ async-mutex@^0.4.0: async@1.x: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.4.0: version "2.6.3" @@ -4447,7 +4540,7 @@ jju@^1.4.0: js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" @@ -4794,6 +4887,11 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -5550,6 +5648,24 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +protobufjs@^7.2.5: + version "7.3.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.0.tgz#a32ec0422c039798c41a0700306a6e305b9cb32c" + integrity sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -6004,9 +6120,9 @@ semver@^5.5.0, semver@^5.6.0: integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.3.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.0.0, semver@^7.5.4: version "7.6.0" @@ -6015,7 +6131,7 @@ semver@^7.0.0, semver@^7.5.4: dependencies: lru-cache "^6.0.0" -semver@^7.3.4, semver@^7.3.7: +semver@^7.3.4, semver@^7.3.7, semver@^7.6.0: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== @@ -6602,9 +6718,9 @@ sync-rpc@^1.2.1: get-port "^3.1.0" synp@^1.9.10: - version "1.9.10" - resolved "https://registry.yarnpkg.com/synp/-/synp-1.9.10.tgz#53163321a600418c9b06af0db499939ffce12907" - integrity sha512-G9Z/TXTaBG1xNslUf3dHFidz/8tvvRaR560WWyOwyI7XrGGEGBTEIIg4hdRh1qFtz8mPYynAUYwWXUg/Zh0Pzw== + version "1.9.13" + resolved "https://registry.yarnpkg.com/synp/-/synp-1.9.13.tgz#90eee678f01dce5dccd228ab9e8d887d2c0728a5" + integrity sha512-qbmzXIDpgtx435n26p7MWgWNvGaNdgZ9zKBm+cXlV6ZhFWaH8MMBQt8PdMGqjdvp63J0k040fO77ClDFDD804Q== dependencies: "@yarnpkg/lockfile" "^1.1.0" bash-glob "^2.0.0" @@ -6613,7 +6729,7 @@ synp@^1.9.10: eol "^0.9.1" lodash "4.17.21" nmtree "^1.0.6" - semver "^7.3.5" + semver "^7.6.0" sort-object-keys "^1.1.3" table-layout@^1.0.1: @@ -7249,7 +7365,7 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.0: +yargs@^17.0.0, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==