Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v26 fixes #1232

Open
wants to merge 16 commits into
base: release-v26
Choose a base branch
from
Open
17 changes: 17 additions & 0 deletions .github/workflows/l1-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,23 @@ jobs:
- name: Compare
run: diff tools/data/Verifier.sol l1-contracts/contracts/state-transition/Verifier.sol

check-verifier-generator-l2:
needs: [build]
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Generate Verifier.sol
working-directory: tools
run: cargo run --bin zksync_verifier_contract_generator --release -- --input_path data/scheduler_key.json --l2_mode

- name: Compare
run: diff tools/data/Verifier.sol l1-contracts/contracts/state-transition/L2Verifier.sol

coverage:
defaults:
run:
Expand Down
17 changes: 0 additions & 17 deletions .github/workflows/l2-contracts-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,6 @@ jobs:
- name: Lint
run: yarn lint:check

check-verifier-generator-l2:
needs: [build]
runs-on: ubuntu-latest

steps:
- name: Checkout the repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Generate Verifier.sol
working-directory: tools
run: cargo run --bin zksync_verifier_contract_generator --release -- --input_path data/scheduler_key.json --l2_mode

- name: Compare
run: diff tools/data/Verifier.sol l2-contracts/contracts/verifier/Verifier.sol

test:
needs: [build, lint]
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/slither.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ jobs:
run: |
rm -rf ./l1-contracts/contracts/state-transition/utils/
rm -rf ./l1-contracts/contracts/state-transition/Verifier.sol
rm -rf ./l1-contracts/contracts/state-transition/L2Verifier.sol
rm -rf ./l1-contracts/contracts/state-transition/TestnetVerifier.sol
rm -rf ./l1-contracts/contracts/state-transition/L2TestnetVerifier.sol
rm -rf ./l1-contracts/contracts/state-transition/chain-deps/GatewayCTMDeployer.sol
rm -rf ./l1-contracts/contracts/dev-contracts/test/VerifierTest.sol
rm -rf ./l1-contracts/contracts/dev-contracts/test/VerifierRecursiveTest.sol
rm -rf ./l1-contracts/contracts/dev-contracts/test/L2VerifierTest.sol
rm -rf ./l1-contracts/contracts/dev-contracts/test/L2VerifierRecursiveTest.sol

- name: Run Slither
working-directory: l1-contracts
Expand Down
228 changes: 114 additions & 114 deletions AllContractsHashes.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ contract ExecutorProvingTest is ExecutorFacet {
bytes32[] memory _blobCommitments,
bytes32[] memory _blobHashes
) external view returns (bytes32) {
return _createBatchCommitment(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes);
(, , bytes32 commitment) = _createBatchCommitment(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes);
return commitment;
}

function processL2Logs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

pragma solidity 0.8.24;

import {Verifier} from "../verifier/Verifier.sol";
import {L2Verifier} from "../../state-transition/L2Verifier.sol";

/// @author Matter Labs
contract VerifierRecursiveTest is Verifier {
contract L2VerifierRecursiveTest is L2Verifier {
// add this to be excluded from coverage report
function test() internal virtual {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

pragma solidity 0.8.24;

import {Verifier} from "../verifier/Verifier.sol";
import {L2Verifier} from "../../state-transition/L2Verifier.sol";

/// @author Matter Labs
contract VerifierTest is Verifier {
contract L2VerifierTest is L2Verifier {
// add this to be excluded from coverage report
function test() internal virtual {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity 0.8.24;

import {Verifier} from "./Verifier.sol";
import {L2Verifier} from "./L2Verifier.sol";
import {IVerifier} from "./chain-interfaces/IVerifier.sol";

/// @author Matter Labs
Expand All @@ -11,9 +11,9 @@ import {IVerifier} from "./chain-interfaces/IVerifier.sol";
/// @dev This contract is used to skip the zkp verification for the testnet environment.
/// If the proof is not empty, it will verify it using the main verifier contract,
/// otherwise, it will skip the verification.
contract TestnetVerifier is Verifier {
constructor(uint256 _l1ChainId) {
assert(_l1ChainId != 1);
contract L2TestnetVerifier is L2Verifier {
constructor() {
assert(block.chainid != 1);
}

/// @dev Verifies a zk-SNARK proof, skipping the verification if the proof is empty.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {IVerifier} from "./chain-interfaces/IVerifier.sol";
/// * Plonk for ZKsync v1.1: https://github.com/matter-labs/solidity_plonk_verifier/raw/recursive/bellman_vk_codegen_recursive/RecursivePlonkUnrolledForEthereum.pdf
/// The notation used in the code is the same as in the papers.
/* solhint-enable max-line-length */
contract Verifier is IVerifier {
contract L2Verifier is IVerifier {
/*//////////////////////////////////////////////////////////////
Verification keys
//////////////////////////////////////////////////////////////*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import {RollupDAManager} from "../data-availability/RollupDAManager.sol";
import {RelayedSLDAValidator} from "../data-availability/RelayedSLDAValidator.sol";
import {ValidiumL1DAValidator} from "../data-availability/ValidiumL1DAValidator.sol";

import {Verifier} from "../Verifier.sol";
import {L2Verifier} from "../L2Verifier.sol";
import {VerifierParams, IVerifier} from "../chain-interfaces/IVerifier.sol";
import {TestnetVerifier} from "../TestnetVerifier.sol";
import {L2TestnetVerifier} from "../L2TestnetVerifier.sol";
import {ValidatorTimelock} from "../ValidatorTimelock.sol";
import {FeeParams} from "../chain-deps/ZKChainStorage.sol";

Expand Down Expand Up @@ -233,9 +233,9 @@ contract GatewayCTMDeployer {
DeployedContracts memory _deployedContracts
) internal {
if (_testnetVerifier) {
_deployedContracts.stateTransition.verifier = address(new TestnetVerifier{salt: _salt}());
_deployedContracts.stateTransition.verifier = address(new L2TestnetVerifier{salt: _salt}());
} else {
_deployedContracts.stateTransition.verifier = address(new Verifier{salt: _salt}());
_deployedContracts.stateTransition.verifier = address(new L2Verifier{salt: _salt}());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity 0.8.24;

import {ZKChainBase} from "./ZKChainBase.sol";
import {IBridgehub} from "../../../bridgehub/IBridgehub.sol";
import {IL1Messenger} from "../../../common/interfaces/IL1Messenger.sol";
import {IMessageRoot} from "../../../bridgehub/IMessageRoot.sol";
import {COMMIT_TIMESTAMP_NOT_OLDER, COMMIT_TIMESTAMP_APPROXIMATION_DELTA, EMPTY_STRING_KECCAK, L2_TO_L1_LOG_SERIALIZE_SIZE, MAX_L2_TO_L1_LOGS_COMMITMENT_BYTES, PACKED_L2_BLOCK_TIMESTAMP_MASK, PUBLIC_INPUT_SHIFT} from "../../../common/Config.sol";
import {IExecutor, L2_LOG_ADDRESS_OFFSET, L2_LOG_KEY_OFFSET, L2_LOG_VALUE_OFFSET, SystemLogKey, LogProcessingOutput, TOTAL_BLOBS_IN_COMMITMENT} from "../../chain-interfaces/IExecutor.sol";
Expand All @@ -21,6 +22,10 @@ import {InvalidBatchesDataLength, MismatchL2DAValidator, MismatchNumberOfLayer1T
// While formally the following import is not used, it is needed to inherit documentation from it
import {IZKChainBase} from "../../chain-interfaces/IZKChainBase.sol";

/// @dev The version that is used for the `Executor` calldata used for relaying the
/// stored batch info.
uint8 constant RELAYED_EXECUTOR_VERSION = 0;

/// @title ZK chain Executor contract capable of processing events emitted in the ZK chain protocol.
/// @author Matter Labs
/// @custom:security-contact [email protected]
Expand All @@ -47,7 +52,7 @@ contract ExecutorFacet is ZKChainBase, IExecutor {
StoredBatchInfo memory _previousBatch,
CommitBatchInfo memory _newBatch,
bytes32 _expectedSystemContractUpgradeTxHash
) internal returns (StoredBatchInfo memory) {
) internal returns (StoredBatchInfo memory storedBatchInfo) {
// only commit next batch
if (_newBatch.batchNumber != _previousBatch.batchNumber + 1) {
revert BatchNumberMismatch(_previousBatch.batchNumber + 1, _newBatch.batchNumber);
Expand Down Expand Up @@ -81,24 +86,43 @@ contract ExecutorFacet is ZKChainBase, IExecutor {
_verifyBatchTimestamp(logOutput.packedBatchAndL2BlockTimestamp, _newBatch.timestamp, _previousBatch.timestamp);

// Create batch commitment for the proof verification
bytes32 commitment = _createBatchCommitment(
(bytes32 metadataHash, bytes32 auxiliaryOutputHash, bytes32 commitment) = _createBatchCommitment(
_newBatch,
daOutput.stateDiffHash,
daOutput.blobsOpeningCommitments,
daOutput.blobsLinearHashes
);

return
StoredBatchInfo({
batchNumber: _newBatch.batchNumber,
batchHash: _newBatch.newStateRoot,
indexRepeatedStorageChanges: _newBatch.indexRepeatedStorageChanges,
numberOfLayer1Txs: _newBatch.numberOfLayer1Txs,
priorityOperationsHash: _newBatch.priorityOperationsHash,
l2LogsTreeRoot: logOutput.l2LogsTreeRoot,
timestamp: _newBatch.timestamp,
commitment: commitment
});
storedBatchInfo = StoredBatchInfo({
batchNumber: _newBatch.batchNumber,
batchHash: _newBatch.newStateRoot,
indexRepeatedStorageChanges: _newBatch.indexRepeatedStorageChanges,
numberOfLayer1Txs: _newBatch.numberOfLayer1Txs,
priorityOperationsHash: _newBatch.priorityOperationsHash,
l2LogsTreeRoot: logOutput.l2LogsTreeRoot,
timestamp: _newBatch.timestamp,
commitment: commitment
});

if (L1_CHAIN_ID != block.chainid) {
// If we are settling on top of Gateway, we always relay the data needed to construct
// a proof for a new batch (and finalize it) even if the data for Gateway transactions has been fully lost.
// This data includes:
// - `StoredBatchInfo` that is needed to execute a block on top of the previous one.
// But also, we need to ensure that the components of the commitment of the batch are available:
// - passThroughDataHash (and its full preimage)
// - metadataHash (only the hash)
// - auxiliaryOutputHash (only the hash)
// The source of the truth for the data from above can be found here:
// https://github.com/matter-labs/zksync-protocol/blob/c80fa4ee94fd0f7f05f7aea364291abb8b4d7351/crates/zkevm_circuits/src/scheduler/mod.rs#L1356-L1369
//
// The full preimage of `passThroughDataHash` consists of the state root as well as the `indexRepeatedStorageChanges`. All
// these values are already included as part of the `storedBatchInfo`, so we do not need to republish those.
// slither-disable-next-line unused-return
IL1Messenger(L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR).sendToL1(
abi.encode(RELAYED_EXECUTOR_VERSION, storedBatchInfo, metadataHash, auxiliaryOutputHash)
StanislavBreadless marked this conversation as resolved.
Show resolved Hide resolved
);
}
}

/// @notice checks that the timestamps of both the new batch and the new L2 block are correct.
Expand Down Expand Up @@ -596,14 +620,14 @@ contract ExecutorFacet is ZKChainBase, IExecutor {
bytes32 _stateDiffHash,
bytes32[] memory _blobCommitments,
bytes32[] memory _blobHashes
) internal view returns (bytes32) {
) internal view returns (bytes32 metadataHash, bytes32 auxiliaryOutputHash, bytes32 commitment) {
bytes32 passThroughDataHash = keccak256(_batchPassThroughData(_newBatchData));
bytes32 metadataHash = keccak256(_batchMetaParameters());
bytes32 auxiliaryOutputHash = keccak256(
metadataHash = keccak256(_batchMetaParameters());
auxiliaryOutputHash = keccak256(
_batchAuxiliaryOutput(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes)
);

return keccak256(abi.encode(passThroughDataHash, metadataHash, auxiliaryOutputHash));
commitment = keccak256(abi.encode(passThroughDataHash, metadataHash, auxiliaryOutputHash));
}

function _batchPassThroughData(CommitBatchInfo memory _batch) internal pure returns (bytes memory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {IBridgehub} from "../../bridgehub/IBridgehub.sol";
import {L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_BRIDGEHUB_ADDR} from "../../common/L2ContractAddresses.sol";
import {BlobHashBlobCommitmentMismatchValue, L1DAValidatorInvalidSender, InvalidPubdataSource} from "../L1StateTransitionErrors.sol";

/// @dev The version that is used for the `RelayedSLDAValidator` calldata.
/// This is needed to ensure easier future-compatible encoding.
uint8 constant RELAYED_SL_DA_VALIDATOR_VERSION = 0;

/// @notice The DA validator intended to be used in Era-environment.
/// @dev For compatibility reasons it accepts calldata in the same format as the `RollupL1DAValidator`, but unlike the latter it
/// does not support blobs.
Expand All @@ -33,7 +37,9 @@ contract RelayedSLDAValidator is IL1DAValidator, CalldataDAGateway {
function _relayCalldata(uint256 _chainId, uint256 _batchNumber, bytes calldata _pubdata) internal {
// Re-sending all the pubdata in pure form to L1.
// slither-disable-next-line unused-return
IL1Messenger(L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR).sendToL1(abi.encode(_chainId, _batchNumber, _pubdata));
IL1Messenger(L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR).sendToL1(
abi.encode(RELAYED_SL_DA_VALIDATOR_VERSION, _chainId, _batchNumber, _pubdata)
);
}

/// @inheritdoc IL1DAValidator
Expand Down
8 changes: 4 additions & 4 deletions l1-contracts/deploy-scripts/GatewayCTMDeployerHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@ library GatewayCTMDeployerHelper {
) internal returns (DeployedContracts memory) {
if (_testnetVerifier) {
_deployedContracts.stateTransition.verifier = _deployInternal(
"TestnetVerifier",
"TestnetVerifier.sol",
"L2TestnetVerifier",
"L2TestnetVerifier.sol",
hex"",
innerConfig
);
} else {
_deployedContracts.stateTransition.verifier = _deployInternal(
"Verifier",
"Verifier.sol",
"L2Verifier",
"L2Verifier.sol",
hex"",
innerConfig
);
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"clean:foundry": "forge clean",
"test": "yarn workspace da-contracts build && hardhat test test/unit_tests/*.spec.ts --network hardhat",
"test:foundry": "forge test --ffi --match-path 'test/foundry/l1/*' --no-match-test 'test_MainnetFork'",
"test:zkfoundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --zksync --match-path 'test/foundry/l2/*'",
"test:zkfoundry": "forge script --sig 0x2dd0ebe3 DeployL1Script --ffi && forge test --zksync --match-path 'test/foundry/l2/*' --gas-limit 2000000000",
"test:mainnet-upgrade-fork": "forge test --match-test test_MainnetFork --ffi --rpc-url $INFURA_MAINNET --gas-limit 20000000000",
"test:fork": "TEST_CONTRACTS_FORK=1 yarn run hardhat test test/unit_tests/*.fork.ts --network hardhat",
"coverage:foundry": "forge coverage --ffi --match-path 'test/foundry/l1/*' --no-match-coverage 'contracts/(bridge/.*L2.*\\.sol|governance/L2AdminFactory\\.sol)' --no-match-test test_MainnetFork",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ contract TestExecutorFacet is ExecutorFacet {
bytes32[] memory _blobCommitments,
bytes32[] memory _blobHashes
) external view returns (bytes32) {
return _createBatchCommitment(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes);
(, , bytes32 commitment) = _createBatchCommitment(_newBatchData, _stateDiffHash, _blobCommitments, _blobHashes);
return commitment;
}

function getBatchProofPublicInput(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import {Test} from "forge-std/Test.sol";

import {Script, console2 as console} from "forge-std/Script.sol";

import {Verifier} from "contracts/verifier/Verifier.sol";
import {VerifierTest} from "contracts/dev-contracts/VerifierTest.sol";
import {L2Verifier} from "contracts/state-transition/L2Verifier.sol";
import {L2VerifierTest} from "contracts/dev-contracts/test/L2VerifierTest.sol";

contract VerifierCaller {
Verifier public verifier;
contract L2VerifierCaller {
L2Verifier public verifier;

constructor(Verifier _verifier) {
constructor(L2Verifier _verifier) {
verifier = _verifier;
}

Expand All @@ -25,14 +25,14 @@ contract VerifierCaller {
}
}

contract VerifierTestTest is Test {
contract L2VerifierTestTest is Test {
uint256 Q_MOD = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
uint256 R_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;

uint256[] public publicInputs;
uint256[] public serializedProof;

Verifier public verifier;
L2Verifier public verifier;

function setUp() public virtual {
publicInputs.push(17257057577815541751225964212897374444694342989384539141520877492729);
Expand Down Expand Up @@ -82,7 +82,7 @@ contract VerifierTestTest is Test {
serializedProof.push(7419167499813234488108910149511390953153207250610705609008080038658070088540);
serializedProof.push(11628425014048216611195735618191126626331446742771562481735017471681943914146);

verifier = new VerifierTest();
verifier = new L2VerifierTest();
}

function testShouldVerify() public view {
Expand All @@ -93,10 +93,10 @@ contract VerifierTestTest is Test {
function testShouldVerifyWithGas() public {
// `gas snapshot` does not work well with zksync setup, so in order to obtain the amount of
// zkevm gas consumed we do the following:
// - Deploy a VerifierCaller contract, which would execute in zkevm context
// - Call the verify function from the VerifierCaller contract and return the gas used
// - Deploy a L2VerifierCaller contract, which would execute in zkevm context
// - Call the verify function from the L2VerifierCaller contract and return the gas used

VerifierCaller caller = new VerifierCaller(verifier);
L2VerifierCaller caller = new L2VerifierCaller(verifier);
(bool success, uint256 gasUsed) = caller.verify(publicInputs, serializedProof);
assert(success);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {VerifierTestTest} from "./Verifier.t.sol";
import {VerifierRecursiveTest} from "contracts/dev-contracts/VerifierRecursiveTest.sol";
import {L2VerifierTestTest} from "./L2Verifier.t.sol";
import {L2VerifierRecursiveTest} from "contracts/dev-contracts/test/L2VerifierRecursiveTest.sol";

contract VerifierRecursiveTestTest is VerifierTestTest {
contract L2VerifierRecursiveTestTest is L2VerifierTestTest {
function setUp() public override {
super.setUp();

Expand All @@ -13,7 +13,7 @@ contract VerifierRecursiveTestTest is VerifierTestTest {
serializedProof.push(16188304989094043810949359833767911976672882599560690320245309499206765021563);
serializedProof.push(3201093556796962656759050531176732990872300033146738631772984017549903765305);

verifier = new VerifierRecursiveTest();
verifier = new L2VerifierRecursiveTest();
}

function testMoreThan4WordsRecursiveInput_shouldRevert() public {
Expand Down
Loading
Loading