From a0a74aaeb42f076d20c4ae8a32925eff2de11d0c Mon Sep 17 00:00:00 2001 From: perekopskiy <53865202+perekopskiy@users.noreply.github.com> Date: Wed, 27 Nov 2024 21:53:09 +0200 Subject: [PATCH] feat: change seal criteria for gateway (#3320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ - replaces sk l1 gas criterion with l1 l2 txs criterion - removes commit aggregation in eth sender - enables execute aggregation only for chains that settle on L1 - adds sk criterion for l2 l1 logs ## Why ❔ - make criteria work with gateway ## Checklist - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zkstack dev fmt` and `zkstack dev lint`. --- core/lib/config/src/configs/eth_sender.rs | 2 - core/lib/config/src/testonly.rs | 1 - ...5f7cef0d50c4938105684971e8adc86bb6366.json | 23 --- ...8aafe4b1aa2250fc535bfcdff39172551d42b.json | 2 +- ...6c32170ea4b47051a100f71a41dd6ed9bb1a9.json | 2 +- ...dde79388b62926ff83d954b4d93dedfe2503a.json | 33 ---- ...b5b5cc7e37dd6a607e9453e822e34ba77cdc3.json | 23 --- ...3ce80f9b2b27758651ccfc09df61a4ae8a363.json | 2 +- ...8eefd4419e8a9eb05a9528da11163f52b2c7.json} | 4 +- ...751dfd285628a75a35b152bccb3c73e9cc057.json | 2 +- ...79d66dd9fbd20941aec20e2e8c3874b15a953.json | 30 +++ ...85c5196c431363802b6b988939c99853b9c97.json | 23 --- ..._drop_predicted_gas_cost_not_null.down.sql | 2 + ...03_drop_predicted_gas_cost_not_null.up.sql | 2 + core/lib/dal/src/blocks_dal.rs | 159 ++-------------- core/lib/dal/src/blocks_web3_dal.rs | 2 +- core/lib/dal/src/eth_sender_dal.rs | 6 +- core/lib/dal/src/models/storage_eth_tx.rs | 4 +- core/lib/env_config/src/eth_sender.rs | 2 - core/lib/protobuf_config/src/eth.rs | 12 -- .../src/proto/config/eth_sender.proto | 2 +- core/lib/types/src/aggregated_operations.rs | 8 + core/lib/types/src/block.rs | 47 ----- core/lib/types/src/eth_sender.rs | 2 +- .../src/types/outputs/execution_result.rs | 1 + .../src/types/outputs/statistic.rs | 5 + .../src/execution_sandbox/vm_metrics.rs | 1 + core/node/api_server/src/tx_sender/mod.rs | 2 +- core/node/eth_sender/src/aggregator.rs | 130 +++++++------ core/node/eth_sender/src/eth_tx_aggregator.rs | 23 ++- core/node/eth_sender/src/eth_tx_manager.rs | 15 +- core/node/eth_sender/src/health.rs | 2 +- core/node/eth_sender/src/lib.rs | 1 - core/node/eth_sender/src/publish_criterion.rs | 159 ++++++++-------- core/node/eth_sender/src/tester.rs | 4 +- core/node/eth_sender/src/utils.rs | 14 -- core/node/genesis/src/lib.rs | 11 +- .../layers/eth_sender/aggregator.rs | 3 +- core/node/state_keeper/src/executor/mod.rs | 10 +- core/node/state_keeper/src/io/persistence.rs | 5 +- .../io/seal_logic/l2_block_seal_subtasks.rs | 2 +- .../state_keeper/src/io/seal_logic/mod.rs | 1 - core/node/state_keeper/src/io/tests/mod.rs | 7 +- core/node/state_keeper/src/keeper.rs | 65 ++----- core/node/state_keeper/src/lib.rs | 2 +- .../src/seal_criteria/conditional_sealer.rs | 9 +- .../src/seal_criteria/criteria/gas.rs | 180 ------------------ .../criteria/gas_for_batch_tip.rs | 4 + .../criteria/geometry_seal_criteria.rs | 5 + .../src/seal_criteria/criteria/l1_l2_txs.rs | 104 ++++++++++ .../src/seal_criteria/criteria/l2_l1_logs.rs | 120 ++++++++++++ .../src/seal_criteria/criteria/mod.rs | 10 +- .../seal_criteria/criteria/pubdata_bytes.rs | 4 + .../src/seal_criteria/criteria/slots.rs | 3 + .../criteria/tx_encoding_size.rs | 5 + .../state_keeper/src/seal_criteria/mod.rs | 21 +- core/node/state_keeper/src/tests/mod.rs | 93 +-------- core/node/state_keeper/src/types.rs | 34 +--- .../src/updates/l1_batch_updates.rs | 20 +- .../src/updates/l2_block_updates.rs | 17 +- core/node/state_keeper/src/updates/mod.rs | 26 +-- core/node/state_keeper/src/utils.rs | 88 --------- etc/env/file_based/general.yaml | 1 - 63 files changed, 584 insertions(+), 1018 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-10b8981f7aa47ce5d3507571af45f7cef0d50c4938105684971e8adc86bb6366.json delete mode 100644 core/lib/dal/.sqlx/query-6069d168d5c4b5131b50500302cdde79388b62926ff83d954b4d93dedfe2503a.json delete mode 100644 core/lib/dal/.sqlx/query-63f5f9bff4b2c15fa4230af2c73b5b5cc7e37dd6a607e9453e822e34ba77cdc3.json rename core/lib/dal/.sqlx/{query-5cc172812d228c5b60be8dd8b8eaf99779da93fc8939dc724a49b286c5568129.json => query-843b299bbffbade83dd673ed4a488eefd4419e8a9eb05a9528da11163f52b2c7.json} (73%) create mode 100644 core/lib/dal/.sqlx/query-a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953.json delete mode 100644 core/lib/dal/.sqlx/query-b9f77e6c15f9e635024b73f1fc985c5196c431363802b6b988939c99853b9c97.json create mode 100644 core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.down.sql create mode 100644 core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.up.sql delete mode 100644 core/node/eth_sender/src/utils.rs delete mode 100644 core/node/state_keeper/src/seal_criteria/criteria/gas.rs create mode 100644 core/node/state_keeper/src/seal_criteria/criteria/l1_l2_txs.rs create mode 100644 core/node/state_keeper/src/seal_criteria/criteria/l2_l1_logs.rs diff --git a/core/lib/config/src/configs/eth_sender.rs b/core/lib/config/src/configs/eth_sender.rs index 7b67f015238d..be2f5b532a3e 100644 --- a/core/lib/config/src/configs/eth_sender.rs +++ b/core/lib/config/src/configs/eth_sender.rs @@ -23,7 +23,6 @@ impl EthConfig { pub fn for_tests() -> Self { Self { sender: Some(SenderConfig { - aggregated_proof_sizes: vec![1], wait_confirmations: Some(10), tx_poll_period: 1, aggregate_tx_poll_period: 1, @@ -82,7 +81,6 @@ pub enum ProofLoadingMode { #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct SenderConfig { - pub aggregated_proof_sizes: Vec, /// Amount of confirmations required to consider L1 transaction committed. /// If not specified L1 transaction will be considered finalized once its block is finalized. pub wait_confirmations: Option, diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index d58867ea7418..1a3f63d9b278 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -399,7 +399,6 @@ impl Distribution for EncodeDist { impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> configs::eth_sender::SenderConfig { configs::eth_sender::SenderConfig { - aggregated_proof_sizes: self.sample_collect(rng), wait_confirmations: self.sample(rng), tx_poll_period: self.sample(rng), aggregate_tx_poll_period: self.sample(rng), diff --git a/core/lib/dal/.sqlx/query-10b8981f7aa47ce5d3507571af45f7cef0d50c4938105684971e8adc86bb6366.json b/core/lib/dal/.sqlx/query-10b8981f7aa47ce5d3507571af45f7cef0d50c4938105684971e8adc86bb6366.json deleted file mode 100644 index d59f237ed3c3..000000000000 --- a/core/lib/dal/.sqlx/query-10b8981f7aa47ce5d3507571af45f7cef0d50c4938105684971e8adc86bb6366.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT COALESCE(SUM(predicted_execute_gas_cost), 0) AS \"sum!\" FROM l1_batches WHERE number BETWEEN $1 AND $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "sum!", - "type_info": "Numeric" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - null - ] - }, - "hash": "10b8981f7aa47ce5d3507571af45f7cef0d50c4938105684971e8adc86bb6366" -} diff --git a/core/lib/dal/.sqlx/query-2234d7728d91cefaee792c900448aafe4b1aa2250fc535bfcdff39172551d42b.json b/core/lib/dal/.sqlx/query-2234d7728d91cefaee792c900448aafe4b1aa2250fc535bfcdff39172551d42b.json index 48fa673b2c91..df60f114f5ef 100644 --- a/core/lib/dal/.sqlx/query-2234d7728d91cefaee792c900448aafe4b1aa2250fc535bfcdff39172551d42b.json +++ b/core/lib/dal/.sqlx/query-2234d7728d91cefaee792c900448aafe4b1aa2250fc535bfcdff39172551d42b.json @@ -103,7 +103,7 @@ false, true, true, - false, + true, true, true, false, diff --git a/core/lib/dal/.sqlx/query-400457c97449097837d5e31d4476c32170ea4b47051a100f71a41dd6ed9bb1a9.json b/core/lib/dal/.sqlx/query-400457c97449097837d5e31d4476c32170ea4b47051a100f71a41dd6ed9bb1a9.json index 3e64cc5f5b2f..c6c189d45fcb 100644 --- a/core/lib/dal/.sqlx/query-400457c97449097837d5e31d4476c32170ea4b47051a100f71a41dd6ed9bb1a9.json +++ b/core/lib/dal/.sqlx/query-400457c97449097837d5e31d4476c32170ea4b47051a100f71a41dd6ed9bb1a9.json @@ -108,7 +108,7 @@ false, true, true, - false, + true, true, true, false, diff --git a/core/lib/dal/.sqlx/query-6069d168d5c4b5131b50500302cdde79388b62926ff83d954b4d93dedfe2503a.json b/core/lib/dal/.sqlx/query-6069d168d5c4b5131b50500302cdde79388b62926ff83d954b4d93dedfe2503a.json deleted file mode 100644 index 98d228726d48..000000000000 --- a/core/lib/dal/.sqlx/query-6069d168d5c4b5131b50500302cdde79388b62926ff83d954b4d93dedfe2503a.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE l1_batches\n SET\n l1_tx_count = $2,\n l2_tx_count = $3,\n l2_to_l1_messages = $4,\n bloom = $5,\n priority_ops_onchain_data = $6,\n predicted_commit_gas_cost = $7,\n predicted_prove_gas_cost = $8,\n predicted_execute_gas_cost = $9,\n initial_bootloader_heap_content = $10,\n used_contract_hashes = $11,\n bootloader_code_hash = $12,\n default_aa_code_hash = $13,\n evm_emulator_code_hash = $14,\n protocol_version = $15,\n system_logs = $16,\n storage_refunds = $17,\n pubdata_costs = $18,\n pubdata_input = $19,\n predicted_circuits_by_type = $20,\n updated_at = NOW(),\n sealed_at = NOW(),\n is_sealed = TRUE\n WHERE\n number = $1\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int4", - "Int4", - "ByteaArray", - "Bytea", - "ByteaArray", - "Int8", - "Int8", - "Int8", - "Jsonb", - "Jsonb", - "Bytea", - "Bytea", - "Bytea", - "Int4", - "ByteaArray", - "Int8Array", - "Int8Array", - "Bytea", - "Jsonb" - ] - }, - "nullable": [] - }, - "hash": "6069d168d5c4b5131b50500302cdde79388b62926ff83d954b4d93dedfe2503a" -} diff --git a/core/lib/dal/.sqlx/query-63f5f9bff4b2c15fa4230af2c73b5b5cc7e37dd6a607e9453e822e34ba77cdc3.json b/core/lib/dal/.sqlx/query-63f5f9bff4b2c15fa4230af2c73b5b5cc7e37dd6a607e9453e822e34ba77cdc3.json deleted file mode 100644 index ab2283fa60c3..000000000000 --- a/core/lib/dal/.sqlx/query-63f5f9bff4b2c15fa4230af2c73b5b5cc7e37dd6a607e9453e822e34ba77cdc3.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT COALESCE(SUM(predicted_prove_gas_cost), 0) AS \"sum!\" FROM l1_batches WHERE number BETWEEN $1 AND $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "sum!", - "type_info": "Numeric" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - null - ] - }, - "hash": "63f5f9bff4b2c15fa4230af2c73b5b5cc7e37dd6a607e9453e822e34ba77cdc3" -} diff --git a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json index 1a3c160cee1b..a6ac67328b14 100644 --- a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json +++ b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json @@ -101,7 +101,7 @@ false, true, true, - false, + true, true, true, false, diff --git a/core/lib/dal/.sqlx/query-5cc172812d228c5b60be8dd8b8eaf99779da93fc8939dc724a49b286c5568129.json b/core/lib/dal/.sqlx/query-843b299bbffbade83dd673ed4a488eefd4419e8a9eb05a9528da11163f52b2c7.json similarity index 73% rename from core/lib/dal/.sqlx/query-5cc172812d228c5b60be8dd8b8eaf99779da93fc8939dc724a49b286c5568129.json rename to core/lib/dal/.sqlx/query-843b299bbffbade83dd673ed4a488eefd4419e8a9eb05a9528da11163f52b2c7.json index c2ccaf3b3d7c..9c339a604c89 100644 --- a/core/lib/dal/.sqlx/query-5cc172812d228c5b60be8dd8b8eaf99779da93fc8939dc724a49b286c5568129.json +++ b/core/lib/dal/.sqlx/query-843b299bbffbade83dd673ed4a488eefd4419e8a9eb05a9528da11163f52b2c7.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO eth_txs (raw_tx, nonce, tx_type, contract_address, predicted_gas_cost, chain_id, created_at, updated_at) VALUES ('\\x00', 0, $1, '', 0, $2, now(), now()) RETURNING id", + "query": "INSERT INTO eth_txs (raw_tx, nonce, tx_type, contract_address, predicted_gas_cost, chain_id, created_at, updated_at) VALUES ('\\x00', 0, $1, '', NULL, $2, now(), now()) RETURNING id", "describe": { "columns": [ { @@ -19,5 +19,5 @@ false ] }, - "hash": "5cc172812d228c5b60be8dd8b8eaf99779da93fc8939dc724a49b286c5568129" + "hash": "843b299bbffbade83dd673ed4a488eefd4419e8a9eb05a9528da11163f52b2c7" } diff --git a/core/lib/dal/.sqlx/query-868bfdc5d8ee5eab395fa690891751dfd285628a75a35b152bccb3c73e9cc057.json b/core/lib/dal/.sqlx/query-868bfdc5d8ee5eab395fa690891751dfd285628a75a35b152bccb3c73e9cc057.json index c2e662ef376e..e47911f3d776 100644 --- a/core/lib/dal/.sqlx/query-868bfdc5d8ee5eab395fa690891751dfd285628a75a35b152bccb3c73e9cc057.json +++ b/core/lib/dal/.sqlx/query-868bfdc5d8ee5eab395fa690891751dfd285628a75a35b152bccb3c73e9cc057.json @@ -102,7 +102,7 @@ false, true, true, - false, + true, true, true, false, diff --git a/core/lib/dal/.sqlx/query-a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953.json b/core/lib/dal/.sqlx/query-a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953.json new file mode 100644 index 000000000000..a64bdb403aef --- /dev/null +++ b/core/lib/dal/.sqlx/query-a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953.json @@ -0,0 +1,30 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE l1_batches\n SET\n l1_tx_count = $2,\n l2_tx_count = $3,\n l2_to_l1_messages = $4,\n bloom = $5,\n priority_ops_onchain_data = $6,\n initial_bootloader_heap_content = $7,\n used_contract_hashes = $8,\n bootloader_code_hash = $9,\n default_aa_code_hash = $10,\n evm_emulator_code_hash = $11,\n protocol_version = $12,\n system_logs = $13,\n storage_refunds = $14,\n pubdata_costs = $15,\n pubdata_input = $16,\n predicted_circuits_by_type = $17,\n updated_at = NOW(),\n sealed_at = NOW(),\n is_sealed = TRUE\n WHERE\n number = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int4", + "Int4", + "ByteaArray", + "Bytea", + "ByteaArray", + "Jsonb", + "Jsonb", + "Bytea", + "Bytea", + "Bytea", + "Int4", + "ByteaArray", + "Int8Array", + "Int8Array", + "Bytea", + "Jsonb" + ] + }, + "nullable": [] + }, + "hash": "a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953" +} diff --git a/core/lib/dal/.sqlx/query-b9f77e6c15f9e635024b73f1fc985c5196c431363802b6b988939c99853b9c97.json b/core/lib/dal/.sqlx/query-b9f77e6c15f9e635024b73f1fc985c5196c431363802b6b988939c99853b9c97.json deleted file mode 100644 index 379c1f75d9b3..000000000000 --- a/core/lib/dal/.sqlx/query-b9f77e6c15f9e635024b73f1fc985c5196c431363802b6b988939c99853b9c97.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT COALESCE(SUM(predicted_commit_gas_cost), 0) AS \"sum!\" FROM l1_batches WHERE number BETWEEN $1 AND $2", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "sum!", - "type_info": "Numeric" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - null - ] - }, - "hash": "b9f77e6c15f9e635024b73f1fc985c5196c431363802b6b988939c99853b9c97" -} diff --git a/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.down.sql b/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.down.sql new file mode 100644 index 000000000000..6d0c32ea6c24 --- /dev/null +++ b/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE eth_txs + ALTER COLUMN predicted_gas_cost SET NOT NULL; diff --git a/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.up.sql b/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.up.sql new file mode 100644 index 000000000000..cbb1e3c1a3f1 --- /dev/null +++ b/core/lib/dal/migrations/20241121142103_drop_predicted_gas_cost_not_null.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE eth_txs + ALTER COLUMN predicted_gas_cost DROP NOT NULL; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 5d27b6067cd0..5002c5a8afbf 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -6,19 +6,18 @@ use std::{ }; use anyhow::Context as _; -use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive}; +use bigdecimal::{BigDecimal, FromPrimitive}; use sqlx::types::chrono::{DateTime, Utc}; use zksync_db_connection::{ connection::Connection, error::{DalResult, SqlxContext}, instrument::{InstrumentExt, Instrumented}, - interpolate_query, match_query_as, }; use zksync_types::{ aggregated_operations::AggregatedActionType, block::{ - BlockGasCount, L1BatchHeader, L1BatchStatistics, L1BatchTreeData, L2BlockHeader, - StorageOracleInfo, UnsealedL1BatchHeader, + L1BatchHeader, L1BatchStatistics, L1BatchTreeData, L2BlockHeader, StorageOracleInfo, + UnsealedL1BatchHeader, }, commitment::{L1BatchCommitmentArtifacts, L1BatchWithMetadata}, fee_model::BatchFeeInput, @@ -688,7 +687,6 @@ impl BlocksDal<'_, '_> { &mut self, header: &L1BatchHeader, initial_bootloader_contents: &[(usize, U256)], - predicted_block_gas: BlockGasCount, storage_refunds: &[u32], pubdata_costs: &[i32], predicted_circuits_by_type: CircuitStatistic, // predicted number of circuits for each circuit type @@ -728,20 +726,17 @@ impl BlocksDal<'_, '_> { l2_to_l1_messages = $4, bloom = $5, priority_ops_onchain_data = $6, - predicted_commit_gas_cost = $7, - predicted_prove_gas_cost = $8, - predicted_execute_gas_cost = $9, - initial_bootloader_heap_content = $10, - used_contract_hashes = $11, - bootloader_code_hash = $12, - default_aa_code_hash = $13, - evm_emulator_code_hash = $14, - protocol_version = $15, - system_logs = $16, - storage_refunds = $17, - pubdata_costs = $18, - pubdata_input = $19, - predicted_circuits_by_type = $20, + initial_bootloader_heap_content = $7, + used_contract_hashes = $8, + bootloader_code_hash = $9, + default_aa_code_hash = $10, + evm_emulator_code_hash = $11, + protocol_version = $12, + system_logs = $13, + storage_refunds = $14, + pubdata_costs = $15, + pubdata_input = $16, + predicted_circuits_by_type = $17, updated_at = NOW(), sealed_at = NOW(), is_sealed = TRUE @@ -754,9 +749,6 @@ impl BlocksDal<'_, '_> { &header.l2_to_l1_messages, header.bloom.as_bytes(), &priority_onchain_data, - i64::from(predicted_block_gas.commit), - i64::from(predicted_block_gas.prove), - i64::from(predicted_block_gas.execute), initial_bootloader_contents, used_contract_hashes, header.base_system_contracts_hashes.bootloader.as_bytes(), @@ -2371,40 +2363,6 @@ impl BlocksDal<'_, '_> { Ok(()) } - /// Returns sum of predicted gas costs on the given L1 batch range. - /// Panics if the sum doesn't fit into `u32`. - pub async fn get_l1_batches_predicted_gas( - &mut self, - number_range: ops::RangeInclusive, - op_type: AggregatedActionType, - ) -> anyhow::Result { - #[derive(Debug)] - struct SumRow { - sum: BigDecimal, - } - - let start = i64::from(number_range.start().0); - let end = i64::from(number_range.end().0); - let query = match_query_as!( - SumRow, - [ - "SELECT COALESCE(SUM(", _, r#"), 0) AS "sum!" FROM l1_batches WHERE number BETWEEN $1 AND $2"# - ], - match (op_type) { - AggregatedActionType::Commit => ("predicted_commit_gas_cost"; start, end), - AggregatedActionType::PublishProofOnchain => ("predicted_prove_gas_cost"; start, end), - AggregatedActionType::Execute => ("predicted_execute_gas_cost"; start, end), - } - ); - - query - .fetch_one(self.storage.conn()) - .await? - .sum - .to_u32() - .context("Sum of predicted gas costs should fit into u32") - } - pub async fn get_l2_block_range_of_l1_batch( &mut self, l1_batch_number: L1BatchNumber, @@ -2932,15 +2890,8 @@ impl BlocksDal<'_, '_> { header.to_unsealed_header(BatchFeeInput::pubdata_independent(100, 100, 100)), ) .await?; - self.mark_l1_batch_as_sealed( - header, - &[], - Default::default(), - &[], - &[], - Default::default(), - ) - .await + self.mark_l1_batch_as_sealed(header, &[], &[], &[], Default::default()) + .await } /// Deletes all L2 blocks and L1 batches, including the genesis ones. Should only be used in tests. @@ -3006,8 +2957,7 @@ impl BlocksDal<'_, '_> { #[cfg(test)] mod tests { - use zksync_contracts::BaseSystemContractsHashes; - use zksync_types::{tx::IncludedTxLocation, Address, ProtocolVersion, ProtocolVersionId}; + use zksync_types::{tx::IncludedTxLocation, Address, ProtocolVersion}; use super::*; use crate::{ @@ -3022,7 +2972,7 @@ mod tests { vec![], action_type, Address::default(), - 1, + Some(1), None, None, false, @@ -3222,77 +3172,4 @@ mod tests { .unwrap() .is_none()); } - - #[tokio::test] - async fn getting_predicted_gas() { - let pool = ConnectionPool::::test_pool().await; - let mut conn = pool.connection().await.unwrap(); - conn.protocol_versions_dal() - .save_protocol_version_with_tx(&ProtocolVersion::default()) - .await - .unwrap(); - let mut header = L1BatchHeader::new( - L1BatchNumber(1), - 100, - BaseSystemContractsHashes::default(), - ProtocolVersionId::default(), - ); - let mut predicted_gas = BlockGasCount { - commit: 2, - prove: 3, - execute: 10, - }; - conn.blocks_dal() - .insert_l1_batch( - header.to_unsealed_header(BatchFeeInput::pubdata_independent(100, 100, 100)), - ) - .await - .unwrap(); - conn.blocks_dal() - .mark_l1_batch_as_sealed(&header, &[], predicted_gas, &[], &[], Default::default()) - .await - .unwrap(); - - header.number = L1BatchNumber(2); - header.timestamp += 100; - predicted_gas += predicted_gas; - conn.blocks_dal() - .insert_l1_batch( - header.to_unsealed_header(BatchFeeInput::pubdata_independent(100, 100, 100)), - ) - .await - .unwrap(); - conn.blocks_dal() - .mark_l1_batch_as_sealed(&header, &[], predicted_gas, &[], &[], Default::default()) - .await - .unwrap(); - - let action_types_and_predicted_gas = [ - (AggregatedActionType::Execute, 10), - (AggregatedActionType::Commit, 2), - (AggregatedActionType::PublishProofOnchain, 3), - ]; - for (action_type, expected_gas) in action_types_and_predicted_gas { - let gas = conn - .blocks_dal() - .get_l1_batches_predicted_gas(L1BatchNumber(1)..=L1BatchNumber(1), action_type) - .await - .unwrap(); - assert_eq!(gas, expected_gas); - - let gas = conn - .blocks_dal() - .get_l1_batches_predicted_gas(L1BatchNumber(2)..=L1BatchNumber(2), action_type) - .await - .unwrap(); - assert_eq!(gas, 2 * expected_gas); - - let gas = conn - .blocks_dal() - .get_l1_batches_predicted_gas(L1BatchNumber(1)..=L1BatchNumber(2), action_type) - .await - .unwrap(); - assert_eq!(gas, 3 * expected_gas); - } - } } diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index c7187a83006b..229f49da6e37 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -1044,7 +1044,7 @@ mod tests { vec![], AggregatedActionType::Commit, Address::default(), - 0, + None, None, None, false, diff --git a/core/lib/dal/src/eth_sender_dal.rs b/core/lib/dal/src/eth_sender_dal.rs index 0e5cbc0bac1b..cc7c694a96fe 100644 --- a/core/lib/dal/src/eth_sender_dal.rs +++ b/core/lib/dal/src/eth_sender_dal.rs @@ -231,7 +231,7 @@ impl EthSenderDal<'_, '_> { raw_tx: Vec, tx_type: AggregatedActionType, contract_address: Address, - predicted_gas_cost: u32, + predicted_gas_cost: Option, from_address: Option
, blob_sidecar: Option, is_gateway: bool, @@ -262,7 +262,7 @@ impl EthSenderDal<'_, '_> { nonce as i64, tx_type.to_string(), address, - i64::from(predicted_gas_cost), + predicted_gas_cost.map(|c| i64::from(c)), from_address.as_ref().map(Address::as_bytes), blob_sidecar.map(|sidecar| bincode::serialize(&sidecar) .expect("can always bincode serialize EthTxBlobSidecar; qed")), @@ -515,7 +515,7 @@ impl EthSenderDal<'_, '_> { // Insert general tx descriptor. let eth_tx_id = sqlx::query_scalar!( "INSERT INTO eth_txs (raw_tx, nonce, tx_type, contract_address, predicted_gas_cost, chain_id, created_at, updated_at) \ - VALUES ('\\x00', 0, $1, '', 0, $2, now(), now()) \ + VALUES ('\\x00', 0, $1, '', NULL, $2, now(), now()) \ RETURNING id", tx_type.to_string(), sl_chain_id.map(|chain_id| chain_id.0 as i64) diff --git a/core/lib/dal/src/models/storage_eth_tx.rs b/core/lib/dal/src/models/storage_eth_tx.rs index a47f6acfff46..b4a124c5d455 100644 --- a/core/lib/dal/src/models/storage_eth_tx.rs +++ b/core/lib/dal/src/models/storage_eth_tx.rs @@ -17,7 +17,7 @@ pub struct StorageEthTx { pub has_failed: bool, pub confirmed_eth_tx_history_id: Option, pub gas_used: Option, - pub predicted_gas_cost: i64, + pub predicted_gas_cost: Option, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, // TODO (SMA-1614): remove the field @@ -80,7 +80,7 @@ impl From for EthTx { raw_tx: tx.raw_tx.clone(), tx_type: AggregatedActionType::from_str(&tx.tx_type).expect("Wrong agg type"), created_at_timestamp: tx.created_at.and_utc().timestamp() as u64, - predicted_gas_cost: tx.predicted_gas_cost as u64, + predicted_gas_cost: tx.predicted_gas_cost.map(|c| c as u64), from_addr: tx.from_addr.map(|f| Address::from_slice(&f)), blob_sidecar: tx.blob_sidecar.map(|b| { bincode::deserialize(&b).expect("EthTxBlobSidecar is encoded correctly; qed") diff --git a/core/lib/env_config/src/eth_sender.rs b/core/lib/env_config/src/eth_sender.rs index d95c6dd3658f..f822109ed935 100644 --- a/core/lib/env_config/src/eth_sender.rs +++ b/core/lib/env_config/src/eth_sender.rs @@ -56,7 +56,6 @@ mod tests { ( EthConfig { sender: Some(SenderConfig { - aggregated_proof_sizes: vec![1, 5], aggregated_block_commit_deadline: 30, aggregated_block_prove_deadline: 3_000, aggregated_block_execute_deadline: 4_000, @@ -128,7 +127,6 @@ mod tests { ETH_SENDER_GAS_ADJUSTER_MAX_BLOB_BASE_FEE_SAMPLES="10" ETH_SENDER_GAS_ADJUSTER_INTERNAL_PUBDATA_PRICING_MULTIPLIER="1.0" ETH_SENDER_WAIT_FOR_PROOFS="false" - ETH_SENDER_SENDER_AGGREGATED_PROOF_SIZES="1,5" ETH_SENDER_SENDER_MAX_AGGREGATED_BLOCKS_TO_COMMIT="3" ETH_SENDER_SENDER_MAX_AGGREGATED_BLOCKS_TO_EXECUTE="4" ETH_SENDER_SENDER_AGGREGATED_BLOCK_COMMIT_DEADLINE="30" diff --git a/core/lib/protobuf_config/src/eth.rs b/core/lib/protobuf_config/src/eth.rs index d4ea1d9f2697..10e80810be57 100644 --- a/core/lib/protobuf_config/src/eth.rs +++ b/core/lib/protobuf_config/src/eth.rs @@ -69,13 +69,6 @@ impl ProtoRepr for proto::Sender { type Type = configs::eth_sender::SenderConfig; fn read(&self) -> anyhow::Result { Ok(Self::Type { - aggregated_proof_sizes: self - .aggregated_proof_sizes - .iter() - .enumerate() - .map(|(i, x)| (*x).try_into().context(i)) - .collect::>() - .context("aggregated_proof_sizes")?, wait_confirmations: self.wait_confirmations, tx_poll_period: *required(&self.tx_poll_period).context("tx_poll_period")?, aggregate_tx_poll_period: *required(&self.aggregate_tx_poll_period) @@ -122,11 +115,6 @@ impl ProtoRepr for proto::Sender { fn build(this: &Self::Type) -> Self { Self { - aggregated_proof_sizes: this - .aggregated_proof_sizes - .iter() - .map(|x| (*x).try_into().unwrap()) - .collect(), wait_confirmations: this.wait_confirmations, tx_poll_period: Some(this.tx_poll_period), aggregate_tx_poll_period: Some(this.aggregate_tx_poll_period), diff --git a/core/lib/protobuf_config/src/proto/config/eth_sender.proto b/core/lib/protobuf_config/src/proto/config/eth_sender.proto index 6438573e08df..1176afd7c442 100644 --- a/core/lib/protobuf_config/src/proto/config/eth_sender.proto +++ b/core/lib/protobuf_config/src/proto/config/eth_sender.proto @@ -28,7 +28,7 @@ enum PubdataSendingMode { } message Sender { - repeated uint64 aggregated_proof_sizes = 1; // ? + reserved 1; reserved "aggregated_proof_sizes"; optional uint64 wait_confirmations = 2; // optional optional uint64 tx_poll_period = 3; // required; s optional uint64 aggregate_tx_poll_period = 4; // required; s diff --git a/core/lib/types/src/aggregated_operations.rs b/core/lib/types/src/aggregated_operations.rs index 44b730c929a3..d68610ffeb41 100644 --- a/core/lib/types/src/aggregated_operations.rs +++ b/core/lib/types/src/aggregated_operations.rs @@ -41,3 +41,11 @@ impl FromStr for AggregatedActionType { } } } + +/// Additional gas cost of processing `Execute` operation per batch. +/// It's applicable iff SL is Ethereum. +pub const L1_BATCH_EXECUTE_BASE_COST: u32 = 30_000; + +/// Additional gas cost of processing `Execute` operation per L1->L2 tx. +/// It's applicable iff SL is Ethereum. +pub const L1_OPERATION_EXECUTE_COST: u32 = 12_500; diff --git a/core/lib/types/src/block.rs b/core/lib/types/src/block.rs index 804da61b7295..c4fd3306f2d5 100644 --- a/core/lib/types/src/block.rs +++ b/core/lib/types/src/block.rs @@ -1,5 +1,3 @@ -use std::{fmt, ops}; - use serde::{Deserialize, Serialize}; use zksync_basic_types::{commitment::PubdataParams, Address, Bloom, BloomInput, H256, U256}; use zksync_contracts::BaseSystemContractsHashes; @@ -177,51 +175,6 @@ impl L1BatchHeader { } } -#[derive(Clone, Copy, Eq, PartialEq, Default)] -pub struct BlockGasCount { - pub commit: u32, - pub prove: u32, - pub execute: u32, -} - -impl fmt::Debug for BlockGasCount { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - formatter, - "c:{}/p:{}/e:{}", - self.commit, self.prove, self.execute - ) - } -} - -impl BlockGasCount { - pub fn any_field_greater_than(&self, bound: u32) -> bool { - self.commit > bound || self.prove > bound || self.execute > bound - } -} - -impl ops::Add for BlockGasCount { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self { - commit: self.commit + rhs.commit, - prove: self.prove + rhs.prove, - execute: self.execute + rhs.execute, - } - } -} - -impl ops::AddAssign for BlockGasCount { - fn add_assign(&mut self, other: Self) { - *self = Self { - commit: self.commit + other.commit, - prove: self.prove + other.prove, - execute: self.execute + other.execute, - }; - } -} - /// Hasher of L2 block contents used by the VM. #[derive(Debug)] pub struct L2BlockHasher { diff --git a/core/lib/types/src/eth_sender.rs b/core/lib/types/src/eth_sender.rs index 12a5a5a8fb13..e8e12993054f 100644 --- a/core/lib/types/src/eth_sender.rs +++ b/core/lib/types/src/eth_sender.rs @@ -47,7 +47,7 @@ pub struct EthTx { pub raw_tx: Vec, pub tx_type: AggregatedActionType, pub created_at_timestamp: u64, - pub predicted_gas_cost: u64, + pub predicted_gas_cost: Option, /// If this field is `Some` then it contains address of a custom operator that has sent /// this transaction. If it is set to `None` this transaction was sent by the main operator. pub from_addr: Option
, diff --git a/core/lib/vm_interface/src/types/outputs/execution_result.rs b/core/lib/vm_interface/src/types/outputs/execution_result.rs index 9bb784fbf71c..e95721dbb461 100644 --- a/core/lib/vm_interface/src/types/outputs/execution_result.rs +++ b/core/lib/vm_interface/src/types/outputs/execution_result.rs @@ -200,6 +200,7 @@ impl VmExecutionResultAndLogs { published_bytecode_bytes, l2_l1_long_messages, l2_to_l1_logs: self.logs.total_l2_to_l1_logs_count(), + user_l2_to_l1_logs: self.logs.user_l2_to_l1_logs.len(), contracts_used: self.statistics.contracts_used, contracts_deployed, vm_events: self.logs.events.len(), diff --git a/core/lib/vm_interface/src/types/outputs/statistic.rs b/core/lib/vm_interface/src/types/outputs/statistic.rs index f8e3851c8321..fdb89c08f498 100644 --- a/core/lib/vm_interface/src/types/outputs/statistic.rs +++ b/core/lib/vm_interface/src/types/outputs/statistic.rs @@ -177,6 +177,7 @@ pub struct TransactionExecutionMetrics { pub published_bytecode_bytes: usize, pub l2_l1_long_messages: usize, pub l2_l1_logs: usize, + pub user_l2_l1_logs: usize, pub contracts_used: usize, pub contracts_deployed: u16, pub vm_events: usize, @@ -201,6 +202,7 @@ impl Default for TransactionExecutionMetrics { published_bytecode_bytes: 0, l2_l1_long_messages: 0, l2_l1_logs: 0, + user_l2_l1_logs: 0, contracts_used: 0, contracts_deployed: 0, vm_events: 0, @@ -221,6 +223,7 @@ pub struct VmExecutionMetrics { pub published_bytecode_bytes: usize, pub l2_l1_long_messages: usize, pub l2_to_l1_logs: usize, + pub user_l2_to_l1_logs: usize, pub contracts_used: usize, pub contracts_deployed: u16, pub vm_events: usize, @@ -238,6 +241,7 @@ impl VmExecutionMetrics { published_bytecode_bytes: tx_metrics.published_bytecode_bytes, l2_l1_long_messages: tx_metrics.l2_l1_long_messages, l2_to_l1_logs: tx_metrics.l2_l1_logs, + user_l2_to_l1_logs: tx_metrics.user_l2_l1_logs, contracts_deployed: tx_metrics.contracts_deployed, contracts_used: tx_metrics.contracts_used, gas_used: tx_metrics.gas_used, @@ -274,6 +278,7 @@ impl ops::Add for VmExecutionMetrics { contracts_used: self.contracts_used + other.contracts_used, l2_l1_long_messages: self.l2_l1_long_messages + other.l2_l1_long_messages, l2_to_l1_logs: self.l2_to_l1_logs + other.l2_to_l1_logs, + user_l2_to_l1_logs: self.user_l2_to_l1_logs + other.user_l2_to_l1_logs, gas_used: self.gas_used + other.gas_used, vm_events: self.vm_events + other.vm_events, storage_logs: self.storage_logs + other.storage_logs, diff --git a/core/node/api_server/src/execution_sandbox/vm_metrics.rs b/core/node/api_server/src/execution_sandbox/vm_metrics.rs index 282d9bdf1b77..2f6d21f3a875 100644 --- a/core/node/api_server/src/execution_sandbox/vm_metrics.rs +++ b/core/node/api_server/src/execution_sandbox/vm_metrics.rs @@ -164,6 +164,7 @@ pub(super) fn collect_tx_execution_metrics( published_bytecode_bytes, l2_l1_long_messages, l2_l1_logs: result.logs.total_l2_to_l1_logs_count(), + user_l2_l1_logs: result.logs.user_l2_to_l1_logs.len(), contracts_used: result.statistics.contracts_used, contracts_deployed, vm_events: result.logs.events.len(), diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 91fb84ab8f17..76cfb83aec54 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -671,7 +671,7 @@ impl TxSender { // but the API assumes we are post boojum. In this situation we will determine a tx as being executable but the StateKeeper will // still reject them as it's not. let protocol_version = ProtocolVersionId::latest(); - let seal_data = SealData::for_transaction(transaction, tx_metrics, protocol_version); + let seal_data = SealData::for_transaction(transaction, tx_metrics); if let Some(reason) = self .0 .sealer diff --git a/core/node/eth_sender/src/aggregator.rs b/core/node/eth_sender/src/aggregator.rs index 3bdbf23242f0..8b0d8dfecea0 100644 --- a/core/node/eth_sender/src/aggregator.rs +++ b/core/node/eth_sender/src/aggregator.rs @@ -12,13 +12,14 @@ use zksync_types::{ helpers::unix_timestamp_ms, protocol_version::{L1VerifierConfig, ProtocolSemanticVersion}, pubdata_da::PubdataSendingMode, - L1BatchNumber, ProtocolVersionId, + settlement::SettlementMode, + Address, L1BatchNumber, ProtocolVersionId, }; use super::{ aggregated_operations::AggregatedOperation, publish_criterion::{ - DataSizeCriterion, GasCriterion, L1BatchPublishCriterion, NumberCriterion, + GasCriterionKind, L1BatchPublishCriterion, L1GasCriterion, NumberCriterion, TimestampDeadlineCriterion, }, }; @@ -44,65 +45,89 @@ impl Aggregator { pub fn new( config: SenderConfig, blob_store: Arc, - operate_4844_mode: bool, + custom_commit_sender_addr: Option
, commitment_mode: L1BatchCommitmentMode, + settlement_mode: SettlementMode, ) -> Self { let pubdata_da = config.pubdata_sending_mode; - Self { - commit_criteria: vec![ + let operate_4844_mode = + custom_commit_sender_addr.is_some() && !settlement_mode.is_gateway(); + + // We do not have a reliable lower bound for gas needed to execute batches on gateway so we do not aggregate. + let execute_criteria: Vec> = if settlement_mode + .is_gateway() + { + if config.max_aggregated_blocks_to_execute > 1 { + tracing::warn!( + "config.max_aggregated_blocks_to_execute is set to {} but \ + aggregator does not support aggregating execute operations when settling on gateway", + config.max_aggregated_blocks_to_execute + ); + } + + vec![Box::from(NumberCriterion { + op: AggregatedActionType::Execute, + limit: 1, + })] + } else { + vec![ Box::from(NumberCriterion { - op: AggregatedActionType::Commit, - limit: config.max_aggregated_blocks_to_commit, + op: AggregatedActionType::Execute, + limit: config.max_aggregated_blocks_to_execute, + }), + Box::from(TimestampDeadlineCriterion { + op: AggregatedActionType::Execute, + deadline_seconds: config.aggregated_block_execute_deadline, + max_allowed_lag: Some(config.timestamp_criteria_max_allowed_lag), }), - Box::from(GasCriterion::new( - AggregatedActionType::Commit, + Box::from(L1GasCriterion::new( config.max_aggregated_tx_gas, + GasCriterionKind::Execute, )), - Box::from(DataSizeCriterion { + ] + }; + + // It only makes sense to aggregate commit operation when validium chain settles to L1. + let commit_criteria: Vec> = if settlement_mode + == SettlementMode::SettlesToL1 + && commitment_mode == L1BatchCommitmentMode::Validium + { + vec![ + Box::from(NumberCriterion { op: AggregatedActionType::Commit, - data_limit: config.max_eth_tx_data_size, - pubdata_da, - commitment_mode, + limit: config.max_aggregated_blocks_to_commit, }), Box::from(TimestampDeadlineCriterion { op: AggregatedActionType::Commit, deadline_seconds: config.aggregated_block_commit_deadline, max_allowed_lag: Some(config.timestamp_criteria_max_allowed_lag), }), - ], - proof_criteria: vec![ - Box::from(NumberCriterion { - op: AggregatedActionType::PublishProofOnchain, - limit: *config.aggregated_proof_sizes.iter().max().unwrap() as u32, - }), - Box::from(GasCriterion::new( - AggregatedActionType::PublishProofOnchain, + Box::from(L1GasCriterion::new( config.max_aggregated_tx_gas, + GasCriterionKind::CommitValidium, )), - Box::from(TimestampDeadlineCriterion { - op: AggregatedActionType::PublishProofOnchain, - deadline_seconds: config.aggregated_block_prove_deadline, - // Currently, we can't use this functionality for proof criterion - // since we don't send dummy and real proofs in the same range, - // so even small ranges must be closed. - max_allowed_lag: None, - }), - ], - execute_criteria: vec![ - Box::from(NumberCriterion { - op: AggregatedActionType::Execute, - limit: config.max_aggregated_blocks_to_execute, - }), - Box::from(GasCriterion::new( - AggregatedActionType::Execute, - config.max_aggregated_tx_gas, - )), - Box::from(TimestampDeadlineCriterion { - op: AggregatedActionType::Execute, - deadline_seconds: config.aggregated_block_execute_deadline, - max_allowed_lag: Some(config.timestamp_criteria_max_allowed_lag), - }), - ], + ] + } else { + if config.max_aggregated_blocks_to_commit > 1 { + tracing::warn!( + "config.max_aggregated_blocks_to_commit is set to {} but \ + aggregator does not support aggregating commit operations anymore", + config.max_aggregated_blocks_to_commit + ); + } + vec![Box::from(NumberCriterion { + op: AggregatedActionType::Commit, + limit: 1, + })] + }; + + Self { + commit_criteria, + proof_criteria: vec![Box::from(NumberCriterion { + op: AggregatedActionType::PublishProofOnchain, + limit: 1, + })], + execute_criteria, config, blob_store, operate_4844_mode, @@ -137,12 +162,7 @@ impl Aggregator { { Some(AggregatedOperation::Execute(op)) } else if let Some(op) = self - .get_proof_operation( - storage, - *self.config.aggregated_proof_sizes.iter().max().unwrap(), - last_sealed_l1_batch_number, - l1_verifier_config, - ) + .get_proof_operation(storage, last_sealed_l1_batch_number, l1_verifier_config) .await { Some(AggregatedOperation::PublishProofOnchain(op)) @@ -250,12 +270,11 @@ impl Aggregator { async fn load_dummy_proof_operations( storage: &mut Connection<'_, Core>, - limit: usize, is_4844_mode: bool, ) -> Vec { let mut ready_for_proof_l1_batches = storage .blocks_dal() - .get_ready_for_dummy_proof_l1_batches(limit) + .get_ready_for_dummy_proof_l1_batches(1) .await .unwrap(); @@ -424,7 +443,6 @@ impl Aggregator { async fn get_proof_operation( &mut self, storage: &mut Connection<'_, Core>, - limit: usize, last_sealed_l1_batch: L1BatchNumber, l1_verifier_config: L1VerifierConfig, ) -> Option { @@ -441,7 +459,7 @@ impl Aggregator { ProofSendingMode::SkipEveryProof => { let ready_for_proof_l1_batches = - Self::load_dummy_proof_operations(storage, limit, self.operate_4844_mode).await; + Self::load_dummy_proof_operations(storage, self.operate_4844_mode).await; self.prepare_dummy_proof_operation( storage, ready_for_proof_l1_batches, @@ -464,7 +482,7 @@ impl Aggregator { } else { let ready_for_proof_batches = storage .blocks_dal() - .get_skipped_for_proof_l1_batches(limit) + .get_skipped_for_proof_l1_batches(1) .await .unwrap(); self.prepare_dummy_proof_operation( diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 7b6280c9592f..dbef6da7b47b 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -15,7 +15,7 @@ use zksync_l1_contract_interface::{ use zksync_shared_metrics::BlockL1Stage; use zksync_types::{ aggregated_operations::AggregatedActionType, - commitment::{L1BatchWithMetadata, SerializeCommitment}, + commitment::{L1BatchCommitmentMode, L1BatchWithMetadata, SerializeCommitment}, eth_sender::{EthTx, EthTxBlobSidecar, EthTxBlobSidecarV1, SidecarBlobV1}, ethabi::{Function, Token}, l2_to_l1_log::UserL2ToL1Log, @@ -30,7 +30,7 @@ use super::aggregated_operations::AggregatedOperation; use crate::{ health::{EthTxAggregatorHealthDetails, EthTxDetails}, metrics::{PubdataKind, METRICS}, - utils::agg_l1_batch_base_cost, + publish_criterion::L1GasCriterion, zksync_functions::ZkSyncFunctions, Aggregator, EthSenderError, }; @@ -589,12 +589,19 @@ impl EthTxAggregator { let encoded_aggregated_op = self.encode_aggregated_op(aggregated_op); let l1_batch_number_range = aggregated_op.l1_batch_range(); - let predicted_gas_for_batches = transaction - .blocks_dal() - .get_l1_batches_predicted_gas(l1_batch_number_range.clone(), op_type) - .await - .unwrap(); - let eth_tx_predicted_gas = agg_l1_batch_base_cost(op_type) + predicted_gas_for_batches; + let eth_tx_predicted_gas = match (op_type, is_gateway, self.aggregator.mode()) { + (AggregatedActionType::Execute, false, _) => Some( + L1GasCriterion::total_execute_gas_amount( + &mut transaction, + l1_batch_number_range.clone(), + ) + .await, + ), + (AggregatedActionType::Commit, false, L1BatchCommitmentMode::Validium) => Some( + L1GasCriterion::total_validium_commit_gas_amount(l1_batch_number_range.clone()), + ), + _ => None, + }; let eth_tx = transaction .eth_sender_dal() diff --git a/core/node/eth_sender/src/eth_tx_manager.rs b/core/node/eth_sender/src/eth_tx_manager.rs index f411e9b3ae4b..17f71b69303a 100644 --- a/core/node/eth_sender/src/eth_tx_manager.rs +++ b/core/node/eth_sender/src/eth_tx_manager.rs @@ -500,13 +500,14 @@ impl EthTxManager { .track_eth_tx_metrics(storage, BlockL1Stage::Mined, tx) .await; - if gas_used > U256::from(tx.predicted_gas_cost) { - tracing::error!( - "Predicted gas {} lower than used gas {gas_used} for tx {:?} {}", - tx.predicted_gas_cost, - tx.tx_type, - tx.id - ); + if let Some(predicted_gas_cost) = tx.predicted_gas_cost { + if gas_used > U256::from(predicted_gas_cost) { + tracing::error!( + "Predicted gas {predicted_gas_cost} lower than used gas {gas_used} for tx {:?} {}", + tx.tx_type, + tx.id + ); + } } tracing::info!( "eth_tx {} with hash {tx_hash:?} for {} is confirmed. Gas spent: {gas_used:?}", diff --git a/core/node/eth_sender/src/health.rs b/core/node/eth_sender/src/health.rs index 1aff80dae6d2..1a07a61e2892 100644 --- a/core/node/eth_sender/src/health.rs +++ b/core/node/eth_sender/src/health.rs @@ -39,7 +39,7 @@ pub struct EthTxDetails { pub nonce: Nonce, pub tx_type: AggregatedActionType, pub created_at_timestamp: u64, - pub predicted_gas_cost: u64, + pub predicted_gas_cost: Option, pub status: Option, } diff --git a/core/node/eth_sender/src/lib.rs b/core/node/eth_sender/src/lib.rs index fc6076ec640b..feec550b011d 100644 --- a/core/node/eth_sender/src/lib.rs +++ b/core/node/eth_sender/src/lib.rs @@ -6,7 +6,6 @@ mod eth_tx_manager; mod health; mod metrics; mod publish_criterion; -mod utils; mod zksync_functions; mod abstract_l1_interface; diff --git a/core/node/eth_sender/src/publish_criterion.rs b/core/node/eth_sender/src/publish_criterion.rs index 30f0820b148a..28ca44697bb6 100644 --- a/core/node/eth_sender/src/publish_criterion.rs +++ b/core/node/eth_sender/src/publish_criterion.rs @@ -1,18 +1,17 @@ -use std::fmt; +use std::{fmt, ops}; use async_trait::async_trait; use chrono::Utc; use zksync_dal::{Connection, Core, CoreDal}; -use zksync_l1_contract_interface::{i_executor::structures::CommitBatchInfo, Tokenizable}; use zksync_types::{ - aggregated_operations::AggregatedActionType, - commitment::{L1BatchCommitmentMode, L1BatchWithMetadata}, - ethabi, - pubdata_da::PubdataSendingMode, + aggregated_operations::{ + AggregatedActionType, L1_BATCH_EXECUTE_BASE_COST, L1_OPERATION_EXECUTE_COST, + }, + commitment::L1BatchWithMetadata, L1BatchNumber, }; -use super::{metrics::METRICS, utils::agg_l1_batch_base_cost}; +use super::metrics::METRICS; #[async_trait] pub trait L1BatchPublishCriterion: fmt::Debug + Send + Sync { @@ -123,32 +122,82 @@ impl L1BatchPublishCriterion for TimestampDeadlineCriterion { } } +#[derive(Debug, Clone, Copy)] +pub enum GasCriterionKind { + CommitValidium, + Execute, +} + +impl From for AggregatedActionType { + fn from(value: GasCriterionKind) -> Self { + match value { + GasCriterionKind::CommitValidium => AggregatedActionType::Commit, + GasCriterionKind::Execute => AggregatedActionType::Execute, + } + } +} + #[derive(Debug)] -pub struct GasCriterion { - pub op: AggregatedActionType, +pub struct L1GasCriterion { pub gas_limit: u32, + pub kind: GasCriterionKind, } -impl GasCriterion { - pub fn new(op: AggregatedActionType, gas_limit: u32) -> GasCriterion { - GasCriterion { op, gas_limit } +impl L1GasCriterion { + /// Base gas cost of processing aggregated `Execute` operation. + /// It's applicable iff SL is Ethereum. + const AGGR_L1_BATCH_EXECUTE_BASE_COST: u32 = 241_000; + + /// Base gas cost of processing aggregated `Commit` operation. + /// It's applicable iff SL is Ethereum. + const AGGR_L1_BATCH_COMMIT_BASE_COST: u32 = 242_000; + + /// Additional gas cost of processing `Commit` operation per batch. + /// It's applicable iff SL is Ethereum. + pub const L1_BATCH_COMMIT_BASE_COST: u32 = 31_000; + + pub fn new(gas_limit: u32, kind: GasCriterionKind) -> L1GasCriterion { + L1GasCriterion { gas_limit, kind } + } + + pub async fn total_execute_gas_amount( + storage: &mut Connection<'_, Core>, + batch_numbers: ops::RangeInclusive, + ) -> u32 { + let mut total = Self::AGGR_L1_BATCH_EXECUTE_BASE_COST; + + for batch_number in batch_numbers.start().0..=batch_numbers.end().0 { + total += Self::get_execute_gas_amount(storage, batch_number.into()).await; + } + + total + } + + pub fn total_validium_commit_gas_amount( + batch_numbers: ops::RangeInclusive, + ) -> u32 { + Self::AGGR_L1_BATCH_COMMIT_BASE_COST + + (batch_numbers.end().0 - batch_numbers.start().0 + 1) + * Self::L1_BATCH_COMMIT_BASE_COST } - async fn get_gas_amount( - &self, + async fn get_execute_gas_amount( storage: &mut Connection<'_, Core>, batch_number: L1BatchNumber, ) -> u32 { - storage + let header = storage .blocks_dal() - .get_l1_batches_predicted_gas(batch_number..=batch_number, self.op) + .get_l1_batch_header(batch_number) .await .unwrap() + .unwrap_or_else(|| panic!("Missing L1 batch header in DB for #{batch_number}")); + + L1_BATCH_EXECUTE_BASE_COST + u32::from(header.l1_tx_count) * L1_OPERATION_EXECUTE_COST } } #[async_trait] -impl L1BatchPublishCriterion for GasCriterion { +impl L1BatchPublishCriterion for L1GasCriterion { fn name(&self) -> &'static str { "gas_limit" } @@ -159,17 +208,25 @@ impl L1BatchPublishCriterion for GasCriterion { consecutive_l1_batches: &[L1BatchWithMetadata], _last_sealed_l1_batch: L1BatchNumber, ) -> Option { - let base_cost = agg_l1_batch_base_cost(self.op); + let aggr_cost = match self.kind { + GasCriterionKind::Execute => Self::AGGR_L1_BATCH_EXECUTE_BASE_COST, + GasCriterionKind::CommitValidium => Self::AGGR_L1_BATCH_COMMIT_BASE_COST, + }; assert!( - self.gas_limit > base_cost, + self.gas_limit > aggr_cost, "Config max gas cost for operations is too low" ); // We're not sure our predictions are accurate, so it's safer to lower the gas limit by 10% - let mut gas_left = (self.gas_limit as f64 * 0.9).round() as u32 - base_cost; + let mut gas_left = (self.gas_limit as f64 * 0.9).round() as u32 - aggr_cost; let mut last_l1_batch = None; for (index, l1_batch) in consecutive_l1_batches.iter().enumerate() { - let batch_gas = self.get_gas_amount(storage, l1_batch.header.number).await; + let batch_gas = match self.kind { + GasCriterionKind::Execute => { + Self::get_execute_gas_amount(storage, l1_batch.header.number).await + } + GasCriterionKind::CommitValidium => Self::L1_BATCH_COMMIT_BASE_COST, + }; if batch_gas >= gas_left { if index == 0 { panic!( @@ -185,70 +242,16 @@ impl L1BatchPublishCriterion for GasCriterion { } if let Some(last_l1_batch) = last_l1_batch { + let op: AggregatedActionType = self.kind.into(); let first_l1_batch_number = consecutive_l1_batches.first().unwrap().header.number.0; tracing::debug!( "`gas_limit` publish criterion (gas={}) triggered for op {} with L1 batch range {:?}", self.gas_limit - gas_left, - self.op, + op, first_l1_batch_number..=last_l1_batch.0 ); - METRICS.block_aggregation_reason[&(self.op, "gas").into()].inc(); + METRICS.block_aggregation_reason[&(op, "gas").into()].inc(); } last_l1_batch } } - -#[derive(Debug)] -pub struct DataSizeCriterion { - pub op: AggregatedActionType, - pub data_limit: usize, - pub pubdata_da: PubdataSendingMode, - pub commitment_mode: L1BatchCommitmentMode, -} - -#[async_trait] -impl L1BatchPublishCriterion for DataSizeCriterion { - fn name(&self) -> &'static str { - "data_size" - } - - async fn last_l1_batch_to_publish( - &mut self, - _storage: &mut Connection<'_, Core>, - consecutive_l1_batches: &[L1BatchWithMetadata], - _last_sealed_l1_batch: L1BatchNumber, - ) -> Option { - const STORED_BLOCK_INFO_SIZE: usize = 96; // size of `StoredBlockInfo` solidity struct - let mut data_size_left = self.data_limit - STORED_BLOCK_INFO_SIZE; - - for (index, l1_batch) in consecutive_l1_batches.iter().enumerate() { - // TODO (PLA-771): Make sure that this estimation is correct. - let commit_token = - CommitBatchInfo::new(self.commitment_mode, l1_batch, self.pubdata_da).into_token(); - let l1_commit_data_size = ethabi::encode(&[commit_token]).len(); - - if data_size_left < l1_commit_data_size { - if index == 0 { - panic!( - "L1 batch #{} requires {} data, which is more than the range limit of {}", - l1_batch.header.number, l1_commit_data_size, self.data_limit - ); - } - - let first_l1_batch_number = consecutive_l1_batches.first().unwrap().header.number.0; - let output = l1_batch.header.number - 1; - tracing::debug!( - "`data_size` publish criterion (data={}) triggered for op {} with L1 batch range {:?}", - self.data_limit - data_size_left, - self.op, - first_l1_batch_number..=output.0 - ); - METRICS.block_aggregation_reason[&(self.op, "data_size").into()].inc(); - return Some(output); - } - data_size_left -= l1_commit_data_size; - } - - None - } -} diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index b62223d0d68b..3caf0cae5f87 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -146,7 +146,6 @@ impl EthSenderTester { PubdataSendingMode::Calldata }; let aggregator_config = SenderConfig { - aggregated_proof_sizes: vec![1], pubdata_sending_mode, ..eth_sender_config.clone().sender.unwrap() }; @@ -256,8 +255,9 @@ impl EthSenderTester { Aggregator::new( aggregator_config.clone(), MockObjectStore::arc(), - aggregator_operate_4844_mode, + custom_commit_sender_addr, commitment_mode, + SettlementMode::SettlesToL1, ), gateway.clone(), // ZKsync contract address diff --git a/core/node/eth_sender/src/utils.rs b/core/node/eth_sender/src/utils.rs deleted file mode 100644 index 98139c201993..000000000000 --- a/core/node/eth_sender/src/utils.rs +++ /dev/null @@ -1,14 +0,0 @@ -use zksync_types::aggregated_operations::AggregatedActionType; - -// TODO(QIT-32): Remove constants(except `L1_OPERATION_EXECUTE_COST`) and logic that use them -const AGGR_L1_BATCH_COMMIT_BASE_COST: u32 = 242_000; -const AGGR_L1_BATCH_PROVE_BASE_COST: u32 = 1_000_000; -const AGGR_L1_BATCH_EXECUTE_BASE_COST: u32 = 241_000; - -pub fn agg_l1_batch_base_cost(op: AggregatedActionType) -> u32 { - match op { - AggregatedActionType::Commit => AGGR_L1_BATCH_COMMIT_BASE_COST, - AggregatedActionType::PublishProofOnchain => AGGR_L1_BATCH_PROVE_BASE_COST, - AggregatedActionType::Execute => AGGR_L1_BATCH_EXECUTE_BASE_COST, - } -} diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 0a0e77d97f95..38972389129e 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -16,7 +16,7 @@ use zksync_merkle_tree::{domain::ZkSyncTree, TreeInstruction}; use zksync_multivm::utils::get_max_gas_per_pubdata_byte; use zksync_system_constants::PRIORITY_EXPIRATION; use zksync_types::{ - block::{BlockGasCount, DeployedContract, L1BatchHeader, L2BlockHasher, L2BlockHeader}, + block::{DeployedContract, L1BatchHeader, L2BlockHasher, L2BlockHeader}, bytecode::BytecodeHash, commitment::{CommitmentInput, L1BatchCommitment}, fee_model::BatchFeeInput, @@ -425,14 +425,7 @@ pub async fn create_genesis_l1_batch( .await?; transaction .blocks_dal() - .mark_l1_batch_as_sealed( - &genesis_l1_batch_header, - &[], - BlockGasCount::default(), - &[], - &[], - Default::default(), - ) + .mark_l1_batch_as_sealed(&genesis_l1_batch_header, &[], &[], &[], Default::default()) .await?; transaction .blocks_dal() diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs index 235158544c54..d2be0b383393 100644 --- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs +++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs @@ -111,8 +111,9 @@ impl WiringLayer for EthTxAggregatorLayer { let aggregator = Aggregator::new( config.clone(), object_store, - eth_client_blobs_addr.is_some(), + eth_client_blobs_addr, self.l1_batch_commit_data_generator_mode, + self.settlement_mode, ); let eth_tx_aggregator = EthTxAggregator::new( diff --git a/core/node/state_keeper/src/executor/mod.rs b/core/node/state_keeper/src/executor/mod.rs index 903dae2f1cad..a6c7b92fa249 100644 --- a/core/node/state_keeper/src/executor/mod.rs +++ b/core/node/state_keeper/src/executor/mod.rs @@ -1,25 +1,23 @@ use zksync_multivm::interface::{ BatchTransactionExecutionResult, Call, CompressedBytecodeInfo, ExecutionResult, Halt, - VmExecutionResultAndLogs, + VmExecutionMetrics, VmExecutionResultAndLogs, }; use zksync_types::Transaction; pub use zksync_vm_executor::batch::MainBatchExecutorFactory; -use crate::ExecutionMetricsForCriteria; - #[cfg(test)] mod tests; /// State keeper representation of a transaction executed in the virtual machine. /// /// A separate type allows to be more typesafe when dealing with halted transactions. It also simplifies testing seal criteria -/// (i.e., without picking transactions that actually produce appropriate `ExecutionMetricsForCriteria`). +/// (i.e., without picking transactions that actually produce appropriate `VmExecutionMetrics`). #[derive(Debug, Clone)] pub enum TxExecutionResult { /// Successful execution of the tx and the block tip dry run. Success { tx_result: Box, - tx_metrics: Box, + tx_metrics: Box, compressed_bytecodes: Vec, call_tracer_result: Vec, gas_remaining: u32, @@ -38,7 +36,7 @@ impl TxExecutionResult { } => Self::BootloaderOutOfGasForTx, ExecutionResult::Halt { reason } => Self::RejectedByVm { reason }, _ => Self::Success { - tx_metrics: Box::new(ExecutionMetricsForCriteria::new(Some(tx), &res.tx_result)), + tx_metrics: Box::new(res.tx_result.get_execution_metrics(Some(tx))), gas_remaining: res.tx_result.statistics.gas_remaining, tx_result: res.tx_result.clone(), compressed_bytecodes: res.compressed_bytecodes, diff --git a/core/node/state_keeper/src/io/persistence.rs b/core/node/state_keeper/src/io/persistence.rs index d8fd99bfc95d..8db7fe4120ed 100644 --- a/core/node/state_keeper/src/io/persistence.rs +++ b/core/node/state_keeper/src/io/persistence.rs @@ -386,8 +386,8 @@ mod tests { use zksync_multivm::interface::{FinishedL1Batch, VmExecutionMetrics}; use zksync_node_genesis::{insert_genesis_batch, GenesisParams}; use zksync_types::{ - api::TransactionStatus, block::BlockGasCount, h256_to_u256, writes::StateDiffRecord, - L1BatchNumber, L2BlockNumber, StorageLogKind, H256, U256, + api::TransactionStatus, h256_to_u256, writes::StateDiffRecord, L1BatchNumber, + L2BlockNumber, StorageLogKind, H256, U256, }; use super::*; @@ -508,7 +508,6 @@ mod tests { tx, tx_result, vec![], - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], ); diff --git a/core/node/state_keeper/src/io/seal_logic/l2_block_seal_subtasks.rs b/core/node/state_keeper/src/io/seal_logic/l2_block_seal_subtasks.rs index a6356a838602..701e121285d4 100644 --- a/core/node/state_keeper/src/io/seal_logic/l2_block_seal_subtasks.rs +++ b/core/node/state_keeper/src/io/seal_logic/l2_block_seal_subtasks.rs @@ -538,10 +538,10 @@ mod tests { user_l2_to_l1_logs, system_l2_to_l1_logs: Default::default(), new_factory_deps, - l1_gas_count: Default::default(), block_execution_metrics: Default::default(), txs_encoding_size: Default::default(), payload_encoding_size: Default::default(), + l1_tx_count: 0, timestamp: 1, number: L2BlockNumber(1), prev_block_hash: Default::default(), diff --git a/core/node/state_keeper/src/io/seal_logic/mod.rs b/core/node/state_keeper/src/io/seal_logic/mod.rs index 419413e127d3..655bf182ba8f 100644 --- a/core/node/state_keeper/src/io/seal_logic/mod.rs +++ b/core/node/state_keeper/src/io/seal_logic/mod.rs @@ -145,7 +145,6 @@ impl UpdatesManager { .mark_l1_batch_as_sealed( &l1_batch, &final_bootloader_memory, - self.pending_l1_gas_count(), &finished_batch.final_execution_state.storage_refunds, &finished_batch.final_execution_state.pubdata_costs, self.pending_execution_metrics().circuit_statistic, diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 5a44bf71ad39..15164328b7a0 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -13,7 +13,7 @@ use zksync_multivm::{ use zksync_node_test_utils::prepare_recovery_snapshot; use zksync_system_constants::KNOWN_CODES_STORAGE_ADDRESS; use zksync_types::{ - block::{BlockGasCount, L2BlockHasher}, + block::L2BlockHasher, bytecode::BytecodeHash, commitment::{L1BatchCommitmentMode, PubdataParams}, fee_model::{BatchFeeInput, PubdataIndependentBatchFeeModelInput}, @@ -279,7 +279,6 @@ async fn processing_storage_logs_when_sealing_l2_block() { l2_block.extend_from_executed_transaction( tx, execution_result, - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -297,7 +296,6 @@ async fn processing_storage_logs_when_sealing_l2_block() { l2_block.extend_from_executed_transaction( tx, execution_result, - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -371,7 +369,6 @@ async fn processing_events_when_sealing_l2_block() { l2_block.extend_from_executed_transaction( tx, execution_result, - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -476,7 +473,6 @@ async fn processing_dynamic_factory_deps_when_sealing_l2_block() { l2_block.extend_from_executed_transaction( tx, execution_result, - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -571,7 +567,6 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom tx.into(), create_execution_result([]), vec![], - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], ); diff --git a/core/node/state_keeper/src/keeper.rs b/core/node/state_keeper/src/keeper.rs index 7fcc53ad2d26..c892fd8534ec 100644 --- a/core/node/state_keeper/src/keeper.rs +++ b/core/node/state_keeper/src/keeper.rs @@ -29,9 +29,8 @@ use crate::{ io::{IoCursor, L1BatchParams, L2BlockParams, OutputHandler, PendingBatchData, StateKeeperIO}, metrics::{AGGREGATION_METRICS, KEEPER_METRICS, L1_BATCH_METRICS}, seal_criteria::{ConditionalSealer, SealData, SealResolution, UnexecutableReason}, - types::ExecutionMetricsForCriteria, updates::UpdatesManager, - utils::{gas_count_from_writes, is_canceled}, + utils::is_canceled, }; /// Amount of time to block on waiting for some resource. The exact value is not really important, @@ -500,7 +499,7 @@ impl ZkSyncStateKeeper { let TxExecutionResult::Success { tx_result, - tx_metrics, + tx_metrics: tx_execution_metrics, compressed_bytecodes, call_tracer_result, .. @@ -517,11 +516,6 @@ impl ZkSyncStateKeeper { .into()); }; - let ExecutionMetricsForCriteria { - l1_gas: tx_l1_gas_this_tx, - execution_metrics: tx_execution_metrics, - } = *tx_metrics; - let tx_hash = tx.hash(); let is_l1 = tx.is_l1(); let exec_result_status = tx_result.result.clone(); @@ -531,20 +525,17 @@ impl ZkSyncStateKeeper { tx, *tx_result, compressed_bytecodes, - tx_l1_gas_this_tx, - tx_execution_metrics, + *tx_execution_metrics, call_tracer_result, ); tracing::debug!( "Finished re-executing tx {tx_hash} by {initiator_account} (is_l1: {is_l1}, \ #{idx_in_l1_batch} in L1 batch #{l1_batch_number}, #{idx_in_l2_block} in L2 block #{l2_block_number}); \ - status: {exec_result_status:?}. L1 gas spent: {tx_l1_gas_this_tx:?}, total in L1 batch: {pending_l1_gas:?}, \ - tx execution metrics: {tx_execution_metrics:?}, block execution metrics: {block_execution_metrics:?}", + status: {exec_result_status:?}. Tx execution metrics: {tx_execution_metrics:?}, block execution metrics: {block_execution_metrics:?}", idx_in_l1_batch = updates_manager.pending_executed_transactions_len(), l1_batch_number = updates_manager.l1_batch.number, idx_in_l2_block = updates_manager.l2_block.executed_transactions.len(), - pending_l1_gas = updates_manager.pending_l1_gas_count(), block_execution_metrics = updates_manager.pending_execution_metrics() ); } @@ -639,7 +630,7 @@ impl ZkSyncStateKeeper { SealResolution::NoSeal | SealResolution::IncludeAndSeal => { let TxExecutionResult::Success { tx_result, - tx_metrics, + tx_metrics: tx_execution_metrics, call_tracer_result, compressed_bytecodes, .. @@ -649,16 +640,11 @@ impl ZkSyncStateKeeper { "Tx inclusion seal resolution must be a result of a successful tx execution", ); }; - let ExecutionMetricsForCriteria { - l1_gas: tx_l1_gas_this_tx, - execution_metrics: tx_execution_metrics, - } = *tx_metrics; updates_manager.extend_from_executed_transaction( tx, *tx_result, compressed_bytecodes, - tx_l1_gas_this_tx, - tx_execution_metrics, + *tx_execution_metrics, call_tracer_result, ); } @@ -714,7 +700,7 @@ impl ZkSyncStateKeeper { SealResolution::NoSeal | SealResolution::IncludeAndSeal => { let TxExecutionResult::Success { tx_result, - tx_metrics, + tx_metrics: tx_execution_metrics, compressed_bytecodes, call_tracer_result, .. @@ -729,17 +715,11 @@ impl ZkSyncStateKeeper { anyhow::bail!("Failed upgrade tx {:?}", tx.hash()); } - let ExecutionMetricsForCriteria { - l1_gas: tx_l1_gas_this_tx, - execution_metrics: tx_execution_metrics, - .. - } = *tx_metrics; updates_manager.extend_from_executed_transaction( tx, *tx_result, compressed_bytecodes, - tx_l1_gas_this_tx, - tx_execution_metrics, + *tx_execution_metrics, call_tracer_result, ); Ok(()) @@ -823,20 +803,15 @@ impl ZkSyncStateKeeper { } TxExecutionResult::Success { tx_result, - tx_metrics, + tx_metrics: tx_execution_metrics, gas_remaining, .. } => { let tx_execution_status = &tx_result.result; - let ExecutionMetricsForCriteria { - l1_gas: tx_l1_gas_this_tx, - execution_metrics: tx_execution_metrics, - } = **tx_metrics; tracing::trace!( "finished tx {:?} by {:?} (is_l1: {}) (#{} in l1 batch {}) (#{} in L2 block {}) \ - status: {:?}. L1 gas spent: {:?}, total in l1 batch: {:?}, \ - tx execution metrics: {:?}, block execution metrics: {:?}", + status: {:?}. Tx execution metrics: {:?}, block execution metrics: {:?}", tx.hash(), tx.initiator_account(), tx.is_l1(), @@ -845,10 +820,8 @@ impl ZkSyncStateKeeper { updates_manager.l2_block.executed_transactions.len() + 1, updates_manager.l2_block.number, tx_execution_status, - tx_l1_gas_this_tx, - updates_manager.pending_l1_gas_count() + tx_l1_gas_this_tx, &tx_execution_metrics, - updates_manager.pending_execution_metrics() + tx_execution_metrics, + updates_manager.pending_execution_metrics() + **tx_execution_metrics, ); let encoding_len = tx.encoding_len(); @@ -858,20 +831,11 @@ impl ZkSyncStateKeeper { .storage_writes_deduplicator .apply_and_rollback(logs_to_apply_iter.clone()); - let block_writes_l1_gas = gas_count_from_writes( - &block_writes_metrics, - updates_manager.protocol_version(), - ); - let tx_writes_metrics = StorageWritesDeduplicator::apply_on_empty_state(logs_to_apply_iter); - let tx_writes_l1_gas = - gas_count_from_writes(&tx_writes_metrics, updates_manager.protocol_version()); - let tx_gas_excluding_writes = tx_l1_gas_this_tx; let tx_data = SealData { - execution_metrics: tx_execution_metrics, - gas_count: tx_gas_excluding_writes + tx_writes_l1_gas, + execution_metrics: **tx_execution_metrics, cumulative_size: encoding_len, writes_metrics: tx_writes_metrics, gas_remaining: *gas_remaining, @@ -879,19 +843,18 @@ impl ZkSyncStateKeeper { let block_data = SealData { execution_metrics: tx_data.execution_metrics + updates_manager.pending_execution_metrics(), - gas_count: tx_gas_excluding_writes - + block_writes_l1_gas - + updates_manager.pending_l1_gas_count(), cumulative_size: tx_data.cumulative_size + updates_manager.pending_txs_encoding_size(), writes_metrics: block_writes_metrics, gas_remaining: *gas_remaining, }; + let is_tx_l1 = tx.is_l1() as usize; self.sealer.should_seal_l1_batch( updates_manager.l1_batch.number.0, updates_manager.batch_timestamp() as u128 * 1_000, updates_manager.pending_executed_transactions_len() + 1, + updates_manager.pending_l1_transactions_len() + is_tx_l1, &block_data, &tx_data, updates_manager.protocol_version(), diff --git a/core/node/state_keeper/src/lib.rs b/core/node/state_keeper/src/lib.rs index 323580ab0434..001d474cb246 100644 --- a/core/node/state_keeper/src/lib.rs +++ b/core/node/state_keeper/src/lib.rs @@ -7,7 +7,7 @@ pub use self::{ mempool_actor::MempoolFetcher, seal_criteria::SequencerSealer, state_keeper_storage::AsyncRocksdbCache, - types::{ExecutionMetricsForCriteria, MempoolGuard}, + types::MempoolGuard, updates::UpdatesManager, }; diff --git a/core/node/state_keeper/src/seal_criteria/conditional_sealer.rs b/core/node/state_keeper/src/seal_criteria/conditional_sealer.rs index cd00d4f89360..4da7dd463104 100644 --- a/core/node/state_keeper/src/seal_criteria/conditional_sealer.rs +++ b/core/node/state_keeper/src/seal_criteria/conditional_sealer.rs @@ -23,11 +23,13 @@ pub trait ConditionalSealer: 'static + fmt::Debug + Send + Sync { ) -> Option<&'static str>; /// Returns the action that should be taken by the state keeper after executing a transaction. + #[allow(clippy::too_many_arguments)] fn should_seal_l1_batch( &self, l1_batch_number: u32, block_open_timestamp_ms: u128, tx_count: usize, + l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -59,6 +61,7 @@ impl ConditionalSealer for SequencerSealer { &self.config, MOCK_BLOCK_TIMESTAMP, TX_COUNT, + TX_COUNT, data, data, protocol_version, @@ -75,6 +78,7 @@ impl ConditionalSealer for SequencerSealer { l1_batch_number: u32, block_open_timestamp_ms: u128, tx_count: usize, + l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -91,6 +95,7 @@ impl ConditionalSealer for SequencerSealer { &self.config, block_open_timestamp_ms, tx_count, + l1_tx_count, block_data, tx_data, protocol_version, @@ -132,13 +137,14 @@ impl SequencerSealer { fn default_sealers(config: &StateKeeperConfig) -> Vec> { vec![ Box::new(criteria::SlotsCriterion), - Box::new(criteria::GasCriterion), Box::new(criteria::PubDataBytesCriterion { max_pubdata_per_batch: config.max_pubdata_per_batch, }), Box::new(criteria::CircuitsCriterion), Box::new(criteria::TxEncodingSizeCriterion), Box::new(criteria::GasForBatchTipCriterion), + Box::new(criteria::L1L2TxsCriterion), + Box::new(criteria::L2L1LogsCriterion), ] } } @@ -163,6 +169,7 @@ impl ConditionalSealer for NoopSealer { _l1_batch_number: u32, _block_open_timestamp_ms: u128, _tx_count: usize, + _l1_tx_count: usize, _block_data: &SealData, _tx_data: &SealData, _protocol_version: ProtocolVersionId, diff --git a/core/node/state_keeper/src/seal_criteria/criteria/gas.rs b/core/node/state_keeper/src/seal_criteria/criteria/gas.rs deleted file mode 100644 index a97ac6ede353..000000000000 --- a/core/node/state_keeper/src/seal_criteria/criteria/gas.rs +++ /dev/null @@ -1,180 +0,0 @@ -use zksync_types::ProtocolVersionId; - -use crate::{ - seal_criteria::{ - SealCriterion, SealData, SealResolution, StateKeeperConfig, UnexecutableReason, - }, - utils::new_block_gas_count, -}; - -/// This is a temporary solution. -/// Instead of checking for gas it simply checks that the contracts' -/// bytecode is large enough. -/// Among all the data which will be published on-chain the contracts' -/// bytecode is by far the largest one and with high probability -/// the slots will run out before the other pubdata becomes too big -#[derive(Debug)] -pub(crate) struct GasCriterion; - -impl SealCriterion for GasCriterion { - fn should_seal( - &self, - config: &StateKeeperConfig, - _block_open_timestamp_ms: u128, - _tx_count: usize, - block_data: &SealData, - tx_data: &SealData, - _protocol_version_id: ProtocolVersionId, - ) -> SealResolution { - let tx_bound = - (config.max_single_tx_gas as f64 * config.reject_tx_at_gas_percentage).round() as u32; - let block_bound = - (config.max_single_tx_gas as f64 * config.close_block_at_gas_percentage).round() as u32; - - if (tx_data.gas_count + new_block_gas_count()).any_field_greater_than(tx_bound) { - UnexecutableReason::TooMuchGas.into() - } else if block_data - .gas_count - .any_field_greater_than(config.max_single_tx_gas) - { - SealResolution::ExcludeAndSeal - } else if block_data.gas_count.any_field_greater_than(block_bound) { - SealResolution::IncludeAndSeal - } else { - SealResolution::NoSeal - } - } - - fn prom_criterion_name(&self) -> &'static str { - "gas" - } -} - -#[cfg(test)] -mod tests { - use zksync_types::block::BlockGasCount; - - use super::*; - - #[test] - fn test_gas_seal_criterion() { - // Create an empty config and only setup fields relevant for the test. - let config = StateKeeperConfig { - max_single_tx_gas: 6000000, - reject_tx_at_gas_percentage: 0.95, - close_block_at_gas_percentage: 0.95, - ..Default::default() - }; - - let criterion = GasCriterion; - - // Empty block should fit into gas criterion. - let empty_block_gas = new_block_gas_count(); - let empty_block_resolution = criterion.should_seal( - &config, - 0, - 0, - &SealData { - gas_count: empty_block_gas, - ..SealData::default() - }, - &SealData::default(), - ProtocolVersionId::latest(), - ); - assert_eq!(empty_block_resolution, SealResolution::NoSeal); - - let tx_gas = BlockGasCount { - commit: config.max_single_tx_gas + 1, - prove: 0, - execute: 0, - }; - // Transaction that needs more gas than a block limit should be unexecutable. - let huge_transaction_resolution = criterion.should_seal( - &config, - 0, - 1, - &SealData { - gas_count: empty_block_gas + tx_gas, - ..SealData::default() - }, - &SealData { - gas_count: tx_gas, - ..SealData::default() - }, - ProtocolVersionId::latest(), - ); - assert_eq!( - huge_transaction_resolution, - UnexecutableReason::TooMuchGas.into() - ); - - // Check criterion workflow - let reject_tx_bound = - (config.max_single_tx_gas as f64 * config.reject_tx_at_gas_percentage).round() as u32; - let tx_gas = BlockGasCount { - commit: reject_tx_bound - empty_block_gas.commit, - prove: reject_tx_bound - empty_block_gas.prove, - execute: reject_tx_bound - empty_block_gas.execute, - }; - let resolution_after_first_tx = criterion.should_seal( - &config, - 0, - 1, - &SealData { - gas_count: empty_block_gas + tx_gas, - ..SealData::default() - }, - &SealData { - gas_count: tx_gas, - ..SealData::default() - }, - ProtocolVersionId::latest(), - ); - assert_eq!(resolution_after_first_tx, SealResolution::NoSeal); - - let resolution_after_second_tx = criterion.should_seal( - &config, - 0, - 2, - &SealData { - gas_count: empty_block_gas + tx_gas + tx_gas, - ..SealData::default() - }, - &SealData { - gas_count: tx_gas, - ..SealData::default() - }, - ProtocolVersionId::latest(), - ); - assert_eq!(resolution_after_second_tx, SealResolution::ExcludeAndSeal); - - // Check criterion workflow - let tx_gas = BlockGasCount { - commit: reject_tx_bound - empty_block_gas.commit - 1, - prove: reject_tx_bound - empty_block_gas.prove - 1, - execute: reject_tx_bound - empty_block_gas.execute - 1, - }; - let close_bound = - (config.max_single_tx_gas as f64 * config.close_block_at_gas_percentage).round() as u32; - let block_gas = BlockGasCount { - commit: close_bound + 1, - prove: close_bound + 1, - execute: close_bound + 1, - }; - let resolution_after_first_tx = criterion.should_seal( - &config, - 0, - 1, - &SealData { - gas_count: block_gas, - ..SealData::default() - }, - &SealData { - gas_count: tx_gas, - ..SealData::default() - }, - ProtocolVersionId::latest(), - ); - assert_eq!(resolution_after_first_tx, SealResolution::IncludeAndSeal); - } -} diff --git a/core/node/state_keeper/src/seal_criteria/criteria/gas_for_batch_tip.rs b/core/node/state_keeper/src/seal_criteria/criteria/gas_for_batch_tip.rs index 69214406bea5..263123cdcff2 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/gas_for_batch_tip.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/gas_for_batch_tip.rs @@ -15,6 +15,7 @@ impl SealCriterion for GasForBatchTipCriterion { _config: &StateKeeperConfig, _block_open_timestamp_ms: u128, tx_count: usize, + _l1_tx_count: usize, _block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -60,6 +61,7 @@ mod tests { &config, Default::default(), 1, + 0, &seal_data, &seal_data, protocol_version, @@ -74,6 +76,7 @@ mod tests { &config, Default::default(), 1, + 0, &seal_data, &seal_data, protocol_version, @@ -87,6 +90,7 @@ mod tests { &config, Default::default(), 2, + 0, &seal_data, &seal_data, protocol_version, diff --git a/core/node/state_keeper/src/seal_criteria/criteria/geometry_seal_criteria.rs b/core/node/state_keeper/src/seal_criteria/criteria/geometry_seal_criteria.rs index 1f3e8d104ce5..657fa1f71800 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/geometry_seal_criteria.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/geometry_seal_criteria.rs @@ -20,6 +20,7 @@ impl SealCriterion for CircuitsCriterion { config: &StateKeeperConfig, _block_open_timestamp_ms: u128, _tx_count: usize, + _l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -94,6 +95,7 @@ mod tests { &config, Default::default(), 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() @@ -114,6 +116,7 @@ mod tests { &config, Default::default(), 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() @@ -134,6 +137,7 @@ mod tests { &config, Default::default(), 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() @@ -154,6 +158,7 @@ mod tests { &config, Default::default(), 0, + 0, &SealData::default(), &SealData { execution_metrics: tx_execution_metrics, diff --git a/core/node/state_keeper/src/seal_criteria/criteria/l1_l2_txs.rs b/core/node/state_keeper/src/seal_criteria/criteria/l1_l2_txs.rs new file mode 100644 index 000000000000..fa679a19bab6 --- /dev/null +++ b/core/node/state_keeper/src/seal_criteria/criteria/l1_l2_txs.rs @@ -0,0 +1,104 @@ +use zksync_types::{ + aggregated_operations::{L1_BATCH_EXECUTE_BASE_COST, L1_OPERATION_EXECUTE_COST}, + ProtocolVersionId, +}; + +use crate::seal_criteria::{SealCriterion, SealData, SealResolution, StateKeeperConfig}; + +#[derive(Debug)] +pub(crate) struct L1L2TxsCriterion; + +impl SealCriterion for L1L2TxsCriterion { + fn should_seal( + &self, + config: &StateKeeperConfig, + _block_open_timestamp_ms: u128, + _tx_count: usize, + l1_tx_count: usize, + _block_data: &SealData, + _tx_data: &SealData, + _protocol_version_id: ProtocolVersionId, + ) -> SealResolution { + // With current gas consumption it's possible to execute 600 L1->L2 txs with 7500000 L1 gas. + const L1_L2_TX_COUNT_LIMIT: usize = 600; + + let block_l1_gas_bound = + (config.max_single_tx_gas as f64 * config.close_block_at_gas_percentage).round() as u32; + let l1_gas = L1_BATCH_EXECUTE_BASE_COST + (l1_tx_count as u32) * L1_OPERATION_EXECUTE_COST; + + // We check not only gas against `block_l1_gas_bound` but also count against `L1_L2_TX_COUNT_LIMIT`. + // It's required in case `max_single_tx_gas` is set to some high value for gateway, + // then chain migrates to L1 and there is some batch with large number of L1->L2 txs that is not yet executed. + // This check guarantees that it will be possible to execute such batch with reasonable gas limit on L1. + if l1_gas >= block_l1_gas_bound || l1_tx_count >= L1_L2_TX_COUNT_LIMIT { + SealResolution::IncludeAndSeal + } else { + SealResolution::NoSeal + } + } + + fn prom_criterion_name(&self) -> &'static str { + "gas" + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_l1_l2_txs_seal_criterion() { + let max_single_tx_gas = 15_000_000; + let close_block_at_gas_percentage = 0.95; + + let gas_bound = (max_single_tx_gas as f64 * close_block_at_gas_percentage).round() as u32; + let l1_tx_count_bound = + (gas_bound - L1_BATCH_EXECUTE_BASE_COST - 1) / L1_OPERATION_EXECUTE_COST; + let l1_tx_count_bound = l1_tx_count_bound.min(599); + + // Create an empty config and only setup fields relevant for the test. + let config = StateKeeperConfig { + max_single_tx_gas, + close_block_at_gas_percentage, + ..Default::default() + }; + + let criterion = L1L2TxsCriterion; + + // Empty block should fit into gas criterion. + let empty_block_resolution = criterion.should_seal( + &config, + 0, + 0, + 0, + &SealData::default(), + &SealData::default(), + ProtocolVersionId::latest(), + ); + assert_eq!(empty_block_resolution, SealResolution::NoSeal); + + // `l1_tx_count_bound` should return `NoSeal`. + let block_resolution = criterion.should_seal( + &config, + 0, + 0, + l1_tx_count_bound as usize, + &SealData::default(), + &SealData::default(), + ProtocolVersionId::latest(), + ); + assert_eq!(block_resolution, SealResolution::NoSeal); + + // `l1_tx_count_bound + 1` should return `IncludeAndSeal`. + let block_resolution = criterion.should_seal( + &config, + 0, + 0, + l1_tx_count_bound as usize + 1, + &SealData::default(), + &SealData::default(), + ProtocolVersionId::latest(), + ); + assert_eq!(block_resolution, SealResolution::IncludeAndSeal); + } +} diff --git a/core/node/state_keeper/src/seal_criteria/criteria/l2_l1_logs.rs b/core/node/state_keeper/src/seal_criteria/criteria/l2_l1_logs.rs new file mode 100644 index 000000000000..e33b94cbda2a --- /dev/null +++ b/core/node/state_keeper/src/seal_criteria/criteria/l2_l1_logs.rs @@ -0,0 +1,120 @@ +use zksync_types::{l2_to_l1_log::l2_to_l1_logs_tree_size, ProtocolVersionId}; + +use crate::seal_criteria::{ + SealCriterion, SealData, SealResolution, StateKeeperConfig, UnexecutableReason, +}; + +#[derive(Debug)] +pub(crate) struct L2L1LogsCriterion; + +impl SealCriterion for L2L1LogsCriterion { + fn should_seal( + &self, + config: &StateKeeperConfig, + _block_open_timestamp_ms: u128, + _tx_count: usize, + _l1_tx_count: usize, + block_data: &SealData, + tx_data: &SealData, + protocol_version_id: ProtocolVersionId, + ) -> SealResolution { + let max_allowed_logs = l2_to_l1_logs_tree_size(protocol_version_id); + + let reject_bound = + (max_allowed_logs as f64 * config.reject_tx_at_geometry_percentage).round() as usize; + let include_and_seal_bound = + (max_allowed_logs as f64 * config.close_block_at_geometry_percentage).round() as usize; + + // Only user logs are included in the tree, so we consider only their number. + if tx_data.execution_metrics.user_l2_to_l1_logs >= reject_bound { + UnexecutableReason::TooMuchUserL2L1Logs.into() + } else if block_data.execution_metrics.user_l2_to_l1_logs > max_allowed_logs { + SealResolution::ExcludeAndSeal + } else if block_data.execution_metrics.user_l2_to_l1_logs >= include_and_seal_bound { + SealResolution::IncludeAndSeal + } else { + SealResolution::NoSeal + } + } + + fn prom_criterion_name(&self) -> &'static str { + "gas" + } +} + +#[cfg(test)] +mod tests { + use test_casing::test_casing; + use zksync_multivm::interface::VmExecutionMetrics; + + use super::*; + + fn query_criterion( + config: &StateKeeperConfig, + block_data_logs: usize, + tx_data_logs: usize, + protocol_version_id: ProtocolVersionId, + ) -> SealResolution { + L2L1LogsCriterion.should_seal( + config, + 0, + 0, + 0, + &SealData { + execution_metrics: VmExecutionMetrics { + user_l2_to_l1_logs: block_data_logs, + ..VmExecutionMetrics::default() + }, + ..SealData::default() + }, + &SealData { + execution_metrics: VmExecutionMetrics { + user_l2_to_l1_logs: tx_data_logs, + ..VmExecutionMetrics::default() + }, + ..SealData::default() + }, + protocol_version_id, + ) + } + + #[test_casing(2, [ProtocolVersionId::Version25, ProtocolVersionId::Version27])] + fn test_l2_l1_logs_seal_criterion(protocol_version: ProtocolVersionId) { + let max_allowed_logs = l2_to_l1_logs_tree_size(protocol_version); + let config = StateKeeperConfig { + close_block_at_geometry_percentage: 0.95, + reject_tx_at_geometry_percentage: 0.9, + ..Default::default() + }; + + let reject_bound = + (max_allowed_logs as f64 * config.reject_tx_at_geometry_percentage).round() as usize; + let include_and_seal_bound = + (max_allowed_logs as f64 * config.close_block_at_geometry_percentage).round() as usize; + + // not enough logs to seal + let resolution = query_criterion( + &config, + reject_bound - 1, + reject_bound - 1, + protocol_version, + ); + assert_eq!(resolution, SealResolution::NoSeal); + + // reject tx with huge number of logs + let resolution = query_criterion(&config, reject_bound, reject_bound, protocol_version); + assert_eq!(resolution, UnexecutableReason::TooMuchUserL2L1Logs.into()); + + // enough logs to include and seal + let resolution = query_criterion(&config, include_and_seal_bound, 1, protocol_version); + assert_eq!(resolution, SealResolution::IncludeAndSeal); + + // not enough logs to exclude and seal + let resolution = query_criterion(&config, max_allowed_logs, 1, protocol_version); + assert_eq!(resolution, SealResolution::IncludeAndSeal); + + // enough logs to exclude and seal + let resolution = query_criterion(&config, max_allowed_logs + 1, 1, protocol_version); + assert_eq!(resolution, SealResolution::ExcludeAndSeal); + } +} diff --git a/core/node/state_keeper/src/seal_criteria/criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/criteria/mod.rs index 6732a8cd2717..d9522a39fad7 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/mod.rs @@ -1,12 +1,14 @@ -mod gas; mod gas_for_batch_tip; mod geometry_seal_criteria; +mod l1_l2_txs; +mod l2_l1_logs; mod pubdata_bytes; mod slots; mod tx_encoding_size; pub(crate) use self::{ - gas::GasCriterion, gas_for_batch_tip::GasForBatchTipCriterion, - geometry_seal_criteria::CircuitsCriterion, pubdata_bytes::PubDataBytesCriterion, - slots::SlotsCriterion, tx_encoding_size::TxEncodingSizeCriterion, + gas_for_batch_tip::GasForBatchTipCriterion, geometry_seal_criteria::CircuitsCriterion, + l1_l2_txs::L1L2TxsCriterion, l2_l1_logs::L2L1LogsCriterion, + pubdata_bytes::PubDataBytesCriterion, slots::SlotsCriterion, + tx_encoding_size::TxEncodingSizeCriterion, }; diff --git a/core/node/state_keeper/src/seal_criteria/criteria/pubdata_bytes.rs b/core/node/state_keeper/src/seal_criteria/criteria/pubdata_bytes.rs index 09fcf2f0fc1b..5cddfffd6899 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/pubdata_bytes.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/pubdata_bytes.rs @@ -20,6 +20,7 @@ impl SealCriterion for PubDataBytesCriterion { config: &StateKeeperConfig, _block_open_timestamp_ms: u128, _tx_count: usize, + _l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -99,6 +100,7 @@ mod tests { &config, 0, 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() @@ -120,6 +122,7 @@ mod tests { &config, 0, 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() @@ -137,6 +140,7 @@ mod tests { &config, 0, 0, + 0, &SealData { execution_metrics: block_execution_metrics, ..SealData::default() diff --git a/core/node/state_keeper/src/seal_criteria/criteria/slots.rs b/core/node/state_keeper/src/seal_criteria/criteria/slots.rs index 81b3a0933801..ad07bf8f8a00 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/slots.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/slots.rs @@ -13,6 +13,7 @@ impl SealCriterion for SlotsCriterion { config: &StateKeeperConfig, _block_open_timestamp_ms: u128, tx_count: usize, + _l1_tx_count: usize, _block_data: &SealData, _tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -54,6 +55,7 @@ mod tests { &config, Default::default(), config.transaction_slots - 1, + 0, &SealData::default(), &SealData::default(), ProtocolVersionId::latest(), @@ -64,6 +66,7 @@ mod tests { &config, Default::default(), config.transaction_slots, + 0, &SealData::default(), &SealData::default(), ProtocolVersionId::latest(), diff --git a/core/node/state_keeper/src/seal_criteria/criteria/tx_encoding_size.rs b/core/node/state_keeper/src/seal_criteria/criteria/tx_encoding_size.rs index 409673d6cac8..54076dc8ccc0 100644 --- a/core/node/state_keeper/src/seal_criteria/criteria/tx_encoding_size.rs +++ b/core/node/state_keeper/src/seal_criteria/criteria/tx_encoding_size.rs @@ -14,6 +14,7 @@ impl SealCriterion for TxEncodingSizeCriterion { config: &StateKeeperConfig, _block_open_timestamp_ms: u128, _tx_count: usize, + _l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version_id: ProtocolVersionId, @@ -65,6 +66,7 @@ mod tests { &config, 0, 0, + 0, &SealData::default(), &SealData::default(), ProtocolVersionId::latest(), @@ -75,6 +77,7 @@ mod tests { &config, 0, 0, + 0, &SealData::default(), &SealData { cumulative_size: bootloader_tx_encoding_space as usize + 1, @@ -91,6 +94,7 @@ mod tests { &config, 0, 0, + 0, &SealData { cumulative_size: bootloader_tx_encoding_space as usize + 1, ..SealData::default() @@ -107,6 +111,7 @@ mod tests { &config, 0, 0, + 0, &SealData { cumulative_size: bootloader_tx_encoding_space as usize, ..SealData::default() diff --git a/core/node/state_keeper/src/seal_criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/mod.rs index 4c6f56a6f5b7..2ea039da57bc 100644 --- a/core/node/state_keeper/src/seal_criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/mod.rs @@ -17,16 +17,10 @@ use zksync_multivm::{ interface::{DeduplicatedWritesMetrics, Halt, TransactionExecutionMetrics, VmExecutionMetrics}, vm_latest::TransactionVmExt, }; -use zksync_types::{ - block::BlockGasCount, utils::display_timestamp, ProtocolVersionId, Transaction, -}; +use zksync_types::{utils::display_timestamp, ProtocolVersionId, Transaction}; pub use self::conditional_sealer::{ConditionalSealer, NoopSealer, SequencerSealer}; -use crate::{ - metrics::AGGREGATION_METRICS, - updates::UpdatesManager, - utils::{gas_count_from_tx_and_metrics, gas_count_from_writes, millis_since}, -}; +use crate::{metrics::AGGREGATION_METRICS, updates::UpdatesManager, utils::millis_since}; mod conditional_sealer; pub(super) mod criteria; @@ -68,6 +62,7 @@ pub enum UnexecutableReason { OutOfGasForBatchTip, BootloaderOutOfGas, NotEnoughGasProvided, + TooMuchUserL2L1Logs, } impl UnexecutableReason { @@ -82,6 +77,7 @@ impl UnexecutableReason { UnexecutableReason::OutOfGasForBatchTip => "OutOfGasForBatchTip", UnexecutableReason::BootloaderOutOfGas => "BootloaderOutOfGas", UnexecutableReason::NotEnoughGasProvided => "NotEnoughGasProvided", + UnexecutableReason::TooMuchUserL2L1Logs => "TooMuchUserL2L1Logs", } } } @@ -106,6 +102,7 @@ impl fmt::Display for UnexecutableReason { UnexecutableReason::OutOfGasForBatchTip => write!(f, "Out of gas for batch tip"), UnexecutableReason::BootloaderOutOfGas => write!(f, "Bootloader out of gas"), UnexecutableReason::NotEnoughGasProvided => write!(f, "Not enough gas provided"), + UnexecutableReason::TooMuchUserL2L1Logs => write!(f, "Too much user l2 l1 logs"), } } } @@ -159,7 +156,6 @@ impl SealResolution { #[derive(Debug, Default)] pub struct SealData { pub(super) execution_metrics: VmExecutionMetrics, - pub(super) gas_count: BlockGasCount, pub(super) cumulative_size: usize, pub(super) writes_metrics: DeduplicatedWritesMetrics, pub(super) gas_remaining: u32, @@ -171,15 +167,11 @@ impl SealData { pub fn for_transaction( transaction: &Transaction, tx_metrics: &TransactionExecutionMetrics, - protocol_version: ProtocolVersionId, ) -> Self { let execution_metrics = VmExecutionMetrics::from_tx_metrics(tx_metrics); let writes_metrics = DeduplicatedWritesMetrics::from_tx_metrics(tx_metrics); - let gas_count = gas_count_from_tx_and_metrics(transaction, &execution_metrics) - + gas_count_from_writes(&writes_metrics, protocol_version); Self { execution_metrics, - gas_count, cumulative_size: transaction.bootloader_encoding_size(), writes_metrics, gas_remaining: tx_metrics.gas_remaining, @@ -188,11 +180,13 @@ impl SealData { } pub(super) trait SealCriterion: fmt::Debug + Send + Sync + 'static { + #[allow(clippy::too_many_arguments)] fn should_seal( &self, config: &StateKeeperConfig, block_open_timestamp_ms: u128, tx_count: usize, + l1_tx_count: usize, block_data: &SealData, tx_data: &SealData, protocol_version: ProtocolVersionId, @@ -287,7 +281,6 @@ mod tests { tx, create_execution_result([]), vec![], - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], ); diff --git a/core/node/state_keeper/src/tests/mod.rs b/core/node/state_keeper/src/tests/mod.rs index d47f8f45df77..b73741998a03 100644 --- a/core/node/state_keeper/src/tests/mod.rs +++ b/core/node/state_keeper/src/tests/mod.rs @@ -17,8 +17,7 @@ use zksync_multivm::{ }; use zksync_node_test_utils::create_l2_transaction; use zksync_types::{ - aggregated_operations::AggregatedActionType, - block::{BlockGasCount, L2BlockExecutionData, L2BlockHasher}, + block::{L2BlockExecutionData, L2BlockHasher}, fee_model::{BatchFeeInput, PubdataIndependentBatchFeeModelInput}, u256_to_h256, AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersionId, StorageKey, StorageLog, StorageLogKind, StorageLogWithPreviousValue, @@ -28,20 +27,16 @@ use zksync_types::{ use crate::{ io::PendingBatchData, keeper::POLL_WAIT_DURATION, - seal_criteria::{ - criteria::{GasCriterion, SlotsCriterion}, - SequencerSealer, UnexecutableReason, - }, + seal_criteria::{criteria::SlotsCriterion, SequencerSealer, UnexecutableReason}, testonly::{ successful_exec, test_batch_executor::{ - random_tx, random_upgrade_tx, rejected_exec, successful_exec_with_log, - MockReadStorageFactory, TestBatchExecutorBuilder, TestIO, TestScenario, FEE_ACCOUNT, + random_tx, random_upgrade_tx, rejected_exec, MockReadStorageFactory, + TestBatchExecutorBuilder, TestIO, TestScenario, FEE_ACCOUNT, }, BASE_SYSTEM_CONTRACTS, }, updates::UpdatesManager, - utils::{gas_count_from_tx_and_metrics, l1_batch_base_cost}, ZkSyncStateKeeper, }; @@ -188,86 +183,6 @@ async fn sealed_by_number_of_txs() { .await; } -#[tokio::test] -async fn sealed_by_gas() { - let first_tx = random_tx(1); - let execution_result = successful_exec_with_log(); - let exec_metrics = execution_result - .tx_result - .get_execution_metrics(Some(&first_tx)); - assert!(exec_metrics.size() > 0); - let l1_gas_per_tx = gas_count_from_tx_and_metrics(&first_tx, &exec_metrics); - assert!(l1_gas_per_tx.commit > 0); - - let config = StateKeeperConfig { - max_single_tx_gas: 62_000 + l1_gas_per_tx.commit * 2, - reject_tx_at_gas_percentage: 1.0, - close_block_at_gas_percentage: 0.5, - ..StateKeeperConfig::default() - }; - let sealer = SequencerSealer::with_sealers(config, vec![Box::new(GasCriterion)]); - - TestScenario::new() - .seal_l2_block_when(|updates| { - updates.l2_block.executed_transactions.len() == 1 - }) - .next_tx("First tx", first_tx, execution_result.clone()) - .l2_block_sealed_with("L2 block with a single tx", move |updates| { - assert_eq!( - updates.l2_block.l1_gas_count, - l1_gas_per_tx, - "L1 gas used by a L2 block should consist of the gas used by its txs" - ); - }) - .next_tx("Second tx", random_tx(1), execution_result) - .l2_block_sealed("L2 block 2") - .batch_sealed_with("Batch sealed with both txs", move |updates| { - assert_eq!( - updates.l1_batch.l1_gas_count, - BlockGasCount { - commit: l1_batch_base_cost(AggregatedActionType::Commit) + l1_gas_per_tx.commit * 2, - prove: l1_batch_base_cost(AggregatedActionType::PublishProofOnchain), - execute: l1_batch_base_cost(AggregatedActionType::Execute), - }, - "L1 gas used by a batch should consist of gas used by its txs + basic block gas cost" - ); - }) - .run(sealer).await; -} - -#[tokio::test] -async fn sealed_by_gas_then_by_num_tx() { - let config = StateKeeperConfig { - max_single_tx_gas: 62_000, - reject_tx_at_gas_percentage: 1.0, - close_block_at_gas_percentage: 0.5, - transaction_slots: 3, - ..StateKeeperConfig::default() - }; - let sealer = SequencerSealer::with_sealers( - config, - vec![Box::new(GasCriterion), Box::new(SlotsCriterion)], - ); - - let execution_result = successful_exec_with_log(); - - // 1st tx is sealed by gas sealer; 2nd, 3rd, & 4th are sealed by slots sealer. - TestScenario::new() - .seal_l2_block_when(|updates| updates.l2_block.executed_transactions.len() == 1) - .next_tx("First tx", random_tx(1), execution_result) - .l2_block_sealed("L2 block 1") - .batch_sealed("Batch 1") - .next_tx("Second tx", random_tx(2), successful_exec()) - .l2_block_sealed("L2 block 2") - .next_tx("Third tx", random_tx(3), successful_exec()) - .l2_block_sealed("L2 block 3") - .next_tx("Fourth tx", random_tx(4), successful_exec()) - .l2_block_sealed("L2 block 4") - .batch_sealed("Batch 2") - .run(sealer) - .await; -} - #[tokio::test] async fn batch_sealed_before_l2_block_does() { let config = StateKeeperConfig { diff --git a/core/node/state_keeper/src/types.rs b/core/node/state_keeper/src/types.rs index db18e32e0963..4861916fc227 100644 --- a/core/node/state_keeper/src/types.rs +++ b/core/node/state_keeper/src/types.rs @@ -5,15 +5,9 @@ use std::{ use zksync_dal::{Connection, Core, CoreDal}; use zksync_mempool::{L2TxFilter, MempoolInfo, MempoolStore}; -use zksync_multivm::interface::{VmExecutionMetrics, VmExecutionResultAndLogs}; -use zksync_types::{ - block::BlockGasCount, Address, Nonce, PriorityOpId, Transaction, TransactionTimeRangeConstraint, -}; +use zksync_types::{Address, Nonce, PriorityOpId, Transaction, TransactionTimeRangeConstraint}; -use super::{ - metrics::StateKeeperGauges, - utils::{gas_count_from_metrics, gas_count_from_tx_and_metrics}, -}; +use super::metrics::StateKeeperGauges; #[derive(Debug, Clone)] pub struct MempoolGuard(Arc>); @@ -101,27 +95,3 @@ impl MempoolGuard { StateKeeperGauges::register(Arc::downgrade(&self.0)); } } - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct ExecutionMetricsForCriteria { - pub l1_gas: BlockGasCount, - pub execution_metrics: VmExecutionMetrics, -} - -impl ExecutionMetricsForCriteria { - pub fn new( - tx: Option<&Transaction>, - execution_result: &VmExecutionResultAndLogs, - ) -> ExecutionMetricsForCriteria { - let execution_metrics = execution_result.get_execution_metrics(tx); - let l1_gas = match tx { - Some(tx) => gas_count_from_tx_and_metrics(tx, &execution_metrics), - None => gas_count_from_metrics(&execution_metrics), - }; - - ExecutionMetricsForCriteria { - l1_gas, - execution_metrics, - } - } -} diff --git a/core/node/state_keeper/src/updates/l1_batch_updates.rs b/core/node/state_keeper/src/updates/l1_batch_updates.rs index aa2e22cac483..f7a93b4870b9 100644 --- a/core/node/state_keeper/src/updates/l1_batch_updates.rs +++ b/core/node/state_keeper/src/updates/l1_batch_updates.rs @@ -1,10 +1,9 @@ use zksync_multivm::interface::{FinishedL1Batch, TransactionExecutionResult, VmExecutionMetrics}; use zksync_types::{ - block::BlockGasCount, priority_op_onchain_data::PriorityOpOnchainData, - ExecuteTransactionCommon, L1BatchNumber, + priority_op_onchain_data::PriorityOpOnchainData, ExecuteTransactionCommon, L1BatchNumber, }; -use crate::{updates::l2_block_updates::L2BlockUpdates, utils::new_block_gas_count}; +use crate::updates::l2_block_updates::L2BlockUpdates; #[derive(Debug)] pub struct L1BatchUpdates { @@ -12,9 +11,8 @@ pub struct L1BatchUpdates { pub executed_transactions: Vec, pub priority_ops_onchain_data: Vec, pub block_execution_metrics: VmExecutionMetrics, - // how much L1 gas will it take to submit this block? - pub l1_gas_count: BlockGasCount, pub txs_encoding_size: usize, + pub l1_tx_count: usize, pub finished: Option, } @@ -25,8 +23,8 @@ impl L1BatchUpdates { executed_transactions: Default::default(), priority_ops_onchain_data: Default::default(), block_execution_metrics: Default::default(), - l1_gas_count: new_block_gas_count(), txs_encoding_size: 0, + l1_tx_count: 0, finished: None, } } @@ -41,9 +39,9 @@ impl L1BatchUpdates { self.executed_transactions .extend(l2_block_updates.executed_transactions); - self.l1_gas_count += l2_block_updates.l1_gas_count; self.block_execution_metrics += l2_block_updates.block_execution_metrics; self.txs_encoding_size += l2_block_updates.txs_encoding_size; + self.l1_tx_count += l2_block_updates.l1_tx_count; } } @@ -53,10 +51,7 @@ mod tests { use zksync_types::{L2BlockNumber, ProtocolVersionId, H256}; use super::*; - use crate::{ - tests::{create_execution_result, create_transaction}, - utils::new_block_gas_count, - }; + use crate::tests::{create_execution_result, create_transaction}; #[test] fn apply_l2_block_with_empty_tx() { @@ -73,7 +68,6 @@ mod tests { l2_block_accumulator.extend_from_executed_transaction( tx, create_execution_result([]), - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -83,12 +77,12 @@ mod tests { l1_batch_accumulator.extend_from_sealed_l2_block(l2_block_accumulator); assert_eq!(l1_batch_accumulator.executed_transactions.len(), 1); - assert_eq!(l1_batch_accumulator.l1_gas_count, new_block_gas_count()); assert_eq!(l1_batch_accumulator.priority_ops_onchain_data.len(), 0); assert_eq!( l1_batch_accumulator.block_execution_metrics.l2_to_l1_logs, 0 ); assert_eq!(l1_batch_accumulator.txs_encoding_size, expected_tx_size); + assert_eq!(l1_batch_accumulator.l1_tx_count, 0); } } diff --git a/core/node/state_keeper/src/updates/l2_block_updates.rs b/core/node/state_keeper/src/updates/l2_block_updates.rs index d258f8eeac0b..628f9e4a2910 100644 --- a/core/node/state_keeper/src/updates/l2_block_updates.rs +++ b/core/node/state_keeper/src/updates/l2_block_updates.rs @@ -8,7 +8,7 @@ use zksync_multivm::{ vm_latest::TransactionVmExt, }; use zksync_types::{ - block::{BlockGasCount, L2BlockHasher}, + block::L2BlockHasher, bytecode::BytecodeHash, l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, L2BlockNumber, ProtocolVersionId, StorageLogWithPreviousValue, Transaction, H256, @@ -24,11 +24,10 @@ pub struct L2BlockUpdates { pub user_l2_to_l1_logs: Vec, pub system_l2_to_l1_logs: Vec, pub new_factory_deps: HashMap>, - /// How much L1 gas will it take to submit this block? - pub l1_gas_count: BlockGasCount, pub block_execution_metrics: VmExecutionMetrics, pub txs_encoding_size: usize, pub payload_encoding_size: usize, + pub l1_tx_count: usize, pub timestamp: u64, pub number: L2BlockNumber, pub prev_block_hash: H256, @@ -51,10 +50,10 @@ impl L2BlockUpdates { user_l2_to_l1_logs: vec![], system_l2_to_l1_logs: vec![], new_factory_deps: HashMap::new(), - l1_gas_count: BlockGasCount::default(), block_execution_metrics: VmExecutionMetrics::default(), txs_encoding_size: 0, payload_encoding_size: 0, + l1_tx_count: 0, timestamp, number, prev_block_hash, @@ -66,7 +65,6 @@ impl L2BlockUpdates { pub(crate) fn extend_from_fictive_transaction( &mut self, result: VmExecutionResultAndLogs, - l1_gas_count: BlockGasCount, execution_metrics: VmExecutionMetrics, ) { self.events.extend(result.logs.events); @@ -76,7 +74,6 @@ impl L2BlockUpdates { self.system_l2_to_l1_logs .extend(result.logs.system_l2_to_l1_logs); - self.l1_gas_count += l1_gas_count; self.block_execution_metrics += execution_metrics; } @@ -85,7 +82,6 @@ impl L2BlockUpdates { &mut self, tx: Transaction, tx_execution_result: VmExecutionResultAndLogs, - tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, compressed_bytecodes: Vec, call_traces: Vec, @@ -143,7 +139,6 @@ impl L2BlockUpdates { }); self.new_factory_deps.extend(known_bytecodes); - self.l1_gas_count += tx_l1_gas_this_tx; self.block_execution_metrics += execution_metrics; self.txs_encoding_size += tx.bootloader_encoding_size(); self.payload_encoding_size += @@ -155,6 +150,9 @@ impl L2BlockUpdates { .extend(tx_execution_result.logs.system_l2_to_l1_logs); self.storage_logs .extend(tx_execution_result.logs.storage_logs); + if tx.is_l1() { + self.l1_tx_count += 1; + } self.executed_transactions.push(TransactionExecutionResult { hash: tx.hash(), @@ -212,7 +210,6 @@ mod tests { accumulator.extend_from_executed_transaction( tx, create_execution_result([]), - BlockGasCount::default(), VmExecutionMetrics::default(), vec![], vec![], @@ -223,10 +220,10 @@ mod tests { assert_eq!(accumulator.storage_logs.len(), 0); assert_eq!(accumulator.user_l2_to_l1_logs.len(), 0); assert_eq!(accumulator.system_l2_to_l1_logs.len(), 0); - assert_eq!(accumulator.l1_gas_count, Default::default()); assert_eq!(accumulator.new_factory_deps.len(), 0); assert_eq!(accumulator.block_execution_metrics.l2_to_l1_logs, 0); assert_eq!(accumulator.txs_encoding_size, bootloader_encoding_size); assert_eq!(accumulator.payload_encoding_size, payload_encoding_size); + assert_eq!(accumulator.l1_tx_count, 0); } } diff --git a/core/node/state_keeper/src/updates/mod.rs b/core/node/state_keeper/src/updates/mod.rs index 752963580e37..06ac4bcd5de0 100644 --- a/core/node/state_keeper/src/updates/mod.rs +++ b/core/node/state_keeper/src/updates/mod.rs @@ -7,8 +7,8 @@ use zksync_multivm::{ utils::{get_batch_base_fee, StorageWritesDeduplicator}, }; use zksync_types::{ - block::BlockGasCount, commitment::PubdataParams, fee_model::BatchFeeInput, Address, - L1BatchNumber, L2BlockNumber, ProtocolVersionId, Transaction, + commitment::PubdataParams, fee_model::BatchFeeInput, Address, L1BatchNumber, L2BlockNumber, + ProtocolVersionId, Transaction, }; pub(crate) use self::{l1_batch_updates::L1BatchUpdates, l2_block_updates::L2BlockUpdates}; @@ -16,7 +16,6 @@ use super::{ io::{IoCursor, L2BlockParams}, metrics::{BATCH_TIP_METRICS, UPDATES_MANAGER_METRICS}, }; -use crate::types::ExecutionMetricsForCriteria; pub mod l1_batch_updates; pub mod l2_block_updates; @@ -117,7 +116,6 @@ impl UpdatesManager { tx: Transaction, tx_execution_result: VmExecutionResultAndLogs, compressed_bytecodes: Vec, - tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, call_traces: Vec, ) { @@ -129,7 +127,6 @@ impl UpdatesManager { self.l2_block.extend_from_executed_transaction( tx, tx_execution_result, - tx_l1_gas_this_tx, execution_metrics, compressed_bytecodes, call_traces, @@ -145,7 +142,7 @@ impl UpdatesManager { ); let result = &finished_batch.block_tip_execution_result; - let batch_tip_metrics = ExecutionMetricsForCriteria::new(None, result); + let batch_tip_execution_metrics = result.get_execution_metrics(None); let before = self.storage_writes_deduplicator.metrics(); self.storage_writes_deduplicator @@ -153,11 +150,8 @@ impl UpdatesManager { let after = self.storage_writes_deduplicator.metrics(); BATCH_TIP_METRICS.observe_writes_metrics(&before, &after, self.protocol_version()); - self.l2_block.extend_from_fictive_transaction( - result.clone(), - batch_tip_metrics.l1_gas, - batch_tip_metrics.execution_metrics, - ); + self.l2_block + .extend_from_fictive_transaction(result.clone(), batch_tip_execution_metrics); self.l1_batch.finished = Some(finished_batch); latency.observe(); @@ -190,8 +184,8 @@ impl UpdatesManager { self.l1_batch.executed_transactions.len() + self.l2_block.executed_transactions.len() } - pub(crate) fn pending_l1_gas_count(&self) -> BlockGasCount { - self.l1_batch.l1_gas_count + self.l2_block.l1_gas_count + pub(crate) fn pending_l1_transactions_len(&self) -> usize { + self.l1_batch.l1_tx_count + self.l2_block.l1_tx_count } pub(crate) fn pending_execution_metrics(&self) -> VmExecutionMetrics { @@ -225,10 +219,7 @@ pub struct L2BlockSealCommand { #[cfg(test)] mod tests { use super::*; - use crate::{ - tests::{create_execution_result, create_transaction, create_updates_manager}, - utils::new_block_gas_count, - }; + use crate::tests::{create_execution_result, create_transaction, create_updates_manager}; #[test] fn apply_l2_block() { @@ -242,7 +233,6 @@ mod tests { tx, create_execution_result([]), vec![], - new_block_gas_count(), VmExecutionMetrics::default(), vec![], ); diff --git a/core/node/state_keeper/src/utils.rs b/core/node/state_keeper/src/utils.rs index af4616fe11dc..eca73b6e3800 100644 --- a/core/node/state_keeper/src/utils.rs +++ b/core/node/state_keeper/src/utils.rs @@ -1,94 +1,6 @@ use std::time::{SystemTime, UNIX_EPOCH}; use tokio::sync::watch; -use zksync_multivm::interface::{DeduplicatedWritesMetrics, VmExecutionMetrics}; -use zksync_types::{ - aggregated_operations::AggregatedActionType, block::BlockGasCount, ExecuteTransactionCommon, - ProtocolVersionId, Transaction, -}; - -// TODO(QIT-32): Remove constants(except `L1_OPERATION_EXECUTE_COST`) and logic that use them -const L1_BATCH_COMMIT_BASE_COST: u32 = 31_000; -const L1_BATCH_PROVE_BASE_COST: u32 = 7_000; -const L1_BATCH_EXECUTE_BASE_COST: u32 = 30_000; - -const EXECUTE_COMMIT_COST: u32 = 0; -const EXECUTE_EXECUTE_COST: u32 = 0; - -const L1_OPERATION_EXECUTE_COST: u32 = 12_500; - -const GAS_PER_BYTE: u32 = 18; - -pub(super) fn l1_batch_base_cost(op: AggregatedActionType) -> u32 { - match op { - AggregatedActionType::Commit => L1_BATCH_COMMIT_BASE_COST, - AggregatedActionType::PublishProofOnchain => L1_BATCH_PROVE_BASE_COST, - AggregatedActionType::Execute => L1_BATCH_EXECUTE_BASE_COST, - } -} - -fn base_tx_cost(tx: &Transaction, op: AggregatedActionType) -> u32 { - match op { - AggregatedActionType::Commit => EXECUTE_COMMIT_COST, - AggregatedActionType::PublishProofOnchain => 0, - AggregatedActionType::Execute => match tx.common_data { - ExecuteTransactionCommon::L1(_) => L1_OPERATION_EXECUTE_COST, - ExecuteTransactionCommon::L2(_) => EXECUTE_EXECUTE_COST, - ExecuteTransactionCommon::ProtocolUpgrade(_) => EXECUTE_EXECUTE_COST, - }, - } -} - -fn additional_pubdata_commit_cost(execution_metrics: &VmExecutionMetrics) -> u32 { - (execution_metrics.size() as u32) * GAS_PER_BYTE -} - -fn additional_writes_commit_cost( - writes_metrics: &DeduplicatedWritesMetrics, - protocol_version: ProtocolVersionId, -) -> u32 { - (writes_metrics.size(protocol_version) as u32) * GAS_PER_BYTE -} - -pub(super) fn new_block_gas_count() -> BlockGasCount { - BlockGasCount { - commit: l1_batch_base_cost(AggregatedActionType::Commit), - prove: l1_batch_base_cost(AggregatedActionType::PublishProofOnchain), - execute: l1_batch_base_cost(AggregatedActionType::Execute), - } -} - -pub(super) fn gas_count_from_tx_and_metrics( - tx: &Transaction, - execution_metrics: &VmExecutionMetrics, -) -> BlockGasCount { - let commit = base_tx_cost(tx, AggregatedActionType::Commit) - + additional_pubdata_commit_cost(execution_metrics); - BlockGasCount { - commit, - prove: base_tx_cost(tx, AggregatedActionType::PublishProofOnchain), - execute: base_tx_cost(tx, AggregatedActionType::Execute), - } -} - -pub(super) fn gas_count_from_metrics(execution_metrics: &VmExecutionMetrics) -> BlockGasCount { - BlockGasCount { - commit: additional_pubdata_commit_cost(execution_metrics), - prove: 0, - execute: 0, - } -} - -pub(super) fn gas_count_from_writes( - writes_metrics: &DeduplicatedWritesMetrics, - protocol_version: ProtocolVersionId, -) -> BlockGasCount { - BlockGasCount { - commit: additional_writes_commit_cost(writes_metrics, protocol_version), - prove: 0, - execute: 0, - } -} pub(super) fn is_canceled(stop_receiver: &watch::Receiver) -> bool { *stop_receiver.borrow() diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 23e8b3ee420c..62c264a376db 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -101,7 +101,6 @@ eth: aggregated_block_execute_deadline: 10 timestamp_criteria_max_allowed_lag: 30 max_eth_tx_data_size: 120000 - aggregated_proof_sizes: [ 1 ] max_aggregated_tx_gas: 15000000 max_acceptable_priority_fee_in_gwei: 100000000000 # typo: value is in wei (100 gwei) pubdata_sending_mode: BLOBS