diff --git a/docs/Overview.md b/docs/Overview.md index 4529a8dda..b3003ec88 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -178,12 +178,12 @@ Each L2 -> L1 system log will have a key that is part of the following: ```solidity enum SystemLogKey { L2_TO_L1_LOGS_TREE_ROOT_KEY, - TOTAL_L2_TO_L1_PUBDATA_KEY, - STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, NUMBER_OF_LAYER_1_TXS_KEY, + L2_DA_VALIDATOR_OUTPUT_HASH_KEY, + USED_L2_DA_VALIDATOR_ADDRESS_KEY, EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY } ``` diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol index e09f3b6a3..45628bfe8 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol @@ -260,6 +260,12 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin { require(currentProtocolVersion == protocolVersion, "STM: protocolVersion not up to date"); + if (block.chainid != L1_CHAIN_ID) { + // We assume that GW -> L1 transactions can never fail and provide no recovery mechanism from it. + // That's why we need to bound the gas that can be consumed during such a migration. + require(s.totalBatchesCommitted == s.totalBatchesExecuted, "Af: not all batches executed"); + } + s.settlementLayer = _settlementLayer; chainBridgeMintData = abi.encode(prepareChainCommitment()); } @@ -391,37 +397,4 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin { commitment.batchHashes = batchHashes; } - - // function recoverFromFailedMigrationToGateway( - // uint256 _settlementLayerChainId, - // uint256 _l2BatchNumber, - // uint256 _l2MessageIndex, - // uint16 _l2TxNumberInBatch, - // bytes32[] calldata _merkleProof - // ) external onlyAdmin { - // require(s.settlementLayerState == SettlementLayerState.MigratedFromL1, "not migrated L1"); - - // bytes32 migrationHash = s.settlementLayerMigrationHash; - // require(migrationHash != bytes32(0), "can not recover when there is no migration"); - - // require( - // IBridgehub(s.bridgehub).proveL1ToL2TransactionStatus( - // _settlementLayerChainId, - // migrationHash, - // _l2BatchNumber, - // _l2MessageIndex, - // _l2TxNumberInBatch, - // _merkleProof, - // TxStatus.Failure - // ), - // "Migration not failed" - // ); - - // s.settlementLayerState = SettlementLayerState.ActiveOnL1; - // s.settlementLayerChainId = 0; - // s.settlementLayerMigrationHash = bytes32(0); - - // // We do not need to perform any additional actions, since no changes related to the chain commitment can be performed - // // while the chain is in the "migrated" state. - // } } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index ea459a6d0..7d514a673 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -16,7 +16,7 @@ import {L2_BOOTLOADER_ADDRESS, L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_SYSTE import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; import {PriorityTree, PriorityOpsBatchInfo} from "../../libraries/PriorityTree.sol"; import {IL1DAValidator, L1DAValidatorOutput} from "../../chain-interfaces/IL1DAValidator.sol"; -import {BatchNumberMismatch, TimeNotReached, ValueMismatch, HashMismatch, NonIncreasingTimestamp, TimestampError, InvalidLogSender, TxHashMismatch, UnexpectedSystemLog, LogAlreadyProcessed, InvalidProtocolVersion, CanOnlyProcessOneBatch, BatchHashMismatch, UpgradeBatchNumberIsNotZero, NonSequentialBatch, CantExecuteUnprovenBatches, SystemLogsSizeTooBig, InvalidNumberOfBlobs, VerifiedBatchesExceedsCommittedBatches, InvalidProof, RevertedBatchNotAfterNewLastBatch, CantRevertExecutedBatch, L2TimestampTooBig, PriorityOperationsRollingHashMismatch} from "../../../common/L1ContractErrors.sol"; +import {MissingSystemLogs, BatchNumberMismatch, TimeNotReached, ValueMismatch, HashMismatch, NonIncreasingTimestamp, TimestampError, InvalidLogSender, TxHashMismatch, UnexpectedSystemLog, LogAlreadyProcessed, InvalidProtocolVersion, CanOnlyProcessOneBatch, BatchHashMismatch, UpgradeBatchNumberIsNotZero, NonSequentialBatch, CantExecuteUnprovenBatches, SystemLogsSizeTooBig, InvalidNumberOfBlobs, VerifiedBatchesExceedsCommittedBatches, InvalidProof, RevertedBatchNotAfterNewLastBatch, CantRevertExecutedBatch, L2TimestampTooBig, PriorityOperationsRollingHashMismatch} from "../../../common/L1ContractErrors.sol"; // While formally the following import is not used, it is needed to inherit documentation from it import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol"; @@ -216,16 +216,15 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { } } - // FIXME: temporarily old logs were kept for backwards compatibility. This check cannot work now. - // // We only require 8 logs to be checked, the 9th is if we are expecting a protocol upgrade // Without the protocol upgrade we expect 8 logs: 2^8 - 1 = 255 // With the protocol upgrade we expect 9 logs: 2^9 - 1 = 511 if (_expectedSystemContractUpgradeTxHash == bytes32(0)) { - // require(processedLogs == 255, "b7"); - } else { - // FIXME: do restore this code to the one that was before - require(_checkBit(processedLogs, uint8(SystemLogKey.EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY)), "b8"); + if (processedLogs != 127) { + revert MissingSystemLogs(127, processedLogs); + } + } else if (processedLogs != 255) { + revert MissingSystemLogs(255, processedLogs); } } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol index 7542c63fe..f492c599f 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol @@ -233,7 +233,6 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { /// @inheritdoc IGetters function getSettlementLayer() external view returns (address) { - // TODO: consider making private so that no one relies on it return s.settlementLayer; } diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol index 61802b674..486240734 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol @@ -115,7 +115,7 @@ interface IAdmin is IZkSyncHyperchainBase { /// @notice Emitted when an upgrade is executed. event ExecuteUpgrade(Diamond.DiamondCutData diamondCut); - /// TODO: maybe include some params + /// @notice Emitted when the migration to the new settlement layer is complete. event MigrationComplete(); /// @notice Emitted when the contract is frozen. diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol index 6f5462f73..86def9b82 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol @@ -8,8 +8,6 @@ import {PriorityOpsBatchInfo} from "../libraries/PriorityTree.sol"; /// @dev Enum used by L2 System Contracts to differentiate logs. enum SystemLogKey { L2_TO_L1_LOGS_TREE_ROOT_KEY, - TOTAL_L2_TO_L1_PUBDATA_KEY, - STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol index f1eb7f865..4a2aa5c9f 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol @@ -156,6 +156,6 @@ interface IGetters is IZkSyncHyperchainBase { /// @return isFreezable Whether the facet can be frozen by the admin or always accessible function isFacetFreezable(address _facet) external view returns (bool isFreezable); - /// TODO + /// @return The address of the current settlement layer. function getSettlementLayer() external view returns (address); } diff --git a/l1-contracts/test/foundry/integration/deploy-scripts/script-out/output-deploy-l1.toml b/l1-contracts/test/foundry/integration/deploy-scripts/script-out/output-deploy-l1.toml index cbb67dc28..917346ec5 100644 --- a/l1-contracts/test/foundry/integration/deploy-scripts/script-out/output-deploy-l1.toml +++ b/l1-contracts/test/foundry/integration/deploy-scripts/script-out/output-deploy-l1.toml @@ -2,13 +2,13 @@ create2_factory_addr = "0x4e59b44847b379578588920cA78FbF26c0B4956C" create2_factory_salt = "0x00000000000000000000000000000000000000000000000000000000000000ff" deployer_addr = "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496" era_chain_id = 9 -force_deployments_data = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002a093831bf373db45086a901f45805c61f07944b1b7f596761f084f8dfc3e0bea2200000000000000000000000000000000000000000000000000000000000100020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000081aa7970c51812dc3a010c7d01b50e0d17dc8ad979ed796c3d846e1b70fae457404e519165deaa186a5f2357eeb1aef830c86b9600000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010e000000000000000000000000000000000000000000000000000000000000000900000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000000000000000000001629ac8f4a74ebd8df4688cdedcfe5120809a334ecdc277c65e30475a8ed6616100000000000000000000000000000000000000000000000000000000000100040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000081aa7970c51812dc3a010c7d01b50e0d17dc8ad9349c400bc5cef9910dcd7cd1328960b14d2c095f0e5d26c14f4f8a467160578500000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000000000000000000000" +force_deployments_data = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000440479fd527ba27eb8ef691b359730a2d9dd5aa41c783d184ac0a851548be5a1f9600000000000000000000000000000000000000000000000000000000000100020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000081aa7970c51812dc3a010c7d01b50e0d17dc8ad9447bf69c0e623e1365f68b9682081c8aaf2005f3346a6bb9df35dc505c91cbbc00000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010e000000000000000000000000000000000000000000000000000000000000000900000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000000000000000000001542f9245b27fa8a082741b6727b86d24c07131b4afdfb66bba0b75c767bf668500000000000000000000000000000000000000000000000000000000000100040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000081aa7970c51812dc3a010c7d01b50e0d17dc8ad9554b5e8820768894caf758e182b80205d2a55d217795c711cc044cf83539f66000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c800000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000000000000000000000a7e2e0952e4de366512e12ba0703e9dd6ea5ca6880aeae0344cdd1b1a3cf13d400000000000000000000000000000000000000000000000000000000000100050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000010002" l1_chain_id = 31337 multicall3_addr = "0xb4CA672635D5E33C2725B4F250Dc5D3BFC489469" owner_address = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" [contracts_config] -diamond_cut_data = "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000ae70b8622851519e3af6215b0d2bf8bb7e94ee5e0000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000062476c57821675af1a33b39eb1655540fdf9a17c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000130e18b681000000000000000000000000000000000000000000000000000000001733894500000000000000000000000000000000000000000000000000000000fc57565f000000000000000000000000000000000000000000000000000000001cc5d1030000000000000000000000000000000000000000000000000000000021f603d700000000000000000000000000000000000000000000000000000000235d9eb50000000000000000000000000000000000000000000000000000000027ae4c16000000000000000000000000000000000000000000000000000000002878fe74000000000000000000000000000000000000000000000000000000003f42d5dd0000000000000000000000000000000000000000000000000000000041cf49bb000000000000000000000000000000000000000000000000000000004623c91d000000000000000000000000000000000000000000000000000000004dd18bf5000000000000000000000000000000000000000000000000000000006223258e0000000000000000000000000000000000000000000000000000000064b554ad0000000000000000000000000000000000000000000000000000000064bf8d6600000000000000000000000000000000000000000000000000000000a9f6d94100000000000000000000000000000000000000000000000000000000b784610700000000000000000000000000000000000000000000000000000000be6f11cf00000000000000000000000000000000000000000000000000000000e76db865000000000000000000000000000000000000000000000000000000000000000000000000000000004e4cf6187167b8e081cb736a75d3554cb7090dfc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000002d06d49e5b00000000000000000000000000000000000000000000000000000000086a56f8000000000000000000000000000000000000000000000000000000000ec6b0b700000000000000000000000000000000000000000000000000000000fe26699e0000000000000000000000000000000000000000000000000000000018e3a941000000000000000000000000000000000000000000000000000000001de72e340000000000000000000000000000000000000000000000000000000029b98c670000000000000000000000000000000000000000000000000000000033ce93fe000000000000000000000000000000000000000000000000000000003408e470000000000000000000000000000000000000000000000000000000003591c1a000000000000000000000000000000000000000000000000000000000396073820000000000000000000000000000000000000000000000000000000039d7d4aa0000000000000000000000000000000000000000000000000000000046657fe90000000000000000000000000000000000000000000000000000000052ef6b2c000000000000000000000000000000000000000000000000000000005518c73b000000000000000000000000000000000000000000000000000000005a59033500000000000000000000000000000000000000000000000000000000631f4bac000000000000000000000000000000000000000000000000000000006a27e8b5000000000000000000000000000000000000000000000000000000006e9960c30000000000000000000000000000000000000000000000000000000074f4d30d0000000000000000000000000000000000000000000000000000000079823c9a000000000000000000000000000000000000000000000000000000007a0ed627000000000000000000000000000000000000000000000000000000007b30c8da00000000000000000000000000000000000000000000000000000000960dcf240000000000000000000000000000000000000000000000000000000098acd7a6000000000000000000000000000000000000000000000000000000009cd939e4000000000000000000000000000000000000000000000000000000009d1b5a8100000000000000000000000000000000000000000000000000000000a1954fc500000000000000000000000000000000000000000000000000000000adfca15e00000000000000000000000000000000000000000000000000000000af6a2dcd00000000000000000000000000000000000000000000000000000000b22dd78e00000000000000000000000000000000000000000000000000000000b8c2f66f00000000000000000000000000000000000000000000000000000000bd7c541200000000000000000000000000000000000000000000000000000000c3bbd2d700000000000000000000000000000000000000000000000000000000cdffacc600000000000000000000000000000000000000000000000000000000d046815600000000000000000000000000000000000000000000000000000000d86970d800000000000000000000000000000000000000000000000000000000db1f0bf900000000000000000000000000000000000000000000000000000000e5355c7500000000000000000000000000000000000000000000000000000000e81e0ba100000000000000000000000000000000000000000000000000000000ea6c029c00000000000000000000000000000000000000000000000000000000ef3f0bae00000000000000000000000000000000000000000000000000000000f5c1182c00000000000000000000000000000000000000000000000000000000facd743b00000000000000000000000000000000000000000000000000000000fd791f3c000000000000000000000000000000000000000000000000000000000000000000000000000000009c68efaa09262647f5bbb9afb4c7fb2dd7c6c642000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b042901c70000000000000000000000000000000000000000000000000000000012f43dab0000000000000000000000000000000000000000000000000000000013f3756e00000000000000000000000000000000000000000000000000000000eb67241900000000000000000000000000000000000000000000000000000000263b7f8e000000000000000000000000000000000000000000000000000000006c0960f9000000000000000000000000000000000000000000000000000000007efda2ae00000000000000000000000000000000000000000000000000000000b473318e00000000000000000000000000000000000000000000000000000000dc8cc04600000000000000000000000000000000000000000000000000000000e4948f4300000000000000000000000000000000000000000000000000000000e717bab700000000000000000000000000000000000000000000000000000000000000000000000000000000b6aac5d171cfc9c0a4069d825873ffac5ce96b83000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000400a22e22000000000000000000000000000000000000000000000000000000000f23da4300000000000000000000000000000000000000000000000000000000c37533bb000000000000000000000000000000000000000000000000000000006edd4f120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000064fd27c7082f2f3e4f8629977eab095b82ddc422000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000182b8000000000000000000000000000000000000000000000000000000000ee6b280000000000000000000000000a4cb26d6933d2c3e76718d30de8547bcdf8dd241" +diamond_cut_data = "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000ae70b8622851519e3af6215b0d2bf8bb7e94ee5e0000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000005dece56f93491d5dda155d918de47cc41e3239b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000130e18b681000000000000000000000000000000000000000000000000000000001733894500000000000000000000000000000000000000000000000000000000fc57565f000000000000000000000000000000000000000000000000000000001cc5d1030000000000000000000000000000000000000000000000000000000021f603d700000000000000000000000000000000000000000000000000000000235d9eb50000000000000000000000000000000000000000000000000000000027ae4c16000000000000000000000000000000000000000000000000000000002878fe74000000000000000000000000000000000000000000000000000000003f42d5dd0000000000000000000000000000000000000000000000000000000041cf49bb000000000000000000000000000000000000000000000000000000004623c91d000000000000000000000000000000000000000000000000000000004dd18bf5000000000000000000000000000000000000000000000000000000006223258e0000000000000000000000000000000000000000000000000000000064b554ad0000000000000000000000000000000000000000000000000000000064bf8d6600000000000000000000000000000000000000000000000000000000a9f6d94100000000000000000000000000000000000000000000000000000000b784610700000000000000000000000000000000000000000000000000000000be6f11cf00000000000000000000000000000000000000000000000000000000e76db86500000000000000000000000000000000000000000000000000000000000000000000000000000000c64c035376af18afb8f7787554c24199fad29383000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000002d06d49e5b00000000000000000000000000000000000000000000000000000000086a56f8000000000000000000000000000000000000000000000000000000000ec6b0b700000000000000000000000000000000000000000000000000000000fe26699e0000000000000000000000000000000000000000000000000000000018e3a941000000000000000000000000000000000000000000000000000000001de72e340000000000000000000000000000000000000000000000000000000029b98c670000000000000000000000000000000000000000000000000000000033ce93fe000000000000000000000000000000000000000000000000000000003408e470000000000000000000000000000000000000000000000000000000003591c1a000000000000000000000000000000000000000000000000000000000396073820000000000000000000000000000000000000000000000000000000039d7d4aa0000000000000000000000000000000000000000000000000000000046657fe90000000000000000000000000000000000000000000000000000000052ef6b2c000000000000000000000000000000000000000000000000000000005518c73b000000000000000000000000000000000000000000000000000000005a59033500000000000000000000000000000000000000000000000000000000631f4bac000000000000000000000000000000000000000000000000000000006a27e8b5000000000000000000000000000000000000000000000000000000006e9960c30000000000000000000000000000000000000000000000000000000074f4d30d0000000000000000000000000000000000000000000000000000000079823c9a000000000000000000000000000000000000000000000000000000007a0ed627000000000000000000000000000000000000000000000000000000007b30c8da00000000000000000000000000000000000000000000000000000000960dcf240000000000000000000000000000000000000000000000000000000098acd7a6000000000000000000000000000000000000000000000000000000009cd939e4000000000000000000000000000000000000000000000000000000009d1b5a8100000000000000000000000000000000000000000000000000000000a1954fc500000000000000000000000000000000000000000000000000000000adfca15e00000000000000000000000000000000000000000000000000000000af6a2dcd00000000000000000000000000000000000000000000000000000000b22dd78e00000000000000000000000000000000000000000000000000000000b8c2f66f00000000000000000000000000000000000000000000000000000000bd7c541200000000000000000000000000000000000000000000000000000000c3bbd2d700000000000000000000000000000000000000000000000000000000cdffacc600000000000000000000000000000000000000000000000000000000d046815600000000000000000000000000000000000000000000000000000000d86970d800000000000000000000000000000000000000000000000000000000db1f0bf900000000000000000000000000000000000000000000000000000000e5355c7500000000000000000000000000000000000000000000000000000000e81e0ba100000000000000000000000000000000000000000000000000000000ea6c029c00000000000000000000000000000000000000000000000000000000ef3f0bae00000000000000000000000000000000000000000000000000000000f5c1182c00000000000000000000000000000000000000000000000000000000facd743b00000000000000000000000000000000000000000000000000000000fd791f3c00000000000000000000000000000000000000000000000000000000000000000000000000000000fc6b3f1e8d93cec434ff208ce9d19011df49b2f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b042901c70000000000000000000000000000000000000000000000000000000012f43dab0000000000000000000000000000000000000000000000000000000013f3756e00000000000000000000000000000000000000000000000000000000eb67241900000000000000000000000000000000000000000000000000000000263b7f8e000000000000000000000000000000000000000000000000000000006c0960f9000000000000000000000000000000000000000000000000000000007efda2ae00000000000000000000000000000000000000000000000000000000b473318e00000000000000000000000000000000000000000000000000000000dc8cc04600000000000000000000000000000000000000000000000000000000e4948f4300000000000000000000000000000000000000000000000000000000e717bab7000000000000000000000000000000000000000000000000000000000000000000000000000000003c526b4b50b8a3f20bf4200e728aeb4c1298179b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000400a22e22000000000000000000000000000000000000000000000000000000000f23da4300000000000000000000000000000000000000000000000000000000c37533bb000000000000000000000000000000000000000000000000000000006edd4f120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000064fd27c7082f2f3e4f8629977eab095b82ddc422000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000001d4c00000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000182b8000000000000000000000000000000000000000000000000000000000ee6b280000000000000000000000000a4cb26d6933d2c3e76718d30de8547bcdf8dd241" diamond_init_batch_overhead_l1_gas = 1000000 diamond_init_max_l2_gas_per_batch = 80000000 diamond_init_max_pubdata_per_batch = 120000 @@ -24,33 +24,33 @@ recursion_node_level_vk_hash = "0x0000000000000000000000000000000000000000000000 [deployed_addresses] blob_versioned_hash_retriever_addr = "0xA4cB26d6933D2c3E76718D30de8547bCDF8dD241" governance_addr = "0x61918895E9eB44Caf1B8B9b7e625C65b9AFda41E" -native_token_vault_addr = "0xe5e7Bd646699F63A72AF6A11983DB4e8127A154A" +native_token_vault_addr = "0x72c8dA88057aEf671Bc2265c97c061a474b079dE" transparent_proxy_admin_addr = "0xD718d5A27a29FF1cD22403426084bA0d479869a0" -validator_timelock_addr = "0x3C3D72cec2cecC40672b9e144b32ADB3b7Fd084F" +validator_timelock_addr = "0x296D4B4d5F4AD8969FB99bD6E1447B68730731f2" [deployed_addresses.bridgehub] -bridgehub_implementation_addr = "0x66CAF057C87e15eF8108502BD90cB52E2E90Cf5e" -bridgehub_proxy_addr = "0x15b26f421C552Ce0EF27EDDa4f646Ae347Fe0B11" -message_root_implementation_addr = "0xD84b2C4928190dC10Bbb7D87de213509D9F59394" -message_root_proxy_addr = "0x9348A4Dfd3bB679b42eFb06bb77F1B98eE5CF465" -stm_deployment_tracker_implementation_addr = "0x72a154C815aF6505cec588885950Fa1Ae784D2C2" -stm_deployment_tracker_proxy_addr = "0x9fA6Bcfd5A27252299d718557Ae6556d14419D34" +bridgehub_implementation_addr = "0x707A27c33F7A4AC4E565DbaDdb5b419a6b584AE6" +bridgehub_proxy_addr = "0x91779E4566816493541AD16df6BF445043c41713" +message_root_implementation_addr = "0xA53Abaa516fc476b93810484131c2E7772d28B89" +message_root_proxy_addr = "0x2BB1Ddf7EC79b03362c75EDF120c68620531dF00" +stm_deployment_tracker_implementation_addr = "0xa7c7453d96bbB4d3fb3d91AA9e3D8a71F2027238" +stm_deployment_tracker_proxy_addr = "0x9014441FA25B02598dAf1C4049B56eC1E2fECDE9" [deployed_addresses.bridges] -erc20_bridge_implementation_addr = "0xc68a437d6146d097Bf7fEa4135B65D97FC2a6D89" -erc20_bridge_proxy_addr = "0x1be63449BF1Ab0fDFE9D53A73A2a484b61368d94" -shared_bridge_implementation_addr = "0x162D9044486A4bA9A8e3AC0E9171D13e6A9eCf1b" -shared_bridge_proxy_addr = "0x4D8C730646430d6BF2B7a965Ad39c12CBDc7eEcD" +erc20_bridge_implementation_addr = "0x9ac46E47b60258225008080348306D7D8F6cf65f" +erc20_bridge_proxy_addr = "0xd5366f3FF894f8dc364844Ed44E7577E56e8bF55" +shared_bridge_implementation_addr = "0x4274E94711858255df5C142D1dE463b8650726a8" +shared_bridge_proxy_addr = "0xF4854259a618c9b580499763e70fDA8d74947323" [deployed_addresses.state_transition] -admin_facet_addr = "0x62476C57821675Af1a33B39EB1655540fDF9a17C" +admin_facet_addr = "0x05deCE56F93491D5dDA155d918dE47cC41E3239b" default_upgrade_addr = "0xf16Fda6af9D791828C86B96d2BEd3055f73AFb13" diamond_init_addr = "0xAe70b8622851519e3Af6215b0d2bf8Bb7e94EE5E" diamond_proxy_addr = "0x0000000000000000000000000000000000000000" -executor_facet_addr = "0xB6aaC5d171Cfc9c0a4069d825873FFaC5ce96b83" -genesis_upgrade_addr = "0x71750BC31260B2802107505b6914C2c1de87fe53" -getters_facet_addr = "0x4E4Cf6187167B8E081cB736A75D3554cB7090dFc" -mailbox_facet_addr = "0x9C68eFaA09262647f5BBb9AFb4C7fb2DD7C6C642" -state_transition_implementation_addr = "0x71464D3Af9c91EbDdEc6e0EAb60e226FAe580d75" -state_transition_proxy_addr = "0xe4f8f48b99d537067f45b46205E9c36a6A4c984a" +executor_facet_addr = "0x3C526b4B50b8A3f20Bf4200e728AEb4C1298179b" +genesis_upgrade_addr = "0x47bE12cEb3F02469fD2d24c563F7a26EAD2214DE" +getters_facet_addr = "0xc64C035376af18aFb8f7787554C24199faD29383" +mailbox_facet_addr = "0xFc6B3f1E8D93CeC434Ff208ce9D19011dF49B2f4" +state_transition_implementation_addr = "0xc4e58Ae93055727E149A20290AB8fc9d2A8713e4" +state_transition_proxy_addr = "0xE738E5bd89Bf84049bcAEa6E5Ee7514BFbE4892f" verifier_addr = "0x64Fd27c7082F2f3E4F8629977eaB095b82ddC422" diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/Committing.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/Committing.t.sol index f2323358d..e7bfa5fc0 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/Committing.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/Committing.t.sol @@ -229,7 +229,7 @@ contract CommittingTest is ExecutorTest { vm.prank(validator); vm.blobhashes(defaultBlobVersionedHashes); - vm.expectRevert(abi.encodeWithSelector(LogAlreadyProcessed.selector, 3)); + vm.expectRevert(abi.encodeWithSelector(LogAlreadyProcessed.selector, 1)); executor.commitBatchesSharedBridge(uint256(0), genesisStoredBatchInfo, wrongNewCommitBatchInfoArray); } @@ -330,9 +330,7 @@ contract CommittingTest is ExecutorTest { } function test_RevertWhen_SystemLogIsFromIncorrectAddress() public { - bytes32[9] memory values = [ - bytes32(""), - bytes32(""), + bytes32[7] memory values = [ bytes32(""), bytes32(""), bytes32(""), @@ -342,26 +340,7 @@ contract CommittingTest is ExecutorTest { bytes32("") ]; - bytes[9] memory errors = [ - bytes.concat("lm"), - bytes.concat(""), - bytes.concat(""), - bytes.concat("sc"), - bytes.concat("sv"), - bytes.concat("bl"), - bytes.concat("bk"), - bytes.concat("lp2"), - bytes.concat("vk") - ]; - for (uint256 i = 0; i < values.length; i++) { - // these logs are not checked by the executor, thus they can't cause a revert - if ( - i == uint256(SystemLogKey.TOTAL_L2_TO_L1_PUBDATA_KEY) || i == uint256(SystemLogKey.STATE_DIFF_HASH_KEY) - ) { - continue; - } - bytes[] memory wrongL2Logs = Utils.createSystemLogs(l2DAValidatorOutputHash); address wrongAddress = makeAddr("randomAddress"); wrongL2Logs[i] = Utils.constructL2Log(true, wrongAddress, i, values[i]); diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 08291b5b1..e6e9c1ea2 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -60,7 +60,7 @@ library Utils { } function createSystemLogs(bytes32 _outputHash) public returns (bytes[] memory) { - bytes[] memory logs = new bytes[](9); + bytes[] memory logs = new bytes[](7); logs[0] = constructL2Log( true, L2_TO_L1_MESSENGER, @@ -68,44 +68,37 @@ library Utils { bytes32("") ); logs[1] = constructL2Log( - true, - L2_TO_L1_MESSENGER, - uint256(SystemLogKey.TOTAL_L2_TO_L1_PUBDATA_KEY), - 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 - ); - logs[2] = constructL2Log(true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.STATE_DIFF_HASH_KEY), bytes32("")); - logs[3] = constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, uint256(SystemLogKey.PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY), bytes32("") ); - logs[4] = constructL2Log( + logs[2] = constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, uint256(SystemLogKey.PREV_BATCH_HASH_KEY), bytes32("") ); - logs[5] = constructL2Log( + logs[3] = constructL2Log( true, L2_BOOTLOADER_ADDRESS, uint256(SystemLogKey.CHAINED_PRIORITY_TXN_HASH_KEY), keccak256("") ); - logs[6] = constructL2Log( + logs[4] = constructL2Log( true, L2_BOOTLOADER_ADDRESS, uint256(SystemLogKey.NUMBER_OF_LAYER_1_TXS_KEY), bytes32("") ); - logs[7] = constructL2Log( + logs[5] = constructL2Log( true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.L2_DA_VALIDATOR_OUTPUT_HASH_KEY), _outputHash ); - logs[8] = constructL2Log( + logs[6] = constructL2Log( true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.USED_L2_DA_VALIDATOR_ADDRESS_KEY), diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.t.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.t.sol index ffa7770ca..0c9ad684f 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.t.sol @@ -45,7 +45,7 @@ contract UtilsTest is Test { function test_CreateSystemLogs() public { bytes[] memory logs = Utils.createSystemLogs(bytes32(0)); - assertEq(logs.length, 9, "logs length should be correct"); + assertEq(logs.length, 7, "logs length should be correct"); assertEq( logs[0], @@ -60,85 +60,68 @@ contract UtilsTest is Test { assertEq( logs[1], - Utils.constructL2Log( - true, - L2_TO_L1_MESSENGER, - uint256(SystemLogKey.TOTAL_L2_TO_L1_PUBDATA_KEY), - 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 - ), - "log[1] should be correct" - ); - - assertEq( - logs[2], - Utils.constructL2Log(true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.STATE_DIFF_HASH_KEY), bytes32("")), - "log[2] should be correct" - ); - - assertEq( - logs[3], Utils.constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, uint256(SystemLogKey.PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY), bytes32("") ), - "log[3] should be correct" + "log[1] should be correct" ); assertEq( - logs[4], + logs[2], Utils.constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, uint256(SystemLogKey.PREV_BATCH_HASH_KEY), bytes32("") ), - "log[4] should be correct" + "log[2] should be correct" ); assertEq( - logs[5], + logs[3], Utils.constructL2Log( true, L2_BOOTLOADER_ADDRESS, uint256(SystemLogKey.CHAINED_PRIORITY_TXN_HASH_KEY), keccak256("") ), - "log[5] should be correct" + "log[3] should be correct" ); assertEq( - logs[6], + logs[4], Utils.constructL2Log( true, L2_BOOTLOADER_ADDRESS, uint256(SystemLogKey.NUMBER_OF_LAYER_1_TXS_KEY), bytes32("") ), - "log[6] should be correct" + "log[4] should be correct" ); assertEq( - logs[7], + logs[5], Utils.constructL2Log( true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.L2_DA_VALIDATOR_OUTPUT_HASH_KEY), bytes32(0) ), - "log[7] should be correct" + "log[5] should be correct" ); assertEq( - logs[8], + logs[6], Utils.constructL2Log( true, L2_TO_L1_MESSENGER, uint256(SystemLogKey.USED_L2_DA_VALIDATOR_ADDRESS_KEY), bytes32(uint256(uint160(L2_DA_VALIDATOR_ADDRESS))) ), - "log[8] should be correct" + "log[6] should be correct" ); } diff --git a/l1-contracts/test/unit_tests/utils.ts b/l1-contracts/test/unit_tests/utils.ts index 70f50de68..3d9fd89b7 100644 --- a/l1-contracts/test/unit_tests/utils.ts +++ b/l1-contracts/test/unit_tests/utils.ts @@ -30,7 +30,6 @@ export const L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR = "0x000000000000000000000000000 export const L2_BYTECODE_COMPRESSOR_ADDRESS = "0x000000000000000000000000000000000000800e"; export const DEPLOYER_SYSTEM_CONTRACT_ADDRESS = "0x0000000000000000000000000000000000008006"; export const PUBDATA_CHUNK_PUBLISHER_ADDRESS = "0x0000000000000000000000000000000000008011"; -const PUBDATA_HASH = "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"; export const SYSTEM_UPGRADE_TX_TYPE = 254; @@ -40,8 +39,6 @@ export function randomAddress() { export enum SYSTEM_LOG_KEYS { L2_TO_L1_LOGS_TREE_ROOT_KEY, - TOTAL_L2_TO_L1_PUBDATA_KEY, - STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, @@ -213,8 +210,6 @@ export function createSystemLogs( ) { return [ constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.L2_TO_L1_LOGS_TREE_ROOT_KEY, ethers.constants.HashZero), - constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.TOTAL_L2_TO_L1_PUBDATA_KEY, PUBDATA_HASH), - constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.STATE_DIFF_HASH_KEY, ethers.constants.HashZero), constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, @@ -264,8 +259,6 @@ export function createSystemLogsWithUpgrade( ) { return [ constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.L2_TO_L1_LOGS_TREE_ROOT_KEY, ethers.constants.HashZero), - constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.TOTAL_L2_TO_L1_PUBDATA_KEY, PUBDATA_HASH), - constructL2Log(true, L2_TO_L1_MESSENGER, SYSTEM_LOG_KEYS.STATE_DIFF_HASH_KEY, ethers.constants.HashZero), constructL2Log( true, L2_SYSTEM_CONTEXT_ADDRESS, diff --git a/l2-contracts/contracts/data-availability/DAErrors.sol b/l2-contracts/contracts/data-availability/DAErrors.sol index 457c7ff8b..c3f032d2a 100644 --- a/l2-contracts/contracts/data-availability/DAErrors.sol +++ b/l2-contracts/contracts/data-availability/DAErrors.sol @@ -3,8 +3,6 @@ pragma solidity 0.8.24; enum PubdataField { - NumberOfLogs, - LogsHash, MsgHash, Bytecode, StateDiffCompressionVersion, diff --git a/l2-contracts/test/foundry/unit/data-availability/RollupL2DAValidator.t.sol b/l2-contracts/test/foundry/unit/data-availability/RollupL2DAValidator.t.sol new file mode 100644 index 000000000..5a56e7118 --- /dev/null +++ b/l2-contracts/test/foundry/unit/data-availability/RollupL2DAValidator.t.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; + +import {TestStateDiffComposer} from "./TestStateDiffComposer.sol"; + +import {RollupL2DAValidator} from "contracts/data-availability/RollupL2DAValidator.sol"; +import {STATE_DIFF_ENTRY_SIZE} from "contracts/data-availability/StateDiffL2DAValidator.sol"; +import {ReconstructionMismatch, PubdataField} from "contracts/data-availability/DAErrors.sol"; + +import {COMPRESSOR_CONTRACT, PUBDATA_CHUNK_PUBLISHER} from "contracts/L2ContractHelper.sol"; + +import {console2 as console} from "forge-std/Script.sol"; + +contract RollupL2DAValidatorTest is Test { + RollupL2DAValidator internal l2DAValidator; + TestStateDiffComposer internal composer; + + function setUp() public { + l2DAValidator = new RollupL2DAValidator(); + composer = new TestStateDiffComposer(); + + bytes memory emptyArray = new bytes(0); + + // Setting dummy state diffs, so it works fine. + composer.setDummyStateDiffs(1, 0, 64, emptyArray, 0, emptyArray); + + bytes memory verifyCompressedStateDiffsData = abi.encodeCall( + COMPRESSOR_CONTRACT.verifyCompressedStateDiffs, + (0, 64, emptyArray, emptyArray) + ); + vm.mockCall(address(COMPRESSOR_CONTRACT), verifyCompressedStateDiffsData, new bytes(32)); + + bytes memory chunkPubdataToBlobsData = abi.encodeCall( + PUBDATA_CHUNK_PUBLISHER.chunkPubdataToBlobs, + (emptyArray) + ); + vm.mockCall(address(PUBDATA_CHUNK_PUBLISHER), chunkPubdataToBlobsData, new bytes(32)); + } + + function finalizeAndCall(bytes memory revertMessage) internal returns (bytes32) { + bytes32 rollingMessagesHash = composer.correctRollingMessagesHash(); + bytes32 rollingBytecodeHash = composer.correctRollingBytecodesHash(); + bytes memory totalL2ToL1PubdataAndStateDiffs = composer.generateTotalStateDiffsAndPubdata(); + + if (revertMessage.length > 0) { + vm.expectRevert(revertMessage); + } + return + l2DAValidator.validatePubdata( + bytes32(0), + bytes32(0), + rollingMessagesHash, + rollingBytecodeHash, + totalL2ToL1PubdataAndStateDiffs + ); + } + + function test_incorrectChainMessagesHash() public { + composer.appendAMessage("message", true, false); + + bytes memory revertMessage = abi.encodeWithSelector( + ReconstructionMismatch.selector, + PubdataField.MsgHash, + composer.correctRollingMessagesHash(), + composer.currentRollingMessagesHash() + ); + finalizeAndCall(revertMessage); + } + + function test_incorrectChainBytecodeHash() public { + composer.appendBytecode(new bytes(32), true, false); + + bytes memory revertMessage = abi.encodeWithSelector( + ReconstructionMismatch.selector, + PubdataField.Bytecode, + composer.correctRollingBytecodesHash(), + composer.currentRollingBytecodesHash() + ); + finalizeAndCall(revertMessage); + } + + function test_incorrectStateDiffVersion() public { + composer.setDummyStateDiffs(2, 0, 64, new bytes(0), 0, new bytes(0)); + + bytes memory revertMessage = abi.encodeWithSelector( + ReconstructionMismatch.selector, + PubdataField.StateDiffCompressionVersion, + bytes32(uint256(1)), + bytes32(uint256(2)) + ); + finalizeAndCall(revertMessage); + } + + function test_nonZeroLeftOver() public { + composer.setDummyStateDiffs(1, 0, 64, new bytes(0), 0, new bytes(32)); + + bytes memory revertMessage = abi.encodeWithSelector( + ReconstructionMismatch.selector, + PubdataField.ExtraData, + bytes32(0), + bytes32(uint256(32)) + ); + finalizeAndCall(revertMessage); + } + + function test_fullCorrectCompression() public { + composer.appendAMessage("message", true, true); + composer.appendBytecode(new bytes(32), true, true); + + uint256 numberOfStateDiffs = 1; + // Just some non-zero array, the structure does not matter here. + bytes memory compressedStateDiffs = new bytes(12); + bytes memory uncompressedStateDiffs = new bytes(STATE_DIFF_ENTRY_SIZE * numberOfStateDiffs); + + composer.setDummyStateDiffs( + 1, + uint24(compressedStateDiffs.length), + 64, + compressedStateDiffs, + uint32(numberOfStateDiffs), + uncompressedStateDiffs + ); + + bytes32 stateDiffsHash = keccak256(uncompressedStateDiffs); + bytes memory verifyCompressedStateDiffsData = abi.encodeCall( + COMPRESSOR_CONTRACT.verifyCompressedStateDiffs, + (numberOfStateDiffs, 64, uncompressedStateDiffs, compressedStateDiffs) + ); + vm.mockCall(address(COMPRESSOR_CONTRACT), verifyCompressedStateDiffsData, abi.encodePacked(stateDiffsHash)); + + bytes memory totalPubdata = composer.getTotalPubdata(); + bytes32 blobHash = keccak256(totalPubdata); + bytes32[] memory blobHashes = new bytes32[](1); + blobHashes[0] = blobHash; + bytes memory chunkPubdataToBlobsData = abi.encodeCall( + PUBDATA_CHUNK_PUBLISHER.chunkPubdataToBlobs, + (totalPubdata) + ); + vm.mockCall(address(PUBDATA_CHUNK_PUBLISHER), chunkPubdataToBlobsData, abi.encode(blobHashes)); + + bytes32 operatorDAHash = finalizeAndCall(new bytes(0)); + + bytes32 expectedOperatorDAHash = keccak256( + abi.encodePacked(stateDiffsHash, keccak256(totalPubdata), uint8(blobHashes.length), blobHashes) + ); + + assertEq(operatorDAHash, expectedOperatorDAHash); + } +} diff --git a/l2-contracts/test/foundry/unit/data-availability/TestStateDiffComposer.sol b/l2-contracts/test/foundry/unit/data-availability/TestStateDiffComposer.sol new file mode 100644 index 000000000..05c639818 --- /dev/null +++ b/l2-contracts/test/foundry/unit/data-availability/TestStateDiffComposer.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT + +import {L2_TO_L1_LOG_SERIALIZE_SIZE} from "contracts/data-availability/StateDiffL2DAValidator.sol"; + +import {L2ContractHelper} from "contracts/L2ContractHelper.sol"; + +/// @notice The contract that is used in testing to compose the pubdata needed for the +/// state diff DA validator. +contract TestStateDiffComposer { + // The following two are always correct + // as these qre expected to be already checked by the L1Messenger + uint256 internal logsNumber; + bytes internal logs; + + uint256 internal messagesNumber; + bytes internal messages; + bytes32 public currentRollingMessagesHash; + bytes32 public correctRollingMessagesHash; + + uint256 internal bytecodesNumber; + bytes internal bytecodes; + bytes32 public currentRollingBytecodesHash; + bytes32 public correctRollingBytecodesHash; + + bytes internal uncomressedStateDiffsPart; + bytes internal compressedStateDiffsPart; + + function appendALog() public { + // This function is not fully implemented, i.e. we do not insert the correct + // content of the log. The reason for that is that it is not needed for the + // testing + + ++logsNumber; + logs = bytes.concat(logs, new bytes(L2_TO_L1_LOG_SERIALIZE_SIZE)); + } + + function appendAMessage(bytes memory message, bool includeToArray, bool includeToCorrectHash) public { + if (includeToArray) { + ++messagesNumber; + messages = bytes.concat(messages, bytes4(uint32(message.length)), message); + currentRollingMessagesHash = keccak256(abi.encode(currentRollingMessagesHash, keccak256(message))); + } + + if (includeToCorrectHash) { + correctRollingMessagesHash = keccak256(abi.encode(correctRollingMessagesHash, keccak256(message))); + } + } + + function appendBytecode(bytes memory bytecode, bool includeToArray, bool includeToCorrectHash) public { + if (includeToArray) { + ++bytecodesNumber; + bytecodes = bytes.concat(bytecodes, bytes4(uint32(bytecode.length)), bytecode); + currentRollingBytecodesHash = keccak256( + abi.encode(currentRollingBytecodesHash, L2ContractHelper.hashL2BytecodeMemory(bytecode)) + ); + } + if (includeToCorrectHash) { + correctRollingBytecodesHash = keccak256( + abi.encode(correctRollingBytecodesHash, L2ContractHelper.hashL2BytecodeMemory(bytecode)) + ); + } + } + + function setDummyStateDiffs( + uint8 _version, + uint24 _compressedStateDiffSize, + uint8 _enumIndexSize, + bytes memory _compressedStateDiffs, + uint32 _numberOfStateDiffs, + bytes memory _stateDiffs + ) public { + compressedStateDiffsPart = abi.encodePacked( + _version, + _compressedStateDiffSize, + _enumIndexSize, + _compressedStateDiffs + ); + + uncomressedStateDiffsPart = abi.encodePacked(_numberOfStateDiffs, _stateDiffs); + } + + function getTotalPubdata() public returns (bytes memory _totalPubdata) { + _totalPubdata = abi.encodePacked( + uint32(logsNumber), + logs, + uint32(messagesNumber), + messages, + uint32(bytecodesNumber), + bytecodes, + compressedStateDiffsPart + ); + } + + function generateTotalStateDiffsAndPubdata() public returns (bytes memory _totalL2ToL1PubdataAndStateDiffs) { + _totalL2ToL1PubdataAndStateDiffs = abi.encodePacked(getTotalPubdata(), uncomressedStateDiffsPart); + } +} diff --git a/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol b/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol new file mode 100644 index 000000000..c54367295 --- /dev/null +++ b/l2-contracts/test/foundry/unit/data-availability/ValidiumL2DAValidator.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +// solhint-disable gas-custom-errors + +import {Test} from "forge-std/Test.sol"; + +import {ValidiumL2DAValidator} from "contracts/data-availability/ValidiumL2DAValidator.sol"; + +contract L2Erc20BridgeTest is Test { + function test_callValidiumDAValidator(address depositor, address receiver, uint256 amount) internal { + ValidiumL2DAValidator validator = new ValidiumL2DAValidator(); + + bytes32 outputHash = validator.validatePubdata(bytes32(0), bytes32(0), bytes32(0), bytes32(0), hex""); + + assertEq(outputHash, bytes32(0)); + } +} diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index d1677fb34..6dd2a63e1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100005d1c6473b263ab40de73ff5461263937a5b5b530d3e21a4a09ffff26e2", + "bytecodeHash": "0x0100005d2e07d901f9f7530c0352881d39faf5fe3342a9859952023efde08052", "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007c7d513c9efb7a0b6889ef23d9e2f12599206c68d47414b9d4a4d35b688", + "bytecodeHash": "0x010007c7e02c8232d673335f7a0bf4e93cc8ace003f58ab7c37e9d3cb55d0a99", "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004df7e1557399a894818311c1204e36704aa2cb8e1b4dc7c19069f4a5a4", + "bytecodeHash": "0x0100004dc8a1644de8694ced12125eca269ab7d680bdef7ff9738a8d6b3c7c5f", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014b38f55ea99e1426e1a590bee7a4532981c2b163364fdf728ca13700af", + "bytecodeHash": "0x0100014b5d3366c794bd56d66003e6522b04228ad9ba7ac51e412388eb4a1d16", "sourceCodeHash": "0x7240b5fb2ea8e184522e731fb14f764ebae52b8a69d1870a55daedac9a3ed617" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010004e5c2c77a9baba3fb7d270c83356c507fd3e7ba472278ec1d4c48758208", + "bytecodeHash": "0x010004e5de8ca987ebff2190fc9249a082417ef2a93ef1c9642af543eecf17d5", "sourceCodeHash": "0x92bc09da23ed9d86ba7a84f0dbf48503c99582ae58cdbebbdcc5f14ea1fcf014" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x010000490ad13757765aaab46fa001866899f2da546a73212eb1ca932638c753", + "bytecodeHash": "0x01000049bf340365d1f711da176afcd895f2c7e0ff4bd1383e2375cce9a51231", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100055de35cfc69c9f9104583cebafb0aa8059f60c4eca0895ffa9da8efba62", + "bytecodeHash": "0x0100055d1df6d5bfe11a8123f1a6d12f8d306258a4a0b6ebd6c24373e1cd555b", "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" }, { @@ -59,63 +59,63 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000390e4ef990eeab943e7c5259b1efd6875f9aaf0c33022c2c7889d6651a", + "bytecodeHash": "0x01000039e18b0a92c14722bca9a87eef1c1917afdf8ffa383f00ed1c47da8956", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x0100006fa34602c123e0252354d614c5b1eb0da3c68f98cd0ba8b15187446a19", + "bytecodeHash": "0x0100006f6b4f871edf5e11a752a8e8eb963eeb48dd058bff6749eb7235971cc1", "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010001f71930117a55abba23949c6777afd29da9ec62c2592657434ebf14b195", + "bytecodeHash": "0x010001f7f9ae1adb089ecba169f6e10f1981f031eebb123f64078b2a118ae04a", "sourceCodeHash": "0x8d22a4019347a45cb0c27bed9e98f7033637a7bdcd90fafb1922caa48f2b05de" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010001031eaf329b64e6a16d520dd365cb92195f46475a3b10eb1352a77c6495", + "bytecodeHash": "0x01000103d97079f37f32641d7493b825e24fb00c8e49d3c89f0b664ccd23ad7c", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "L2GenesisUpgrade", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2GenesisUpgrade.sol/L2GenesisUpgrade.json", "sourceCodePath": "contracts-preprocessed/L2GenesisUpgrade.sol", - "bytecodeHash": "0x010000d58674e0a1b0e07b3587401d7e17a9b62986c34a9171463a39f8e92bf3", + "bytecodeHash": "0x010000d5696456676605b43a10d7cd0f33fbc465b4afa49f874e1cebba7aa6c4", "sourceCodeHash": "0x27584533f7229befe23288d5a157514cdbdfd5935295efaf5fe1da11a12569f3" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005deecb5b2ce8f6fd90c5bdce18a43e933a3f2b5f7ba0343d8b1c6d2b78", + "bytecodeHash": "0x0100005db7df69a12c3b379f4ae12d3be20d1008824d49e2ac0d601cdd4544be", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d900645c7940341daa06f46dbf804acfb98fb6437fd28fdaf46da79c1f", + "bytecodeHash": "0x010000d90d0318d546cda8958c88105657769679f17d7c460773a0501817898e", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000049299f3ee802b7e84d6a655dc67924a3bf5aa377347fb05a09e59abc57", + "bytecodeHash": "0x0100004900240bd8dcb7d87634a7547fb6d6ffaea7a190fb61c6850b375b7bd1", "sourceCodeHash": "0x04d3d2e4019081c87aae5c22a060d84ae2e9d631ebce59801ecce37b9c87e4c7" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a717f01d12bc8686cbec93be57f6c8dd13a8912ad698bef9e6ed873fa1", + "bytecodeHash": "0x010001a7c0458a11bd86f2fcbc0643f84ec93a4d4e4356ce0db3367c357ff222", "sourceCodeHash": "0xb3b8c1f57928938ac590984442bc96c2c888282793014845d5ce2f90bbf2677f" }, { @@ -185,35 +185,35 @@ "contractName": "bootloader_test", "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003cb529c933b02800df76c52ecd5c75c9a426449834a444b03e6ee33e90a", - "sourceCodeHash": "0xe478f7c49dc5e69c82ffd1b88dd94b8f6bde5716829fc9be2302fe3e452ccbf9" + "bytecodeHash": "0x010003cb2fe407ac312db0aa6a6e746ca41cd19ab0eea216a14ec725f5cc7444", + "sourceCodeHash": "0xd7748f25eeb4f17b5d5bc09172f09ffdd9b8a34d011b3fb62aac5b494231b168" }, { "contractName": "fee_estimate", "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x01000931cba6b0eae852a0e3b05d5276fbd396b631b922c92fc613719283fdb5", - "sourceCodeHash": "0x17dcacbdaea19447e2fef615f3488fe8f3d68f1cdeed913e32373af08534e8b3" + "bytecodeHash": "0x01000931a58a1d205bdf0b87674e56f96bb5f2192173c96a07886121b6867c47", + "sourceCodeHash": "0x67877a2bd129d189c32e63333325fff1e0ee19650a270b6bfa55906e1eaa79d6" }, { "contractName": "gas_test", "bytecodePath": "bootloader/build/artifacts/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x010008b783276a2887da8e7a6d66bd499eb60004227b692c329e43d4576c624c", - "sourceCodeHash": "0x3fae183e6f154c66148579eb68a6e412328c27aa4ae7687a8a6348e97cf83383" + "bytecodeHash": "0x010008b7e13ae7b54e537ea6f7b4e030f7b3c81e44b05f41dea2eb13c19e6235", + "sourceCodeHash": "0xa173ad90cabe1b3431ee803b2c9b3943ece686c98df1600dad4cec28f5a027c8" }, { "contractName": "playground_batch", "bytecodePath": "bootloader/build/artifacts/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x01000937545179d7a4ba1f862260de4e9815dc68e0f4166ee40a392911247d32", - "sourceCodeHash": "0x505644754c6771415c044a8fc7618bd1368fdee5bd618d05ffc0f14be6222a68" + "bytecodeHash": "0x010009358206ce648b88a76f3199a3ea0c0e1183a9ebfca11cdcba924453db98", + "sourceCodeHash": "0xda17354bca78e6b816ce8f7d1d7ff45e1c5ed0cd9f6ea0437b7cac614ff2019c" }, { "contractName": "proved_batch", "bytecodePath": "bootloader/build/artifacts/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010008c71c7330aa11b7915a0772d08d446eca39d7a432541347a42aee686146", - "sourceCodeHash": "0x048c2951119868de0b8b8c8f15d0d664d221b4541f47768ca82ee2dfa42de993" + "bytecodeHash": "0x010008c753336bc8d1ddca235602b9f31d346412b2d463cd342899f7bfb73baf", + "sourceCodeHash": "0x7a5776e8001a2d93e14165af0b08cadcf1170354401d0c31fdc0d2a8f8439989" } ] diff --git a/system-contracts/bootloader/bootloader.yul b/system-contracts/bootloader/bootloader.yul index 73b65186c..1c58a3bf7 100644 --- a/system-contracts/bootloader/bootloader.yul +++ b/system-contracts/bootloader/bootloader.yul @@ -3900,17 +3900,17 @@ object "Bootloader" { /// @dev Log key used by Executor.sol for processing. See Constants.sol::SystemLogKey enum function chainedPriorityTxnHashLogKey() -> ret { - ret := 5 + ret := 3 } /// @dev Log key used by Executor.sol for processing. See Constants.sol::SystemLogKey enum function numberOfLayer1TxsLogKey() -> ret { - ret := 6 + ret := 4 } /// @dev Log key used by Executor.sol for processing. See Constants.sol::SystemLogKey enum function protocolUpgradeTxHashKey() -> ret { - ret := 9 + ret := 7 } //////////////////////////////////////////////////////////////////////////// diff --git a/system-contracts/bootloader/tests/bootloader/bootloader_test.yul b/system-contracts/bootloader/tests/bootloader/bootloader_test.yul index 7658ae9bb..9e620fccf 100644 --- a/system-contracts/bootloader/tests/bootloader/bootloader_test.yul +++ b/system-contracts/bootloader/tests/bootloader/bootloader_test.yul @@ -105,7 +105,7 @@ function TEST_systemLogKeys() { let numberOfLayer1TxsLogKey := numberOfLayer1TxsLogKey() let protocolUpgradeTxHashKey := protocolUpgradeTxHashKey() - testing_assertEq(chainedPriorityTxnHashLogKey, 5, "Invalid priority txn hash log key") - testing_assertEq(numberOfLayer1TxsLogKey, 6, "Invalid num layer 1 txns log key") - testing_assertEq(protocolUpgradeTxHashKey, 9, "Invalid protocol upgrade txn hash log key") + testing_assertEq(chainedPriorityTxnHashLogKey, 3, "Invalid priority txn hash log key") + testing_assertEq(numberOfLayer1TxsLogKey, 4, "Invalid num layer 1 txns log key") + testing_assertEq(protocolUpgradeTxHashKey, 7, "Invalid protocol upgrade txn hash log key") } diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 6aa3fc34d..a0b22c047 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -117,8 +117,6 @@ uint256 constant STATE_DIFF_ENTRY_SIZE = 272; enum SystemLogKey { L2_TO_L1_LOGS_TREE_ROOT_KEY, - TOTAL_L2_TO_L1_PUBDATA_KEY, - STATE_DIFF_HASH_KEY, PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, PREV_BATCH_HASH_KEY, CHAINED_PRIORITY_TXN_HASH_KEY, diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index a54c4efd0..d61e99c10 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -129,8 +129,6 @@ enum PubdataField { LogsHash, MsgHash, Bytecode, - StateDiffCompressionVersion, - ExtraData, InputDAFunctionSig, InputLogsHash, InputLogsRootHash, diff --git a/system-contracts/package.json b/system-contracts/package.json index 70e7208b7..e55cb1a7b 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -66,6 +66,7 @@ "preprocess:system-contracts": "rm -rf ./contracts-preprocessed && ts-node scripts/preprocess-system-contracts.ts", "verify-on-explorer": "hardhat run scripts/verify-on-explorer.ts", "test": "yarn build:test-system-contracts && hardhat test --network zkSyncTestNode", + "test-no-build": "hardhat test --network zkSyncTestNode", "test-node": "hardhat node-zksync --tag v0.0.1-vm1.5.0", "test:bootloader": "cd bootloader/test_infra && cargo run" } diff --git a/system-contracts/test/L1Messenger.spec.ts b/system-contracts/test/L1Messenger.spec.ts index a67d4089f..225b197d6 100644 --- a/system-contracts/test/L1Messenger.spec.ts +++ b/system-contracts/test/L1Messenger.spec.ts @@ -1,32 +1,33 @@ import { ethers, network } from "hardhat"; import type { L1Messenger } from "../typechain"; +import { IL2DAValidatorFactory } from "../typechain/IL2DAValidatorFactory"; import { L1MessengerFactory } from "../typechain"; import { prepareEnvironment, setResult } from "./shared/mocks"; -import type { StateDiff } from "./shared/utils"; -import { compressStateDiffs, deployContractOnAddress, encodeStateDiffs, getCode, getWallets } from "./shared/utils"; -import { utils } from "zksync-ethers"; +import { deployContractOnAddress, getCode, getWallets } from "./shared/utils"; +import { utils, L2VoidSigner } from "zksync-ethers"; import type { Wallet } from "zksync-ethers"; import { TEST_KNOWN_CODE_STORAGE_CONTRACT_ADDRESS, TEST_L1_MESSENGER_SYSTEM_CONTRACT_ADDRESS, TEST_BOOTLOADER_FORMAL_ADDRESS, - TWO_IN_256, } from "./shared/constants"; import { expect } from "chai"; -import { BigNumber } from "ethers"; import { randomBytes } from "crypto"; -// FIXME: restore the test after the changes from the custom DA integration -describe.skip("L1Messenger tests", () => { +const EXPECTED_DA_INPUT_OFFSET = 160; +const L2_TO_L1_LOGS_MERKLE_TREE_LEAVES = 16_384; +const L2_TO_L1_LOG_SERIALIZE_SIZE = 88; +const L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH = "0x72abee45b59e344af8a6e520241c4744aff26ed411f4c4b00f8af09adada43ba"; + +describe("L1Messenger tests", () => { let l1Messenger: L1Messenger; let wallet: Wallet; let l1MessengerAccount: ethers.Signer; let knownCodeStorageAccount: ethers.Signer; let bootloaderAccount: ethers.Signer; - let stateDiffsSetupData: StateDiffSetupData; let logData: LogData; - let bytecodeData: ContentLengthPair; let emulator: L1MessengerPubdataEmulator; + let bytecode; before(async () => { await prepareEnvironment(); @@ -37,13 +38,16 @@ describe.skip("L1Messenger tests", () => { knownCodeStorageAccount = await ethers.getImpersonatedSigner(TEST_KNOWN_CODE_STORAGE_CONTRACT_ADDRESS); bootloaderAccount = await ethers.getImpersonatedSigner(TEST_BOOTLOADER_FORMAL_ADDRESS); // setup - stateDiffsSetupData = await setupStateDiffs(); logData = setupLogData(l1MessengerAccount, l1Messenger); - bytecodeData = await setupBytecodeData(ethers.constants.AddressZero); + bytecode = await getCode(TEST_L1_MESSENGER_SYSTEM_CONTRACT_ADDRESS); await setResult("SystemContext", "txNumberInBlock", [], { failure: false, returnData: ethers.utils.defaultAbiCoder.encode(["uint16"], [1]), }); + await setResult("IMessageRoot", "getAggregatedRoot", [], { + failure: false, + returnData: ethers.constants.HashZero, + }); emulator = new L1MessengerPubdataEmulator(); }); @@ -51,7 +55,10 @@ describe.skip("L1Messenger tests", () => { // cleaning the state of l1Messenger await l1Messenger .connect(bootloaderAccount) - .publishPubdataAndClearState(emulator.buildTotalL2ToL1PubdataAndStateDiffs()); + .publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger) + ); await network.provider.request({ method: "hardhat_stopImpersonatingAccount", params: [TEST_L1_MESSENGER_SYSTEM_CONTRACT_ADDRESS], @@ -74,23 +81,15 @@ describe.skip("L1Messenger tests", () => { emulator.addLog(logData.logs[0].log); await (await l1Messenger.connect(l1MessengerAccount).sendToL1(logData.messages[0].message)).wait(); emulator.addLog(logData.messages[0].log); - emulator.addMessage({ - lengthBytes: logData.messages[0].currentMessageLengthBytes, - content: logData.messages[0].message, - }); - await ( - await l1Messenger - .connect(knownCodeStorageAccount) - .requestBytecodeL1Publication(await ethers.utils.hexlify(utils.hashBytecode(bytecodeData.content)), { - gasLimit: 130000000, - }) - ).wait(); - emulator.addBytecode(bytecodeData); - emulator.setStateDiffsSetupData(stateDiffsSetupData); + await ( await l1Messenger .connect(bootloaderAccount) - .publishPubdataAndClearState(emulator.buildTotalL2ToL1PubdataAndStateDiffs(), { gasLimit: 1000000000 }) + .publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger), + { gasLimit: 1000000000 } + ) ).wait(); }); @@ -99,7 +98,21 @@ describe.skip("L1Messenger tests", () => { await expect( l1Messenger .connect(bootloaderAccount) - .publishPubdataAndClearState(emulator.buildTotalL2ToL1PubdataAndStateDiffs({ numberOfLogs: 0x4002 })) + .publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { numberOfLogs: 0x4002 }) + ) + ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); + }); + + it("should revert Invalid input DA signature", async () => { + await expect( + l1Messenger + .connect(bootloaderAccount) + .publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { l2DaValidatorFunctionSig: "0x12121212" }) + ) ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); }); @@ -121,50 +134,71 @@ describe.skip("L1Messenger tests", () => { await expect( l1Messenger .connect(bootloaderAccount) - .publishPubdataAndClearState(emulator.buildTotalL2ToL1PubdataAndStateDiffs(overrideData)) + .publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, overrideData) + ) ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); }); - it("should revert chainedMessageHash mismatch", async () => { - // Buffer.alloc(32, 6), to trigger the revert - const wrongMessage = { lengthBytes: logData.messages[0].currentMessageLengthBytes, content: Buffer.alloc(32, 6) }; - const overrideData = { messages: [...emulator.messages] }; - overrideData.messages[0] = wrongMessage; + it("should revert Invalid input msgs hash", async () => { + const correctChainedMessagesHash = await l1Messenger.provider.getStorageAt(l1Messenger.address, 2); + await expect( - l1Messenger - .connect(bootloaderAccount) - .publishPubdataAndClearState(emulator.buildTotalL2ToL1PubdataAndStateDiffs(overrideData)) + l1Messenger.connect(bootloaderAccount).publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { + chainedMessagesHash: ethers.utils.keccak256(correctChainedMessagesHash), + }) + ) ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); }); - it("should revert state diff compression version mismatch", async () => { - await ( - await l1Messenger - .connect(knownCodeStorageAccount) - .requestBytecodeL1Publication(await ethers.utils.hexlify(utils.hashBytecode(bytecodeData.content)), { - gasLimit: 130000000, + it("should revert Invalid bytecodes hash", async () => { + const correctChainedBytecodesHash = await l1Messenger.provider.getStorageAt(l1Messenger.address, 3); + + await expect( + l1Messenger.connect(bootloaderAccount).publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { + chainedBytecodeHash: ethers.utils.keccak256(correctChainedBytecodesHash), }) - ).wait(); - // modify version to trigger the revert + ) + ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); + }); + + it("should revert Invalid offset", async () => { await expect( l1Messenger.connect(bootloaderAccount).publishPubdataAndClearState( - emulator.buildTotalL2ToL1PubdataAndStateDiffs({ - version: ethers.utils.hexZeroPad(ethers.utils.hexlify(66), 1), + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { + operatorDataOffset: EXPECTED_DA_INPUT_OFFSET + 1, }) ) ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); }); - it("should revert extra data", async () => { - // add extra data to trigger the revert + it("should revert Invalid length", async () => { await expect( l1Messenger .connect(bootloaderAccount) .publishPubdataAndClearState( - ethers.utils.concat([emulator.buildTotalL2ToL1PubdataAndStateDiffs(), Buffer.alloc(1, 64)]) + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { operatorDataLength: 1 }) ) ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); }); + + it("should revert Invalid root hash", async () => { + await expect( + l1Messenger.connect(bootloaderAccount).publishPubdataAndClearState( + ethers.constants.AddressZero, + await emulator.buildTotalL2ToL1PubdataAndStateDiffs(l1Messenger, { + chainedLogsRootHash: ethers.constants.HashZero, + }) + ) + ).to.be.revertedWithCustomError(l1Messenger, "ReconstructionMismatch"); + }); }); describe("sendL2ToL1Log", async () => { @@ -236,10 +270,6 @@ describe.skip("L1Messenger tests", () => { .and.to.emit(l1Messenger, "L2ToL1LogSent") .withArgs([0, true, 1, l1Messenger.address, expectedKey, ethers.utils.keccak256(logData.messages[0].message)]); emulator.addLog(logData.messages[0].log); - emulator.addMessage({ - lengthBytes: logData.messages[0].currentMessageLengthBytes, - content: logData.messages[0].message, - }); }); }); @@ -256,85 +286,16 @@ describe.skip("L1Messenger tests", () => { await expect( l1Messenger .connect(knownCodeStorageAccount) - .requestBytecodeL1Publication(await ethers.utils.hexlify(utils.hashBytecode(bytecodeData.content)), { - gasLimit: 130000000, + .requestBytecodeL1Publication(ethers.utils.hexlify(utils.hashBytecode(bytecode)), { + gasLimit: 230000000, }) ) .to.emit(l1Messenger, "BytecodeL1PublicationRequested") - .withArgs(await ethers.utils.hexlify(utils.hashBytecode(bytecodeData.content))); - emulator.addBytecode(bytecodeData); + .withArgs(ethers.utils.hexlify(utils.hashBytecode(bytecode))); }); }); }); -// Interface represents the structure of the data that that is used in totalL2ToL1PubdataAndStateDiffs. -interface StateDiffSetupData { - encodedStateDiffs: string; - compressedStateDiffs: string; - enumerationIndexSizeBytes: string; - numberOfStateDiffsBytes: string; - compressedStateDiffsSizeBytes: string; -} - -async function setupStateDiffs(): Promise { - const stateDiffs: StateDiff[] = [ - { - key: "0x1234567890123456789012345678901234567890123456789012345678901230", - index: 0, - initValue: BigNumber.from("0x1234567890123456789012345678901234567890123456789012345678901231"), - finalValue: BigNumber.from("0x1234567890123456789012345678901234567890123456789012345678901230"), - }, - { - key: "0x1234567890123456789012345678901234567890123456789012345678901232", - index: 1, - initValue: TWO_IN_256.sub(1), - finalValue: BigNumber.from(1), - }, - { - key: "0x1234567890123456789012345678901234567890123456789012345678901234", - index: 0, - initValue: TWO_IN_256.div(2), - finalValue: BigNumber.from(1), - }, - { - key: "0x1234567890123456789012345678901234567890123456789012345678901236", - index: 2323, - initValue: BigNumber.from("0x1234567890123456789012345678901234567890123456789012345678901237"), - finalValue: BigNumber.from("0x0239329298382323782378478237842378478237847237237872373272373272"), - }, - { - key: "0x1234567890123456789012345678901234567890123456789012345678901238", - index: 2, - initValue: BigNumber.from(0), - finalValue: BigNumber.from(1), - }, - ]; - const encodedStateDiffs = encodeStateDiffs(stateDiffs); - const compressedStateDiffs = compressStateDiffs(4, stateDiffs); - const enumerationIndexSizeBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(4), 1); - await setResult( - "Compressor", - "verifyCompressedStateDiffs", - [stateDiffs.length, 4, encodedStateDiffs, compressedStateDiffs], - { - failure: false, - returnData: ethers.utils.defaultAbiCoder.encode(["bytes32"], [ethers.utils.keccak256(encodedStateDiffs)]), - } - ); - const numberOfStateDiffsBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(stateDiffs.length), 4); - const compressedStateDiffsSizeBytes = ethers.utils.hexZeroPad( - ethers.utils.hexlify(ethers.utils.arrayify(compressedStateDiffs).length), - 3 - ); - return { - encodedStateDiffs, - compressedStateDiffs, - enumerationIndexSizeBytes, - numberOfStateDiffsBytes, - compressedStateDiffsSizeBytes, - }; -} - // Interface for L2ToL1Log struct. interface L2ToL1Log { l2ShardId: number; @@ -417,47 +378,34 @@ function setupLogData(l1MessengerAccount: ethers.Signer, l1Messenger: L1Messenge }; } -// Represents the structure of the bytecode/message data that is part of the pubdata. -interface ContentLengthPair { - content: string; - lengthBytes: string; -} - -async function setupBytecodeData(l1MessengerAddress: string): Promise { - const content = await getCode(l1MessengerAddress); - const lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(ethers.utils.arrayify(content).length), 4); - return { - content, - lengthBytes, - }; -} - // Used for emulating the pubdata published by the L1Messenger. class L1MessengerPubdataEmulator implements EmulatorData { numberOfLogs: number; encodedLogs: string[]; - numberOfMessages: number; - messages: ContentLengthPair[]; - numberOfBytecodes: number; - bytecodes: ContentLengthPair[]; - stateDiffsSetupData: StateDiffSetupData; - version: string; + l2DaValidatorFunctionSig: string; + chainedLogsHash: string; + chainedLogsRootHash: string; + operatorDataOffset: number; + operatorDataLength: number; + + // These two fields are always zero, we need + // them just to extend the interface. + chainedMessagesHash: string; + chainedBytecodeHash: string; constructor() { this.numberOfLogs = 0; this.encodedLogs = []; - this.numberOfMessages = 0; - this.messages = []; - this.numberOfBytecodes = 0; - this.bytecodes = []; - this.stateDiffsSetupData = { - compressedStateDiffsSizeBytes: "", - enumerationIndexSizeBytes: "", - compressedStateDiffs: "", - numberOfStateDiffsBytes: "", - encodedStateDiffs: "", - }; - this.version = ethers.utils.hexZeroPad(ethers.utils.hexlify(1), 1); + + const factoryInterface = IL2DAValidatorFactory.connect( + ethers.constants.AddressZero, + new L2VoidSigner(ethers.constants.AddressZero) + ); + this.l2DaValidatorFunctionSig = factoryInterface.interface.getSighash("validatePubdata"); + + this.chainedLogsHash = ethers.constants.HashZero; + this.chainedLogsRootHash = ethers.constants.HashZero; + this.operatorDataOffset = EXPECTED_DA_INPUT_OFFSET; } addLog(log: string): void { @@ -465,70 +413,80 @@ class L1MessengerPubdataEmulator implements EmulatorData { this.numberOfLogs++; } - addMessage(message: ContentLengthPair): void { - this.messages.push(message); - this.numberOfMessages++; - } - - addBytecode(bytecode: ContentLengthPair): void { - this.bytecodes.push(bytecode); - this.numberOfBytecodes++; - } - - setStateDiffsSetupData(data: StateDiffSetupData) { - this.stateDiffsSetupData = data; - } + async buildTotalL2ToL1PubdataAndStateDiffs( + l1Messenger: L1Messenger, + overrideData: EmulatorOverrideData = {} + ): Promise { + const storedChainedMessagesHash = await l1Messenger.provider.getStorageAt(l1Messenger.address, 2); + const storedChainedBytecodesHash = await l1Messenger.provider.getStorageAt(l1Messenger.address, 3); - buildTotalL2ToL1PubdataAndStateDiffs(overrideData: EmulatorOverrideData = {}): string { const { + l2DaValidatorFunctionSig = this.l2DaValidatorFunctionSig, + chainedLogsHash = calculateChainedLogsHash(this.encodedLogs), + chainedLogsRootHash = calculateLogsRootHash(this.encodedLogs), + chainedMessagesHash = storedChainedMessagesHash, + chainedBytecodeHash = storedChainedBytecodesHash, + operatorDataOffset = this.operatorDataOffset, numberOfLogs = this.numberOfLogs, encodedLogs = this.encodedLogs, - numberOfMessages = this.numberOfMessages, - messages = this.messages, - numberOfBytecodes = this.numberOfBytecodes, - bytecodes = this.bytecodes, - stateDiffsSetupData = this.stateDiffsSetupData, - version = this.version, } = overrideData; - - const messagePairs = []; - for (let i = 0; i < numberOfMessages; i++) { - messagePairs.push(messages[i].lengthBytes, messages[i].content); - } - - const bytecodePairs = []; - for (let i = 0; i < numberOfBytecodes; i++) { - bytecodePairs.push(bytecodes[i].lengthBytes, bytecodes[i].content); - } + const operatorDataLength = overrideData.operatorDataLength + ? overrideData.operatorDataLength + : numberOfLogs * L2_TO_L1_LOG_SERIALIZE_SIZE + 4; return ethers.utils.concat([ + l2DaValidatorFunctionSig, + chainedLogsHash, + chainedLogsRootHash, + chainedMessagesHash, + chainedBytecodeHash, + ethers.utils.defaultAbiCoder.encode(["uint256"], [operatorDataOffset]), + ethers.utils.defaultAbiCoder.encode(["uint256"], [operatorDataLength]), ethers.utils.hexZeroPad(ethers.utils.hexlify(numberOfLogs), 4), ...encodedLogs, - ethers.utils.hexZeroPad(ethers.utils.hexlify(numberOfMessages), 4), - ...messagePairs, - ethers.utils.hexZeroPad(ethers.utils.hexlify(numberOfBytecodes), 4), - ...bytecodePairs, - version, - stateDiffsSetupData.compressedStateDiffsSizeBytes, - stateDiffsSetupData.enumerationIndexSizeBytes, - stateDiffsSetupData.compressedStateDiffs, - stateDiffsSetupData.numberOfStateDiffsBytes, - stateDiffsSetupData.encodedStateDiffs, ]); } } // Represents the structure of the data that the emulator uses. interface EmulatorData { + l2DaValidatorFunctionSig: string; + chainedLogsHash: string; + chainedLogsRootHash: string; + chainedMessagesHash: string; + chainedBytecodeHash: string; + operatorDataOffset: number; + operatorDataLength: number; numberOfLogs: number; encodedLogs: string[]; - numberOfMessages: number; - messages: ContentLengthPair[]; - numberOfBytecodes: number; - bytecodes: ContentLengthPair[]; - stateDiffsSetupData: StateDiffSetupData; - version: string; } // Represents a type that allows for overriding specific properties of the EmulatorData. // This is useful when you want to change some properties of the emulator data without affecting the others. type EmulatorOverrideData = Partial; + +function calculateChainedLogsHash(logs: string[]): string { + let hash = ethers.constants.HashZero; + for (const log of logs) { + const logHash = ethers.utils.keccak256(log); + hash = ethers.utils.keccak256(ethers.utils.concat([hash, logHash])); + } + + return hash; +} + +function calculateLogsRootHash(logs: string[]): string { + const logsTreeArray: string[] = new Array(L2_TO_L1_LOGS_MERKLE_TREE_LEAVES).fill(L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH); + for (let i = 0; i < logs.length; i++) { + logsTreeArray[i] = ethers.utils.keccak256(logs[i]); + } + + let length = L2_TO_L1_LOGS_MERKLE_TREE_LEAVES; + + while (length > 1) { + for (let i = 0; i < length; i += 2) { + logsTreeArray[i / 2] = ethers.utils.keccak256(ethers.utils.concat([logsTreeArray[i], logsTreeArray[i + 1]])); + } + length /= 2; + } + return logsTreeArray[0]; +} diff --git a/system-contracts/test/shared/mocks.ts b/system-contracts/test/shared/mocks.ts index 846b0be38..8e38ba278 100644 --- a/system-contracts/test/shared/mocks.ts +++ b/system-contracts/test/shared/mocks.ts @@ -15,6 +15,7 @@ import { TEST_COMPRESSOR_CONTRACT_ADDRESS, TEST_PUBDATA_CHUNK_PUBLISHER_ADDRESS, REAL_BRIDGEHUB_ADDRESS, + REAL_L2_MESSAGE_ROOT_ADDRESS, } from "./constants"; import { deployContractOnAddress, getWallets, loadArtifact } from "./utils"; @@ -43,6 +44,8 @@ const TEST_SYSTEM_CONTRACTS_MOCKS = { // For bridgehub we mock the real address for simplicity. // In case of need, it can be ported to use the test address. IBridgehub: REAL_BRIDGEHUB_ADDRESS, + // For similar reasons we mock the L2 message real root only for simplicity + IMessageRoot: REAL_L2_MESSAGE_ROOT_ADDRESS, }; // Deploys mocks, and cleans previous call results during deployments.