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

feat: Validium mode abstraction #1015

Closed

Conversation

ilitteri
Copy link
Contributor

@ilitteri ilitteri commented Feb 5, 2024

Initiating the system

The system is initiated at compile time by running zk init --validium-mode. This flag sets different configurations across the system to convert the system into a Validium operator as described below.

Not sending pubdata to L1

L1 batches are committed by the commitBatches method of the Executor.sol contract. It receives a StoredBatchInfo (last committed batch info) and an array of CommitBatchInfo (data needed to commit the batch) as parameters. The pubdata is part of the CommitBatchInfo therefore not sending it to L1 means not including it in said struct.

/// @inheritdoc IExecutor
function commitBatches(
    StoredBatchInfo memory _lastCommittedBatchData,
    CommitBatchInfo[] calldata _newBatchesData
) external nonReentrant onlyValidator {
    // Check that we commit batches after last committed batch
    require(s.storedBatchHashes[s.totalBatchesCommitted] == _hashStoredBatchInfo(_lastCommittedBatchData), "i"); // incorrect previous batch data
    require(_newBatchesData.length > 0, "No batches to commit");

    bytes32 systemContractsUpgradeTxHash = s.l2SystemContractsUpgradeTxHash;
    // Upgrades are rarely done so we optimize a case with no active system contracts upgrade.
    if (systemContractsUpgradeTxHash == bytes32(0) || s.l2SystemContractsUpgradeBatchNumber != 0) {
        _commitBatchesWithoutSystemContractsUpgrade(_lastCommittedBatchData, _newBatchesData);
    } else {
        _commitBatchesWithSystemContractsUpgrade(
            _lastCommittedBatchData,
            _newBatchesData,
            systemContractsUpgradeTxHash
        );
    }

    s.totalBatchesCommitted = s.totalBatchesCommitted + _newBatchesData.length;
}

The transaction that executes a call to commitBatches with its calldata is constructed and sent by the server. Particularly, the eth_tx_aggregator constructs it and saves it in the Postgres database and then it is picked up by the eth_tx_manager and sent to the L1 (as explained above).

In our proposal, the calldata saved in the database by the eth_tx_aggregator does not contain the pubdata for every CommitBatchInfo in Validium mode, it does in Rollup mode.

CommitBatches is in charge of encoding the calldata for commitBatches, it implements the trait Tokenize to perform such a task. Said implementation iterates over every batch to commit, and wraps them into CommitBatchInfo (Rust counterpart of Solidity’s) which also implements Tokenize which finally encodes it. Here it lays the logic we need to abstract.

To abstract this, we defined the L1BatchCommitGenerator trait one method l1_commit_data(&self, l1_batch_with_metadata: &L1BatchWithMetadata).

pub trait L1BatchCommitDataGenerator
where
    Self: std::fmt::Debug + Send + Sync,
{
    fn l1_commit_data(&self, l1_batch_with_metadata: &L1BatchWithMetadata) -> Token;
}

For the Rollup mode, we have a RollupModeL1BatchCommitGenerator struct implementing L1BatchCommitGenerator in such a way that l1_commit_data includes the pubdata, and a ValidiumModeL1BatchCommitGenerator struct for Validium mode, not including the pubdata in l1_commit_data.

#[derive(Debug, Clone)]
pub struct RollupModeL1BatchCommitDataGenerator {}

#[derive(Debug, Clone)]
pub struct ValidiumModeL1BatchCommitDataGenerator {}

impl L1BatchCommitDataGenerator for RollupModeL1BatchCommitDataGenerator {
    fn l1_commit_data(&self, l1_batch_with_metadata: &L1BatchWithMetadata) -> Token {
        Token::Tuple(rollup_mode_l1_commit_data(l1_batch_with_metadata))
    }
}

impl L1BatchCommitDataGenerator for ValidiumModeL1BatchCommitDataGenerator {
    fn l1_commit_data(&self, l1_batch_with_metadata: &L1BatchWithMetadata) -> Token {
        Token::Tuple(validium_mode_l1_commit_data(l1_batch_with_metadata))
    }
}

validium_mode_l1_commit_data is implemented in such a way that it does not include the pubdata in the CommitBatchInfo encoding

fn validium_mode_l1_commit_data(l1_batch_with_metadata: &L1BatchWithMetadata) -> Vec<Token> {
    let header = &l1_batch_with_metadata.header;
    let metadata = &l1_batch_with_metadata.metadata;
    let commit_data = vec![
        // `batchNumber`
        Token::Uint(U256::from(header.number.0)),
        // `timestamp`
        Token::Uint(U256::from(header.timestamp)),
        // `indexRepeatedStorageChanges`
        Token::Uint(U256::from(metadata.rollup_last_leaf_index)),
        // `newStateRoot`
        Token::FixedBytes(metadata.merkle_root_hash.as_bytes().to_vec()),
        // `numberOfLayer1Txs`
        Token::Uint(U256::from(header.l1_tx_count)),
        // `priorityOperationsHash`
        Token::FixedBytes(header.priority_ops_onchain_data_hash().as_bytes().to_vec()),
        // `bootloaderHeapInitialContentsHash`
        Token::FixedBytes(
            metadata
                .bootloader_initial_content_commitment
                .unwrap()
                .as_bytes()
                .to_vec(),
        ),
        // `eventsQueueStateHash`
        Token::FixedBytes(
            metadata
                .events_queue_commitment
                .unwrap()
                .as_bytes()
                .to_vec(),
        ),
        // `systemLogs`
        Token::Bytes(metadata.l2_l1_messages_compressed.clone()),
    ];
    commit_data
}

In rollup_mode_l1_commit_data the same as in validium_mode_l1_commit_data is being done but the pubdata is added at the end of the commit data.

fn rollup_mode_l1_commit_data(l1_batch_with_metadata: &L1BatchWithMetadata) -> Vec<Token> {
    let mut commit_data = validium_mode_l1_commit_data(l1_batch_with_metadata);
    commit_data.push(Token::Bytes(utils::construct_pubdata(
        l1_batch_with_metadata,
    )));
    commit_data
}

A field l1_batch_commit_data_generator: Arc<dyn L1BatchCommitGenerator> was added to CommitBatchInfo to perform the L1 commit data encoding.

/// Encoding for `CommitBatchInfo` from `IExecutor.sol`
#[derive(Debug)]
pub struct CommitBatchInfo&lt;'a&gt; {
    pub l1_batch_with_metadata: &amp;'a L1BatchWithMetadata,
    pub l1_batch_commit_data_generator: Arc&lt;dyn L1BatchCommitDataGenerator&gt;,
}

impl&lt;'a&gt; CommitBatchInfo&lt;'a&gt; {
    pub fn new(
        l1_batch_with_metadata: &amp;'a L1BatchWithMetadata,
        l1_batch_commit_data_generator: Arc&lt;dyn L1BatchCommitDataGenerator&gt;,
    ) -&gt; Self {
        Self {
            l1_batch_with_metadata,
            l1_batch_commit_data_generator,
        }
    }
}

impl&lt;'a&gt; Tokenizable for CommitBatchInfo&lt;'a&gt; {
    fn from_token(_token: Token) -&gt; Result&lt;Self, Web3ContractError&gt;
    where
        Self: Sized,
    {
        // Currently there is no need to decode this struct.
        // We still want to implement `Tokenizable` trait for it, so that *once* it's needed
        // the implementation is provided here and not in some other inconsistent way.
        Err(Web3ContractError::Api(Web3ApiError::Decoder(
            &quot;Not implemented&quot;.to_string(),
        )))
    }

    fn into_token(self) -&gt; Token {
        if self
            .l1_batch_with_metadata
            .header
            .protocol_version
            .unwrap()
            .is_pre_boojum()
        {
            pre_boojum_into_token(self.l1_batch_with_metadata)
        } else {
            self.l1_batch_commit_data_generator
                .l1_commit_data(self.l1_batch_with_metadata)
        }
    }
}

The same field was also added to the Aggregator and CommitBatches structs. The first one instantiates CommitBatchess and the latter instantiates CommitBatchInfos.

// Input required to encode `commitBatches` call.
#[derive(Debug, Clone)]
pub struct CommitBatches {
    pub last_committed_l1_batch: L1BatchWithMetadata,
    pub l1_batches: Vec&lt;L1BatchWithMetadata&gt;,
    pub l1_batch_commit_data_generator: Arc&lt;dyn L1BatchCommitDataGenerator&gt;,
}

#[derive(Debug)]
pub struct Aggregator {
    commit_criteria: Vec&lt;Box&lt;dyn L1BatchPublishCriterion&gt;&gt;,
    proof_criteria: Vec&lt;Box&lt;dyn L1BatchPublishCriterion&gt;&gt;,
    execute_criteria: Vec&lt;Box&lt;dyn L1BatchPublishCriterion&gt;&gt;,
    config: SenderConfig,
    blob_store: Arc&lt;dyn ObjectStore&gt;,
    l1_batch_commit_data_generator: Arc&lt;dyn L1BatchCommitDataGenerator&gt;,
}

Which of the mentioned trait implementors will be instantiated as the l1_batch_commit_generator value of the Aggregator's field will depend on the l1_batch_commit_generator_mode value in the chain.toml file, state_keeper section.

let l1_batch_commit_generator: Arc&lt;dyn L1BatchCommitGenerator&gt; =
    match state_keeper_config.l1_batch_commit_generator_mode {
        Arc::new(ValidiumModeL1BatchCommitGenerator {})
    } else {
        Arc::new(RollupModeL1BatchCommitGenerator {})
    };

Contracts changes

The following lines in Executor.sol are being skipped by solpp when the Validium mode flag is set to true:

  • bytes32 providedL2ToL1PubdataHash = keccak256(_newBatch.totalL2ToL1Pubdata);
  • require(logSender == L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, "ln");
  • require(providedL2ToL1PubdataHash == logValue, "wp");

We also have to change how the DiamondInit is initialized due to the new fee model changes:

  • The pubdataPricingMode is fixed to PubdataPricingMode.Rollup, this value will depend on the VALIDIUM_MODE env now.

Not charging for pubdata

When running the stack as a Validium, gas-used calculations have to account for the fact that pubdata is no longer published, and thus certain operations like storage become cheaper (they don’t pay for pubdata inclusion on L1). Under the new fee model that was recently merged, every change needed here is managed through the following configuration values. With this in mind, all that’s needed is, when running zk init, if the user is initializing the stack in Validium mode (passing the --validium-mode flag) we should load the following config specified for Validium in the file etc/env/base/chain.toml:

chore(docs): Update documentation about our new fee model by mm-zk · Pull Request #904 · matter-labs/zksync-era

flag rollup with calldata rollup with 4844 (blobs) value for validium value for DA
l1_pubdata_price 510'000'000'000 3'000'000'000 0 5'000
max_pubdata_per_batch 120'000 250'000 1'000'000'000'000 1'000'000
pubdata_overhead_part 0.7 0.4 0 0.1
compute_overhead_part 0.5 0.7 1 1
batch_overhead_l1_gas 1'000'000 1'000'000 1'000'000 1'400'000

The only flag not available in the chain.toml is the l1_pubdata_price as it is computed and set by the function estimate_effective_pubdata_price() defined in the L1GasPriceProvider trait, implemented by GasAdjuster. To make this value equal to zero, we need to set the const L1_GAS_PER_PUBDATA_BYTE to zero for validium, and 17 for rollup. For this, we’ve added a new field in the GasAdjusterConfig struct which is loaded from the eth_sender.toml file (hence the same field was added there to be read).

ilitteri and others added 30 commits January 25, 2024 14:38
- Needs to fix errors in tests related to the new Generic Data Type
…ods from L1BatchWithMetadata as they're now part of the L1BatchCommitter trait and utils in the case of construct_pubdata
…mmitOperation construction and DatasizeCriterion::last_l1_batch_to_publish usage
…_publish parameter (only used by DataSizeCriterion)
…ter depending on the VALIDIUM_MODE env value
…class/zksync-era into feat_validium_pubdata_abstraction
* Rename Validium pubdata abstraction and implementors

* Rename struct fields and variables

* feat: Abstract commit data generator initialization (#94)

* Add L1BatchCommitDataGeneratorMode to StateKeeperConfig

* Initialize L1BatchCommitter depending on the StateKeeperConfig

* Fix bad merge
* add variable to .toml

* zk fmt
@mationorato mationorato changed the base branch from lambdaclass_validium_mode to main February 21, 2024 21:22
@mationorato mationorato changed the base branch from main to lambdaclass_validium_mode February 21, 2024 21:23
@mationorato mationorato changed the base branch from lambdaclass_validium_mode to main February 21, 2024 21:23
@mationorato mationorato changed the base branch from main to lambdaclass_validium_mode February 21, 2024 21:24
@mationorato mationorato changed the base branch from lambdaclass_validium_mode to main February 21, 2024 21:25
@mationorato mationorato mentioned this pull request Mar 19, 2024
6 tasks
github-merge-queue bot pushed a commit that referenced this pull request Mar 28, 2024
## What ❔

This is the final PR for merging the Validium feature into the project.
It contains all off the addressed issues coming from
#1015 + the EIP-4844
feature available on the main branch

## Why ❔

The Validium feature was develop isolated and in parallel from EIP4844
feature, but now we need to release it integrated with this feature,
which was already deployed into mainnet.

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.
- [x] Spellcheck has been run via `zk spellcheck`.
- [x] Linkcheck has been run via `zk linkcheck`.

---------

Co-authored-by: Jordi <jordi.bonet.valiente@lambdaclass.com>
Co-authored-by: toni-calvin <antonio.calvin@lambdaclass.com>
Co-authored-by: ilitteri <ilitteri@fi.uba.ar>
Co-authored-by: Ivan Litteri <67517699+ilitteri@users.noreply.github.com>
Co-authored-by: Joaquin Carletti <joaquin.carletti@lambdaclass.com>
Co-authored-by: Santiago Pittella <santiagopittella@Santiagos-MacBook-Air-6.local>
Co-authored-by: Mario Rugiero <mrugiero@gmail.com>
Co-authored-by: Joaquin Carletti <56092489+ColoCarletti@users.noreply.github.com>
Co-authored-by: Igor Aleksanov <popzxc@yandex.ru>
Co-authored-by: Roman Brodetski <rb@matterlabs.dev>
@mationorato
Copy link
Contributor

I will close this as the merge was done here #1461

@mationorato mationorato closed this Apr 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.