From 5a60e5897d2656b9fc057a2271cb7477fc77dfc7 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 3 Oct 2024 11:54:36 +0100 Subject: [PATCH 01/68] Add timestamp asserter --- contracts | 2 +- core/bin/zksync_server/src/node_builder.rs | 1 + core/lib/config/src/configs/contracts.rs | 2 ++ core/lib/config/src/testonly.rs | 1 + core/lib/multivm/src/tracers/validator/mod.rs | 8 ++++++++ core/lib/protobuf_config/src/contracts.rs | 9 +++++++++ .../protobuf_config/src/proto/config/contracts.proto | 1 + core/lib/vm_interface/src/types/tracer.rs | 3 +++ core/node/api_server/src/execution_sandbox/execute.rs | 6 +++++- core/node/api_server/src/execution_sandbox/tests.rs | 2 ++ .../node/api_server/src/execution_sandbox/validate.rs | 3 +++ core/node/api_server/src/tx_sender/mod.rs | 4 ++++ core/node/api_server/src/web3/testonly.rs | 1 + .../contracts/custom-account/custom-account.sol | 2 ++ .../contracts/custom-account/custom-account.sol | 2 ++ zk_toolbox/crates/config/src/contracts.rs | 11 ++++++++++- .../src/forge_interface/deploy_l2_contracts/output.rs | 7 +++++++ .../src/commands/chain/deploy_l2_contracts.rs | 3 ++- 18 files changed, 64 insertions(+), 4 deletions(-) diff --git a/contracts b/contracts index bce4b2d0f34b..2ff97e2549ee 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit bce4b2d0f34bd87f1aaadd291772935afb1c3bd6 +Subproject commit 2ff97e2549ee9100b7860b40c68c12bcba0cab3c diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 4600b0f9e543..3a337b57fe5a 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -319,6 +319,7 @@ impl MainNodeBuilder { .fee_account .address(), self.genesis_config.l2_chain_id, + self.contracts_config.l1_erc20_bridge_proxy_addr, ), postgres_storage_caches_config, rpc_config.vm_concurrency_limit(), diff --git a/core/lib/config/src/configs/contracts.rs b/core/lib/config/src/configs/contracts.rs index b68720ebaefe..9a6e9fc6aacd 100644 --- a/core/lib/config/src/configs/contracts.rs +++ b/core/lib/config/src/configs/contracts.rs @@ -35,6 +35,7 @@ pub struct ContractsConfig { pub l1_weth_bridge_proxy_addr: Option
, pub l2_weth_bridge_addr: Option
, pub l2_testnet_paymaster_addr: Option
, + pub l2_timestamp_asserter_addr: Option
, pub l1_multicall3_addr: Address, pub ecosystem_contracts: Option, // Used by the RPC API and by the node builder in wiring the BaseTokenRatioProvider layer. @@ -57,6 +58,7 @@ impl ContractsConfig { l2_weth_bridge_addr: Some(Address::repeat_byte(0x0c)), l2_testnet_paymaster_addr: Some(Address::repeat_byte(0x11)), l1_multicall3_addr: Address::repeat_byte(0x12), + l2_timestamp_asserter_addr: Some(Address::repeat_byte(0x19)), governance_addr: Address::repeat_byte(0x13), base_token_addr: Some(Address::repeat_byte(0x14)), ecosystem_contracts: Some(EcosystemContracts::for_tests()), diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 19f34cf38f74..21f2804033c6 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -256,6 +256,7 @@ impl Distribution for EncodeDist { l1_weth_bridge_proxy_addr: self.sample_opt(|| rng.gen()), l2_weth_bridge_addr: self.sample_opt(|| rng.gen()), l2_testnet_paymaster_addr: self.sample_opt(|| rng.gen()), + l2_timestamp_asserter_addr: self.sample_opt(|| rng.gen()), l1_multicall3_addr: rng.gen(), ecosystem_contracts: self.sample(rng), base_token_addr: self.sample_opt(|| rng.gen()), diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index a1573f24c668..77964d64ea48 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -43,6 +43,7 @@ pub struct ValidationTracer { trusted_address_slots: HashSet<(Address, U256)>, computational_gas_used: u32, computational_gas_limit: u32, + timestamp_asserter_address: Option
, vm_version: VmVersion, pub result: Arc>, _marker: PhantomData H>, @@ -69,6 +70,7 @@ impl ValidationTracer { trusted_address_slots: params.trusted_address_slots, computational_gas_used: 0, computational_gas_limit: params.computational_gas_limit, + timestamp_asserter_address: params.timestamp_asserter_address, vm_version, result: result.clone(), _marker: Default::default(), @@ -142,6 +144,11 @@ impl ValidationTracer { return true; } + // Allow to read any storage slot from the timesttamp asserter contract + if self.timestamp_asserter_address == Some(msg_sender) { + return true; + } + false } @@ -189,6 +196,7 @@ impl ValidationTracer { trusted_addresses: self.trusted_addresses.clone(), trusted_address_slots: self.trusted_address_slots.clone(), computational_gas_limit: self.computational_gas_limit, + timestamp_asserter_address: self.timestamp_asserter_address, } } } diff --git a/core/lib/protobuf_config/src/contracts.rs b/core/lib/protobuf_config/src/contracts.rs index 84c404367503..369967ff58a7 100644 --- a/core/lib/protobuf_config/src/contracts.rs +++ b/core/lib/protobuf_config/src/contracts.rs @@ -92,6 +92,12 @@ impl ProtoRepr for proto::Contracts { .map(|x| parse_h160(x)) .transpose() .context("l2_testnet_paymaster_addr")?, + l2_timestamp_asserter_addr: l2 + .timestamp_asserter_addr + .as_ref() + .map(|x| parse_h160(x)) + .transpose() + .context("l2_timestamp_asserter_addr")?, l1_multicall3_addr: required(&l1.multicall3_addr) .and_then(|x| parse_h160(x)) .context("l1_multicall3_addr")?, @@ -142,6 +148,9 @@ impl ProtoRepr for proto::Contracts { }), l2: Some(proto::L2 { testnet_paymaster_addr: this.l2_testnet_paymaster_addr.map(|a| format!("{:?}", a)), + timestamp_asserter_addr: this + .l2_timestamp_asserter_addr + .map(|a| format!("{:?}", a)), }), bridges: Some(proto::Bridges { shared: Some(proto::Bridge { diff --git a/core/lib/protobuf_config/src/proto/config/contracts.proto b/core/lib/protobuf_config/src/proto/config/contracts.proto index f4488c7901a1..d686690bcdbd 100644 --- a/core/lib/protobuf_config/src/proto/config/contracts.proto +++ b/core/lib/protobuf_config/src/proto/config/contracts.proto @@ -21,6 +21,7 @@ message L1 { message L2 { optional string testnet_paymaster_addr = 1; // optional; H160 + optional string timestamp_asserter_addr = 2; // optional; H160 } message Bridge { diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index ba07772c7f23..951e78a12255 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -57,6 +57,9 @@ pub struct ValidationParams { pub trusted_address_slots: HashSet<(Address, U256)>, /// Number of computational gas that validation step is allowed to use. pub computational_gas_limit: u32, + /// Address of the timestamp asserter. This contract is allowed to touch block.timestamp regardless + /// of the calling context. + pub timestamp_asserter_address: Option
, } /// Rules that can be violated when validating a transaction. diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index d974f2e9aa1d..a9e6c148fe36 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -15,7 +15,7 @@ use zksync_multivm::interface::{ }; use zksync_state::{PostgresStorage, PostgresStorageCaches}; use zksync_types::{ - api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Transaction, + api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Address, Transaction, }; use zksync_vm_executor::oneshot::{MainOneshotExecutor, MockOneshotExecutor}; @@ -100,6 +100,7 @@ pub(crate) struct SandboxExecutor { engine: SandboxExecutorEngine, pub(super) options: SandboxExecutorOptions, storage_caches: Option, + pub(super) timestamp_asserter_address: Option
, } impl SandboxExecutor { @@ -107,6 +108,7 @@ impl SandboxExecutor { options: SandboxExecutorOptions, caches: PostgresStorageCaches, missed_storage_invocation_limit: usize, + timestamp_asserter_address: Option
, ) -> Self { let mut executor = MainOneshotExecutor::new(missed_storage_invocation_limit); executor @@ -115,6 +117,7 @@ impl SandboxExecutor { engine: SandboxExecutorEngine::Real(executor), options, storage_caches: Some(caches), + timestamp_asserter_address, } } @@ -123,6 +126,7 @@ impl SandboxExecutor { engine: SandboxExecutorEngine::Mock(executor), options: SandboxExecutorOptions::mock().await, storage_caches: None, + timestamp_asserter_address: None, } } diff --git a/core/node/api_server/src/execution_sandbox/tests.rs b/core/node/api_server/src/execution_sandbox/tests.rs index f98ddc2e7965..2c93dbe4a338 100644 --- a/core/node/api_server/src/execution_sandbox/tests.rs +++ b/core/node/api_server/src/execution_sandbox/tests.rs @@ -205,6 +205,7 @@ async fn test_instantiating_vm(connection: Connection<'static, Core>, block_args SandboxExecutorOptions::mock().await, PostgresStorageCaches::new(1, 1), usize::MAX, + None, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); @@ -265,6 +266,7 @@ async fn validating_transaction(set_balance: bool) { SandboxExecutorOptions::mock().await, PostgresStorageCaches::new(1, 1), usize::MAX, + None, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); diff --git a/core/node/api_server/src/execution_sandbox/validate.rs b/core/node/api_server/src/execution_sandbox/validate.rs index 9a3c88f8bf0c..7e2dbe855fcf 100644 --- a/core/node/api_server/src/execution_sandbox/validate.rs +++ b/core/node/api_server/src/execution_sandbox/validate.rs @@ -46,6 +46,7 @@ impl SandboxExecutor { &tx, self.options.eth_call.validation_computational_gas_limit(), whitelisted_tokens_for_aa, + self.timestamp_asserter_address, ) .await .context("failed getting validation params")?; @@ -80,6 +81,7 @@ pub(super) async fn get_validation_params( tx: &L2Tx, computational_gas_limit: u32, whitelisted_tokens_for_aa: &[Address], + timestamp_asserter_address: Option
, ) -> anyhow::Result { let method_latency = EXECUTION_METRICS.get_validation_params.start(); let user_address = tx.common_data.initiator_address; @@ -126,5 +128,6 @@ pub(super) async fn get_validation_params( trusted_addresses, trusted_address_slots, computational_gas_limit, + timestamp_asserter_address, }) } diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index e2285c167110..54ac29628dab 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -189,6 +189,7 @@ impl TxSenderBuilder { executor_options, storage_caches, missed_storage_invocation_limit, + self.config.timestamp_asserter_addr, ); TxSender(Arc::new(TxSenderInner { @@ -218,6 +219,7 @@ pub struct TxSenderConfig { pub validation_computational_gas_limit: u32, pub chain_id: L2ChainId, pub whitelisted_tokens_for_aa: Vec
, + pub timestamp_asserter_addr: Option
, } impl TxSenderConfig { @@ -226,6 +228,7 @@ impl TxSenderConfig { web3_json_config: &Web3JsonRpcConfig, fee_account_addr: Address, chain_id: L2ChainId, + timestamp_asserter_addr: Option
, ) -> Self { Self { fee_account_addr, @@ -237,6 +240,7 @@ impl TxSenderConfig { .validation_computational_gas_limit, chain_id, whitelisted_tokens_for_aa: web3_json_config.whitelisted_tokens_for_aa.clone(), + timestamp_asserter_addr, } } } diff --git a/core/node/api_server/src/web3/testonly.rs b/core/node/api_server/src/web3/testonly.rs index 93309fc09cf1..44a362ceb337 100644 --- a/core/node/api_server/src/web3/testonly.rs +++ b/core/node/api_server/src/web3/testonly.rs @@ -31,6 +31,7 @@ pub(crate) async fn create_test_tx_sender( &web3_config, wallets.state_keeper.unwrap().fee_account.address(), l2_chain_id, + None, ); let storage_caches = PostgresStorageCaches::new(1, 1); diff --git a/core/tests/ts-integration/contracts/custom-account/custom-account.sol b/core/tests/ts-integration/contracts/custom-account/custom-account.sol index fc90355ac64e..b1a75b700eeb 100644 --- a/core/tests/ts-integration/contracts/custom-account/custom-account.sol +++ b/core/tests/ts-integration/contracts/custom-account/custom-account.sol @@ -27,6 +27,8 @@ contract CustomAccount is IAccount { bytes4 constant EIP1271_SUCCESS_RETURN_VALUE = 0x1626ba7e; function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { + require(block.timestamp > 0, "Hello"); + magic = _validateTransaction(_suggestedSignedTxHash, _transaction); lastTxHash = _txHash; diff --git a/etc/contracts-test-data/contracts/custom-account/custom-account.sol b/etc/contracts-test-data/contracts/custom-account/custom-account.sol index 7601f5cd7b87..bb876bc6a2cd 100644 --- a/etc/contracts-test-data/contracts/custom-account/custom-account.sol +++ b/etc/contracts-test-data/contracts/custom-account/custom-account.sol @@ -24,6 +24,8 @@ contract CustomAccount is IAccount { bytes4 constant EIP1271_SUCCESS_RETURN_VALUE = 0x1626ba7e; function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { + require(block.timestamp > 0, "Hello"); + // By default we consider the transaction as successful magic = VALIDATION_SUCCESS_MAGIC; diff --git a/zk_toolbox/crates/config/src/contracts.rs b/zk_toolbox/crates/config/src/contracts.rs index 8296aa188527..93ed80a71b09 100644 --- a/zk_toolbox/crates/config/src/contracts.rs +++ b/zk_toolbox/crates/config/src/contracts.rs @@ -7,7 +7,7 @@ use crate::{ deploy_ecosystem::output::DeployL1Output, deploy_l2_contracts::output::{ ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, - Multicall3Output, + Multicall3Output, TimestampAsserterOutput, }, register_chain::output::RegisterChainOutput, }, @@ -108,6 +108,14 @@ impl ContractsConfig { self.l2.multicall3 = Some(multicall3_output.multicall3); Ok(()) } + + pub fn set_timestamp_asserter( + &mut self, + timestamp_asserter_output: &TimestampAsserterOutput, + ) -> anyhow::Result<()> { + self.l2.timestamp_asserter = Some(timestamp_asserter_output.timestamp_asserter); + Ok(()) + } } impl FileConfigWithDefaultName for ContractsConfig { @@ -159,4 +167,5 @@ pub struct L2Contracts { pub default_l2_upgrader: Address, pub consensus_registry: Option
, pub multicall3: Option
, + pub timestamp_asserter: Option
, } diff --git a/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs b/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs index ca5cac12c02d..70687f889f46 100644 --- a/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs +++ b/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs @@ -8,6 +8,8 @@ impl ZkToolboxConfig for DefaultL2UpgradeOutput {} impl ZkToolboxConfig for ConsensusRegistryOutput {} impl ZkToolboxConfig for Multicall3Output {} +impl ZkToolboxConfig for TimestampAsserterOutput {} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InitializeBridgeOutput { pub l2_shared_bridge_implementation: Address, @@ -29,3 +31,8 @@ pub struct ConsensusRegistryOutput { pub struct Multicall3Output { pub multicall3: Address, } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TimestampAsserterOutput { + pub timestamp_asserter: Address, +} diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs index 5bfc0a623488..b56b5053766a 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs @@ -13,7 +13,7 @@ use config::{ input::DeployL2ContractsInput, output::{ ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, - Multicall3Output, + Multicall3Output, TimestampAsserterOutput, }, }, script_params::DEPLOY_L2_CONTRACTS_SCRIPT_PARAMS, @@ -209,6 +209,7 @@ pub async fn deploy_l2_contracts( contracts_config.set_default_l2_upgrade(&DefaultL2UpgradeOutput::read(shell, out)?)?; contracts_config.set_consensus_registry(&ConsensusRegistryOutput::read(shell, out)?)?; contracts_config.set_multicall3(&Multicall3Output::read(shell, out)?)?; + contracts_config.set_timestamp_asserter(&TimestampAsserterOutput::read(shell, out)?)?; Ok(()) }, ) From 70ad274b3626278dac917d9c8702923f60e26a11 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 3 Oct 2024 18:26:53 +0100 Subject: [PATCH 02/68] Add timestamp asserter to tracer and tests --- core/bin/zksync_server/src/node_builder.rs | 2 +- .../custom-account/custom-account.sol | 12 +++++++-- core/tests/ts-integration/src/env.ts | 11 ++++++-- core/tests/ts-integration/src/types.ts | 1 + .../tests/custom-account.test.ts | 27 +++++++++++++++---- zk_toolbox/crates/config/src/contracts.rs | 6 ++--- .../src/commands/chain/deploy_l2_contracts.rs | 3 ++- 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 3a337b57fe5a..c7bf2ee0ea0d 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -319,7 +319,7 @@ impl MainNodeBuilder { .fee_account .address(), self.genesis_config.l2_chain_id, - self.contracts_config.l1_erc20_bridge_proxy_addr, + self.contracts_config.l2_timestamp_asserter_addr, ), postgres_storage_caches_config, rpc_config.vm_concurrency_limit(), diff --git a/core/tests/ts-integration/contracts/custom-account/custom-account.sol b/core/tests/ts-integration/contracts/custom-account/custom-account.sol index b1a75b700eeb..b9e59a9cea69 100644 --- a/core/tests/ts-integration/contracts/custom-account/custom-account.sol +++ b/core/tests/ts-integration/contracts/custom-account/custom-account.sol @@ -9,6 +9,10 @@ import './SystemContractsCaller.sol'; import './interfaces/IAccount.sol'; +interface ITimestampAsserter { + function assertTimestampInRange(uint256 start, uint256 end) external view; +} + contract CustomAccount is IAccount { event BootloaderBalance(uint256); @@ -18,16 +22,20 @@ contract CustomAccount is IAccount { uint256 public gasToSpent; bytes32 public lastTxHash; + address public timestampAsserterAddress; - constructor(bool _violateValidationRules) { + constructor(bool _violateValidationRules, address _timestampAsserterAddress) { violateValidationRules = _violateValidationRules; + timestampAsserterAddress = _timestampAsserterAddress; } // bytes4(keccak256("isValidSignature(bytes32,bytes)") bytes4 constant EIP1271_SUCCESS_RETURN_VALUE = 0x1626ba7e; function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { - require(block.timestamp > 0, "Hello"); + ITimestampAsserter timestampAsserter = ITimestampAsserter(timestampAsserterAddress); + // number of seconds up to 30/12/2050 + timestampAsserter.assertTimestampInRange(0, 2555971200); magic = _validateTransaction(_suggestedSignedTxHash, _transaction); lastTxHash = _txHash; diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 1de917c2362c..80ddbafb8999 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -165,6 +165,7 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise { ); const healthcheckPort = process.env.API_HEALTHCHECK_PORT ?? '3071'; + if (!process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR) { + throw new Error('CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR is not defined'); + } + const timestampAsserterAddress = process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER.toString(); return { maxLogsLimit, pathToHome, @@ -312,7 +318,8 @@ export async function loadTestEnvironmentFromEnv(): Promise { decimals: baseToken?.decimals || token.decimals, l1Address: baseToken?.address || token.address, l2Address: baseTokenAddressL2 - } + }, + timestampAsserterAddress }; } diff --git a/core/tests/ts-integration/src/types.ts b/core/tests/ts-integration/src/types.ts index c513480c1b41..7df8f6337605 100644 --- a/core/tests/ts-integration/src/types.ts +++ b/core/tests/ts-integration/src/types.ts @@ -94,6 +94,7 @@ export interface TestEnvironment { */ baseToken: Token; healthcheckPort: string; + timestampAsserterAddress: string; } /** diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 46ddba95323a..6edeb578e94c 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -25,11 +25,13 @@ describe('Tests for the custom account behavior', () => { let customAccount: zksync.Contract; let erc20Address: string; let erc20: zksync.Contract; + let timestampAsserterAddress: string; beforeAll(() => { testMaster = TestMaster.getInstance(__filename); alice = testMaster.mainAccount(); erc20Address = testMaster.environment().erc20Token.l2Address; + timestampAsserterAddress = testMaster.environment().timestampAsserterAddress; erc20 = new zksync.Contract( erc20Address, zksync.utils.IERC20, @@ -40,7 +42,12 @@ describe('Tests for the custom account behavior', () => { test('Should deploy custom account', async () => { const violateRules = false; - customAccount = await deployContract(alice, contracts.customAccount, [violateRules], 'createAccount'); + customAccount = await deployContract( + alice, + contracts.customAccount, + [violateRules, timestampAsserterAddress], + 'createAccount' + ); // Now we need to check that it was correctly marked as an account: const contractAccountInfo = await alice.provider.getContractAccountInfo(await customAccount.getAddress()); @@ -112,7 +119,12 @@ describe('Tests for the custom account behavior', () => { test('Should not allow violating validation rules', async () => { // We configure account to violate storage access rules during tx validation. const violateRules = true; - const badCustomAccount = await deployContract(alice, contracts.customAccount, [violateRules], 'createAccount'); + const badCustomAccount = await deployContract( + alice, + contracts.customAccount, + [violateRules, timestampAsserterAddress], + 'createAccount' + ); const badCustomAccountAddress = await badCustomAccount.getAddress(); // Fund the account. @@ -145,7 +157,12 @@ describe('Tests for the custom account behavior', () => { // Note that we supply "create" instead of "createAccount" here -- the code is the same, but it'll // be treated as a common contract. const violateRules = false; - const nonAccount = await deployContract(alice, contracts.customAccount, [violateRules], 'create'); + const nonAccount = await deployContract( + alice, + contracts.customAccount, + [violateRules, timestampAsserterAddress], + 'create' + ); const nonAccountAddress = await nonAccount.getAddress(); // Fund the account. @@ -203,7 +220,7 @@ describe('Tests for the custom account behavior', () => { const badCustomAccount = await deployContract( alice, contracts.customAccount, - [violateStorageRules], + [violateStorageRules, timestampAsserterAddress], 'createAccount' ); const badCustomAccountAddress = await badCustomAccount.getAddress(); @@ -244,7 +261,7 @@ describe('Tests for the custom account behavior', () => { const badCustomAccount = await deployContract( alice, contracts.customAccount, - [violateStorageRules], + [violateStorageRules, timestampAsserterAddress], 'createAccount' ); const badCustomAccountAddress = await badCustomAccount.getAddress(); diff --git a/zk_toolbox/crates/config/src/contracts.rs b/zk_toolbox/crates/config/src/contracts.rs index 93ed80a71b09..fee30164ae2b 100644 --- a/zk_toolbox/crates/config/src/contracts.rs +++ b/zk_toolbox/crates/config/src/contracts.rs @@ -109,11 +109,11 @@ impl ContractsConfig { Ok(()) } - pub fn set_timestamp_asserter( + pub fn set_timestamp_asserter_addr( &mut self, timestamp_asserter_output: &TimestampAsserterOutput, ) -> anyhow::Result<()> { - self.l2.timestamp_asserter = Some(timestamp_asserter_output.timestamp_asserter); + self.l2.timestamp_asserter_addr = Some(timestamp_asserter_output.timestamp_asserter); Ok(()) } } @@ -167,5 +167,5 @@ pub struct L2Contracts { pub default_l2_upgrader: Address, pub consensus_registry: Option
, pub multicall3: Option
, - pub timestamp_asserter: Option
, + pub timestamp_asserter_addr: Option
, } diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs index b56b5053766a..cd130103f26e 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs @@ -209,7 +209,8 @@ pub async fn deploy_l2_contracts( contracts_config.set_default_l2_upgrade(&DefaultL2UpgradeOutput::read(shell, out)?)?; contracts_config.set_consensus_registry(&ConsensusRegistryOutput::read(shell, out)?)?; contracts_config.set_multicall3(&Multicall3Output::read(shell, out)?)?; - contracts_config.set_timestamp_asserter(&TimestampAsserterOutput::read(shell, out)?)?; + contracts_config + .set_timestamp_asserter_addr(&TimestampAsserterOutput::read(shell, out)?)?; Ok(()) }, ) From 5223913b7f82ee7f2d774968a631983a73a8d74a Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 4 Oct 2024 16:54:34 +0100 Subject: [PATCH 03/68] Capture validation traces as transaction gets executed --- core/lib/multivm/src/tracers/validator/mod.rs | 13 +++++-- .../src/tracers/validator/vm_latest/mod.rs | 36 ++++++++++++++++++- core/lib/vm_executor/src/oneshot/mock.rs | 8 +++-- core/lib/vm_executor/src/oneshot/mod.rs | 8 ++--- core/lib/vm_interface/src/executor.rs | 4 +-- core/lib/vm_interface/src/types/tracer.rs | 10 ++++++ .../src/execution_sandbox/execute.rs | 4 +-- .../src/execution_sandbox/validate.rs | 4 +-- core/tests/ts-integration/src/env.ts | 2 +- 9 files changed, 72 insertions(+), 17 deletions(-) diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index 77964d64ea48..82eb821b04ae 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, marker::PhantomData, sync::Arc}; +use std::{cell::RefCell, collections::HashSet, marker::PhantomData, sync::Arc}; use once_cell::sync::OnceCell; use zksync_system_constants::{ @@ -9,6 +9,7 @@ use zksync_types::{ vm::VmVersion, web3::keccak256, AccountTreeId, Address, StorageKey, H256, U256, }; use zksync_utils::{be_bytes_to_safe_address, u256_to_account_address, u256_to_h256}; +use zksync_vm_interface::tracer::ValidationTraces; use self::types::{NewTrustedValidationItems, ValidationTracerMode}; use crate::{ @@ -46,6 +47,7 @@ pub struct ValidationTracer { timestamp_asserter_address: Option
, vm_version: VmVersion, pub result: Arc>, + pub traces: Arc>, _marker: PhantomData H>, } @@ -55,8 +57,13 @@ impl ValidationTracer { pub fn new( params: ValidationParams, vm_version: VmVersion, - ) -> (Self, Arc>) { + ) -> ( + Self, + Arc>, + Arc>, + ) { let result = Arc::new(OnceCell::new()); + let traces = Arc::new(RefCell::new(ValidationTraces::default())); ( Self { validation_mode: ValidationTracerMode::NoValidation, @@ -73,9 +80,11 @@ impl ValidationTracer { timestamp_asserter_address: params.timestamp_asserter_address, vm_version, result: result.clone(), + traces: traces.clone(), _marker: Default::default(), }, result, + traces, ) } diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index c206bd6fb2ad..eee919a966af 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -1,9 +1,11 @@ +use std::cmp; + use zk_evm_1_5_0::{ tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{ContextOpcode, FarCallABI, LogOpcode, Opcode}, }; use zksync_system_constants::KECCAK256_PRECOMPILE_ADDRESS; -use zksync_types::{get_code_key, AccountTreeId, StorageKey, H256}; +use zksync_types::{get_code_key, AccountTreeId, StorageKey, H256, U256}; use zksync_utils::{h256_to_account_address, u256_to_account_address, u256_to_h256}; use crate::{ @@ -81,6 +83,38 @@ impl ValidationTracer { called_address, )); } + // If this is a call to the timestamp asserter, extract the function arguments and store them in ValidationTraces. + // These arguments are used by the mempool for transaction filtering. The call data length should be 68 bytes: + // a 4-byte function selector followed by two U256 values. + // TODO: if any more functions will be added to the TimestampAsserter contract in the future, verify the function selector too + if Some(called_address) == self.timestamp_asserter_address + && far_call_abi.memory_quasi_fat_pointer.length == 68 + { + let calldata_page = get_calldata_page_via_abi( + &far_call_abi, + state.vm_local_state.callstack.current.base_memory_page, + ); + let calldata = memory.read_unaligned_bytes( + calldata_page as usize, + far_call_abi.memory_quasi_fat_pointer.start as usize, + 68, + ); + + let start = U256::from_big_endian( + &calldata[calldata.len() - 64..calldata.len() - 32], + ); + let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); + + let mut traces_mut = self.traces.borrow_mut(); + traces_mut.range_start = match traces_mut.range_start { + Some(current_value) => Some(cmp::max(current_value, start)), + None => Some(start), + }; + traces_mut.range_end = match traces_mut.range_end { + Some(current_value) => Some(cmp::min(current_value, end)), + None => Some(end), + }; + } } } Opcode::Context(context) => { diff --git a/core/lib/vm_executor/src/oneshot/mock.rs b/core/lib/vm_executor/src/oneshot/mock.rs index 8f3a12603c1a..534956c3ecbe 100644 --- a/core/lib/vm_executor/src/oneshot/mock.rs +++ b/core/lib/vm_executor/src/oneshot/mock.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use zksync_multivm::interface::{ executor::{OneshotExecutor, TransactionValidator}, storage::ReadStorage, - tracer::{ValidationError, ValidationParams}, + tracer::{ValidationError, ValidationParams, ValidationTraces}, ExecutionResult, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, TxExecutionArgs, TxExecutionMode, VmExecutionResultAndLogs, }; @@ -122,14 +122,16 @@ where env: OneshotEnv, tx: L2Tx, _validation_params: ValidationParams, - ) -> anyhow::Result> { + ) -> anyhow::Result> { Ok( match self .mock_inspect(env, TxExecutionArgs::for_validation(tx)) .result { ExecutionResult::Halt { reason } => Err(ValidationError::FailedTx(reason)), - ExecutionResult::Success { .. } | ExecutionResult::Revert { .. } => Ok(()), + ExecutionResult::Success { .. } | ExecutionResult::Revert { .. } => { + Ok(ValidationTraces::default()) + } }, ) } diff --git a/core/lib/vm_executor/src/oneshot/mod.rs b/core/lib/vm_executor/src/oneshot/mod.rs index cb75f396b5d5..61f1ce37a844 100644 --- a/core/lib/vm_executor/src/oneshot/mod.rs +++ b/core/lib/vm_executor/src/oneshot/mod.rs @@ -18,7 +18,7 @@ use zksync_multivm::{ interface::{ executor::{OneshotExecutor, TransactionValidator}, storage::{ReadStorage, StoragePtr, StorageView, WriteStorage}, - tracer::{ValidationError, ValidationParams}, + tracer::{ValidationError, ValidationParams, ValidationTraces}, ExecutionResult, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, StoredL2BlockEnv, TxExecutionArgs, TxExecutionMode, VmExecutionMode, VmInterface, }, @@ -141,7 +141,7 @@ where env: OneshotEnv, tx: L2Tx, validation_params: ValidationParams, - ) -> anyhow::Result> { + ) -> anyhow::Result> { anyhow::ensure!( env.system.execution_mode == TxExecutionMode::VerifyExecute, "Unexpected execution mode for tx validation: {:?} (expected `VerifyExecute`)", @@ -150,7 +150,7 @@ where let execution_latency_histogram = self.execution_latency_histogram; tokio::task::spawn_blocking(move || { - let (validation_tracer, mut validation_result) = + let (validation_tracer, mut validation_result, validation_traces) = ValidationTracer::::new( validation_params, env.system.version.into(), @@ -174,7 +174,7 @@ where match (exec_result.result, validation_result) { (_, Err(violated_rule)) => Err(ValidationError::ViolatedRule(violated_rule)), (ExecutionResult::Halt { reason }, _) => Err(ValidationError::FailedTx(reason)), - _ => Ok(()), + _ => Ok(validation_traces.borrow().clone()), } }) .await diff --git a/core/lib/vm_interface/src/executor.rs b/core/lib/vm_interface/src/executor.rs index 119f975fecd5..11a542ca4fcf 100644 --- a/core/lib/vm_interface/src/executor.rs +++ b/core/lib/vm_interface/src/executor.rs @@ -7,7 +7,7 @@ use zksync_types::{l2::L2Tx, Transaction}; use crate::{ storage::{ReadStorage, StorageView}, - tracer::{ValidationError, ValidationParams}, + tracer::{ValidationError, ValidationParams, ValidationTraces}, BatchTransactionExecutionResult, FinishedL1Batch, L1BatchEnv, L2BlockEnv, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, SystemEnv, TxExecutionArgs, }; @@ -68,5 +68,5 @@ pub trait TransactionValidator: OneshotExecutor { env: OneshotEnv, tx: L2Tx, validation_params: ValidationParams, - ) -> anyhow::Result>; + ) -> anyhow::Result>; } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index 951e78a12255..ebeab53c3a53 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -107,6 +107,16 @@ pub enum ValidationError { ViolatedRule(ViolatedValidationRule), } +/// Traces the validation of a transaction, providing visibility into the aspects the transaction interacts with. +/// For instance, the `range_start` and `range_end` fields represent the range within which the transaction might make +/// assertions on `block.timestamp`. This information is crucial for the caller, as expired transactions should +/// be excluded from the mempool. +#[derive(Debug, Clone, Default)] +pub struct ValidationTraces { + pub range_start: Option, + pub range_end: Option, +} + impl fmt::Display for ValidationError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index a9e6c148fe36..a18d0378def4 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -9,7 +9,7 @@ use zksync_dal::{Connection, Core}; use zksync_multivm::interface::{ executor::{OneshotExecutor, TransactionValidator}, storage::ReadStorage, - tracer::{ValidationError, ValidationParams}, + tracer::{ValidationError, ValidationParams, ValidationTraces}, Call, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, TransactionExecutionMetrics, TxExecutionArgs, VmExecutionResultAndLogs, }; @@ -290,7 +290,7 @@ where env: OneshotEnv, tx: L2Tx, validation_params: ValidationParams, - ) -> anyhow::Result> { + ) -> anyhow::Result> { match &self.engine { SandboxExecutorEngine::Real(executor) => { executor diff --git a/core/node/api_server/src/execution_sandbox/validate.rs b/core/node/api_server/src/execution_sandbox/validate.rs index 7e2dbe855fcf..ec77cc01cc7f 100644 --- a/core/node/api_server/src/execution_sandbox/validate.rs +++ b/core/node/api_server/src/execution_sandbox/validate.rs @@ -5,7 +5,7 @@ use tracing::Instrument; use zksync_dal::{Connection, Core, CoreDal}; use zksync_multivm::interface::{ executor::TransactionValidator, - tracer::{ValidationError as RawValidationError, ValidationParams}, + tracer::{ValidationError as RawValidationError, ValidationParams, ValidationTraces}, }; use zksync_types::{ api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Address, @@ -39,7 +39,7 @@ impl SandboxExecutor { block_args: BlockArgs, fee_input: BatchFeeInput, whitelisted_tokens_for_aa: &[Address], - ) -> Result<(), ValidationError> { + ) -> Result { let total_latency = SANDBOX_METRICS.sandbox[&SandboxStage::ValidateInSandbox].start(); let validation_params = get_validation_params( &mut connection, diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 80ddbafb8999..147bcda56a58 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -287,7 +287,7 @@ export async function loadTestEnvironmentFromEnv(): Promise { if (!process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR) { throw new Error('CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR is not defined'); } - const timestampAsserterAddress = process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER.toString(); + const timestampAsserterAddress = process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR.toString(); return { maxLogsLimit, pathToHome, From d167279ce810716ccf889e511c7fea7fd92c6109 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 10:56:59 +0100 Subject: [PATCH 04/68] Add block.timestamp columns --- contracts | 2 +- ...b0dd75acbe4248159d2fb62d9e9878c158016.json | 18 ++++++++ ...50e42abbaf365a1b041d0e7a809796ef0fe63.json | 22 --------- ...95254f94dddb4ed84a675c2655421758b049.json} | 4 +- ...e2d457914c737660b37e9f66b576bbc9a7904.json | 12 +++++ ...a2d505a1aabf52ff4136d2ed1b39c70dd1632.json | 12 +++++ ...f1a855e76b37b6ed36ae612b551f9a6a55633.json | 18 -------- ...b9086ba42bac53629793a42d67b353c30210.json} | 4 +- ...2c5eeab06ff664141fa542229e7c9a46d4410.json | 34 -------------- ...0800383e6b73a8b48dc3e589a29a4367cbb5a.json | 15 ------ ...1e4657024c66a42e1bbc261c92c9e1c79930.json} | 4 +- ...b3c0210383d8698f6f84f694fece9fd59f3d5.json | 16 ------- ...d656e2a26752fa71ae936ff2eb821b0734b61.json | 14 ++++++ ...36d50db45560befec6418020b01c55d94a98.json} | 4 +- ...8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json | 42 +++++++++++++++++ ...3bb67bd12f2b635af783897f9d2a4f4ead2e.json} | 4 +- ...07554ce738a2d7005472e7e76a64a8fbd57ad.json | 14 ------ ...1edf3965f7ce67341d957ec680a18a0c39ea.json} | 4 +- ...0fd5e1330393d8b04c7cf03b8c7ab2edad5d1.json | 32 ------------- ...b671fa559dfdb29b315b17ae2f86533d247e9.json | 16 +++++++ ...2826095e9290f0c1157094bd0c44e06012e42.json | 12 +++++ ...0ff145ac2f388a246b9c7b32193e2d4208dd.json} | 4 +- ...7d8bbdbee28d4ac2a2c0a331298c5e39b71d.json} | 4 +- ...d23f83a260adf56000748c4b19752e2948ab5.json | 34 ++++++++++++++ ...ec87cf78f40429222b3163f3c5235c87e007f.json | 31 +++++++++++++ ...0c8fdca5c5731d490c1ac3ed56266b1d5a8a5.json | 32 +++++++++++++ ...77a428820fdcea9969aff3b29ca16727357b.json} | 16 ++++++- ...d0a586ce73d09ee28887cb1ad1c0392250629.json | 34 ++++++++++++++ ...e0d51f86d30d5ad92496e4aa087a3c4aae09f.json | 34 -------------- ...5d3a0eed793f7b64ad3ed035f20e896371721.json | 31 ------------- ...bd2225e57ae8d42042ac107b35a36c522f0d8.json | 34 ++++++++++++++ ...cab02b0656d863dbfce4b5dad7bc72e52b05d.json | 34 -------------- ...8997f003e26768c5de663160d89af54a1ee7.json} | 4 +- ...1885d320c146cd8fad77c107ef12fa38e6c98.json | 40 ---------------- ...eb0539849f7fd590712103db7d45d119caca2.json | 15 ++++++ ...2687cfe890fe89c748f836bad6eb0cc0fcf5.json} | 4 +- ...8e7265828e3ae78e391ef235b700f0adfe5e4.json | 22 +++++++++ ...7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json | 12 +++++ ...b50ebc862a133734382bad8fdfa3a93d8b743.json | 29 ------------ ...2745b90c68ebec5706b106ef69cb61333466e.json | 29 ++++++++++++ ...3940_add_block_timestamp_asserter.down.sql | 2 + ...073940_add_block_timestamp_asserter.up.sql | 2 + core/lib/dal/src/blocks_web3_dal.rs | 8 +++- .../lib/dal/src/models/storage_transaction.rs | 3 ++ core/lib/dal/src/pruning_dal/tests.rs | 8 +++- core/lib/dal/src/sync_dal.rs | 8 +++- core/lib/dal/src/tests/mod.rs | 46 +++++++++++++++---- core/lib/dal/src/transactions_dal.rs | 32 ++++++++++--- core/lib/dal/src/transactions_web3_dal.rs | 20 ++++++-- .../src/tx_sender/master_pool_sink.rs | 5 +- core/node/api_server/src/tx_sender/mod.rs | 2 +- core/node/api_server/src/tx_sender/proxy.rs | 39 +++++++++++++--- core/node/api_server/src/tx_sender/tx_sink.rs | 3 +- core/node/api_server/src/web3/tests/mod.rs | 22 +++++++-- .../io/seal_logic/l2_block_seal_subtasks.rs | 4 +- core/node/state_keeper/src/io/tests/mod.rs | 10 +++- core/node/state_keeper/src/mempool_actor.rs | 20 ++++++-- core/node/vm_runner/src/tests/mod.rs | 10 +++- 58 files changed, 597 insertions(+), 393 deletions(-) create mode 100644 core/lib/dal/.sqlx/query-048f255042f0a75c04bc19369c4b0dd75acbe4248159d2fb62d9e9878c158016.json delete mode 100644 core/lib/dal/.sqlx/query-05c2a77d9f65d435e2df63a300850e42abbaf365a1b041d0e7a809796ef0fe63.json rename core/lib/dal/.sqlx/{query-2b1aa207a058f66265acf2c21b8ed5d8007789c0fc1eab948f6d7339dfb69147.json => query-08740b96c883fce75b6238bb6bdc95254f94dddb4ed84a675c2655421758b049.json} (80%) delete mode 100644 core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json rename core/lib/dal/.sqlx/{query-69c885498b186f3b7cbb215112ec86783d7da0ec1d008680872f3619cf217923.json => query-28c5a9f99af4d2857346e0df73c9b9086ba42bac53629793a42d67b353c30210.json} (60%) delete mode 100644 core/lib/dal/.sqlx/query-33a78184559d0c0d13469fa799e2c5eeab06ff664141fa542229e7c9a46d4410.json delete mode 100644 core/lib/dal/.sqlx/query-3518a3e93da8115b54426d72aea0800383e6b73a8b48dc3e589a29a4367cbb5a.json rename core/lib/dal/.sqlx/{query-469db79fcf8d692507317080e0d843620210aff3a9a7aa8a249db50c1c56d927.json => query-37b653ba8a544224ef6fb88e073d1e4657024c66a42e1bbc261c92c9e1c79930.json} (60%) delete mode 100644 core/lib/dal/.sqlx/query-3ddb13ffbafae2374527886e592b3c0210383d8698f6f84f694fece9fd59f3d5.json create mode 100644 core/lib/dal/.sqlx/query-403b0b1c93f973aedb41aad7700d656e2a26752fa71ae936ff2eb821b0734b61.json rename core/lib/dal/.sqlx/{query-546c729829083b7eba94fea742c162d717ffcf46fdf5d2ce5d32555353b6da6b.json => query-41b2d575151bff136037d6f1d75f36d50db45560befec6418020b01c55d94a98.json} (52%) create mode 100644 core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json rename core/lib/dal/.sqlx/{query-03e00f422f991f8f12aad0083e1c42cfea253a182ca5df143a183cd522ecac33.json => query-499571f0484f4a54541450f935853bb67bd12f2b635af783897f9d2a4f4ead2e.json} (81%) delete mode 100644 core/lib/dal/.sqlx/query-5137159db7d3ff456e368e6246b07554ce738a2d7005472e7e76a64a8fbd57ad.json rename core/lib/dal/.sqlx/{query-5d1f588b2b652105b4452be1cc6c7573fe040d47d17d9bd4e2a2b6d3131a4f9c.json => query-6083e429948c139e36cfce2c5ed41edf3965f7ce67341d957ec680a18a0c39ea.json} (57%) delete mode 100644 core/lib/dal/.sqlx/query-66b3f476cf4487239190175d2940fd5e1330393d8b04c7cf03b8c7ab2edad5d1.json create mode 100644 core/lib/dal/.sqlx/query-7204d08f6fb83c83c09eb2942ecb671fa559dfdb29b315b17ae2f86533d247e9.json rename core/lib/dal/.sqlx/{query-dac29d7eb16782713acb7aa68aaa8b12b67678e983dc2570be28fe9b1e016c28.json => query-7f3ca3f1d0b3414575e71af98b810ff145ac2f388a246b9c7b32193e2d4208dd.json} (62%) rename core/lib/dal/.sqlx/{query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json => query-96adbd0c9a5786a6cca74324353c7d8bbdbee28d4ac2a2c0a331298c5e39b71d.json} (66%) create mode 100644 core/lib/dal/.sqlx/query-9badf9f287fd5f8a11cc855b230d23f83a260adf56000748c4b19752e2948ab5.json create mode 100644 core/lib/dal/.sqlx/query-9f7b35311f0afff1be7dc489348ec87cf78f40429222b3163f3c5235c87e007f.json create mode 100644 core/lib/dal/.sqlx/query-a329c468b25d6d5533766b8ad3d0c8fdca5c5731d490c1ac3ed56266b1d5a8a5.json rename core/lib/dal/.sqlx/{query-6621de90a024cc85946f17948e5c171cd0e4d38bd6e9cfec58b2d7f53a3204e1.json => query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json} (93%) create mode 100644 core/lib/dal/.sqlx/query-a65364d10a20420211022dc8234d0a586ce73d09ee28887cb1ad1c0392250629.json delete mode 100644 core/lib/dal/.sqlx/query-a8d55f14de2f489fdc12c8da540e0d51f86d30d5ad92496e4aa087a3c4aae09f.json delete mode 100644 core/lib/dal/.sqlx/query-acfd5a60fda5782bddb8cba033a5d3a0eed793f7b64ad3ed035f20e896371721.json create mode 100644 core/lib/dal/.sqlx/query-ad8cbc084ef8bc5995031c807bbbd2225e57ae8d42042ac107b35a36c522f0d8.json delete mode 100644 core/lib/dal/.sqlx/query-bf481c2b498420f80765b837059cab02b0656d863dbfce4b5dad7bc72e52b05d.json rename core/lib/dal/.sqlx/{query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json => query-c4e81f78ef078cbed2d588be91418997f003e26768c5de663160d89af54a1ee7.json} (78%) delete mode 100644 core/lib/dal/.sqlx/query-cf8cff1e6d277088519ef7dfbdb1885d320c146cd8fad77c107ef12fa38e6c98.json create mode 100644 core/lib/dal/.sqlx/query-d1490262c7a2a583928a611ae69eb0539849f7fd590712103db7d45d119caca2.json rename core/lib/dal/.sqlx/{query-ba2343a38e37d104786f9276d91f67d2ef1428c61ae84003c9b52b03204d1f0a.json => query-d43ae07cf1539826363573d121392687cfe890fe89c748f836bad6eb0cc0fcf5.json} (70%) create mode 100644 core/lib/dal/.sqlx/query-ddfb7ba0592f1e6714a4496cee18e7265828e3ae78e391ef235b700f0adfe5e4.json delete mode 100644 core/lib/dal/.sqlx/query-f3a049c7eb0d8903737f02fa154b50ebc862a133734382bad8fdfa3a93d8b743.json create mode 100644 core/lib/dal/.sqlx/query-fce6fff384875df689dc422153a2745b90c68ebec5706b106ef69cb61333466e.json create mode 100644 core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql create mode 100644 core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql diff --git a/contracts b/contracts index 2ff97e2549ee..bce4b2d0f34b 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 2ff97e2549ee9100b7860b40c68c12bcba0cab3c +Subproject commit bce4b2d0f34bd87f1aaadd291772935afb1c3bd6 diff --git a/core/lib/dal/.sqlx/query-048f255042f0a75c04bc19369c4b0dd75acbe4248159d2fb62d9e9878c158016.json b/core/lib/dal/.sqlx/query-048f255042f0a75c04bc19369c4b0dd75acbe4248159d2fb62d9e9878c158016.json new file mode 100644 index 000000000000..8c41c0ab9763 --- /dev/null +++ b/core/lib/dal/.sqlx/query-048f255042f0a75c04bc19369c4b0dd75acbe4248159d2fb62d9e9878c158016.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n protocol_versions (\n id,\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n upgrade_tx_hash,\n created_at\n )\n VALUES\n ($1, $2, $3, $4, $5, NOW())\n ON CONFLICT DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Int8", + "Bytea", + "Bytea", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "048f255042f0a75c04bc19369c4b0dd75acbe4248159d2fb62d9e9878c158016" +} diff --git a/core/lib/dal/.sqlx/query-05c2a77d9f65d435e2df63a300850e42abbaf365a1b041d0e7a809796ef0fe63.json b/core/lib/dal/.sqlx/query-05c2a77d9f65d435e2df63a300850e42abbaf365a1b041d0e7a809796ef0fe63.json deleted file mode 100644 index f3c85b9b43dc..000000000000 --- a/core/lib/dal/.sqlx/query-05c2a77d9f65d435e2df63a300850e42abbaf365a1b041d0e7a809796ef0fe63.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE proof_generation_details\n SET\n status = 'picked_by_prover',\n updated_at = NOW(),\n prover_taken_at = NOW()\n WHERE\n l1_batch_number = (\n SELECT\n l1_batch_number\n FROM\n proof_generation_details\n LEFT JOIN l1_batches ON l1_batch_number = l1_batches.number\n WHERE\n (\n vm_run_data_blob_url IS NOT NULL\n AND proof_gen_data_blob_url IS NOT NULL\n AND l1_batches.hash IS NOT NULL\n AND l1_batches.aux_data_hash IS NOT NULL\n AND l1_batches.meta_parameters_hash IS NOT NULL\n AND status = 'unpicked'\n )\n OR (\n status = 'picked_by_prover'\n AND prover_taken_at < NOW() - $1::INTERVAL\n )\n ORDER BY\n l1_batch_number ASC\n LIMIT\n 1\n )\n RETURNING\n proof_generation_details.l1_batch_number\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "l1_batch_number", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Interval" - ] - }, - "nullable": [ - false - ] - }, - "hash": "05c2a77d9f65d435e2df63a300850e42abbaf365a1b041d0e7a809796ef0fe63" -} diff --git a/core/lib/dal/.sqlx/query-2b1aa207a058f66265acf2c21b8ed5d8007789c0fc1eab948f6d7339dfb69147.json b/core/lib/dal/.sqlx/query-08740b96c883fce75b6238bb6bdc95254f94dddb4ed84a675c2655421758b049.json similarity index 80% rename from core/lib/dal/.sqlx/query-2b1aa207a058f66265acf2c21b8ed5d8007789c0fc1eab948f6d7339dfb69147.json rename to core/lib/dal/.sqlx/query-08740b96c883fce75b6238bb6bdc95254f94dddb4ed84a675c2655421758b049.json index 96b48892516d..51392a6ed8f8 100644 --- a/core/lib/dal/.sqlx/query-2b1aa207a058f66265acf2c21b8ed5d8007789c0fc1eab948f6d7339dfb69147.json +++ b/core/lib/dal/.sqlx/query-08740b96c883fce75b6238bb6bdc95254f94dddb4ed84a675c2655421758b049.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n DELETE FROM transactions\n WHERE\n miniblock_number IS NULL\n AND received_at < NOW() - $1::INTERVAL\n AND is_priority = FALSE\n AND error IS NULL\n RETURNING\n hash\n ", + "query": "\n DELETE FROM transactions\n WHERE\n miniblock_number IS NULL\n AND received_at < NOW() - $1::INTERVAL\n AND is_priority = FALSE\n AND error IS NULL\n RETURNING\n hash\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "2b1aa207a058f66265acf2c21b8ed5d8007789c0fc1eab948f6d7339dfb69147" + "hash": "08740b96c883fce75b6238bb6bdc95254f94dddb4ed84a675c2655421758b049" } diff --git a/core/lib/dal/.sqlx/query-0f1856e55a370280a078d048f09e2d457914c737660b37e9f66b576bbc9a7904.json b/core/lib/dal/.sqlx/query-0f1856e55a370280a078d048f09e2d457914c737660b37e9f66b576bbc9a7904.json index 498e839a63d7..87234b51dd80 100644 --- a/core/lib/dal/.sqlx/query-0f1856e55a370280a078d048f09e2d457914c737660b37e9f66b576bbc9a7904.json +++ b/core/lib/dal/.sqlx/query-0f1856e55a370280a078d048f09e2d457914c737660b37e9f66b576bbc9a7904.json @@ -182,6 +182,16 @@ "ordinal": 35, "name": "upgrade_id", "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" } ], "parameters": { @@ -226,6 +236,8 @@ false, true, true, + true, + true, true ] }, diff --git a/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json b/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json index 7b939d137db9..371bb33fd6d8 100644 --- a/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json +++ b/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json @@ -182,6 +182,16 @@ "ordinal": 35, "name": "upgrade_id", "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" } ], "parameters": { @@ -223,6 +233,8 @@ false, true, true, + true, + true, true ] }, diff --git a/core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json b/core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json deleted file mode 100644 index ee88bcdf39bd..000000000000 --- a/core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n protocol_versions (\n id,\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n upgrade_tx_hash,\n created_at\n )\n VALUES\n ($1, $2, $3, $4, $5, NOW())\n ON CONFLICT DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Int8", - "Bytea", - "Bytea", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633" -} diff --git a/core/lib/dal/.sqlx/query-69c885498b186f3b7cbb215112ec86783d7da0ec1d008680872f3619cf217923.json b/core/lib/dal/.sqlx/query-28c5a9f99af4d2857346e0df73c9b9086ba42bac53629793a42d67b353c30210.json similarity index 60% rename from core/lib/dal/.sqlx/query-69c885498b186f3b7cbb215112ec86783d7da0ec1d008680872f3619cf217923.json rename to core/lib/dal/.sqlx/query-28c5a9f99af4d2857346e0df73c9b9086ba42bac53629793a42d67b353c30210.json index 82575c807fb3..93520d4ded3e 100644 --- a/core/lib/dal/.sqlx/query-69c885498b186f3b7cbb215112ec86783d7da0ec1d008680872f3619cf217923.json +++ b/core/lib/dal/.sqlx/query-28c5a9f99af4d2857346e0df73c9b9086ba42bac53629793a42d67b353c30210.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n DELETE FROM transactions\n WHERE\n hash = ANY ($1)\n ", + "query": "\n DELETE FROM transactions\n WHERE\n hash = ANY($1)\n ", "describe": { "columns": [], "parameters": { @@ -10,5 +10,5 @@ }, "nullable": [] }, - "hash": "69c885498b186f3b7cbb215112ec86783d7da0ec1d008680872f3619cf217923" + "hash": "28c5a9f99af4d2857346e0df73c9b9086ba42bac53629793a42d67b353c30210" } diff --git a/core/lib/dal/.sqlx/query-33a78184559d0c0d13469fa799e2c5eeab06ff664141fa542229e7c9a46d4410.json b/core/lib/dal/.sqlx/query-33a78184559d0c0d13469fa799e2c5eeab06ff664141fa542229e7c9a46d4410.json deleted file mode 100644 index 6dcc1acfd358..000000000000 --- a/core/lib/dal/.sqlx/query-33a78184559d0c0d13469fa799e2c5eeab06ff664141fa542229e7c9a46d4410.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n hash = data_table.hash,\n signature = data_table.signature,\n gas_limit = data_table.gas_limit,\n max_fee_per_gas = data_table.max_fee_per_gas,\n max_priority_fee_per_gas = data_table.max_priority_fee_per_gas,\n gas_per_pubdata_limit = data_table.gas_per_pubdata_limit,\n input = data_table.input,\n data = data_table.data,\n tx_format = data_table.tx_format,\n miniblock_number = $21,\n index_in_block = data_table.index_in_block,\n error = NULLIF(data_table.error, ''),\n effective_gas_price = data_table.effective_gas_price,\n execution_info = data_table.new_execution_info,\n refunded_gas = data_table.refunded_gas,\n value = data_table.value,\n contract_address = data_table.contract_address,\n paymaster = data_table.paymaster,\n paymaster_input = data_table.paymaster_input,\n in_mempool = FALSE,\n updated_at = NOW()\n FROM\n (\n SELECT\n data_table_temp.*\n FROM\n (\n SELECT\n UNNEST($1::bytea[]) AS initiator_address,\n UNNEST($2::INT[]) AS nonce,\n UNNEST($3::bytea[]) AS hash,\n UNNEST($4::bytea[]) AS signature,\n UNNEST($5::NUMERIC[]) AS gas_limit,\n UNNEST($6::NUMERIC[]) AS max_fee_per_gas,\n UNNEST($7::NUMERIC[]) AS max_priority_fee_per_gas,\n UNNEST($8::NUMERIC[]) AS gas_per_pubdata_limit,\n UNNEST($9::INT[]) AS tx_format,\n UNNEST($10::INTEGER[]) AS index_in_block,\n UNNEST($11::VARCHAR[]) AS error,\n UNNEST($12::NUMERIC[]) AS effective_gas_price,\n UNNEST($13::jsonb[]) AS new_execution_info,\n UNNEST($14::bytea[]) AS input,\n UNNEST($15::jsonb[]) AS data,\n UNNEST($16::BIGINT[]) AS refunded_gas,\n UNNEST($17::NUMERIC[]) AS value,\n UNNEST($18::bytea[]) AS contract_address,\n UNNEST($19::bytea[]) AS paymaster,\n UNNEST($20::bytea[]) AS paymaster_input\n ) AS data_table_temp\n JOIN transactions ON transactions.initiator_address = data_table_temp.initiator_address\n AND transactions.nonce = data_table_temp.nonce\n ORDER BY\n transactions.hash\n ) AS data_table\n WHERE\n transactions.initiator_address = data_table.initiator_address\n AND transactions.nonce = data_table.nonce\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "Int4Array", - "ByteaArray", - "ByteaArray", - "NumericArray", - "NumericArray", - "NumericArray", - "NumericArray", - "Int4Array", - "Int4Array", - "VarcharArray", - "NumericArray", - "JsonbArray", - "ByteaArray", - "JsonbArray", - "Int8Array", - "NumericArray", - "ByteaArray", - "ByteaArray", - "ByteaArray", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "33a78184559d0c0d13469fa799e2c5eeab06ff664141fa542229e7c9a46d4410" -} diff --git a/core/lib/dal/.sqlx/query-3518a3e93da8115b54426d72aea0800383e6b73a8b48dc3e589a29a4367cbb5a.json b/core/lib/dal/.sqlx/query-3518a3e93da8115b54426d72aea0800383e6b73a8b48dc3e589a29a4367cbb5a.json deleted file mode 100644 index a2351b5eef86..000000000000 --- a/core/lib/dal/.sqlx/query-3518a3e93da8115b54426d72aea0800383e6b73a8b48dc3e589a29a4367cbb5a.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n call_traces (tx_hash, call_trace)\n SELECT\n u.tx_hash,\n u.call_trace\n FROM\n UNNEST($1::bytea[], $2::bytea[]) AS u (tx_hash, call_trace)\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "ByteaArray" - ] - }, - "nullable": [] - }, - "hash": "3518a3e93da8115b54426d72aea0800383e6b73a8b48dc3e589a29a4367cbb5a" -} diff --git a/core/lib/dal/.sqlx/query-469db79fcf8d692507317080e0d843620210aff3a9a7aa8a249db50c1c56d927.json b/core/lib/dal/.sqlx/query-37b653ba8a544224ef6fb88e073d1e4657024c66a42e1bbc261c92c9e1c79930.json similarity index 60% rename from core/lib/dal/.sqlx/query-469db79fcf8d692507317080e0d843620210aff3a9a7aa8a249db50c1c56d927.json rename to core/lib/dal/.sqlx/query-37b653ba8a544224ef6fb88e073d1e4657024c66a42e1bbc261c92c9e1c79930.json index fe91d27abb11..f4b52c688cb0 100644 --- a/core/lib/dal/.sqlx/query-469db79fcf8d692507317080e0d843620210aff3a9a7aa8a249db50c1c56d927.json +++ b/core/lib/dal/.sqlx/query-37b653ba8a544224ef6fb88e073d1e4657024c66a42e1bbc261c92c9e1c79930.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n miniblock_number = $1,\n index_in_block = data_table.index_in_block,\n error = NULLIF(data_table.error, ''),\n in_mempool = FALSE,\n execution_info = execution_info || data_table.new_execution_info,\n refunded_gas = data_table.refunded_gas,\n effective_gas_price = data_table.effective_gas_price,\n updated_at = NOW()\n FROM\n (\n SELECT\n UNNEST($2::bytea[]) AS hash,\n UNNEST($3::INTEGER[]) AS index_in_block,\n UNNEST($4::VARCHAR[]) AS error,\n UNNEST($5::jsonb[]) AS new_execution_info,\n UNNEST($6::BIGINT[]) AS refunded_gas,\n UNNEST($7::NUMERIC[]) AS effective_gas_price\n ) AS data_table\n WHERE\n transactions.hash = data_table.hash\n ", + "query": "\n UPDATE transactions\n SET\n miniblock_number = $1,\n index_in_block = data_table.index_in_block,\n error = NULLIF(data_table.error, ''),\n in_mempool = FALSE,\n execution_info = execution_info || data_table.new_execution_info,\n refunded_gas = data_table.refunded_gas,\n effective_gas_price = data_table.effective_gas_price,\n updated_at = NOW()\n FROM\n (\n SELECT\n UNNEST($2::bytea []) AS hash,\n UNNEST($3::integer []) AS index_in_block,\n UNNEST($4::varchar []) AS error,\n UNNEST($5::jsonb []) AS new_execution_info,\n UNNEST($6::bigint []) AS refunded_gas,\n UNNEST($7::numeric []) AS effective_gas_price\n ) AS data_table\n WHERE\n transactions.hash = data_table.hash\n ", "describe": { "columns": [], "parameters": { @@ -16,5 +16,5 @@ }, "nullable": [] }, - "hash": "469db79fcf8d692507317080e0d843620210aff3a9a7aa8a249db50c1c56d927" + "hash": "37b653ba8a544224ef6fb88e073d1e4657024c66a42e1bbc261c92c9e1c79930" } diff --git a/core/lib/dal/.sqlx/query-3ddb13ffbafae2374527886e592b3c0210383d8698f6f84f694fece9fd59f3d5.json b/core/lib/dal/.sqlx/query-3ddb13ffbafae2374527886e592b3c0210383d8698f6f84f694fece9fd59f3d5.json deleted file mode 100644 index 5652e186ceb9..000000000000 --- a/core/lib/dal/.sqlx/query-3ddb13ffbafae2374527886e592b3c0210383d8698f6f84f694fece9fd59f3d5.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n protocol_patches (minor, patch, snark_wrapper_vk_hash, created_at)\n VALUES\n ($1, $2, $3, NOW())\n ON CONFLICT DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Int4", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "3ddb13ffbafae2374527886e592b3c0210383d8698f6f84f694fece9fd59f3d5" -} diff --git a/core/lib/dal/.sqlx/query-403b0b1c93f973aedb41aad7700d656e2a26752fa71ae936ff2eb821b0734b61.json b/core/lib/dal/.sqlx/query-403b0b1c93f973aedb41aad7700d656e2a26752fa71ae936ff2eb821b0734b61.json new file mode 100644 index 000000000000..6cb9dec6838c --- /dev/null +++ b/core/lib/dal/.sqlx/query-403b0b1c93f973aedb41aad7700d656e2a26752fa71ae936ff2eb821b0734b61.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n proof_generation_details (l1_batch_number, status, created_at, updated_at)\n VALUES\n ($1, 'unpicked', NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "403b0b1c93f973aedb41aad7700d656e2a26752fa71ae936ff2eb821b0734b61" +} diff --git a/core/lib/dal/.sqlx/query-546c729829083b7eba94fea742c162d717ffcf46fdf5d2ce5d32555353b6da6b.json b/core/lib/dal/.sqlx/query-41b2d575151bff136037d6f1d75f36d50db45560befec6418020b01c55d94a98.json similarity index 52% rename from core/lib/dal/.sqlx/query-546c729829083b7eba94fea742c162d717ffcf46fdf5d2ce5d32555353b6da6b.json rename to core/lib/dal/.sqlx/query-41b2d575151bff136037d6f1d75f36d50db45560befec6418020b01c55d94a98.json index 70b94f739098..f5dccac1a01c 100644 --- a/core/lib/dal/.sqlx/query-546c729829083b7eba94fea742c162d717ffcf46fdf5d2ce5d32555353b6da6b.json +++ b/core/lib/dal/.sqlx/query-41b2d575151bff136037d6f1d75f36d50db45560befec6418020b01c55d94a98.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n in_mempool = FALSE\n FROM\n UNNEST($1::bytea[]) AS s (address)\n WHERE\n transactions.in_mempool = TRUE\n AND transactions.initiator_address = s.address\n ", + "query": "\n UPDATE transactions\n SET\n in_mempool = FALSE\n FROM\n UNNEST($1::bytea []) AS s (address)\n WHERE\n transactions.in_mempool = TRUE\n AND transactions.initiator_address = s.address\n ", "describe": { "columns": [], "parameters": { @@ -10,5 +10,5 @@ }, "nullable": [] }, - "hash": "546c729829083b7eba94fea742c162d717ffcf46fdf5d2ce5d32555353b6da6b" + "hash": "41b2d575151bff136037d6f1d75f36d50db45560befec6418020b01c55d94a98" } diff --git a/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json b/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json new file mode 100644 index 000000000000..63364370a7dd --- /dev/null +++ b/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at,\n block_timestamp_range_start,\n block_timestamp_range_end\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n NOW(),\n NOW(),\n $20,\n $21\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL,\n block_timestamp_range_start = $20,\n block_timestamp_range_end = $21\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "is_replaced!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Bytea", + "Int8", + "Bytea", + "Numeric", + "Numeric", + "Numeric", + "Numeric", + "Bytea", + "Jsonb", + "Int4", + "Bytea", + "Numeric", + "Bytea", + "Bytea", + "Int8", + "Int4", + "Int4", + "Timestamp", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + null + ] + }, + "hash": "44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8" +} diff --git a/core/lib/dal/.sqlx/query-03e00f422f991f8f12aad0083e1c42cfea253a182ca5df143a183cd522ecac33.json b/core/lib/dal/.sqlx/query-499571f0484f4a54541450f935853bb67bd12f2b635af783897f9d2a4f4ead2e.json similarity index 81% rename from core/lib/dal/.sqlx/query-03e00f422f991f8f12aad0083e1c42cfea253a182ca5df143a183cd522ecac33.json rename to core/lib/dal/.sqlx/query-499571f0484f4a54541450f935853bb67bd12f2b635af783897f9d2a4f4ead2e.json index 12498582adaa..ddc3772a1a5c 100644 --- a/core/lib/dal/.sqlx/query-03e00f422f991f8f12aad0083e1c42cfea253a182ca5df143a183cd522ecac33.json +++ b/core/lib/dal/.sqlx/query-499571f0484f4a54541450f935853bb67bd12f2b635af783897f9d2a4f4ead2e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n l1_batch_number = NULL,\n miniblock_number = NULL,\n error = NULL,\n index_in_block = NULL,\n execution_info = '{}'\n WHERE\n miniblock_number > $1\n RETURNING\n hash\n ", + "query": "\n UPDATE transactions\n SET\n l1_batch_number = NULL,\n miniblock_number = NULL,\n error = NULL,\n index_in_block = NULL,\n execution_info = '{}'\n WHERE\n miniblock_number > $1\n RETURNING\n hash\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "03e00f422f991f8f12aad0083e1c42cfea253a182ca5df143a183cd522ecac33" + "hash": "499571f0484f4a54541450f935853bb67bd12f2b635af783897f9d2a4f4ead2e" } diff --git a/core/lib/dal/.sqlx/query-5137159db7d3ff456e368e6246b07554ce738a2d7005472e7e76a64a8fbd57ad.json b/core/lib/dal/.sqlx/query-5137159db7d3ff456e368e6246b07554ce738a2d7005472e7e76a64a8fbd57ad.json deleted file mode 100644 index 07ef0aba074d..000000000000 --- a/core/lib/dal/.sqlx/query-5137159db7d3ff456e368e6246b07554ce738a2d7005472e7e76a64a8fbd57ad.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n proof_generation_details (l1_batch_number, status, created_at, updated_at)\n VALUES\n ($1, 'unpicked', NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [] - }, - "hash": "5137159db7d3ff456e368e6246b07554ce738a2d7005472e7e76a64a8fbd57ad" -} diff --git a/core/lib/dal/.sqlx/query-5d1f588b2b652105b4452be1cc6c7573fe040d47d17d9bd4e2a2b6d3131a4f9c.json b/core/lib/dal/.sqlx/query-6083e429948c139e36cfce2c5ed41edf3965f7ce67341d957ec680a18a0c39ea.json similarity index 57% rename from core/lib/dal/.sqlx/query-5d1f588b2b652105b4452be1cc6c7573fe040d47d17d9bd4e2a2b6d3131a4f9c.json rename to core/lib/dal/.sqlx/query-6083e429948c139e36cfce2c5ed41edf3965f7ce67341d957ec680a18a0c39ea.json index 8d566e0c6cf2..c6760a336dc6 100644 --- a/core/lib/dal/.sqlx/query-5d1f588b2b652105b4452be1cc6c7573fe040d47d17d9bd4e2a2b6d3131a4f9c.json +++ b/core/lib/dal/.sqlx/query-6083e429948c139e36cfce2c5ed41edf3965f7ce67341d957ec680a18a0c39ea.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n l1_batch_number = $3,\n l1_batch_tx_index = data_table.l1_batch_tx_index,\n updated_at = NOW()\n FROM\n (\n SELECT\n UNNEST($1::INT[]) AS l1_batch_tx_index,\n UNNEST($2::bytea[]) AS hash\n ) AS data_table\n WHERE\n transactions.hash = data_table.hash\n ", + "query": "\n UPDATE transactions\n SET\n l1_batch_number = $3,\n l1_batch_tx_index = data_table.l1_batch_tx_index,\n updated_at = NOW()\n FROM\n (\n SELECT\n UNNEST($1::INT []) AS l1_batch_tx_index,\n UNNEST($2::BYTEA []) AS hash\n ) AS data_table\n WHERE\n transactions.hash = data_table.hash\n ", "describe": { "columns": [], "parameters": { @@ -12,5 +12,5 @@ }, "nullable": [] }, - "hash": "5d1f588b2b652105b4452be1cc6c7573fe040d47d17d9bd4e2a2b6d3131a4f9c" + "hash": "6083e429948c139e36cfce2c5ed41edf3965f7ce67341d957ec680a18a0c39ea" } diff --git a/core/lib/dal/.sqlx/query-66b3f476cf4487239190175d2940fd5e1330393d8b04c7cf03b8c7ab2edad5d1.json b/core/lib/dal/.sqlx/query-66b3f476cf4487239190175d2940fd5e1330393d8b04c7cf03b8c7ab2edad5d1.json deleted file mode 100644 index 0cf4a1e32005..000000000000 --- a/core/lib/dal/.sqlx/query-66b3f476cf4487239190175d2940fd5e1330393d8b04c7cf03b8c7ab2edad5d1.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n upgrade_id,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n miniblock_number,\n index_in_block,\n error,\n execution_info,\n refunded_gas,\n effective_gas_price,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n TRUE,\n data_table.initiator_address,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.data,\n data_table.upgrade_id,\n data_table.contract_address,\n data_table.l1_block_number,\n data_table.value,\n '\\x0000000000000000000000000000000000000000'::bytea,\n '\\x'::bytea,\n data_table.tx_format,\n data_table.l1_tx_mint,\n data_table.l1_tx_refund_recipient,\n $19,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.execution_info,\n data_table.refunded_gas,\n data_table.effective_gas_price,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::BYTEA[]) AS hash,\n UNNEST($2::BYTEA[]) AS initiator_address,\n UNNEST($3::NUMERIC[]) AS gas_limit,\n UNNEST($4::NUMERIC[]) AS max_fee_per_gas,\n UNNEST($5::NUMERIC[]) AS gas_per_pubdata_limit,\n UNNEST($6::JSONB[]) AS data,\n UNNEST($7::INT[]) AS upgrade_id,\n UNNEST($8::BYTEA[]) AS contract_address,\n UNNEST($9::INT[]) AS l1_block_number,\n UNNEST($10::NUMERIC[]) AS value,\n UNNEST($11::INTEGER[]) AS tx_format,\n UNNEST($12::NUMERIC[]) AS l1_tx_mint,\n UNNEST($13::BYTEA[]) AS l1_tx_refund_recipient,\n UNNEST($14::INT[]) AS index_in_block,\n UNNEST($15::VARCHAR[]) AS error,\n UNNEST($16::JSONB[]) AS execution_info,\n UNNEST($17::BIGINT[]) AS refunded_gas,\n UNNEST($18::NUMERIC[]) AS effective_gas_price\n ) AS data_table\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "ByteaArray", - "NumericArray", - "NumericArray", - "NumericArray", - "JsonbArray", - "Int4Array", - "ByteaArray", - "Int4Array", - "NumericArray", - "Int4Array", - "NumericArray", - "ByteaArray", - "Int4Array", - "VarcharArray", - "JsonbArray", - "Int8Array", - "NumericArray", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "66b3f476cf4487239190175d2940fd5e1330393d8b04c7cf03b8c7ab2edad5d1" -} diff --git a/core/lib/dal/.sqlx/query-7204d08f6fb83c83c09eb2942ecb671fa559dfdb29b315b17ae2f86533d247e9.json b/core/lib/dal/.sqlx/query-7204d08f6fb83c83c09eb2942ecb671fa559dfdb29b315b17ae2f86533d247e9.json new file mode 100644 index 000000000000..01adb17775c3 --- /dev/null +++ b/core/lib/dal/.sqlx/query-7204d08f6fb83c83c09eb2942ecb671fa559dfdb29b315b17ae2f86533d247e9.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n protocol_patches (minor, patch, snark_wrapper_vk_hash, created_at)\n VALUES\n ($1, $2, $3, NOW())\n ON CONFLICT DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Int4", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "7204d08f6fb83c83c09eb2942ecb671fa559dfdb29b315b17ae2f86533d247e9" +} diff --git a/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json b/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json index 707b7ce9e75c..b95878189ce4 100644 --- a/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json +++ b/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json @@ -182,6 +182,16 @@ "ordinal": 35, "name": "upgrade_id", "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" } ], "parameters": { @@ -225,6 +235,8 @@ false, true, true, + true, + true, true ] }, diff --git a/core/lib/dal/.sqlx/query-dac29d7eb16782713acb7aa68aaa8b12b67678e983dc2570be28fe9b1e016c28.json b/core/lib/dal/.sqlx/query-7f3ca3f1d0b3414575e71af98b810ff145ac2f388a246b9c7b32193e2d4208dd.json similarity index 62% rename from core/lib/dal/.sqlx/query-dac29d7eb16782713acb7aa68aaa8b12b67678e983dc2570be28fe9b1e016c28.json rename to core/lib/dal/.sqlx/query-7f3ca3f1d0b3414575e71af98b810ff145ac2f388a246b9c7b32193e2d4208dd.json index c0258c12311b..830e43b00ed3 100644 --- a/core/lib/dal/.sqlx/query-dac29d7eb16782713acb7aa68aaa8b12b67678e983dc2570be28fe9b1e016c28.json +++ b/core/lib/dal/.sqlx/query-7f3ca3f1d0b3414575e71af98b810ff145ac2f388a246b9c7b32193e2d4208dd.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n DELETE FROM call_traces\n WHERE\n tx_hash = ANY ($1)\n ", + "query": "\n DELETE FROM call_traces\n WHERE\n tx_hash = ANY($1)\n ", "describe": { "columns": [], "parameters": { @@ -10,5 +10,5 @@ }, "nullable": [] }, - "hash": "dac29d7eb16782713acb7aa68aaa8b12b67678e983dc2570be28fe9b1e016c28" + "hash": "7f3ca3f1d0b3414575e71af98b810ff145ac2f388a246b9c7b32193e2d4208dd" } diff --git a/core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json b/core/lib/dal/.sqlx/query-96adbd0c9a5786a6cca74324353c7d8bbdbee28d4ac2a2c0a331298c5e39b71d.json similarity index 66% rename from core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json rename to core/lib/dal/.sqlx/query-96adbd0c9a5786a6cca74324353c7d8bbdbee28d4ac2a2c0a331298c5e39b71d.json index 0b1f56ef9f33..3b8accb4fda2 100644 --- a/core/lib/dal/.sqlx/query-bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e.json +++ b/core/lib/dal/.sqlx/query-96adbd0c9a5786a6cca74324353c7d8bbdbee28d4ac2a2c0a331298c5e39b71d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n protocol_version,\n index_in_block\n FROM\n transactions\n INNER JOIN miniblocks ON transactions.miniblock_number = miniblocks.number\n WHERE\n transactions.hash = $1\n ", + "query": "\n SELECT\n protocol_version,\n index_in_block\n FROM\n transactions\n INNER JOIN miniblocks ON transactions.miniblock_number = miniblocks.number\n WHERE\n transactions.hash = $1\n ", "describe": { "columns": [ { @@ -24,5 +24,5 @@ true ] }, - "hash": "bdfd7e9d4462ac9cf6f91fced84355e6aec05ba4af297a03169e3122a67ae53e" + "hash": "96adbd0c9a5786a6cca74324353c7d8bbdbee28d4ac2a2c0a331298c5e39b71d" } diff --git a/core/lib/dal/.sqlx/query-9badf9f287fd5f8a11cc855b230d23f83a260adf56000748c4b19752e2948ab5.json b/core/lib/dal/.sqlx/query-9badf9f287fd5f8a11cc855b230d23f83a260adf56000748c4b19752e2948ab5.json new file mode 100644 index 000000000000..aa120d6b8f6e --- /dev/null +++ b/core/lib/dal/.sqlx/query-9badf9f287fd5f8a11cc855b230d23f83a260adf56000748c4b19752e2948ab5.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE transactions\n SET\n hash = data_table.hash,\n signature = data_table.signature,\n gas_limit = data_table.gas_limit,\n max_fee_per_gas = data_table.max_fee_per_gas,\n max_priority_fee_per_gas = data_table.max_priority_fee_per_gas,\n gas_per_pubdata_limit = data_table.gas_per_pubdata_limit,\n input = data_table.input,\n data = data_table.data,\n tx_format = data_table.tx_format,\n miniblock_number = $21,\n index_in_block = data_table.index_in_block,\n error = NULLIF(data_table.error, ''),\n effective_gas_price = data_table.effective_gas_price,\n execution_info = data_table.new_execution_info,\n refunded_gas = data_table.refunded_gas,\n value = data_table.value,\n contract_address = data_table.contract_address,\n paymaster = data_table.paymaster,\n paymaster_input = data_table.paymaster_input,\n in_mempool = FALSE,\n updated_at = NOW()\n FROM\n (\n SELECT\n data_table_temp.*\n FROM\n (\n SELECT\n UNNEST($1::bytea []) AS initiator_address,\n UNNEST($2::int []) AS nonce,\n UNNEST($3::bytea []) AS hash,\n UNNEST($4::bytea []) AS signature,\n UNNEST($5::numeric []) AS gas_limit,\n UNNEST($6::numeric []) AS max_fee_per_gas,\n UNNEST($7::numeric []) AS max_priority_fee_per_gas,\n UNNEST($8::numeric []) AS gas_per_pubdata_limit,\n UNNEST($9::int []) AS tx_format,\n UNNEST($10::integer []) AS index_in_block,\n UNNEST($11::varchar []) AS error,\n UNNEST($12::numeric []) AS effective_gas_price,\n UNNEST($13::jsonb []) AS new_execution_info,\n UNNEST($14::bytea []) AS input,\n UNNEST($15::jsonb []) AS data,\n UNNEST($16::bigint []) AS refunded_gas,\n UNNEST($17::numeric []) AS value,\n UNNEST($18::bytea []) AS contract_address,\n UNNEST($19::bytea []) AS paymaster,\n UNNEST($20::bytea []) AS paymaster_input\n ) AS data_table_temp\n JOIN transactions\n ON\n transactions.initiator_address\n = data_table_temp.initiator_address\n AND transactions.nonce = data_table_temp.nonce\n ORDER BY\n transactions.hash\n ) AS data_table\n WHERE\n transactions.initiator_address = data_table.initiator_address\n AND transactions.nonce = data_table.nonce\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "Int4Array", + "ByteaArray", + "ByteaArray", + "NumericArray", + "NumericArray", + "NumericArray", + "NumericArray", + "Int4Array", + "Int4Array", + "VarcharArray", + "NumericArray", + "JsonbArray", + "ByteaArray", + "JsonbArray", + "Int8Array", + "NumericArray", + "ByteaArray", + "ByteaArray", + "ByteaArray", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "9badf9f287fd5f8a11cc855b230d23f83a260adf56000748c4b19752e2948ab5" +} diff --git a/core/lib/dal/.sqlx/query-9f7b35311f0afff1be7dc489348ec87cf78f40429222b3163f3c5235c87e007f.json b/core/lib/dal/.sqlx/query-9f7b35311f0afff1be7dc489348ec87cf78f40429222b3163f3c5235c87e007f.json new file mode 100644 index 000000000000..30d66d0890b8 --- /dev/null +++ b/core/lib/dal/.sqlx/query-9f7b35311f0afff1be7dc489348ec87cf78f40429222b3163f3c5235c87e007f.json @@ -0,0 +1,31 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n priority_op_id,\n full_fee,\n layer_2_tip_fee,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n TRUE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n $16,\n $17,\n $18,\n NOW(),\n NOW()\n )\n ON CONFLICT (hash) DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Bytea", + "Bytea", + "Numeric", + "Numeric", + "Numeric", + "Jsonb", + "Int8", + "Numeric", + "Numeric", + "Bytea", + "Int4", + "Numeric", + "Bytea", + "Bytea", + "Int4", + "Numeric", + "Bytea", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "9f7b35311f0afff1be7dc489348ec87cf78f40429222b3163f3c5235c87e007f" +} diff --git a/core/lib/dal/.sqlx/query-a329c468b25d6d5533766b8ad3d0c8fdca5c5731d490c1ac3ed56266b1d5a8a5.json b/core/lib/dal/.sqlx/query-a329c468b25d6d5533766b8ad3d0c8fdca5c5731d490c1ac3ed56266b1d5a8a5.json new file mode 100644 index 000000000000..d7947345cf61 --- /dev/null +++ b/core/lib/dal/.sqlx/query-a329c468b25d6d5533766b8ad3d0c8fdca5c5731d490c1ac3ed56266b1d5a8a5.json @@ -0,0 +1,32 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n upgrade_id,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n miniblock_number,\n index_in_block,\n error,\n execution_info,\n refunded_gas,\n effective_gas_price,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n TRUE,\n data_table.initiator_address,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.data,\n data_table.upgrade_id,\n data_table.contract_address,\n data_table.l1_block_number,\n data_table.value,\n '\\x0000000000000000000000000000000000000000'::bytea,\n '\\x'::bytea,\n data_table.tx_format,\n data_table.l1_tx_mint,\n data_table.l1_tx_refund_recipient,\n $19,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.execution_info,\n data_table.refunded_gas,\n data_table.effective_gas_price,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::bytea []) AS hash,\n UNNEST($2::bytea []) AS initiator_address,\n UNNEST($3::numeric []) AS gas_limit,\n UNNEST($4::numeric []) AS max_fee_per_gas,\n UNNEST($5::numeric []) AS gas_per_pubdata_limit,\n UNNEST($6::jsonb []) AS data,\n UNNEST($7::int []) AS upgrade_id,\n UNNEST($8::bytea []) AS contract_address,\n UNNEST($9::int []) AS l1_block_number,\n UNNEST($10::numeric []) AS value,\n UNNEST($11::integer []) AS tx_format,\n UNNEST($12::numeric []) AS l1_tx_mint,\n UNNEST($13::bytea []) AS l1_tx_refund_recipient,\n UNNEST($14::int []) AS index_in_block,\n UNNEST($15::varchar []) AS error,\n UNNEST($16::jsonb []) AS execution_info,\n UNNEST($17::bigint []) AS refunded_gas,\n UNNEST($18::numeric []) AS effective_gas_price\n ) AS data_table\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "ByteaArray", + "NumericArray", + "NumericArray", + "NumericArray", + "JsonbArray", + "Int4Array", + "ByteaArray", + "Int4Array", + "NumericArray", + "Int4Array", + "NumericArray", + "ByteaArray", + "Int4Array", + "VarcharArray", + "JsonbArray", + "Int8Array", + "NumericArray", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "a329c468b25d6d5533766b8ad3d0c8fdca5c5731d490c1ac3ed56266b1d5a8a5" +} diff --git a/core/lib/dal/.sqlx/query-6621de90a024cc85946f17948e5c171cd0e4d38bd6e9cfec58b2d7f53a3204e1.json b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json similarity index 93% rename from core/lib/dal/.sqlx/query-6621de90a024cc85946f17948e5c171cd0e4d38bd6e9cfec58b2d7f53a3204e1.json rename to core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json index 8ba437fe2cee..83c977551b95 100644 --- a/core/lib/dal/.sqlx/query-6621de90a024cc85946f17948e5c171cd0e4d38bd6e9cfec58b2d7f53a3204e1.json +++ b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", + "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", "describe": { "columns": [ { @@ -182,6 +182,16 @@ "ordinal": 35, "name": "upgrade_id", "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" } ], "parameters": { @@ -228,8 +238,10 @@ false, true, true, + true, + true, true ] }, - "hash": "6621de90a024cc85946f17948e5c171cd0e4d38bd6e9cfec58b2d7f53a3204e1" + "hash": "a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b" } diff --git a/core/lib/dal/.sqlx/query-a65364d10a20420211022dc8234d0a586ce73d09ee28887cb1ad1c0392250629.json b/core/lib/dal/.sqlx/query-a65364d10a20420211022dc8234d0a586ce73d09ee28887cb1ad1c0392250629.json new file mode 100644 index 000000000000..58195689f5d4 --- /dev/null +++ b/core/lib/dal/.sqlx/query-a65364d10a20420211022dc8234d0a586ce73d09ee28887cb1ad1c0392250629.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n miniblock_number,\n index_in_block,\n error,\n effective_gas_price,\n refunded_gas,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n FALSE,\n data_table.initiator_address,\n data_table.nonce,\n data_table.signature,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.max_priority_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.input,\n data_table.data,\n data_table.tx_format,\n data_table.contract_address,\n data_table.value,\n data_table.paymaster,\n data_table.paymaster_input,\n data_table.new_execution_info,\n $21,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.effective_gas_price,\n data_table.refunded_gas,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::bytea []) AS hash,\n UNNEST($2::bytea []) AS initiator_address,\n UNNEST($3::int []) AS nonce,\n UNNEST($4::bytea []) AS signature,\n UNNEST($5::numeric []) AS gas_limit,\n UNNEST($6::numeric []) AS max_fee_per_gas,\n UNNEST($7::numeric []) AS max_priority_fee_per_gas,\n UNNEST($8::numeric []) AS gas_per_pubdata_limit,\n UNNEST($9::bytea []) AS input,\n UNNEST($10::jsonb []) AS data,\n UNNEST($11::int []) AS tx_format,\n UNNEST($12::bytea []) AS contract_address,\n UNNEST($13::numeric []) AS value,\n UNNEST($14::bytea []) AS paymaster,\n UNNEST($15::bytea []) AS paymaster_input,\n UNNEST($16::jsonb []) AS new_execution_info,\n UNNEST($17::integer []) AS index_in_block,\n UNNEST($18::varchar []) AS error,\n UNNEST($19::numeric []) AS effective_gas_price,\n UNNEST($20::bigint []) AS refunded_gas\n ) AS data_table\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "ByteaArray", + "Int4Array", + "ByteaArray", + "NumericArray", + "NumericArray", + "NumericArray", + "NumericArray", + "ByteaArray", + "JsonbArray", + "Int4Array", + "ByteaArray", + "NumericArray", + "ByteaArray", + "ByteaArray", + "JsonbArray", + "Int4Array", + "VarcharArray", + "NumericArray", + "Int8Array", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "a65364d10a20420211022dc8234d0a586ce73d09ee28887cb1ad1c0392250629" +} diff --git a/core/lib/dal/.sqlx/query-a8d55f14de2f489fdc12c8da540e0d51f86d30d5ad92496e4aa087a3c4aae09f.json b/core/lib/dal/.sqlx/query-a8d55f14de2f489fdc12c8da540e0d51f86d30d5ad92496e4aa087a3c4aae09f.json deleted file mode 100644 index b00999f21448..000000000000 --- a/core/lib/dal/.sqlx/query-a8d55f14de2f489fdc12c8da540e0d51f86d30d5ad92496e4aa087a3c4aae09f.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n priority_op_id,\n full_fee,\n layer_2_tip_fee,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n miniblock_number,\n index_in_block,\n error,\n execution_info,\n refunded_gas,\n effective_gas_price,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n TRUE,\n data_table.initiator_address,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.data,\n data_table.priority_op_id,\n data_table.full_fee,\n data_table.layer_2_tip_fee,\n data_table.contract_address,\n data_table.l1_block_number,\n data_table.value,\n '\\x0000000000000000000000000000000000000000'::bytea,\n '\\x'::bytea,\n data_table.tx_format,\n data_table.l1_tx_mint,\n data_table.l1_tx_refund_recipient,\n $21,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.execution_info,\n data_table.refunded_gas,\n data_table.effective_gas_price,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::BYTEA[]) AS hash,\n UNNEST($2::BYTEA[]) AS initiator_address,\n UNNEST($3::NUMERIC[]) AS gas_limit,\n UNNEST($4::NUMERIC[]) AS max_fee_per_gas,\n UNNEST($5::NUMERIC[]) AS gas_per_pubdata_limit,\n UNNEST($6::JSONB[]) AS data,\n UNNEST($7::BIGINT[]) AS priority_op_id,\n UNNEST($8::NUMERIC[]) AS full_fee,\n UNNEST($9::NUMERIC[]) AS layer_2_tip_fee,\n UNNEST($10::BYTEA[]) AS contract_address,\n UNNEST($11::INT[]) AS l1_block_number,\n UNNEST($12::NUMERIC[]) AS value,\n UNNEST($13::INTEGER[]) AS tx_format,\n UNNEST($14::NUMERIC[]) AS l1_tx_mint,\n UNNEST($15::BYTEA[]) AS l1_tx_refund_recipient,\n UNNEST($16::INT[]) AS index_in_block,\n UNNEST($17::VARCHAR[]) AS error,\n UNNEST($18::JSONB[]) AS execution_info,\n UNNEST($19::BIGINT[]) AS refunded_gas,\n UNNEST($20::NUMERIC[]) AS effective_gas_price\n ) AS data_table\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "ByteaArray", - "NumericArray", - "NumericArray", - "NumericArray", - "JsonbArray", - "Int8Array", - "NumericArray", - "NumericArray", - "ByteaArray", - "Int4Array", - "NumericArray", - "Int4Array", - "NumericArray", - "ByteaArray", - "Int4Array", - "VarcharArray", - "JsonbArray", - "Int8Array", - "NumericArray", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "a8d55f14de2f489fdc12c8da540e0d51f86d30d5ad92496e4aa087a3c4aae09f" -} diff --git a/core/lib/dal/.sqlx/query-acfd5a60fda5782bddb8cba033a5d3a0eed793f7b64ad3ed035f20e896371721.json b/core/lib/dal/.sqlx/query-acfd5a60fda5782bddb8cba033a5d3a0eed793f7b64ad3ed035f20e896371721.json deleted file mode 100644 index 9232ef6d0096..000000000000 --- a/core/lib/dal/.sqlx/query-acfd5a60fda5782bddb8cba033a5d3a0eed793f7b64ad3ed035f20e896371721.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n priority_op_id,\n full_fee,\n layer_2_tip_fee,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n TRUE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n $16,\n $17,\n $18,\n NOW(),\n NOW()\n )\n ON CONFLICT (hash) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Jsonb", - "Int8", - "Numeric", - "Numeric", - "Bytea", - "Int4", - "Numeric", - "Bytea", - "Bytea", - "Int4", - "Numeric", - "Bytea", - "Timestamp" - ] - }, - "nullable": [] - }, - "hash": "acfd5a60fda5782bddb8cba033a5d3a0eed793f7b64ad3ed035f20e896371721" -} diff --git a/core/lib/dal/.sqlx/query-ad8cbc084ef8bc5995031c807bbbd2225e57ae8d42042ac107b35a36c522f0d8.json b/core/lib/dal/.sqlx/query-ad8cbc084ef8bc5995031c807bbbd2225e57ae8d42042ac107b35a36c522f0d8.json new file mode 100644 index 000000000000..b07701218c31 --- /dev/null +++ b/core/lib/dal/.sqlx/query-ad8cbc084ef8bc5995031c807bbbd2225e57ae8d42042ac107b35a36c522f0d8.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n priority_op_id,\n full_fee,\n layer_2_tip_fee,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n miniblock_number,\n index_in_block,\n error,\n execution_info,\n refunded_gas,\n effective_gas_price,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n TRUE,\n data_table.initiator_address,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.data,\n data_table.priority_op_id,\n data_table.full_fee,\n data_table.layer_2_tip_fee,\n data_table.contract_address,\n data_table.l1_block_number,\n data_table.value,\n '\\x0000000000000000000000000000000000000000'::bytea,\n '\\x'::bytea,\n data_table.tx_format,\n data_table.l1_tx_mint,\n data_table.l1_tx_refund_recipient,\n $21,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.execution_info,\n data_table.refunded_gas,\n data_table.effective_gas_price,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::bytea []) AS hash,\n UNNEST($2::bytea []) AS initiator_address,\n UNNEST($3::numeric []) AS gas_limit,\n UNNEST($4::numeric []) AS max_fee_per_gas,\n UNNEST($5::numeric []) AS gas_per_pubdata_limit,\n UNNEST($6::jsonb []) AS data,\n UNNEST($7::bigint []) AS priority_op_id,\n UNNEST($8::numeric []) AS full_fee,\n UNNEST($9::numeric []) AS layer_2_tip_fee,\n UNNEST($10::bytea []) AS contract_address,\n UNNEST($11::int []) AS l1_block_number,\n UNNEST($12::numeric []) AS value,\n UNNEST($13::integer []) AS tx_format,\n UNNEST($14::numeric []) AS l1_tx_mint,\n UNNEST($15::bytea []) AS l1_tx_refund_recipient,\n UNNEST($16::int []) AS index_in_block,\n UNNEST($17::varchar []) AS error,\n UNNEST($18::jsonb []) AS execution_info,\n UNNEST($19::bigint []) AS refunded_gas,\n UNNEST($20::numeric []) AS effective_gas_price\n ) AS data_table\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "ByteaArray", + "NumericArray", + "NumericArray", + "NumericArray", + "JsonbArray", + "Int8Array", + "NumericArray", + "NumericArray", + "ByteaArray", + "Int4Array", + "NumericArray", + "Int4Array", + "NumericArray", + "ByteaArray", + "Int4Array", + "VarcharArray", + "JsonbArray", + "Int8Array", + "NumericArray", + "Int8" + ] + }, + "nullable": [] + }, + "hash": "ad8cbc084ef8bc5995031c807bbbd2225e57ae8d42042ac107b35a36c522f0d8" +} diff --git a/core/lib/dal/.sqlx/query-bf481c2b498420f80765b837059cab02b0656d863dbfce4b5dad7bc72e52b05d.json b/core/lib/dal/.sqlx/query-bf481c2b498420f80765b837059cab02b0656d863dbfce4b5dad7bc72e52b05d.json deleted file mode 100644 index c353a35ec5e1..000000000000 --- a/core/lib/dal/.sqlx/query-bf481c2b498420f80765b837059cab02b0656d863dbfce4b5dad7bc72e52b05d.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n miniblock_number,\n index_in_block,\n error,\n effective_gas_price,\n refunded_gas,\n received_at,\n created_at,\n updated_at\n )\n SELECT\n data_table.hash,\n FALSE,\n data_table.initiator_address,\n data_table.nonce,\n data_table.signature,\n data_table.gas_limit,\n data_table.max_fee_per_gas,\n data_table.max_priority_fee_per_gas,\n data_table.gas_per_pubdata_limit,\n data_table.input,\n data_table.data,\n data_table.tx_format,\n data_table.contract_address,\n data_table.value,\n data_table.paymaster,\n data_table.paymaster_input,\n data_table.new_execution_info,\n $21,\n data_table.index_in_block,\n NULLIF(data_table.error, ''),\n data_table.effective_gas_price,\n data_table.refunded_gas,\n NOW(),\n NOW(),\n NOW()\n FROM\n (\n SELECT\n UNNEST($1::bytea[]) AS hash,\n UNNEST($2::bytea[]) AS initiator_address,\n UNNEST($3::INT[]) AS nonce,\n UNNEST($4::bytea[]) AS signature,\n UNNEST($5::NUMERIC[]) AS gas_limit,\n UNNEST($6::NUMERIC[]) AS max_fee_per_gas,\n UNNEST($7::NUMERIC[]) AS max_priority_fee_per_gas,\n UNNEST($8::NUMERIC[]) AS gas_per_pubdata_limit,\n UNNEST($9::bytea[]) AS input,\n UNNEST($10::jsonb[]) AS data,\n UNNEST($11::INT[]) AS tx_format,\n UNNEST($12::bytea[]) AS contract_address,\n UNNEST($13::NUMERIC[]) AS value,\n UNNEST($14::bytea[]) AS paymaster,\n UNNEST($15::bytea[]) AS paymaster_input,\n UNNEST($16::jsonb[]) AS new_execution_info,\n UNNEST($17::INTEGER[]) AS index_in_block,\n UNNEST($18::VARCHAR[]) AS error,\n UNNEST($19::NUMERIC[]) AS effective_gas_price,\n UNNEST($20::BIGINT[]) AS refunded_gas\n ) AS data_table\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "ByteaArray", - "Int4Array", - "ByteaArray", - "NumericArray", - "NumericArray", - "NumericArray", - "NumericArray", - "ByteaArray", - "JsonbArray", - "Int4Array", - "ByteaArray", - "NumericArray", - "ByteaArray", - "ByteaArray", - "JsonbArray", - "Int4Array", - "VarcharArray", - "NumericArray", - "Int8Array", - "Int8" - ] - }, - "nullable": [] - }, - "hash": "bf481c2b498420f80765b837059cab02b0656d863dbfce4b5dad7bc72e52b05d" -} diff --git a/core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json b/core/lib/dal/.sqlx/query-c4e81f78ef078cbed2d588be91418997f003e26768c5de663160d89af54a1ee7.json similarity index 78% rename from core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json rename to core/lib/dal/.sqlx/query-c4e81f78ef078cbed2d588be91418997f003e26768c5de663160d89af54a1ee7.json index 3297d411d8a7..162c722add9b 100644 --- a/core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json +++ b/core/lib/dal/.sqlx/query-c4e81f78ef078cbed2d588be91418997f003e26768c5de663160d89af54a1ee7.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n protocol_versions.id AS \"minor!\",\n protocol_versions.timestamp,\n protocol_versions.bootloader_code_hash,\n protocol_versions.default_account_code_hash,\n protocol_patches.patch,\n protocol_patches.snark_wrapper_vk_hash\n FROM\n protocol_versions\n JOIN protocol_patches ON protocol_patches.minor = protocol_versions.id\n WHERE\n id = $1\n ORDER BY\n protocol_patches.patch DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n protocol_versions.id AS \"minor!\",\n protocol_versions.timestamp,\n protocol_versions.bootloader_code_hash,\n protocol_versions.default_account_code_hash,\n protocol_patches.patch,\n protocol_patches.snark_wrapper_vk_hash\n FROM\n protocol_versions\n JOIN protocol_patches ON protocol_patches.minor = protocol_versions.id\n WHERE\n id = $1\n ORDER BY\n protocol_patches.patch DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -48,5 +48,5 @@ false ] }, - "hash": "85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc" + "hash": "c4e81f78ef078cbed2d588be91418997f003e26768c5de663160d89af54a1ee7" } diff --git a/core/lib/dal/.sqlx/query-cf8cff1e6d277088519ef7dfbdb1885d320c146cd8fad77c107ef12fa38e6c98.json b/core/lib/dal/.sqlx/query-cf8cff1e6d277088519ef7dfbdb1885d320c146cd8fad77c107ef12fa38e6c98.json deleted file mode 100644 index 1bd791a3f829..000000000000 --- a/core/lib/dal/.sqlx/query-cf8cff1e6d277088519ef7dfbdb1885d320c146cd8fad77c107ef12fa38e6c98.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT('gas_used', $16::BIGINT, 'storage_writes', $17::INT, 'contracts_used', $18::INT),\n $19,\n NOW(),\n NOW()\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info = JSONB_BUILD_OBJECT('gas_used', $16::BIGINT, 'storage_writes', $17::INT, 'contracts_used', $18::INT),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "is_replaced!", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Int8", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Numeric", - "Bytea", - "Jsonb", - "Int4", - "Bytea", - "Numeric", - "Bytea", - "Bytea", - "Int8", - "Int4", - "Int4", - "Timestamp" - ] - }, - "nullable": [ - null - ] - }, - "hash": "cf8cff1e6d277088519ef7dfbdb1885d320c146cd8fad77c107ef12fa38e6c98" -} diff --git a/core/lib/dal/.sqlx/query-d1490262c7a2a583928a611ae69eb0539849f7fd590712103db7d45d119caca2.json b/core/lib/dal/.sqlx/query-d1490262c7a2a583928a611ae69eb0539849f7fd590712103db7d45d119caca2.json new file mode 100644 index 000000000000..e3b05aff72a2 --- /dev/null +++ b/core/lib/dal/.sqlx/query-d1490262c7a2a583928a611ae69eb0539849f7fd590712103db7d45d119caca2.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n call_traces (tx_hash, call_trace)\n SELECT\n u.tx_hash,\n u.call_trace\n FROM\n UNNEST($1::bytea [], $2::bytea []) AS u (tx_hash, call_trace)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "ByteaArray" + ] + }, + "nullable": [] + }, + "hash": "d1490262c7a2a583928a611ae69eb0539849f7fd590712103db7d45d119caca2" +} diff --git a/core/lib/dal/.sqlx/query-ba2343a38e37d104786f9276d91f67d2ef1428c61ae84003c9b52b03204d1f0a.json b/core/lib/dal/.sqlx/query-d43ae07cf1539826363573d121392687cfe890fe89c748f836bad6eb0cc0fcf5.json similarity index 70% rename from core/lib/dal/.sqlx/query-ba2343a38e37d104786f9276d91f67d2ef1428c61ae84003c9b52b03204d1f0a.json rename to core/lib/dal/.sqlx/query-d43ae07cf1539826363573d121392687cfe890fe89c748f836bad6eb0cc0fcf5.json index ff6082651184..650b9f8d4399 100644 --- a/core/lib/dal/.sqlx/query-ba2343a38e37d104786f9276d91f67d2ef1428c61ae84003c9b52b03204d1f0a.json +++ b/core/lib/dal/.sqlx/query-d43ae07cf1539826363573d121392687cfe890fe89c748f836bad6eb0cc0fcf5.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n DELETE FROM transactions\n WHERE\n in_mempool = TRUE\n AND initiator_address = ANY ($1)\n ", + "query": "\n DELETE FROM transactions\n WHERE\n in_mempool = TRUE\n AND initiator_address = ANY($1)\n ", "describe": { "columns": [], "parameters": { @@ -10,5 +10,5 @@ }, "nullable": [] }, - "hash": "ba2343a38e37d104786f9276d91f67d2ef1428c61ae84003c9b52b03204d1f0a" + "hash": "d43ae07cf1539826363573d121392687cfe890fe89c748f836bad6eb0cc0fcf5" } diff --git a/core/lib/dal/.sqlx/query-ddfb7ba0592f1e6714a4496cee18e7265828e3ae78e391ef235b700f0adfe5e4.json b/core/lib/dal/.sqlx/query-ddfb7ba0592f1e6714a4496cee18e7265828e3ae78e391ef235b700f0adfe5e4.json new file mode 100644 index 000000000000..472c0cb26953 --- /dev/null +++ b/core/lib/dal/.sqlx/query-ddfb7ba0592f1e6714a4496cee18e7265828e3ae78e391ef235b700f0adfe5e4.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE proof_generation_details\n SET\n status = 'picked_by_prover',\n updated_at = NOW(),\n prover_taken_at = NOW()\n WHERE\n l1_batch_number = (\n SELECT\n l1_batch_number\n FROM\n proof_generation_details\n LEFT JOIN l1_batches ON l1_batch_number = l1_batches.number\n WHERE\n (\n vm_run_data_blob_url IS NOT NULL\n AND proof_gen_data_blob_url IS NOT NULL\n AND l1_batches.hash IS NOT NULL\n AND l1_batches.aux_data_hash IS NOT NULL\n AND l1_batches.meta_parameters_hash IS NOT NULL\n AND status = 'unpicked'\n )\n OR (\n status = 'picked_by_prover'\n AND prover_taken_at < NOW() - $1::INTERVAL\n )\n ORDER BY\n l1_batch_number ASC\n LIMIT\n 1\n )\n RETURNING\n proof_generation_details.l1_batch_number\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "l1_batch_number", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Interval" + ] + }, + "nullable": [ + false + ] + }, + "hash": "ddfb7ba0592f1e6714a4496cee18e7265828e3ae78e391ef235b700f0adfe5e4" +} diff --git a/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json b/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json index 2cd001b274da..8bae63790be7 100644 --- a/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json +++ b/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json @@ -182,6 +182,16 @@ "ordinal": 35, "name": "upgrade_id", "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" } ], "parameters": { @@ -225,6 +235,8 @@ false, true, true, + true, + true, true ] }, diff --git a/core/lib/dal/.sqlx/query-f3a049c7eb0d8903737f02fa154b50ebc862a133734382bad8fdfa3a93d8b743.json b/core/lib/dal/.sqlx/query-f3a049c7eb0d8903737f02fa154b50ebc862a133734382bad8fdfa3a93d8b743.json deleted file mode 100644 index 6869b4f50b18..000000000000 --- a/core/lib/dal/.sqlx/query-f3a049c7eb0d8903737f02fa154b50ebc862a133734382bad8fdfa3a93d8b743.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n upgrade_id,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n TRUE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n $16,\n NOW(),\n NOW()\n )\n ON CONFLICT (hash) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Jsonb", - "Int4", - "Bytea", - "Int4", - "Numeric", - "Bytea", - "Bytea", - "Int4", - "Numeric", - "Bytea", - "Timestamp" - ] - }, - "nullable": [] - }, - "hash": "f3a049c7eb0d8903737f02fa154b50ebc862a133734382bad8fdfa3a93d8b743" -} diff --git a/core/lib/dal/.sqlx/query-fce6fff384875df689dc422153a2745b90c68ebec5706b106ef69cb61333466e.json b/core/lib/dal/.sqlx/query-fce6fff384875df689dc422153a2745b90c68ebec5706b106ef69cb61333466e.json new file mode 100644 index 000000000000..8c4129fec07a --- /dev/null +++ b/core/lib/dal/.sqlx/query-fce6fff384875df689dc422153a2745b90c68ebec5706b106ef69cb61333466e.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n gas_limit,\n max_fee_per_gas,\n gas_per_pubdata_limit,\n data,\n upgrade_id,\n contract_address,\n l1_block_number,\n value,\n paymaster,\n paymaster_input,\n tx_format,\n l1_tx_mint,\n l1_tx_refund_recipient,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n TRUE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n $16,\n NOW(),\n NOW()\n )\n ON CONFLICT (hash) DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Bytea", + "Bytea", + "Numeric", + "Numeric", + "Numeric", + "Jsonb", + "Int4", + "Bytea", + "Int4", + "Numeric", + "Bytea", + "Bytea", + "Int4", + "Numeric", + "Bytea", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "fce6fff384875df689dc422153a2745b90c68ebec5706b106ef69cb61333466e" +} diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql new file mode 100644 index 000000000000..b39ad42a73e8 --- /dev/null +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE transactions DROP COLUMN block_timestamp_range_start; +ALTER TABLE transactions DROP COLUMN block_timestamp_range_end; \ No newline at end of file diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql new file mode 100644 index 000000000000..f6a9e2970a95 --- /dev/null +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE transactions ADD COLUMN block_timestamp_range_start TIMESTAMP DEFAULT NULL; +ALTER TABLE transactions ADD COLUMN block_timestamp_range_end TIMESTAMP DEFAULT NULL; \ No newline at end of file diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 3d17a919a073..715cb9bcfc72 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -774,7 +774,7 @@ mod tests { block::{L2BlockHasher, L2BlockHeader}, Address, L2BlockNumber, ProtocolVersion, ProtocolVersionId, }; - use zksync_vm_interface::TransactionExecutionMetrics; + use zksync_vm_interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use super::*; use crate::{ @@ -1061,7 +1061,11 @@ mod tests { let mut tx_results = vec![]; for (i, tx) in transactions.into_iter().enumerate() { conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); let mut tx_result = mock_execution_result(tx); diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index bb219ee1d61b..b79ae3fd1031 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -68,6 +68,9 @@ pub struct StorageTransaction { pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, + pub block_timestamp_range_start: Option, + pub block_timestamp_range_end: Option, + // DEPRECATED. pub l1_block_number: Option, } diff --git a/core/lib/dal/src/pruning_dal/tests.rs b/core/lib/dal/src/pruning_dal/tests.rs index 4f94ff7f63d3..70dda48d8c82 100644 --- a/core/lib/dal/src/pruning_dal/tests.rs +++ b/core/lib/dal/src/pruning_dal/tests.rs @@ -5,7 +5,7 @@ use zksync_types::{ tx::IncludedTxLocation, AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersion, ProtocolVersionId, StorageKey, StorageLog, H256, }; -use zksync_vm_interface::TransactionExecutionMetrics; +use zksync_vm_interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use super::*; use crate::{ @@ -457,7 +457,11 @@ async fn transactions_are_handled_correctly_after_pruning() { let tx = mock_l2_transaction(); let tx_hash = tx.hash(); conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); conn.blocks_dal() diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index ec6ee0f92812..21060eab972b 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -108,7 +108,7 @@ mod tests { block::{L1BatchHeader, L2BlockHeader}, Address, L1BatchNumber, ProtocolVersion, ProtocolVersionId, Transaction, }; - use zksync_vm_interface::TransactionExecutionMetrics; + use zksync_vm_interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use super::*; use crate::{ @@ -163,7 +163,11 @@ mod tests { }; let tx = mock_l2_transaction(); conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); conn.blocks_dal() diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index dc672fa1f807..10b12f19561f 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -16,8 +16,8 @@ use zksync_types::{ L2ChainId, PriorityOpId, ProtocolVersion, ProtocolVersionId, H160, H256, U256, }; use zksync_vm_interface::{ - TransactionExecutionMetrics, TransactionExecutionResult, TxExecutionStatus, VmEvent, - VmExecutionMetrics, + tracer::ValidationTraces, TransactionExecutionMetrics, TransactionExecutionResult, + TxExecutionStatus, VmEvent, VmExecutionMetrics, }; use crate::{ @@ -206,14 +206,22 @@ async fn workflow_with_submit_tx_equal_hashes() { let tx = mock_l2_transaction(); let result = transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); assert_eq!(result, L2TxSubmissionResult::Added); let result = transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); @@ -232,7 +240,11 @@ async fn workflow_with_submit_tx_diff_hashes() { let initiator_address = tx.common_data.initiator_address; let result = transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); @@ -242,7 +254,11 @@ async fn workflow_with_submit_tx_diff_hashes() { tx.common_data.nonce = nonce; tx.common_data.initiator_address = initiator_address; let result = transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); @@ -266,13 +282,21 @@ async fn remove_stuck_txs() { let mut tx = mock_l2_transaction(); tx.received_timestamp_ms = unix_timestamp_ms() - Duration::new(1000, 0).as_millis() as u64; transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); // Tx in mempool let tx = mock_l2_transaction(); transactions_dal - .insert_transaction_l2(&tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); @@ -289,7 +313,11 @@ async fn remove_stuck_txs() { executed_tx.received_timestamp_ms = unix_timestamp_ms() - Duration::new(1000, 0).as_millis() as u64; transactions_dal - .insert_transaction_l2(&executed_tx, mock_tx_execution_metrics()) + .insert_transaction_l2( + &executed_tx, + mock_tx_execution_metrics(), + ValidationTraces::default(), + ) .await .unwrap(); diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 408837d699e6..965c0db4615c 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -16,7 +16,8 @@ use zksync_types::{ }; use zksync_utils::u256_to_big_decimal; use zksync_vm_interface::{ - Call, TransactionExecutionMetrics, TransactionExecutionResult, TxExecutionStatus, + tracer::ValidationTraces, Call, TransactionExecutionMetrics, TransactionExecutionResult, + TxExecutionStatus, }; use crate::{ @@ -263,6 +264,7 @@ impl TransactionsDal<'_, '_> { &mut self, tx: &L2Tx, exec_info: TransactionExecutionMetrics, + validation_traces: ValidationTraces, ) -> DalResult { let tx_hash = tx.hash(); let is_duplicate = sqlx::query!( @@ -313,6 +315,12 @@ impl TransactionsDal<'_, '_> { let nanosecs = ((tx.received_timestamp_ms % 1000) * 1_000_000) as u32; #[allow(deprecated)] let received_at = NaiveDateTime::from_timestamp_opt(secs, nanosecs).unwrap(); + let block_timestamp_range_start = validation_traces + .range_start + .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); + let block_timestamp_range_end = validation_traces + .range_end + .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); // Besides just adding or updating(on conflict) the record, we want to extract some info // from the query below, to indicate what actually happened: // 1) transaction is added @@ -346,7 +354,9 @@ impl TransactionsDal<'_, '_> { execution_info, received_at, created_at, - updated_at + updated_at, + block_timestamp_range_start, + block_timestamp_range_end ) VALUES ( @@ -369,7 +379,9 @@ impl TransactionsDal<'_, '_> { JSONB_BUILD_OBJECT('gas_used', $16::BIGINT, 'storage_writes', $17::INT, 'contracts_used', $18::INT), $19, NOW(), - NOW() + NOW(), + $20, + $21 ) ON CONFLICT (initiator_address, nonce) DO UPDATE @@ -392,7 +404,9 @@ impl TransactionsDal<'_, '_> { received_at = $19, created_at = NOW(), updated_at = NOW(), - error = NULL + error = NULL, + block_timestamp_range_start = $20, + block_timestamp_range_end = $21 WHERE transactions.is_priority = FALSE AND transactions.miniblock_number IS NULL @@ -425,7 +439,9 @@ impl TransactionsDal<'_, '_> { exec_info.gas_used as i64, (exec_info.initial_storage_writes + exec_info.repeated_storage_writes) as i32, exec_info.contracts_used as i32, - received_at + received_at, + block_timestamp_range_start, + block_timestamp_range_end, ) .instrument("insert_transaction_l2") .with_arg("tx_hash", &tx_hash) @@ -2211,7 +2227,11 @@ mod tests { let tx = mock_l2_transaction(); let tx_hash = tx.hash(); conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); let mut tx_result = mock_execution_result(tx); diff --git a/core/lib/dal/src/transactions_web3_dal.rs b/core/lib/dal/src/transactions_web3_dal.rs index f5a3c492f8af..ad61da0e1d14 100644 --- a/core/lib/dal/src/transactions_web3_dal.rs +++ b/core/lib/dal/src/transactions_web3_dal.rs @@ -489,7 +489,7 @@ mod tests { use std::collections::HashMap; use zksync_types::{l2::L2Tx, Nonce, ProtocolVersion, ProtocolVersionId}; - use zksync_vm_interface::TransactionExecutionMetrics; + use zksync_vm_interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use super::*; use crate::{ @@ -505,7 +505,11 @@ mod tests { for tx in &txs { conn.transactions_dal() - .insert_transaction_l2(tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); } @@ -685,7 +689,11 @@ mod tests { tx.common_data.initiator_address = initiator; tx_by_nonce.insert(nonce, tx.clone()); conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); } @@ -754,7 +762,11 @@ mod tests { tx.common_data.nonce = Nonce(1); tx.common_data.initiator_address = initiator; conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); diff --git a/core/node/api_server/src/tx_sender/master_pool_sink.rs b/core/node/api_server/src/tx_sender/master_pool_sink.rs index 736edf0b2475..06333f0c1369 100644 --- a/core/node/api_server/src/tx_sender/master_pool_sink.rs +++ b/core/node/api_server/src/tx_sender/master_pool_sink.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::{Entry, HashMap}; use tokio::sync::Mutex; use zksync_dal::{transactions_dal::L2TxSubmissionResult, ConnectionPool, Core, CoreDal}; -use zksync_multivm::interface::TransactionExecutionMetrics; +use zksync_multivm::interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use zksync_shared_metrics::{TxStage, APP_METRICS}; use zksync_types::{l2::L2Tx, Address, Nonce, H256}; @@ -31,6 +31,7 @@ impl TxSink for MasterPoolSink { &self, tx: &L2Tx, execution_metrics: TransactionExecutionMetrics, + validation_traces: ValidationTraces, ) -> Result { let address_and_nonce = (tx.initiator_account(), tx.nonce()); @@ -55,7 +56,7 @@ impl TxSink for MasterPoolSink { let result = match self.master_pool.connection_tagged("api").await { Ok(mut connection) => connection .transactions_dal() - .insert_transaction_l2(tx, execution_metrics) + .insert_transaction_l2(tx, execution_metrics, validation_traces) .await .inspect(|submission_res_handle| { APP_METRICS.processed_txs[&TxStage::Mempool(*submission_res_handle)].inc(); diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 54ac29628dab..d67199338075 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -360,7 +360,7 @@ impl TxSender { let submission_res_handle = self .0 .tx_sink - .submit_tx(&tx, execution_output.metrics) + .submit_tx(&tx, execution_output.metrics, validation_result.unwrap()) .await?; match submission_res_handle { diff --git a/core/node/api_server/src/tx_sender/proxy.rs b/core/node/api_server/src/tx_sender/proxy.rs index 536a9767c1f2..bba462404cf0 100644 --- a/core/node/api_server/src/tx_sender/proxy.rs +++ b/core/node/api_server/src/tx_sender/proxy.rs @@ -11,7 +11,7 @@ use zksync_dal::{ helpers::wait_for_l1_batch, transactions_dal::L2TxSubmissionResult, Connection, ConnectionPool, Core, CoreDal, DalError, }; -use zksync_multivm::interface::TransactionExecutionMetrics; +use zksync_multivm::interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use zksync_shared_metrics::{TxStage, APP_METRICS}; use zksync_types::{api, l2::L2Tx, Address, Nonce, H256, U256}; use zksync_web3_decl::{ @@ -309,6 +309,7 @@ impl TxSink for TxProxy { &self, tx: &L2Tx, _execution_metrics: TransactionExecutionMetrics, + _validation_traces: ValidationTraces, ) -> Result { // We're running an external node: we have to proxy the transaction to the main node. // But before we do that, save the tx to cache in case someone will request it @@ -416,7 +417,11 @@ mod tests { let proxy = TxProxy::new(Box::new(main_node_client)); proxy - .submit_tx(&tx, TransactionExecutionMetrics::default()) + .submit_tx( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); assert!(send_tx_called.load(Ordering::Relaxed)); @@ -525,7 +530,11 @@ mod tests { let proxy = TxProxy::new(Box::new(main_node_client)); proxy - .submit_tx(&tx, TransactionExecutionMetrics::default()) + .submit_tx( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap_err(); @@ -585,7 +594,11 @@ mod tests { // Add transaction to the cache let proxy = TxProxy::new(Box::new(main_node_client)); proxy - .submit_tx(&tx, TransactionExecutionMetrics::default()) + .submit_tx( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); assert_eq!(proxy.tx_cache.get(tx.hash()).await.unwrap(), tx); @@ -662,15 +675,27 @@ mod tests { .build(); let proxy = TxProxy::new(Box::new(main_node_client)); proxy - .submit_tx(&tx, TransactionExecutionMetrics::default()) + .submit_tx( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); proxy - .submit_tx(&replacing_tx, TransactionExecutionMetrics::default()) + .submit_tx( + &replacing_tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); proxy - .submit_tx(&future_tx, TransactionExecutionMetrics::default()) + .submit_tx( + &future_tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); { diff --git a/core/node/api_server/src/tx_sender/tx_sink.rs b/core/node/api_server/src/tx_sender/tx_sink.rs index 3d764816fe0d..1a6a7a733ccd 100644 --- a/core/node/api_server/src/tx_sender/tx_sink.rs +++ b/core/node/api_server/src/tx_sender/tx_sink.rs @@ -1,5 +1,5 @@ use zksync_dal::{transactions_dal::L2TxSubmissionResult, Connection, Core}; -use zksync_multivm::interface::TransactionExecutionMetrics; +use zksync_multivm::interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use zksync_types::{ api::{Transaction, TransactionDetails, TransactionId}, l2::L2Tx, @@ -28,6 +28,7 @@ pub trait TxSink: std::fmt::Debug + Send + Sync + 'static { &self, tx: &L2Tx, execution_metrics: TransactionExecutionMetrics, + validation_traces: ValidationTraces, ) -> Result; /// Attempts to look up the pending nonce for the account in the sink-specific storage. diff --git a/core/node/api_server/src/web3/tests/mod.rs b/core/node/api_server/src/web3/tests/mod.rs index 632e263c6536..10a795e50765 100644 --- a/core/node/api_server/src/web3/tests/mod.rs +++ b/core/node/api_server/src/web3/tests/mod.rs @@ -18,8 +18,8 @@ use zksync_config::{ }; use zksync_dal::{transactions_dal::L2TxSubmissionResult, Connection, ConnectionPool, CoreDal}; use zksync_multivm::interface::{ - TransactionExecutionMetrics, TransactionExecutionResult, TxExecutionStatus, VmEvent, - VmExecutionMetrics, + tracer::ValidationTraces, TransactionExecutionMetrics, TransactionExecutionResult, + TxExecutionStatus, VmEvent, VmExecutionMetrics, }; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{ @@ -318,7 +318,11 @@ async fn store_custom_l2_block( let l2_tx = result.transaction.clone().try_into().unwrap(); let tx_submission_result = storage .transactions_dal() - .insert_transaction_l2(&l2_tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &l2_tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); assert_matches!(tx_submission_result, L2TxSubmissionResult::Added); @@ -721,7 +725,11 @@ impl HttpTest for TransactionCountTest { pending_tx.common_data.nonce = Nonce(2); storage .transactions_dal() - .insert_transaction_l2(&pending_tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &pending_tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); @@ -801,7 +809,11 @@ impl HttpTest for TransactionCountAfterSnapshotRecoveryTest { let mut storage = pool.connection().await?; storage .transactions_dal() - .insert_transaction_l2(&pending_tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &pending_tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); 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 7ef466805e36..216fae850dff 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 @@ -456,7 +456,7 @@ impl L2BlockSealSubtask for InsertL2ToL1LogsSubtask { mod tests { use zksync_dal::{ConnectionPool, Core}; use zksync_multivm::{ - interface::{TransactionExecutionResult, TxExecutionStatus}, + interface::{tracer::ValidationTraces, TransactionExecutionResult, TxExecutionStatus}, utils::{get_max_batch_gas_limit, get_max_gas_per_pubdata_byte}, zk_evm_latest::ethereum_types::H256, VmVersion, @@ -484,7 +484,7 @@ mod tests { .await .unwrap() .transactions_dal() - .insert_transaction_l2(&tx, Default::default()) + .insert_transaction_l2(&tx, Default::default(), ValidationTraces::default()) .await .unwrap(); let tx_hash = tx.hash(); diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 7ea01e6af1e8..ab176462b7de 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -5,7 +5,9 @@ use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{ConnectionPool, Core, CoreDal}; use zksync_mempool::L2TxFilter; use zksync_multivm::{ - interface::{TransactionExecutionMetrics, VmEvent, VmExecutionMetrics}, + interface::{ + tracer::ValidationTraces, TransactionExecutionMetrics, VmEvent, VmExecutionMetrics, + }, utils::derive_base_fee_and_gas_per_pubdata, }; use zksync_node_test_utils::prepare_recovery_snapshot; @@ -429,7 +431,11 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom ); storage .transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); diff --git a/core/node/state_keeper/src/mempool_actor.rs b/core/node/state_keeper/src/mempool_actor.rs index dbe1e4cb977f..a5cec5b5a318 100644 --- a/core/node/state_keeper/src/mempool_actor.rs +++ b/core/node/state_keeper/src/mempool_actor.rs @@ -158,7 +158,7 @@ async fn get_transaction_nonces( #[cfg(test)] mod tests { - use zksync_multivm::interface::TransactionExecutionMetrics; + use zksync_multivm::interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use zksync_node_fee_model::MockBatchFeeParamsProvider; use zksync_node_genesis::{insert_genesis_batch, GenesisParams}; use zksync_node_test_utils::create_l2_transaction; @@ -246,7 +246,11 @@ mod tests { let mut storage = pool.connection().await.unwrap(); storage .transactions_dal() - .insert_transaction_l2(&transaction, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &transaction, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); drop(storage); @@ -302,7 +306,11 @@ mod tests { let mut storage = pool.connection().await.unwrap(); storage .transactions_dal() - .insert_transaction_l2(&transaction, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &transaction, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); drop(storage); @@ -355,7 +363,11 @@ mod tests { .unwrap(); storage .transactions_dal() - .insert_transaction_l2(&transaction, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &transaction, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); drop(storage); diff --git a/core/node/vm_runner/src/tests/mod.rs b/core/node/vm_runner/src/tests/mod.rs index 53bef106a8f4..1245a5f32e39 100644 --- a/core/node/vm_runner/src/tests/mod.rs +++ b/core/node/vm_runner/src/tests/mod.rs @@ -20,7 +20,9 @@ use zksync_types::{ StorageLog, StorageLogKind, StorageValue, H160, H256, L2_BASE_TOKEN_ADDRESS, U256, }; use zksync_utils::{bytecode::hash_bytecode, h256_to_u256, u256_to_h256}; -use zksync_vm_interface::{L1BatchEnv, L2BlockEnv, SystemEnv, TransactionExecutionMetrics}; +use zksync_vm_interface::{ + tracer::ValidationTraces, L1BatchEnv, L2BlockEnv, SystemEnv, TransactionExecutionMetrics, +}; use super::*; @@ -242,7 +244,11 @@ async fn store_l1_batches( let account = accounts.choose_mut(&mut rng).unwrap(); let tx = create_l2_transaction(account, 1000000, 100); conn.transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await?; let mut logs = Vec::new(); let mut written_keys = Vec::new(); From c65a2c084d58d8330371cdd5754093afb2fd1203 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 12:00:51 +0100 Subject: [PATCH 05/68] Clean up custom accounts --- .../contracts/custom-account/custom-account.sol | 4 +++- .../contracts/custom-account/custom-account.sol | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tests/ts-integration/contracts/custom-account/custom-account.sol b/core/tests/ts-integration/contracts/custom-account/custom-account.sol index b9e59a9cea69..53241aae6063 100644 --- a/core/tests/ts-integration/contracts/custom-account/custom-account.sol +++ b/core/tests/ts-integration/contracts/custom-account/custom-account.sol @@ -34,7 +34,9 @@ contract CustomAccount is IAccount { function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { ITimestampAsserter timestampAsserter = ITimestampAsserter(timestampAsserterAddress); - // number of seconds up to 30/12/2050 + // This assertion exists to ensure that block.timestamp can be asserted in AA by using + // ITimestampAsserter contract + // 2555971200 is a number of seconds up to 30/12/2050 timestampAsserter.assertTimestampInRange(0, 2555971200); magic = _validateTransaction(_suggestedSignedTxHash, _transaction); diff --git a/etc/contracts-test-data/contracts/custom-account/custom-account.sol b/etc/contracts-test-data/contracts/custom-account/custom-account.sol index bb876bc6a2cd..7601f5cd7b87 100644 --- a/etc/contracts-test-data/contracts/custom-account/custom-account.sol +++ b/etc/contracts-test-data/contracts/custom-account/custom-account.sol @@ -24,8 +24,6 @@ contract CustomAccount is IAccount { bytes4 constant EIP1271_SUCCESS_RETURN_VALUE = 0x1626ba7e; function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { - require(block.timestamp > 0, "Hello"); - // By default we consider the transaction as successful magic = VALIDATION_SUCCESS_MAGIC; From 28af0e3bd25ac3ff66d2aaa61e44f7ca58c5d3b4 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 12:20:41 +0100 Subject: [PATCH 06/68] fix test --- core/lib/env_config/src/contracts.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/lib/env_config/src/contracts.rs b/core/lib/env_config/src/contracts.rs index 298c43b80ccd..6d5db4979460 100644 --- a/core/lib/env_config/src/contracts.rs +++ b/core/lib/env_config/src/contracts.rs @@ -72,6 +72,7 @@ mod tests { }), base_token_addr: Some(SHARED_BRIDGE_ETHER_TOKEN_ADDRESS), chain_admin_addr: Some(addr("0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347ff")), + l2_timestamp_asserter_addr: Some(addr("0x0000000000000000000000000000000000000002")), } } @@ -98,6 +99,7 @@ CONTRACTS_STATE_TRANSITION_PROXY_ADDR="0xd90f1c081c6117241624e97cb6147257c3cb209 CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR="0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347e5" CONTRACTS_BASE_TOKEN_ADDR="0x0000000000000000000000000000000000000001" CONTRACTS_CHAIN_ADMIN_ADDR="0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347ff" +CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR="0x0000000000000000000000000000000000000002" "#; lock.set_env(config); From 46c11bf4a3d778881f587ec4e8f39bc6c0c9a953 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 12:31:03 +0100 Subject: [PATCH 07/68] Allow deprecated function --- core/lib/dal/src/transactions_dal.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 7041fd5f5428..8c5d18beac4a 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -315,9 +315,11 @@ impl TransactionsDal<'_, '_> { let nanosecs = ((tx.received_timestamp_ms % 1000) * 1_000_000) as u32; #[allow(deprecated)] let received_at = NaiveDateTime::from_timestamp_opt(secs, nanosecs).unwrap(); + #[allow(deprecated)] let block_timestamp_range_start = validation_traces .range_start .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); + #[allow(deprecated)] let block_timestamp_range_end = validation_traces .range_end .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); From 82628d3ed537eefa9011493972eaa71fd6f45971 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 12:46:20 +0100 Subject: [PATCH 08/68] Fix compilation errors --- core/bin/external_node/src/config/mod.rs | 1 + core/node/api_server/src/tx_sender/tests/mod.rs | 2 +- core/node/state_keeper/src/io/common/tests.rs | 8 ++++++-- core/node/state_keeper/src/io/tests/tester.rs | 10 ++++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 56ee3edfd253..5a8f08096761 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1439,6 +1439,7 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { chain_id: config.required.l2_chain_id, // Does not matter for EN. whitelisted_tokens_for_aa: Default::default(), + timestamp_asserter_addr: None, } } } diff --git a/core/node/api_server/src/tx_sender/tests/mod.rs b/core/node/api_server/src/tx_sender/tests/mod.rs index 3d48e320abcb..4d25162e7684 100644 --- a/core/node/api_server/src/tx_sender/tests/mod.rs +++ b/core/node/api_server/src/tx_sender/tests/mod.rs @@ -154,7 +154,7 @@ async fn create_real_tx_sender(pool: ConnectionPool) -> TxSender { .unwrap(); let pg_caches = PostgresStorageCaches::new(1, 1); - let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX); + let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX, None); create_test_tx_sender(pool, genesis_params.config().l2_chain_id, tx_executor) .await .0 diff --git a/core/node/state_keeper/src/io/common/tests.rs b/core/node/state_keeper/src/io/common/tests.rs index b2a24acb4956..eadd4c5e4650 100644 --- a/core/node/state_keeper/src/io/common/tests.rs +++ b/core/node/state_keeper/src/io/common/tests.rs @@ -9,7 +9,7 @@ use futures::FutureExt; use zksync_config::GenesisConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{ConnectionPool, Core}; -use zksync_multivm::interface::TransactionExecutionMetrics; +use zksync_multivm::interface::{tracer::ValidationTraces, TransactionExecutionMetrics}; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{ create_l1_batch, create_l2_block, create_l2_transaction, execute_l2_transaction, @@ -355,7 +355,11 @@ async fn store_pending_l2_blocks( let tx = create_l2_transaction(10, 100); storage .transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); let mut new_l2_block = create_l2_block(l2_block_number); diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 2dc45a5eaaa0..ed01e93dd3ae 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -11,7 +11,9 @@ use zksync_contracts::BaseSystemContracts; use zksync_dal::{ConnectionPool, Core, CoreDal}; use zksync_eth_client::{clients::MockSettlementLayer, BaseFees}; use zksync_multivm::{ - interface::{TransactionExecutionMetrics, TransactionExecutionResult}, + interface::{ + tracer::ValidationTraces, TransactionExecutionMetrics, TransactionExecutionResult, + }, vm_latest::constants::BATCH_COMPUTATIONAL_GAS_LIMIT, }; use zksync_node_fee_model::{ @@ -175,7 +177,11 @@ impl Tester { let tx = create_l2_transaction(10, 100); storage .transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); storage From a1972f48f4256465bfb676002d7c89066c6fca5e Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 13:19:40 +0100 Subject: [PATCH 09/68] Change refcell to mutex --- core/lib/multivm/src/tracers/validator/mod.rs | 12 +++++++---- .../src/tracers/validator/vm_latest/mod.rs | 20 ++++++++++--------- core/lib/vm_executor/src/oneshot/mod.rs | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index 82eb821b04ae..d2c8a769bafe 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -1,4 +1,8 @@ -use std::{cell::RefCell, collections::HashSet, marker::PhantomData, sync::Arc}; +use std::{ + collections::HashSet, + marker::PhantomData, + sync::{Arc, Mutex}, +}; use once_cell::sync::OnceCell; use zksync_system_constants::{ @@ -47,7 +51,7 @@ pub struct ValidationTracer { timestamp_asserter_address: Option
, vm_version: VmVersion, pub result: Arc>, - pub traces: Arc>, + pub traces: Arc>, _marker: PhantomData H>, } @@ -60,10 +64,10 @@ impl ValidationTracer { ) -> ( Self, Arc>, - Arc>, + Arc>, ) { let result = Arc::new(OnceCell::new()); - let traces = Arc::new(RefCell::new(ValidationTraces::default())); + let traces = Arc::new(Mutex::new(ValidationTraces::default())); ( Self { validation_mode: ValidationTracerMode::NoValidation, diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index eee919a966af..325715c41c2e 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -105,15 +105,17 @@ impl ValidationTracer { ); let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); - let mut traces_mut = self.traces.borrow_mut(); - traces_mut.range_start = match traces_mut.range_start { - Some(current_value) => Some(cmp::max(current_value, start)), - None => Some(start), - }; - traces_mut.range_end = match traces_mut.range_end { - Some(current_value) => Some(cmp::min(current_value, end)), - None => Some(end), - }; + { + let mut traces_mut = self.traces.lock().unwrap(); + traces_mut.range_start = match traces_mut.range_start { + Some(current_value) => Some(cmp::max(current_value, start)), + None => Some(start), + }; + traces_mut.range_end = match traces_mut.range_end { + Some(current_value) => Some(cmp::min(current_value, end)), + None => Some(end), + }; + } } } } diff --git a/core/lib/vm_executor/src/oneshot/mod.rs b/core/lib/vm_executor/src/oneshot/mod.rs index 61f1ce37a844..1fa8a8769dc8 100644 --- a/core/lib/vm_executor/src/oneshot/mod.rs +++ b/core/lib/vm_executor/src/oneshot/mod.rs @@ -174,7 +174,7 @@ where match (exec_result.result, validation_result) { (_, Err(violated_rule)) => Err(ValidationError::ViolatedRule(violated_rule)), (ExecutionResult::Halt { reason }, _) => Err(ValidationError::FailedTx(reason)), - _ => Ok(validation_traces.borrow().clone()), + _ => Ok(validation_traces.lock().unwrap().clone()), } }) .await From 0892349453d921410264887f020c664e167231b0 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 13:55:17 +0100 Subject: [PATCH 10/68] Switched to the latest contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index bce4b2d0f34b..2ff97e2549ee 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit bce4b2d0f34bd87f1aaadd291772935afb1c3bd6 +Subproject commit 2ff97e2549ee9100b7860b40c68c12bcba0cab3c From 547a9fe5b76d9803f594946e8c78853d446db9ef Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 15:33:40 +0100 Subject: [PATCH 11/68] latest contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 2ff97e2549ee..7c823ef65591 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 2ff97e2549ee9100b7860b40c68c12bcba0cab3c +Subproject commit 7c823ef65591110968e7755ccbf1a5b740177219 From 5b28a9d424b99474a8ad9d40832115add26aa9c2 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 8 Oct 2024 16:38:26 +0100 Subject: [PATCH 12/68] Update contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 7c823ef65591..142222a62c32 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 7c823ef65591110968e7755ccbf1a5b740177219 +Subproject commit 142222a62c32466868699edc996a61f6c592880a From 86cad9f6229cb2a2323016405e4903e538748d87 Mon Sep 17 00:00:00 2001 From: Danil Date: Wed, 9 Oct 2024 10:55:57 +0200 Subject: [PATCH 13/68] Fix building contracts Signed-off-by: Danil --- .github/workflows/new-build-core-template.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index fba6a68b8eec..fa7cfb7970f6 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -59,11 +59,13 @@ jobs: if [ $(jq length <<<"$tags") -eq 0 ]; then echo "No tag found on all pages." echo "BUILD_CONTRACTS=true" >> "$GITHUB_ENV" + mkdir -p contracts/l1-contracts/artifacts/ exit 0 fi filtered_tag=$(jq -r --arg commit_sha "$commit_sha" 'map(select(.commit.sha == $commit_sha)) | .[].name' <<<"$tags") if [[ ! -z "$filtered_tag" ]]; then echo "BUILD_CONTRACTS=false" >> "$GITHUB_ENV" + mkdir -p contracts/l1-contracts/out break fi ((page++)) @@ -76,6 +78,8 @@ jobs: tar -C ./contracts -zxf l1-contracts.tar.gz tar -C ./contracts -zxf l2-contracts.tar.gz tar -C ./contracts -zxf system-contracts.tar.gz + # TODO Remove mkdir once we use foundry inside contracts repo + mkdir -p contracts/l1-contracts/out - name: Install Apt dependencies shell: bash From c724a3f28982c11dab7c5d88dfb86552a8faadbd Mon Sep 17 00:00:00 2001 From: Danil Date: Wed, 9 Oct 2024 11:50:38 +0200 Subject: [PATCH 14/68] mkdir Signed-off-by: Danil --- .github/workflows/new-build-core-template.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index fa7cfb7970f6..8a0c6df0c48c 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -144,6 +144,9 @@ jobs: run: | cp etc/tokens/{test,localhost}.json zk_supervisor contracts + # TODO Remove mkdir once we use foundry inside contracts repo + mkdir -p contracts/l1-contracts/artifacts/ + - name: Upload contracts uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 From 8ba4a04bd1294fe3e9bc8b1b4aa933b99935f06b Mon Sep 17 00:00:00 2001 From: Danil Date: Wed, 9 Oct 2024 11:59:39 +0200 Subject: [PATCH 15/68] Fix building contracts Signed-off-by: Danil --- .github/workflows/new-build-core-template.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index 8a0c6df0c48c..f94bf3b3bfe9 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -59,13 +59,11 @@ jobs: if [ $(jq length <<<"$tags") -eq 0 ]; then echo "No tag found on all pages." echo "BUILD_CONTRACTS=true" >> "$GITHUB_ENV" - mkdir -p contracts/l1-contracts/artifacts/ exit 0 fi filtered_tag=$(jq -r --arg commit_sha "$commit_sha" 'map(select(.commit.sha == $commit_sha)) | .[].name' <<<"$tags") if [[ ! -z "$filtered_tag" ]]; then echo "BUILD_CONTRACTS=false" >> "$GITHUB_ENV" - mkdir -p contracts/l1-contracts/out break fi ((page++)) @@ -143,9 +141,9 @@ jobs: shell: bash run: | cp etc/tokens/{test,localhost}.json - zk_supervisor contracts # TODO Remove mkdir once we use foundry inside contracts repo mkdir -p contracts/l1-contracts/artifacts/ + zk_supervisor contracts - name: Upload contracts From 4a30b868c30ff261e2abe83b3e503f1141819458 Mon Sep 17 00:00:00 2001 From: Danil Date: Wed, 9 Oct 2024 12:04:34 +0200 Subject: [PATCH 16/68] Create artifacts Signed-off-by: Danil --- .github/workflows/new-build-core-template.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index f94bf3b3bfe9..9a88f927e635 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -141,8 +141,6 @@ jobs: shell: bash run: | cp etc/tokens/{test,localhost}.json - # TODO Remove mkdir once we use foundry inside contracts repo - mkdir -p contracts/l1-contracts/artifacts/ zk_supervisor contracts @@ -212,6 +210,14 @@ jobs: path: | ./contracts + # TODO Remove it when we migrate to foundry inside contracts repository + - name: Create necessary artefacts + shell: bash + run: | + mkdir -p contracts/l1-contracts/artifacts/ + mkdir -p contracts/l1-contracts/out + + - name: login to Docker registries if: ${{ inputs.action == 'push' }} shell: bash From 173fb29f6ba547fe1cc17e9174db3e2c36fb25e3 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 10 Oct 2024 13:28:21 +0100 Subject: [PATCH 17/68] Add timestamp asserter ranges --- contracts | 2 +- core/bin/external_node/src/config/mod.rs | 4 +- core/bin/zksync_server/src/main.rs | 3 +- core/bin/zksync_server/src/node_builder.rs | 2 + core/lib/config/src/configs/chain.rs | 10 +++- core/lib/config/src/configs/general.rs | 6 ++- core/lib/config/src/testonly.rs | 14 ++++- ...90c5629fa3c8776e60d993bd365d27669754.json} | 4 +- ...c5223c9d5e2e42d89bb456d24c601edc06a05.json | 40 -------------- core/lib/dal/src/transactions_dal.rs | 8 +++ core/lib/env_config/src/lib.rs | 1 + core/lib/env_config/src/timestamp_asserter.rs | 54 +++++++++++++++++++ core/lib/multivm/src/tracers/validator/mod.rs | 7 +++ core/lib/protobuf_config/src/general.rs | 5 ++ core/lib/protobuf_config/src/lib.rs | 1 + .../src/proto/config/general.proto | 2 + .../src/proto/config/timestamp_asserter.proto | 8 +++ .../protobuf_config/src/timestamp_asserter.rs | 19 +++++++ core/lib/vm_interface/src/types/tracer.rs | 4 ++ .../src/temp_config_store/mod.rs | 5 +- .../src/execution_sandbox/execute.rs | 8 +++ .../src/execution_sandbox/validate.rs | 6 +++ core/node/api_server/src/tx_sender/mod.rs | 19 +++++-- core/node/api_server/src/web3/testonly.rs | 7 ++- 24 files changed, 184 insertions(+), 55 deletions(-) rename core/lib/dal/.sqlx/{query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json => query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json} (87%) delete mode 100644 core/lib/dal/.sqlx/query-ca428423f278feea2942fd2c78fc5223c9d5e2e42d89bb456d24c601edc06a05.json create mode 100644 core/lib/env_config/src/timestamp_asserter.rs create mode 100644 core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto create mode 100644 core/lib/protobuf_config/src/timestamp_asserter.rs diff --git a/contracts b/contracts index 142222a62c32..69ee5349cdcb 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 142222a62c32466868699edc996a61f6c592880a +Subproject commit 69ee5349cdcb95228bb288f8f12470fe466af94d diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 5a8f08096761..33df59074488 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1439,7 +1439,9 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { chain_id: config.required.l2_chain_id, // Does not matter for EN. whitelisted_tokens_for_aa: Default::default(), - timestamp_asserter_addr: None, + timestamp_asserter_address: None, + timestamp_asserter_min_range_sec: 0, + timestamp_asserter_min_time_till_end_sec: 0, } } } diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index da0a93f624df..8a461b995b3c 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -7,7 +7,7 @@ use zksync_config::{ api::{HealthCheckConfig, MerkleTreeApiConfig, Web3JsonRpcConfig}, chain::{ CircuitBreakerConfig, MempoolConfig, NetworkConfig, OperationsManagerConfig, - StateKeeperConfig, + StateKeeperConfig, TimestampAsserterConfig, }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, @@ -196,5 +196,6 @@ fn load_env_config() -> anyhow::Result { external_proof_integration_api_config: ExternalProofIntegrationApiConfig::from_env().ok(), experimental_vm_config: ExperimentalVmConfig::from_env().ok(), prover_job_monitor_config: None, + timestamp_asserter_config: TimestampAsserterConfig::from_env().ok(), }) } diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index c7bf2ee0ea0d..7115bb7a04eb 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -303,6 +303,7 @@ impl MainNodeBuilder { fn add_tx_sender_layer(mut self) -> anyhow::Result { let sk_config = try_load_config!(self.configs.state_keeper_config); let rpc_config = try_load_config!(self.configs.api_config).web3_json_rpc; + let timestamp_asserter_config = try_load_config!(self.configs.timestamp_asserter_config); let postgres_storage_caches_config = PostgresStorageCachesConfig { factory_deps_cache_size: rpc_config.factory_deps_cache_size() as u64, initial_writes_cache_size: rpc_config.initial_writes_cache_size() as u64, @@ -320,6 +321,7 @@ impl MainNodeBuilder { .address(), self.genesis_config.l2_chain_id, self.contracts_config.l2_timestamp_asserter_addr, + timestamp_asserter_config, ), postgres_storage_caches_config, rpc_config.vm_concurrency_limit(), diff --git a/core/lib/config/src/configs/chain.rs b/core/lib/config/src/configs/chain.rs index c117064dbc40..a1ea47bddcf3 100644 --- a/core/lib/config/src/configs/chain.rs +++ b/core/lib/config/src/configs/chain.rs @@ -1,6 +1,6 @@ use std::{str::FromStr, time::Duration}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use zksync_basic_types::{ commitment::L1BatchCommitmentMode, network::Network, Address, L2ChainId, H256, }; @@ -244,3 +244,11 @@ impl MempoolConfig { Duration::from_millis(self.delay_interval) } } + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)] +pub struct TimestampAsserterConfig { + /// Minimum difference in seconds between the range start and range end + pub min_range_sec: u32, + /// Minimum time between current block.timestamp and the end of the asserted range + pub min_time_till_end_sec: u32, +} diff --git a/core/lib/config/src/configs/general.rs b/core/lib/config/src/configs/general.rs index bb733510f77d..dfb81af1cf8c 100644 --- a/core/lib/config/src/configs/general.rs +++ b/core/lib/config/src/configs/general.rs @@ -1,7 +1,10 @@ use crate::{ configs::{ base_token_adjuster::BaseTokenAdjusterConfig, - chain::{CircuitBreakerConfig, MempoolConfig, OperationsManagerConfig, StateKeeperConfig}, + chain::{ + CircuitBreakerConfig, MempoolConfig, OperationsManagerConfig, StateKeeperConfig, + TimestampAsserterConfig, + }, consensus::ConsensusConfig, da_client::DAClientConfig, da_dispatcher::DADispatcherConfig, @@ -56,4 +59,5 @@ pub struct GeneralConfig { pub external_proof_integration_api_config: Option, pub experimental_vm_config: Option, pub prover_job_monitor_config: Option, + pub timestamp_asserter_config: Option, } diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 3a827db05752..37dc459ee43d 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -16,8 +16,8 @@ use zksync_crypto_primitives::K256PrivateKey; use crate::{ configs::{ - self, da_client::DAClientConfig::Avail, eth_sender::PubdataSendingMode, - external_price_api_client::ForcedPriceClientConfig, + self, chain::TimestampAsserterConfig, da_client::DAClientConfig::Avail, + eth_sender::PubdataSendingMode, external_price_api_client::ForcedPriceClientConfig, }, AvailConfig, }; @@ -1176,6 +1176,16 @@ impl Distribution for EncodeDist { external_proof_integration_api_config: self.sample(rng), experimental_vm_config: self.sample(rng), prover_job_monitor_config: self.sample(rng), + timestamp_asserter_config: self.sample(rng), + } + } +} + +impl Distribution for EncodeDist { + fn sample(&self, rng: &mut R) -> TimestampAsserterConfig { + TimestampAsserterConfig { + min_range_sec: self.sample(rng), + min_time_till_end_sec: self.sample(rng), } } } diff --git a/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json b/core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json similarity index 87% rename from core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json rename to core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json index 83c977551b95..74a35ddf3b20 100644 --- a/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json +++ b/core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", + "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n AND (block_timestamp_range_start IS NULL OR block_timestamp_range_start <= CURRENT_DATE)\n AND (block_timestamp_range_end IS NULL OR block_timestamp_range_end >= CURRENT_DATE)\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", "describe": { "columns": [ { @@ -243,5 +243,5 @@ true ] }, - "hash": "a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b" + "hash": "4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754" } diff --git a/core/lib/dal/.sqlx/query-ca428423f278feea2942fd2c78fc5223c9d5e2e42d89bb456d24c601edc06a05.json b/core/lib/dal/.sqlx/query-ca428423f278feea2942fd2c78fc5223c9d5e2e42d89bb456d24c601edc06a05.json deleted file mode 100644 index c234cbe42356..000000000000 --- a/core/lib/dal/.sqlx/query-ca428423f278feea2942fd2c78fc5223c9d5e2e42d89bb456d24c601edc06a05.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n NOW(),\n NOW()\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "is_replaced!", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Int8", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Numeric", - "Bytea", - "Jsonb", - "Int4", - "Bytea", - "Numeric", - "Bytea", - "Bytea", - "Int8", - "Int4", - "Int4", - "Timestamp" - ] - }, - "nullable": [ - null - ] - }, - "hash": "ca428423f278feea2942fd2c78fc5223c9d5e2e42d89bb456d24c601edc06a05" -} diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 8c5d18beac4a..02a89a665d7f 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -1809,6 +1809,14 @@ impl TransactionsDal<'_, '_> { ) ) AND tx_format != $4 + AND ( + block_timestamp_range_start IS NULL + OR block_timestamp_range_start <= CURRENT_DATE + ) + AND ( + block_timestamp_range_end IS NULL + OR block_timestamp_range_end >= CURRENT_DATE + ) ORDER BY is_priority DESC, priority_op_id, diff --git a/core/lib/env_config/src/lib.rs b/core/lib/env_config/src/lib.rs index b72c2c5d5b94..325288056b35 100644 --- a/core/lib/env_config/src/lib.rs +++ b/core/lib/env_config/src/lib.rs @@ -33,6 +33,7 @@ mod vm_runner; mod wallets; mod da_client; +mod timestamp_asserter; pub trait FromEnv: Sized { fn from_env() -> anyhow::Result; diff --git a/core/lib/env_config/src/timestamp_asserter.rs b/core/lib/env_config/src/timestamp_asserter.rs new file mode 100644 index 000000000000..a7d5c50d8ae5 --- /dev/null +++ b/core/lib/env_config/src/timestamp_asserter.rs @@ -0,0 +1,54 @@ +use zksync_config::configs::chain::TimestampAsserterConfig; + +use crate::{envy_load, FromEnv}; + +impl FromEnv for TimestampAsserterConfig { + fn from_env() -> anyhow::Result { + envy_load("timestamp_asserter", "TIMESTAMP_ASSERTER_") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_utils::EnvMutex; + + static MUTEX: EnvMutex = EnvMutex::new(); + + #[test] + fn from_env_timestamp_asserter() { + let mut lock = MUTEX.lock(); + let config = r#" + TIMESTAMP_ASSERTER_MIN_RANGE_SEC=1 + TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC=2 + "#; + lock.set_env(config); + + let actual = TimestampAsserterConfig::from_env().unwrap(); + assert_eq!( + actual, + TimestampAsserterConfig { + min_range_sec: 1, + min_time_till_end_sec: 2, + } + ); + } + + #[test] + fn from_env_timestamp_asserter_with_defaults() { + let mut lock = MUTEX.lock(); + lock.remove_env(&[ + "TIMESTAMP_ASSERTER_MIN_RANGE_SEC", + "TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC", + ]); + + let actual = TimestampAsserterConfig::from_env().unwrap(); + assert_eq!( + actual, + TimestampAsserterConfig { + min_range_sec: 0, + min_time_till_end_sec: 0, + } + ); + } +} diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index d2c8a769bafe..ec8278139bc4 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -49,6 +49,8 @@ pub struct ValidationTracer { computational_gas_used: u32, computational_gas_limit: u32, timestamp_asserter_address: Option
, + timestamp_asserter_min_range_sec: u32, + timestamp_asserter_min_time_till_end_sec: u32, vm_version: VmVersion, pub result: Arc>, pub traces: Arc>, @@ -82,6 +84,9 @@ impl ValidationTracer { computational_gas_used: 0, computational_gas_limit: params.computational_gas_limit, timestamp_asserter_address: params.timestamp_asserter_address, + timestamp_asserter_min_range_sec: params.timestamp_asserter_min_range_sec, + timestamp_asserter_min_time_till_end_sec: params + .timestamp_asserter_min_time_till_end_sec, vm_version, result: result.clone(), traces: traces.clone(), @@ -210,6 +215,8 @@ impl ValidationTracer { trusted_address_slots: self.trusted_address_slots.clone(), computational_gas_limit: self.computational_gas_limit, timestamp_asserter_address: self.timestamp_asserter_address, + timestamp_asserter_min_range_sec: self.timestamp_asserter_min_range_sec, + timestamp_asserter_min_time_till_end_sec: self.timestamp_asserter_min_time_till_end_sec, } } } diff --git a/core/lib/protobuf_config/src/general.rs b/core/lib/protobuf_config/src/general.rs index b73539a0897f..83b4c84f20bf 100644 --- a/core/lib/protobuf_config/src/general.rs +++ b/core/lib/protobuf_config/src/general.rs @@ -46,6 +46,7 @@ impl ProtoRepr for proto::GeneralConfig { ), experimental_vm_config: read_optional_repr(&self.experimental_vm), prover_job_monitor_config: read_optional_repr(&self.prover_job_monitor), + timestamp_asserter_config: read_optional_repr(&self.timestamp_asserter), }) } @@ -106,6 +107,10 @@ impl ProtoRepr for proto::GeneralConfig { .prover_job_monitor_config .as_ref() .map(ProtoRepr::build), + timestamp_asserter: this + .timestamp_asserter_config + .as_ref() + .map(ProtoRepr::build), } } } diff --git a/core/lib/protobuf_config/src/lib.rs b/core/lib/protobuf_config/src/lib.rs index c89199359aaa..6a606c29c85a 100644 --- a/core/lib/protobuf_config/src/lib.rs +++ b/core/lib/protobuf_config/src/lib.rs @@ -35,6 +35,7 @@ mod snapshot_recovery; mod snapshots_creator; #[cfg(test)] mod tests; +mod timestamp_asserter; mod utils; mod vm_runner; mod wallets; diff --git a/core/lib/protobuf_config/src/proto/config/general.proto b/core/lib/protobuf_config/src/proto/config/general.proto index ee70b61b18b3..216272f3f9ad 100644 --- a/core/lib/protobuf_config/src/proto/config/general.proto +++ b/core/lib/protobuf_config/src/proto/config/general.proto @@ -26,6 +26,7 @@ import "zksync/config/external_proof_integration_api.proto"; import "zksync/core/consensus.proto"; import "zksync/config/prover_job_monitor.proto"; import "zksync/config/da_client.proto"; +import "zksync/config/timestamp_asserter.proto"; message GeneralConfig { optional database.Postgres postgres = 1; @@ -62,4 +63,5 @@ message GeneralConfig { optional experimental.Vm experimental_vm = 44; optional prover_job_monitor.ProverJobMonitor prover_job_monitor = 45; optional da_client.DataAvailabilityClient da_client = 46; + optional timestamp_asserter.TimestampAsserter timestamp_asserter = 47; } diff --git a/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto b/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto new file mode 100644 index 000000000000..85b7590ca595 --- /dev/null +++ b/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package zksync.config.timestamp_asserter; + +message TimestampAsserter { + optional uint32 min_range_sec = 1; // required; u32 + optional uint32 min_time_till_end_sec = 2; // required; u32 +} diff --git a/core/lib/protobuf_config/src/timestamp_asserter.rs b/core/lib/protobuf_config/src/timestamp_asserter.rs new file mode 100644 index 000000000000..80e00c71a383 --- /dev/null +++ b/core/lib/protobuf_config/src/timestamp_asserter.rs @@ -0,0 +1,19 @@ +use zksync_config::configs::chain::TimestampAsserterConfig; +use zksync_protobuf::{required, ProtoRepr}; + +impl ProtoRepr for crate::proto::config::timestamp_asserter::TimestampAsserter { + type Type = TimestampAsserterConfig; + fn read(&self) -> anyhow::Result { + Ok(Self::Type { + min_range_sec: *required(&self.min_range_sec).unwrap_or(&0), + min_time_till_end_sec: *required(&self.min_time_till_end_sec).unwrap_or(&0), + }) + } + + fn build(this: &Self::Type) -> Self { + Self { + min_range_sec: Some(this.min_range_sec), + min_time_till_end_sec: Some(this.min_time_till_end_sec), + } + } +} diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index ebeab53c3a53..32b7d24c8685 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -60,6 +60,10 @@ pub struct ValidationParams { /// Address of the timestamp asserter. This contract is allowed to touch block.timestamp regardless /// of the calling context. pub timestamp_asserter_address: Option
, + /// Minimum difference in seconds between the range start and range end + pub timestamp_asserter_min_range_sec: u32, + /// Minimum time between current block.timestamp and the end of the asserted range + pub timestamp_asserter_min_time_till_end_sec: u32, } /// Rules that can be violated when validating a transaction. diff --git a/core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs b/core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs index eb2170bcc848..5faef68507fa 100644 --- a/core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs +++ b/core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs @@ -6,7 +6,7 @@ use zksync_config::{ api::{HealthCheckConfig, MerkleTreeApiConfig, Web3JsonRpcConfig}, chain::{ CircuitBreakerConfig, MempoolConfig, NetworkConfig, OperationsManagerConfig, - StateKeeperConfig, + StateKeeperConfig, TimestampAsserterConfig, }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, @@ -81,6 +81,7 @@ pub struct TempConfigStore { pub external_proof_integration_api_config: Option, pub experimental_vm_config: Option, pub prover_job_monitor_config: Option, + pub timestamp_asserter_config: Option, } impl TempConfigStore { @@ -122,6 +123,7 @@ impl TempConfigStore { .clone(), experimental_vm_config: self.experimental_vm_config.clone(), prover_job_monitor_config: self.prover_job_monitor_config.clone(), + timestamp_asserter_config: self.timestamp_asserter_config.clone(), } } @@ -203,6 +205,7 @@ fn load_env_config() -> anyhow::Result { external_proof_integration_api_config: ExternalProofIntegrationApiConfig::from_env().ok(), experimental_vm_config: ExperimentalVmConfig::from_env().ok(), prover_job_monitor_config: ProverJobMonitorConfig::from_env().ok(), + timestamp_asserter_config: TimestampAsserterConfig::from_env().ok(), }) } diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index 84aec51a0fcc..0700096e0764 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -101,6 +101,8 @@ pub(crate) struct SandboxExecutor { pub(super) options: SandboxExecutorOptions, storage_caches: Option, pub(super) timestamp_asserter_address: Option
, + pub(super) timestamp_asserter_min_range_sec: u32, + pub(super) timestamp_asserter_min_time_till_end_sec: u32, } impl SandboxExecutor { @@ -109,6 +111,8 @@ impl SandboxExecutor { caches: PostgresStorageCaches, missed_storage_invocation_limit: usize, timestamp_asserter_address: Option
, + timestamp_asserter_min_range_sec: u32, + timestamp_asserter_min_time_till_end_sec: u32, ) -> Self { let mut executor = MainOneshotExecutor::new(missed_storage_invocation_limit); executor @@ -118,6 +122,8 @@ impl SandboxExecutor { options, storage_caches: Some(caches), timestamp_asserter_address, + timestamp_asserter_min_range_sec, + timestamp_asserter_min_time_till_end_sec, } } @@ -127,6 +133,8 @@ impl SandboxExecutor { options: SandboxExecutorOptions::mock().await, storage_caches: None, timestamp_asserter_address: None, + timestamp_asserter_min_range_sec: 0, + timestamp_asserter_min_time_till_end_sec: 0, } } diff --git a/core/node/api_server/src/execution_sandbox/validate.rs b/core/node/api_server/src/execution_sandbox/validate.rs index ec77cc01cc7f..c98e4fed2d82 100644 --- a/core/node/api_server/src/execution_sandbox/validate.rs +++ b/core/node/api_server/src/execution_sandbox/validate.rs @@ -47,6 +47,8 @@ impl SandboxExecutor { self.options.eth_call.validation_computational_gas_limit(), whitelisted_tokens_for_aa, self.timestamp_asserter_address, + self.timestamp_asserter_min_range_sec, + self.timestamp_asserter_min_time_till_end_sec, ) .await .context("failed getting validation params")?; @@ -82,6 +84,8 @@ pub(super) async fn get_validation_params( computational_gas_limit: u32, whitelisted_tokens_for_aa: &[Address], timestamp_asserter_address: Option
, + timestamp_asserter_min_range_sec: u32, + timestamp_asserter_min_time_till_end_sec: u32, ) -> anyhow::Result { let method_latency = EXECUTION_METRICS.get_validation_params.start(); let user_address = tx.common_data.initiator_address; @@ -129,5 +133,7 @@ pub(super) async fn get_validation_params( trusted_address_slots, computational_gas_limit, timestamp_asserter_address, + timestamp_asserter_min_range_sec, + timestamp_asserter_min_time_till_end_sec, }) } diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 5a9fc90349e5..d33e784c053e 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -4,7 +4,10 @@ use std::sync::Arc; use anyhow::Context as _; use tokio::sync::RwLock; -use zksync_config::configs::{api::Web3JsonRpcConfig, chain::StateKeeperConfig}; +use zksync_config::configs::{ + api::Web3JsonRpcConfig, + chain::{StateKeeperConfig, TimestampAsserterConfig}, +}; use zksync_dal::{ transactions_dal::L2TxSubmissionResult, Connection, ConnectionPool, Core, CoreDal, }; @@ -182,7 +185,9 @@ impl TxSenderBuilder { executor_options, storage_caches, missed_storage_invocation_limit, - self.config.timestamp_asserter_addr, + self.config.timestamp_asserter_address, + self.config.timestamp_asserter_min_range_sec, + self.config.timestamp_asserter_min_time_till_end_sec, ); TxSender(Arc::new(TxSenderInner { @@ -212,7 +217,9 @@ pub struct TxSenderConfig { pub validation_computational_gas_limit: u32, pub chain_id: L2ChainId, pub whitelisted_tokens_for_aa: Vec
, - pub timestamp_asserter_addr: Option
, + pub timestamp_asserter_address: Option
, + pub timestamp_asserter_min_range_sec: u32, + pub timestamp_asserter_min_time_till_end_sec: u32, } impl TxSenderConfig { @@ -222,6 +229,7 @@ impl TxSenderConfig { fee_account_addr: Address, chain_id: L2ChainId, timestamp_asserter_addr: Option
, + timestamp_asserter_config: TimestampAsserterConfig, ) -> Self { Self { fee_account_addr, @@ -233,7 +241,10 @@ impl TxSenderConfig { .validation_computational_gas_limit, chain_id, whitelisted_tokens_for_aa: web3_json_config.whitelisted_tokens_for_aa.clone(), - timestamp_asserter_addr, + timestamp_asserter_address: timestamp_asserter_addr, + timestamp_asserter_min_range_sec: timestamp_asserter_config.min_range_sec, + timestamp_asserter_min_time_till_end_sec: timestamp_asserter_config + .min_time_till_end_sec, } } } diff --git a/core/node/api_server/src/web3/testonly.rs b/core/node/api_server/src/web3/testonly.rs index 1746ed808e20..4181a5263a14 100644 --- a/core/node/api_server/src/web3/testonly.rs +++ b/core/node/api_server/src/web3/testonly.rs @@ -3,7 +3,11 @@ use std::{pin::Pin, time::Instant}; use tokio::sync::watch; -use zksync_config::configs::{api::Web3JsonRpcConfig, chain::StateKeeperConfig, wallets::Wallets}; +use zksync_config::configs::{ + api::Web3JsonRpcConfig, + chain::{StateKeeperConfig, TimestampAsserterConfig}, + wallets::Wallets, +}; use zksync_dal::ConnectionPool; use zksync_health_check::CheckHealth; use zksync_node_fee_model::MockBatchFeeParamsProvider; @@ -32,6 +36,7 @@ pub(crate) async fn create_test_tx_sender( wallets.state_keeper.unwrap().fee_account.address(), l2_chain_id, None, + TimestampAsserterConfig::default(), ); let storage_caches = PostgresStorageCaches::new(1, 1); From 9c0d5bbde4911f16b2bf9fbbf8a6364e5ce6d982 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 10 Oct 2024 13:34:27 +0100 Subject: [PATCH 18/68] Merge from main --- zk_toolbox/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zk_toolbox/Cargo.lock b/zk_toolbox/Cargo.lock index a1efa9fe00b2..78d50161a4d2 100644 --- a/zk_toolbox/Cargo.lock +++ b/zk_toolbox/Cargo.lock @@ -3827,7 +3827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.79", @@ -6315,7 +6315,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -6864,7 +6864,7 @@ dependencies = [ [[package]] name = "zksync_consensus_utils" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10bac8f471b182d4fa3d40cf158aac3624fe636a1ff0b4cf3fe26a0e20c68a42" dependencies = [ From a54e6eb1f310d3e52d3ed7d83d4aa7e866c030d8 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 10 Oct 2024 14:01:33 +0100 Subject: [PATCH 19/68] fix lint --- ...f526b631743b18afbcec8e07aef386857f4e.json} | 4 ++-- .../src/tracers/validator/vm_latest/mod.rs | 19 ++++++++++++++++++- core/lib/vm_interface/src/types/tracer.rs | 5 +++++ .../api_server/src/execution_sandbox/tests.rs | 4 ++++ .../api_server/src/tx_sender/tests/mod.rs | 2 +- core/node/consensus/src/registry/tests.rs | 2 +- core/node/consensus/src/tests/attestation.rs | 4 ++-- core/node/state_keeper/src/io/tests/mod.rs | 6 +++++- 8 files changed, 38 insertions(+), 8 deletions(-) rename core/lib/dal/.sqlx/{query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json => query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json} (84%) diff --git a/core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json b/core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json similarity index 84% rename from core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json rename to core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json index 74a35ddf3b20..b60cb8b9b47f 100644 --- a/core/lib/dal/.sqlx/query-4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754.json +++ b/core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n AND (block_timestamp_range_start IS NULL OR block_timestamp_range_start <= CURRENT_DATE)\n AND (block_timestamp_range_end IS NULL OR block_timestamp_range_end >= CURRENT_DATE)\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", + "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n AND (\n block_timestamp_range_start IS NULL\n OR block_timestamp_range_start <= CURRENT_DATE\n )\n AND (\n block_timestamp_range_end IS NULL\n OR block_timestamp_range_end >= CURRENT_DATE\n )\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", "describe": { "columns": [ { @@ -243,5 +243,5 @@ true ] }, - "hash": "4a8439c6b1ee2e3027c45e2bdd8090c5629fa3c8776e60d993bd365d27669754" + "hash": "cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e" } diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 325715c41c2e..9d98fa9d3257 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -1,4 +1,7 @@ -use std::cmp; +use std::{ + cmp, + time::{SystemTime, UNIX_EPOCH}, +}; use zk_evm_1_5_0::{ tracing::{BeforeExecutionData, VmLocalStateData}, @@ -105,6 +108,20 @@ impl ValidationTracer { ); let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); + if start.as_u32() - end.as_u32() < self.timestamp_asserter_min_range_sec { + return Err(ViolatedValidationRule::TimestampAssertionInvalidRange); + } + + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Incorrect system time") + .as_secs(); + + if end.as_u32() < now as u32 + self.timestamp_asserter_min_time_till_end_sec + { + return Err(ViolatedValidationRule::TimestampAssertionInvalidRange); + } + { let mut traces_mut = self.traces.lock().unwrap(); traces_mut.range_start = match traces_mut.range_start { diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index 32b7d24c8685..9a2536a63308 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -77,6 +77,8 @@ pub enum ViolatedValidationRule { TouchedDisallowedContext, /// The transaction used too much gas during validation. TookTooManyComputationalGas(u32), + /// The transaction passed incorrect parameters into timestamp asserter + TimestampAssertionInvalidRange, } impl fmt::Display for ViolatedValidationRule { @@ -98,6 +100,9 @@ impl fmt::Display for ViolatedValidationRule { "Took too many computational gas, allowed limit: {gas_limit}" ) } + ViolatedValidationRule::TimestampAssertionInvalidRange => { + write!(f, "Invalid range used with timestamp asserter") + } } } } diff --git a/core/node/api_server/src/execution_sandbox/tests.rs b/core/node/api_server/src/execution_sandbox/tests.rs index 154083458575..1a5e795c0d7f 100644 --- a/core/node/api_server/src/execution_sandbox/tests.rs +++ b/core/node/api_server/src/execution_sandbox/tests.rs @@ -218,6 +218,8 @@ async fn test_instantiating_vm(connection: Connection<'static, Core>, block_args PostgresStorageCaches::new(1, 1), usize::MAX, None, + 0, + 0, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); @@ -267,6 +269,8 @@ async fn validating_transaction(set_balance: bool) { PostgresStorageCaches::new(1, 1), usize::MAX, None, + 0, + 0, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); diff --git a/core/node/api_server/src/tx_sender/tests/mod.rs b/core/node/api_server/src/tx_sender/tests/mod.rs index 6b46c0463746..db514f05e4a5 100644 --- a/core/node/api_server/src/tx_sender/tests/mod.rs +++ b/core/node/api_server/src/tx_sender/tests/mod.rs @@ -154,7 +154,7 @@ async fn create_real_tx_sender(pool: ConnectionPool) -> TxSender { .unwrap(); let pg_caches = PostgresStorageCaches::new(1, 1); - let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX, None); + let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX, None, 0, 0); create_test_tx_sender(pool, genesis_params.config().l2_chain_id, tx_executor) .await .0 diff --git a/core/node/consensus/src/registry/tests.rs b/core/node/consensus/src/registry/tests.rs index 33392a7f206d..89afc20e1d57 100644 --- a/core/node/consensus/src/registry/tests.rs +++ b/core/node/consensus/src/registry/tests.rs @@ -80,7 +80,7 @@ async fn test_attester_committee() { .wrap("wait_for_batch_info()")?; // Read the attester committee using the vm. - let batch = attester::BatchNumber(node.last_batch().0.into()); + let batch = attester::BatchNumber(node.last_batch().0); assert_eq!( Some(committee), registry diff --git a/core/node/consensus/src/tests/attestation.rs b/core/node/consensus/src/tests/attestation.rs index bd3886bd4c89..2701a986e9e9 100644 --- a/core/node/consensus/src/tests/attestation.rs +++ b/core/node/consensus/src/tests/attestation.rs @@ -79,7 +79,7 @@ async fn test_attestation_status_api(version: ProtocolVersionId) { let status = fetch_status().await?; assert_eq!( status.next_batch_to_attest, - attester::BatchNumber(first_batch.0.into()) + attester::BatchNumber(first_batch.0) ); tracing::info!("Insert a cert"); @@ -237,7 +237,7 @@ async fn test_multiple_attesters(version: ProtocolVersionId, pregenesis: bool) { } tracing::info!("Wait for the batches to be attested"); - let want_last = attester::BatchNumber(validator.last_sealed_batch().0.into()); + let want_last = attester::BatchNumber(validator.last_sealed_batch().0); validator_pool .wait_for_batch_certificates_and_verify(ctx, want_last, Some(registry_addr)) .await?; diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 46165e087ce8..6784ecde69e0 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -589,7 +589,11 @@ async fn continue_unsealed_batch_on_restart(commitment_mode: L1BatchCommitmentMo ); storage .transactions_dal() - .insert_transaction_l2(&tx, TransactionExecutionMetrics::default()) + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) .await .unwrap(); From 3a8234d8fd843c8bd496aec72e916fc8790a41cc Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 10 Oct 2024 14:28:22 +0100 Subject: [PATCH 20/68] Update config --- etc/env/file_based/general.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index a4ba8c0201a6..0f1e8e05b30b 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -375,3 +375,8 @@ da_dispatcher: external_proof_integration_api: http_port: 3073 + +timestamp_asserter: + min_range_sec: 300 + pub min_time_till_end_sec: 60 + From 980d7a7b6c40bae7e06f6ebcab8820353b9434d4 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 10 Oct 2024 17:20:05 +0100 Subject: [PATCH 21/68] Update EN --- core/bin/external_node/src/config/mod.rs | 30 +++++++++++++++++-- core/lib/env_config/src/timestamp_asserter.rs | 18 ----------- core/lib/web3_decl/src/namespaces/zks.rs | 3 ++ .../web3/backend_jsonrpsee/namespaces/zks.rs | 4 +++ .../api_server/src/web3/namespaces/zks.rs | 4 +++ core/node/api_server/src/web3/state.rs | 2 ++ core/tests/ts-integration/src/env.ts | 2 +- 7 files changed, 41 insertions(+), 22 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 33df59074488..2a81b6c6d8db 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -116,6 +116,7 @@ pub(crate) struct RemoteENConfig { pub l1_weth_bridge_addr: Option
, pub l2_weth_bridge_addr: Option
, pub l2_testnet_paymaster_addr: Option
, + pub l2_timestamp_asserter_addr: Option
, pub base_token_addr: Address, pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, pub dummy_verifier: bool, @@ -141,6 +142,10 @@ impl RemoteENConfig { .get_main_contract() .rpc_context("get_main_contract") .await?; + let timestamp_asserter_address = client + .get_timestamp_asserter() + .rpc_context("get_timestamp_asserter") + .await?; let base_token_addr = match client.get_base_token_l1_address().await { Err(ClientError::Call(err)) if [ @@ -200,6 +205,7 @@ impl RemoteENConfig { .as_ref() .map(|a| a.dummy_verifier) .unwrap_or_default(), + l2_timestamp_asserter_addr: timestamp_asserter_address, }) } @@ -220,6 +226,7 @@ impl RemoteENConfig { l2_shared_bridge_addr: Some(Address::repeat_byte(6)), l1_batch_commit_data_generator_mode: L1BatchCommitmentMode::Rollup, dummy_verifier: true, + l2_timestamp_asserter_addr: None, } } } @@ -447,6 +454,10 @@ pub(crate) struct OptionalENConfig { pub gateway_url: Option, /// Interval for bridge addresses refreshing in seconds. bridge_addresses_refresh_interval_sec: Option, + /// Minimum difference in seconds between the range start and range end for TimestampAsserter + pub timestamp_asserter_min_range_sec: u32, + /// Minimum time between current block.timestamp and the end of the asserted range for TimestampAsserter + pub timestamp_asserter_min_time_till_end_sec: u32, } impl OptionalENConfig { @@ -678,6 +689,16 @@ impl OptionalENConfig { contracts_diamond_proxy_addr: None, gateway_url: enconfig.gateway_url.clone(), bridge_addresses_refresh_interval_sec: enconfig.bridge_addresses_refresh_interval_sec, + timestamp_asserter_min_range_sec: general_config + .timestamp_asserter_config + .as_ref() + .map(|x| x.min_range_sec) + .unwrap_or(0), + timestamp_asserter_min_time_till_end_sec: general_config + .timestamp_asserter_config + .as_ref() + .map(|x| x.min_time_till_end_sec) + .unwrap_or(0), }) } @@ -1417,6 +1438,7 @@ impl From<&ExternalNodeConfig> for InternalApiConfig { filters_disabled: config.optional.filters_disabled, dummy_verifier: config.remote.dummy_verifier, l1_batch_commit_data_generator_mode: config.remote.l1_batch_commit_data_generator_mode, + timestamp_asserter_address: config.remote.l2_timestamp_asserter_addr, } } } @@ -1439,9 +1461,11 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { chain_id: config.required.l2_chain_id, // Does not matter for EN. whitelisted_tokens_for_aa: Default::default(), - timestamp_asserter_address: None, - timestamp_asserter_min_range_sec: 0, - timestamp_asserter_min_time_till_end_sec: 0, + timestamp_asserter_address: config.remote.l2_timestamp_asserter_addr, + timestamp_asserter_min_range_sec: config.optional.timestamp_asserter_min_range_sec, + timestamp_asserter_min_time_till_end_sec: config + .optional + .timestamp_asserter_min_time_till_end_sec, } } } diff --git a/core/lib/env_config/src/timestamp_asserter.rs b/core/lib/env_config/src/timestamp_asserter.rs index a7d5c50d8ae5..3d22d89d9c82 100644 --- a/core/lib/env_config/src/timestamp_asserter.rs +++ b/core/lib/env_config/src/timestamp_asserter.rs @@ -33,22 +33,4 @@ mod tests { } ); } - - #[test] - fn from_env_timestamp_asserter_with_defaults() { - let mut lock = MUTEX.lock(); - lock.remove_env(&[ - "TIMESTAMP_ASSERTER_MIN_RANGE_SEC", - "TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC", - ]); - - let actual = TimestampAsserterConfig::from_env().unwrap(); - assert_eq!( - actual, - TimestampAsserterConfig { - min_range_sec: 0, - min_time_till_end_sec: 0, - } - ); - } } diff --git a/core/lib/web3_decl/src/namespaces/zks.rs b/core/lib/web3_decl/src/namespaces/zks.rs index 47aae2a0835e..07a7cc4ff1c2 100644 --- a/core/lib/web3_decl/src/namespaces/zks.rs +++ b/core/lib/web3_decl/src/namespaces/zks.rs @@ -51,6 +51,9 @@ pub trait ZksNamespace { #[method(name = "getTestnetPaymaster")] async fn get_testnet_paymaster(&self) -> RpcResult>; + #[method(name = "getTimestampAsserter")] + async fn get_timestamp_asserter(&self) -> RpcResult>; + #[method(name = "getBridgeContracts")] async fn get_bridge_contracts(&self) -> RpcResult; diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/zks.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/zks.rs index 31c8f15bb1ea..21f3f5ae49e1 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/zks.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/zks.rs @@ -58,6 +58,10 @@ impl ZksNamespaceServer for ZksNamespace { Ok(self.get_bridge_contracts_impl().await) } + async fn get_timestamp_asserter(&self) -> RpcResult> { + Ok(self.get_timestamp_asserter_impl()) + } + async fn l1_chain_id(&self) -> RpcResult { Ok(self.l1_chain_id_impl()) } diff --git a/core/node/api_server/src/web3/namespaces/zks.rs b/core/node/api_server/src/web3/namespaces/zks.rs index bcfd7daf3461..1a4114bd2c6a 100644 --- a/core/node/api_server/src/web3/namespaces/zks.rs +++ b/core/node/api_server/src/web3/namespaces/zks.rs @@ -151,6 +151,10 @@ impl ZksNamespace { self.state.bridge_addresses_handle.read().await } + pub fn get_timestamp_asserter_impl(&self) -> Option
{ + self.state.api_config.timestamp_asserter_address + } + pub fn l1_chain_id_impl(&self) -> U64 { U64::from(*self.state.api_config.l1_chain_id) } diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 18c206eaf584..96248e8b9cb7 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -115,6 +115,7 @@ pub struct InternalApiConfig { pub filters_disabled: bool, pub dummy_verifier: bool, pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, + pub timestamp_asserter_address: Option
, } impl InternalApiConfig { @@ -167,6 +168,7 @@ impl InternalApiConfig { filters_disabled: web3_config.filters_disabled, dummy_verifier: genesis_config.dummy_verifier, l1_batch_commit_data_generator_mode: genesis_config.l1_batch_commit_data_generator_mode, + timestamp_asserter_address: contracts_config.l2_timestamp_asserter_addr, } } } diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 147bcda56a58..83107be8ea3f 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -87,7 +87,7 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise Date: Fri, 11 Oct 2024 09:21:11 +0100 Subject: [PATCH 22/68] Fix EN test --- core/bin/external_node/src/config/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/bin/external_node/src/config/tests.rs b/core/bin/external_node/src/config/tests.rs index a32be3eff725..34ca89637369 100644 --- a/core/bin/external_node/src/config/tests.rs +++ b/core/bin/external_node/src/config/tests.rs @@ -128,6 +128,8 @@ fn parsing_optional_config_from_env() { "zks_getProof=100,eth_call=2", ), ("EN_L1_BATCH_COMMIT_DATA_GENERATOR_MODE", "Validium"), + ("EN_TIMESTAMP_ASSERTER_MIN_RANGE_SEC", "1"), + ("EN_TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC", "2"), ]; let env_vars = env_vars .into_iter() From 7453e0088025558765fb353d45ba8081fc5c1554 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 11 Oct 2024 09:51:04 +0100 Subject: [PATCH 23/68] Fix EN test --- core/bin/external_node/src/config/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 2a81b6c6d8db..819cae5c212f 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -455,8 +455,10 @@ pub(crate) struct OptionalENConfig { /// Interval for bridge addresses refreshing in seconds. bridge_addresses_refresh_interval_sec: Option, /// Minimum difference in seconds between the range start and range end for TimestampAsserter + #[serde(default = "OptionalENConfig::default_timestamp_asserter_min_range_sec")] pub timestamp_asserter_min_range_sec: u32, /// Minimum time between current block.timestamp and the end of the asserted range for TimestampAsserter + #[serde(default = "OptionalENConfig::default_timestamp_asserter_min_time_till_end_sec")] pub timestamp_asserter_min_time_till_end_sec: u32, } @@ -833,6 +835,14 @@ impl OptionalENConfig { 3_600 * 24 * 7 // 7 days } + const fn default_timestamp_asserter_min_range_sec() -> u32 { + 10 * 60 + } + + const fn default_timestamp_asserter_min_time_till_end_sec() -> u32 { + 2 * 60 + } + fn from_env() -> anyhow::Result { let mut result: OptionalENConfig = envy::prefixed("EN_") .from_env() From bafd5c05b4d7f4942948a05881b513c9cf7e0f86 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 11 Oct 2024 10:18:00 +0100 Subject: [PATCH 24/68] config typo --- etc/env/file_based/general.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 0f1e8e05b30b..cb5cbebc0d97 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -378,5 +378,5 @@ external_proof_integration_api: timestamp_asserter: min_range_sec: 300 - pub min_time_till_end_sec: 60 + min_time_till_end_sec: 60 From 1df73ac838564574bb82738ad44bb88a918e8118 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 11 Oct 2024 15:33:41 +0100 Subject: [PATCH 25/68] Add mempool filtering --- .../lib/dal/src/models/storage_transaction.rs | 15 ++++-- core/lib/dal/src/transactions_dal.rs | 10 ++-- core/lib/mempool/src/mempool_store.rs | 16 ++++-- core/lib/mempool/src/types.rs | 54 ++++++++++++++----- core/lib/types/src/lib.rs | 17 ++++++ core/node/state_keeper/src/io/mempool.rs | 4 +- core/node/state_keeper/src/mempool_actor.rs | 13 +++-- core/node/state_keeper/src/types.rs | 14 +++-- 8 files changed, 111 insertions(+), 32 deletions(-) diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index d92f52919d98..d23d84c30dda 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -12,9 +12,9 @@ use zksync_types::{ transaction_request::PaymasterParams, web3::Bytes, Address, Execute, ExecuteTransactionCommon, L1TxCommonData, L2ChainId, L2TxCommonData, Nonce, - PackedEthSignature, PriorityOpId, ProtocolVersionId, Transaction, EIP_1559_TX_TYPE, - EIP_2930_TX_TYPE, EIP_712_TX_TYPE, H160, H256, PRIORITY_OPERATION_L2_TX_TYPE, - PROTOCOL_UPGRADE_TX_TYPE, U256, U64, + PackedEthSignature, PriorityOpId, ProtocolVersionId, Transaction, + TransactionTimeRangeConstraint, EIP_1559_TX_TYPE, EIP_2930_TX_TYPE, EIP_712_TX_TYPE, H160, + H256, PRIORITY_OPERATION_L2_TX_TYPE, PROTOCOL_UPGRADE_TX_TYPE, U256, U64, }; use zksync_utils::{bigdecimal_to_u256, h256_to_account_address}; use zksync_vm_interface::Call; @@ -324,6 +324,15 @@ impl From for Transaction { } } +impl From for TransactionTimeRangeConstraint { + fn from(tx: StorageTransaction) -> Self { + Self { + range_start: tx.block_timestamp_range_start, + range_end: tx.block_timestamp_range_end, + } + } +} + #[derive(sqlx::FromRow)] pub(crate) struct StorageTransactionReceipt { pub error: Option, diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 02a89a665d7f..09a1b4d7f6e4 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -12,7 +12,8 @@ use zksync_db_connection::{ use zksync_types::{ block::L2BlockExecutionData, l1::L1Tx, l2::L2Tx, protocol_upgrade::ProtocolUpgradeTx, Address, ExecuteTransactionCommon, L1BatchNumber, L1BlockNumber, L2BlockNumber, PriorityOpId, - ProtocolVersionId, Transaction, H256, PROTOCOL_UPGRADE_TX_TYPE, U256, + ProtocolVersionId, Transaction, TransactionTimeRangeConstraint, H256, PROTOCOL_UPGRADE_TX_TYPE, + U256, }; use zksync_utils::u256_to_big_decimal; use zksync_vm_interface::{ @@ -1745,7 +1746,7 @@ impl TransactionsDal<'_, '_> { gas_per_pubdata: u32, fee_per_gas: u64, limit: usize, - ) -> DalResult> { + ) -> DalResult> { let stashed_addresses: Vec<_> = stashed_accounts.iter().map(Address::as_bytes).collect(); sqlx::query!( r#" @@ -1844,7 +1845,10 @@ impl TransactionsDal<'_, '_> { .fetch_all(self.storage) .await?; - let transactions = transactions.into_iter().map(|tx| tx.into()).collect(); + let transactions = transactions + .into_iter() + .map(|tx| (tx.clone().into(), tx.into())) + .collect(); Ok(transactions) } diff --git a/core/lib/mempool/src/mempool_store.rs b/core/lib/mempool/src/mempool_store.rs index 334a4783a76c..36763e19d49b 100644 --- a/core/lib/mempool/src/mempool_store.rs +++ b/core/lib/mempool/src/mempool_store.rs @@ -2,6 +2,7 @@ use std::collections::{hash_map, BTreeSet, HashMap, HashSet}; use zksync_types::{ l1::L1Tx, l2::L2Tx, Address, ExecuteTransactionCommon, Nonce, PriorityOpId, Transaction, + TransactionTimeRangeConstraint, }; use crate::types::{AccountTransactions, L2TxFilter, MempoolScore}; @@ -54,10 +55,10 @@ impl MempoolStore { /// in other cases mempool relies on state keeper and its internal state to keep that info up to date pub fn insert( &mut self, - transactions: Vec, + transactions: Vec<(Transaction, TransactionTimeRangeConstraint)>, initial_nonces: HashMap, ) { - for transaction in transactions { + for (transaction, constraint) in transactions { let Transaction { common_data, execute, @@ -85,6 +86,7 @@ impl MempoolStore { received_timestamp_ms, raw_bytes, }, + constraint, &initial_nonces, ); } @@ -98,17 +100,18 @@ impl MempoolStore { fn insert_l2_transaction( &mut self, transaction: L2Tx, + constraint: TransactionTimeRangeConstraint, initial_nonces: &HashMap, ) { let account = transaction.initiator_account(); let metadata = match self.l2_transactions_per_account.entry(account) { - hash_map::Entry::Occupied(mut txs) => txs.get_mut().insert(transaction), + hash_map::Entry::Occupied(mut txs) => txs.get_mut().insert(transaction, constraint), hash_map::Entry::Vacant(entry) => { let account_nonce = initial_nonces.get(&account).cloned().unwrap_or(Nonce(0)); entry .insert(AccountTransactions::new(account_nonce)) - .insert(transaction) + .insert(transaction, constraint) } }; if let Some(score) = metadata.previous_score { @@ -182,12 +185,13 @@ impl MempoolStore { /// When a state_keeper starts the block over after a rejected transaction, /// we have to rollback the nonces/ids in the mempool and /// reinsert the transactions from the block back into mempool. - pub fn rollback(&mut self, tx: &Transaction) { + pub fn rollback(&mut self, tx: &Transaction) -> TransactionTimeRangeConstraint { // rolling back the nonces and priority ids match &tx.common_data { ExecuteTransactionCommon::L1(data) => { // reset next priority id self.next_priority_id = self.next_priority_id.min(data.serial_id); + TransactionTimeRangeConstraint::default() } ExecuteTransactionCommon::L2(_) => { if let Some(score) = self @@ -197,7 +201,9 @@ impl MempoolStore { .reset(tx) { self.l2_priority_queue.remove(&score); + return score.time_range_constraint; } + TransactionTimeRangeConstraint::default() } ExecuteTransactionCommon::ProtocolUpgrade(_) => { panic!("Protocol upgrade tx is not supposed to be in mempool"); diff --git a/core/lib/mempool/src/types.rs b/core/lib/mempool/src/types.rs index 99a63ffd08e2..8f46318688e6 100644 --- a/core/lib/mempool/src/types.rs +++ b/core/lib/mempool/src/types.rs @@ -1,14 +1,19 @@ -use std::{cmp::Ordering, collections::HashMap}; +use std::{ + cmp::Ordering, + collections::HashMap, + time::{SystemTime, UNIX_EPOCH}, +}; use zksync_types::{ - fee::Fee, fee_model::BatchFeeInput, l2::L2Tx, Address, Nonce, Transaction, U256, + fee::Fee, fee_model::BatchFeeInput, l2::L2Tx, Address, Nonce, Transaction, + TransactionTimeRangeConstraint, U256, }; /// Pending mempool transactions of account #[derive(Debug)] pub(crate) struct AccountTransactions { /// transactions that belong to given account keyed by transaction nonce - transactions: HashMap, + transactions: HashMap, /// account nonce in mempool /// equals to committed nonce in db + number of transactions sent to state keeper nonce: Nonce, @@ -23,18 +28,22 @@ impl AccountTransactions { } /// Inserts new transaction for given account. Returns insertion metadata - pub fn insert(&mut self, transaction: L2Tx) -> InsertionMetadata { + pub fn insert( + &mut self, + transaction: L2Tx, + constraint: TransactionTimeRangeConstraint, + ) -> InsertionMetadata { let mut metadata = InsertionMetadata::default(); let nonce = transaction.common_data.nonce; // skip insertion if transaction is old if nonce < self.nonce { return metadata; } - let new_score = Self::score_for_transaction(&transaction); + let new_score = Self::score_for_transaction(&transaction, constraint); let previous_score = self .transactions - .insert(nonce, transaction) - .map(|tx| Self::score_for_transaction(&tx)); + .insert(nonce, (transaction, constraint)) + .map(|(tx, constraint)| Self::score_for_transaction(&tx, constraint)); metadata.is_new = previous_score.is_none(); if nonce == self.nonce { metadata.new_score = Some(new_score); @@ -54,8 +63,8 @@ impl AccountTransactions { let score = self .transactions .get(&self.nonce) - .map(Self::score_for_transaction); - (transaction, score) + .map(|(tx, c)| Self::score_for_transaction(tx, *c)); + (transaction.0, score) } /// Handles transaction rejection. Returns optional score of its successor @@ -67,18 +76,22 @@ impl AccountTransactions { self.nonce = self.nonce.min(tx_nonce); self.transactions .get(&(tx_nonce + 1)) - .map(Self::score_for_transaction) + .map(|(tx, c)| Self::score_for_transaction(tx, *c)) } pub fn len(&self) -> usize { self.transactions.len() } - fn score_for_transaction(transaction: &L2Tx) -> MempoolScore { + fn score_for_transaction( + transaction: &L2Tx, + constraint: TransactionTimeRangeConstraint, + ) -> MempoolScore { MempoolScore { account: transaction.initiator_account(), received_at_ms: transaction.received_timestamp_ms, fee_data: transaction.common_data.fee.clone(), + time_range_constraint: constraint, } } } @@ -93,12 +106,28 @@ pub struct MempoolScore { // transactions that have acceptable fee values (so transactions // with fee too low would be ignored until prices go down). pub fee_data: Fee, + pub time_range_constraint: TransactionTimeRangeConstraint, } impl MempoolScore { /// Checks whether transaction matches requirements provided by state keeper. pub fn matches_filter(&self, filter: &L2TxFilter) -> bool { - self.fee_data.max_fee_per_gas >= U256::from(filter.fee_per_gas) + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Invalid system time") + .as_secs() as i64; + + let matches_range = self + .time_range_constraint + .range_start + .map_or(true, |x| x.and_utc().timestamp() < now) + && self + .time_range_constraint + .range_end + .map_or(true, |x| x.and_utc().timestamp() > now); + + matches_range + && self.fee_data.max_fee_per_gas >= U256::from(filter.fee_per_gas) && self.fee_data.gas_per_pubdata_limit >= U256::from(filter.gas_per_pubdata) } } @@ -166,6 +195,7 @@ mod tests { max_priority_fee_per_gas: U256::from(MAX_PRIORITY_FEE_PER_GAS), gas_per_pubdata_limit: U256::from(GAS_PER_PUBDATA_LIMIT), }, + time_range_constraint: TransactionTimeRangeConstraint::default(), }; let noop_filter = filter(0, 0); diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index a50fc8a655b7..12445995588c 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -8,6 +8,7 @@ use std::fmt; use anyhow::Context as _; +use chrono::NaiveDateTime; use fee::encoding_len; pub use l1::L1TxCommonData; pub use l2::L2TxCommonData; @@ -417,3 +418,19 @@ impl Transaction { }) } } + +#[derive( + Clone, + Serialize, + Deserialize, + Debug, + Default, + Eq, + PartialEq, + Hash, + Copy +)] +pub struct TransactionTimeRangeConstraint { + pub range_start: Option, + pub range_end: Option, +} diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index f771a2dda4ce..9a7d1eba0192 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -300,9 +300,9 @@ impl StateKeeperIO for MempoolIO { async fn rollback(&mut self, tx: Transaction) -> anyhow::Result<()> { // Reset nonces in the mempool. - self.mempool.rollback(&tx); + let constraint = self.mempool.rollback(&tx); // Insert the transaction back. - self.mempool.insert(vec![tx], HashMap::new()); + self.mempool.insert(vec![(tx, constraint)], HashMap::new()); Ok(()) } diff --git a/core/node/state_keeper/src/mempool_actor.rs b/core/node/state_keeper/src/mempool_actor.rs index a5cec5b5a318..681d1a7379af 100644 --- a/core/node/state_keeper/src/mempool_actor.rs +++ b/core/node/state_keeper/src/mempool_actor.rs @@ -1,6 +1,7 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; use anyhow::Context as _; +use itertools::Itertools; #[cfg(test)] use tokio::sync::mpsc; use tokio::sync::watch; @@ -96,7 +97,7 @@ impl MempoolFetcher { .await .context("failed creating L2 transaction filter")?; - let transactions = storage + let transactions_with_constraints = storage .transactions_dal() .sync_mempool( &mempool_info.stashed_accounts, @@ -107,6 +108,12 @@ impl MempoolFetcher { ) .await .context("failed syncing mempool")?; + + let transactions = transactions_with_constraints + .iter() + .map(|(t, _c)| t) + .collect_vec(); + let nonces = get_transaction_nonces(&mut storage, &transactions).await?; drop(storage); @@ -116,7 +123,7 @@ impl MempoolFetcher { self.transaction_hashes_sender.send(transaction_hashes).ok(); } let all_transactions_loaded = transactions.len() < self.sync_batch_size; - self.mempool.insert(transactions, nonces); + self.mempool.insert(transactions_with_constraints, nonces); latency.observe(); if all_transactions_loaded { @@ -130,7 +137,7 @@ impl MempoolFetcher { /// Loads nonces for all distinct `transactions` initiators from the storage. async fn get_transaction_nonces( storage: &mut Connection<'_, Core>, - transactions: &[Transaction], + transactions: &[&Transaction], ) -> anyhow::Result> { let (nonce_keys, address_by_nonce_key): (Vec<_>, HashMap<_, _>) = transactions .iter() diff --git a/core/node/state_keeper/src/types.rs b/core/node/state_keeper/src/types.rs index e112871a6475..1da68a986db2 100644 --- a/core/node/state_keeper/src/types.rs +++ b/core/node/state_keeper/src/types.rs @@ -6,7 +6,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}; +use zksync_types::{ + block::BlockGasCount, Address, Nonce, PriorityOpId, Transaction, TransactionTimeRangeConstraint, +}; use super::{ metrics::StateKeeperGauges, @@ -30,7 +32,11 @@ impl MempoolGuard { Self(Arc::new(Mutex::new(store))) } - pub fn insert(&mut self, transactions: Vec, nonces: HashMap) { + pub fn insert( + &mut self, + transactions: Vec<(Transaction, TransactionTimeRangeConstraint)>, + nonces: HashMap, + ) { self.0 .lock() .expect("failed to acquire mempool lock") @@ -51,11 +57,11 @@ impl MempoolGuard { .next_transaction(filter) } - pub fn rollback(&mut self, rejected: &Transaction) { + pub fn rollback(&mut self, rejected: &Transaction) -> TransactionTimeRangeConstraint { self.0 .lock() .expect("failed to acquire mempool lock") - .rollback(rejected); + .rollback(rejected) } pub fn get_mempool_info(&mut self) -> MempoolInfo { From 730442244f19cfa2c433fd6b7de22ed7777d16a0 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Mon, 14 Oct 2024 10:22:35 +0100 Subject: [PATCH 26/68] Fix mempool tests --- core/lib/mempool/src/mempool_store.rs | 15 +++++++++++ core/lib/mempool/src/tests.rs | 38 +++++++++++++-------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/core/lib/mempool/src/mempool_store.rs b/core/lib/mempool/src/mempool_store.rs index 36763e19d49b..1a21fa09571d 100644 --- a/core/lib/mempool/src/mempool_store.rs +++ b/core/lib/mempool/src/mempool_store.rs @@ -97,6 +97,21 @@ impl MempoolStore { } } + #[cfg(test)] + pub fn insert_without_constraints( + &mut self, + transactions: Vec, + initial_nonces: HashMap, + ) { + self.insert( + transactions + .into_iter() + .map(|x| (x, TransactionTimeRangeConstraint::default())) + .collect(), + initial_nonces, + ); + } + fn insert_l2_transaction( &mut self, transaction: L2Tx, diff --git a/core/lib/mempool/src/tests.rs b/core/lib/mempool/src/tests.rs index 96ef600984f9..b571e24f8c35 100644 --- a/core/lib/mempool/src/tests.rs +++ b/core/lib/mempool/src/tests.rs @@ -27,7 +27,7 @@ fn basic_flow() { gen_l2_tx(account1, Nonce(1)), ]; assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert_eq!( view(mempool.next_transaction(&L2TxFilter::default())), (account0, 0) @@ -46,7 +46,7 @@ fn basic_flow() { ); assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); // unclog second account and insert more transactions - mempool.insert( + mempool.insert_without_constraints( vec![gen_l2_tx(account1, Nonce(0)), gen_l2_tx(account0, Nonce(3))], HashMap::new(), ); @@ -72,10 +72,10 @@ fn missing_txns() { ]; let mut nonces = HashMap::new(); nonces.insert(account, Nonce(5)); - mempool.insert(transactions, nonces); + mempool.insert_without_constraints(transactions, nonces); assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); // missing transaction unclogs mempool - mempool.insert(vec![gen_l2_tx(account, Nonce(5))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l2_tx(account, Nonce(5))], HashMap::new()); assert_eq!( view(mempool.next_transaction(&L2TxFilter::default())), (account, 5) @@ -90,7 +90,7 @@ fn missing_txns() { ); // filling remaining gap - mempool.insert(vec![gen_l2_tx(account, Nonce(8))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l2_tx(account, Nonce(8))], HashMap::new()); assert_eq!( view(mempool.next_transaction(&L2TxFilter::default())), (account, 8) @@ -110,7 +110,7 @@ fn prioritize_l1_txns() { gen_l2_tx(account, Nonce(1)), gen_l1_tx(PriorityOpId(0)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert!(mempool .next_transaction(&L2TxFilter::default()) .unwrap() @@ -125,9 +125,9 @@ fn l1_txns_priority_id() { gen_l1_tx(PriorityOpId(2)), gen_l1_tx(PriorityOpId(3)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert!(mempool.next_transaction(&L2TxFilter::default()).is_none()); - mempool.insert(vec![gen_l1_tx(PriorityOpId(0))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l1_tx(PriorityOpId(0))], HashMap::new()); for idx in 0..4 { let data = mempool .next_transaction(&L2TxFilter::default()) @@ -153,7 +153,7 @@ fn rejected_tx() { gen_l2_tx(account, Nonce(3)), gen_l2_tx(account, Nonce(5)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert_eq!( view(mempool.next_transaction(&L2TxFilter::default())), (account, 0) @@ -167,7 +167,7 @@ fn rejected_tx() { assert!(mempool.next_transaction(&L2TxFilter::default()).is_none()); // replace transaction and unblock account - mempool.insert(vec![gen_l2_tx(account, Nonce(1))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l2_tx(account, Nonce(1))], HashMap::new()); assert_eq!( view(mempool.next_transaction(&L2TxFilter::default())), (account, 1) @@ -186,9 +186,9 @@ fn rejected_tx() { fn replace_tx() { let mut mempool = MempoolStore::new(PriorityOpId(0), 100); let account = Address::random(); - mempool.insert(vec![gen_l2_tx(account, Nonce(0))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l2_tx(account, Nonce(0))], HashMap::new()); // replace it - mempool.insert( + mempool.insert_without_constraints( vec![gen_l2_tx_with_timestamp( account, Nonce(0), @@ -206,7 +206,7 @@ fn two_ready_txs() { let account0 = Address::random(); let account1 = Address::random(); let transactions = vec![gen_l2_tx(account0, Nonce(0)), gen_l2_tx(account1, Nonce(0))]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert_eq!( HashSet::<(_, _)>::from_iter(vec![ view(mempool.next_transaction(&L2TxFilter::default())), @@ -228,10 +228,10 @@ fn mempool_size() { gen_l2_tx(account0, Nonce(3)), gen_l2_tx(account1, Nonce(1)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); assert_eq!(mempool.stats().l2_transaction_count, 5); // replacement - mempool.insert(vec![gen_l2_tx(account0, Nonce(2))], HashMap::new()); + mempool.insert_without_constraints(vec![gen_l2_tx(account0, Nonce(2))], HashMap::new()); assert_eq!(mempool.stats().l2_transaction_count, 5); // load next mempool.next_transaction(&L2TxFilter::default()); @@ -261,7 +261,7 @@ fn filtering() { // First account will have two transactions: one with too low pubdata price and one with the right value. // Second account will have just one transaction with the right value. - mempool.insert( + mempool.insert_without_constraints( gen_transactions_for_filtering(vec![ (account0, Nonce(0), unix_timestamp_ms(), 0), (account0, Nonce(1), unix_timestamp_ms(), 1), @@ -302,7 +302,7 @@ fn stashed_accounts() { let account0 = Address::random(); let account1 = Address::random(); - mempool.insert( + mempool.insert_without_constraints( gen_transactions_for_filtering(vec![ (account0, Nonce(0), unix_timestamp_ms(), 0), (account0, Nonce(1), unix_timestamp_ms(), 1), @@ -332,14 +332,14 @@ fn mempool_capacity() { gen_l2_tx(account1, Nonce(1)), gen_l2_tx(account2, Nonce(1)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); // the mempool is full. Accounts with non-sequential nonces got stashed assert_eq!( HashSet::<_>::from_iter(mempool.get_mempool_info().purged_accounts), HashSet::<_>::from_iter(vec![account1, account2]), ); // verify that existing good-to-go transactions and new ones got picked - mempool.insert( + mempool.insert_without_constraints( vec![gen_l2_tx_with_timestamp( account1, Nonce(0), From 34c5a6c175aa32ca18cc91325c03250727edfb50 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Mon, 14 Oct 2024 10:44:15 +0100 Subject: [PATCH 27/68] Fix compilation errors --- core/node/eth_watch/src/tests.rs | 3 +++ core/node/state_keeper/src/io/tests/tester.rs | 2 +- core/node/state_keeper/src/mempool_actor.rs | 4 ++-- core/node/state_keeper/src/types.rs | 15 +++++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index d9faf7b664e6..12ac8bdbf3f7 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -620,6 +620,9 @@ async fn get_all_db_txs(storage: &mut Connection<'_, Core>) -> Vec .sync_mempool(&[], &[], 0, 0, 1000) .await .unwrap() + .into_iter() + .map(|x| x.0) + .collect() } fn tx_into_log(tx: L1Tx) -> Log { diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 1a9ce8445b95..94a51fb44ae3 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -257,7 +257,7 @@ impl Tester { gas_per_pubdata: u32, ) -> L2Tx { let tx = create_l2_transaction(fee_per_gas, gas_per_pubdata.into()); - guard.insert(vec![tx.clone().into()], Default::default()); + guard.insert_without_constraint(vec![tx.clone().into()], Default::default()); tx } } diff --git a/core/node/state_keeper/src/mempool_actor.rs b/core/node/state_keeper/src/mempool_actor.rs index 681d1a7379af..59146bfeff0f 100644 --- a/core/node/state_keeper/src/mempool_actor.rs +++ b/core/node/state_keeper/src/mempool_actor.rs @@ -119,7 +119,7 @@ impl MempoolFetcher { #[cfg(test)] { - let transaction_hashes = transactions.iter().map(Transaction::hash).collect(); + let transaction_hashes = transactions.iter().map(|x| x.hash()).collect(); self.transaction_hashes_sender.send(transaction_hashes).ok(); } let all_transactions_loaded = transactions.len() < self.sync_batch_size; @@ -207,7 +207,7 @@ mod tests { let nonces = get_transaction_nonces( &mut storage, - &[transaction.into(), other_transaction.into()], + &[&transaction.into(), &other_transaction.into()], ) .await .unwrap(); diff --git a/core/node/state_keeper/src/types.rs b/core/node/state_keeper/src/types.rs index 1da68a986db2..6a890f501404 100644 --- a/core/node/state_keeper/src/types.rs +++ b/core/node/state_keeper/src/types.rs @@ -43,6 +43,21 @@ impl MempoolGuard { .insert(transactions, nonces); } + #[cfg(test)] + pub fn insert_without_constraint( + &mut self, + transactions: Vec, + nonces: HashMap, + ) { + self.insert( + transactions + .into_iter() + .map(|x| (x, TransactionTimeRangeConstraint::default())) + .collect(), + nonces, + ); + } + pub fn has_next(&self, filter: &L2TxFilter) -> bool { self.0 .lock() From 772150928bcd8b4b42b11b8cd00f571c36870ab3 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 15 Oct 2024 10:04:21 +0100 Subject: [PATCH 28/68] Updated mempool handling --- Cargo.lock | 1 + core/lib/mempool/Cargo.toml | 2 + core/lib/mempool/src/mempool_store.rs | 19 +++++--- core/lib/mempool/src/tests.rs | 43 +++++++++++++++-- core/lib/mempool/src/types.rs | 48 +++++-------------- .../lib/vm_interface/src/types/errors/halt.rs | 4 ++ .../api_server/src/execution_sandbox/error.rs | 3 ++ core/node/api_server/src/tx_sender/result.rs | 6 +++ core/node/state_keeper/src/io/mempool.rs | 29 ++++++++++- .../state_keeper/src/seal_criteria/mod.rs | 1 + core/node/state_keeper/src/types.rs | 5 +- 11 files changed, 114 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9f7a88764ef..703d8e4eb6bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10402,6 +10402,7 @@ dependencies = [ name = "zksync_mempool" version = "0.1.0" dependencies = [ + "chrono", "tracing", "zksync_types", ] diff --git a/core/lib/mempool/Cargo.toml b/core/lib/mempool/Cargo.toml index ca2203f174f6..d0354047f8f3 100644 --- a/core/lib/mempool/Cargo.toml +++ b/core/lib/mempool/Cargo.toml @@ -13,3 +13,5 @@ categories.workspace = true [dependencies] zksync_types.workspace = true tracing.workspace = true +chrono = { workspace = true, features = ["serde"] } + diff --git a/core/lib/mempool/src/mempool_store.rs b/core/lib/mempool/src/mempool_store.rs index 1a21fa09571d..15c9edabb81f 100644 --- a/core/lib/mempool/src/mempool_store.rs +++ b/core/lib/mempool/src/mempool_store.rs @@ -151,10 +151,17 @@ impl MempoolStore { } /// Returns next transaction for execution from mempool - pub fn next_transaction(&mut self, filter: &L2TxFilter) -> Option { + pub fn next_transaction( + &mut self, + filter: &L2TxFilter, + ) -> Option<(Transaction, TransactionTimeRangeConstraint)> { if let Some(transaction) = self.l1_transactions.remove(&self.next_priority_id) { self.next_priority_id += 1; - return Some(transaction.into()); + // L1 transactions can't use block.timestamp in AA and hence do not need to have a constraint + return Some(( + transaction.into(), + TransactionTimeRangeConstraint::default(), + )); } let mut removed = 0; @@ -181,7 +188,7 @@ impl MempoolStore { self.stashed_accounts.push(stashed_pointer.account); } // insert pointer to the next transaction if it exists - let (transaction, score) = self + let (transaction, constraint, score) = self .l2_transactions_per_account .get_mut(&tx_pointer.account) .expect("mempool: dangling pointer in priority queue") @@ -194,7 +201,7 @@ impl MempoolStore { .size .checked_sub((removed + 1) as u64) .expect("mempool size can't be negative"); - Some(transaction.into()) + Some((transaction.into(), constraint)) } /// When a state_keeper starts the block over after a rejected transaction, @@ -209,14 +216,14 @@ impl MempoolStore { TransactionTimeRangeConstraint::default() } ExecuteTransactionCommon::L2(_) => { - if let Some(score) = self + if let Some((score, constraint)) = self .l2_transactions_per_account .get_mut(&tx.initiator_account()) .expect("account is not available in mempool") .reset(tx) { self.l2_priority_queue.remove(&score); - return score.time_range_constraint; + return constraint; } TransactionTimeRangeConstraint::default() } diff --git a/core/lib/mempool/src/tests.rs b/core/lib/mempool/src/tests.rs index b571e24f8c35..5e53cb4d0014 100644 --- a/core/lib/mempool/src/tests.rs +++ b/core/lib/mempool/src/tests.rs @@ -9,7 +9,7 @@ use zksync_types::{ l1::{OpProcessingType, PriorityQueueType}, l2::L2Tx, Address, Execute, ExecuteTransactionCommon, L1TxCommonData, Nonce, PriorityOpId, Transaction, - H256, U256, + TransactionTimeRangeConstraint, H256, U256, }; use crate::{mempool_store::MempoolStore, types::L2TxFilter}; @@ -114,6 +114,7 @@ fn prioritize_l1_txns() { assert!(mempool .next_transaction(&L2TxFilter::default()) .unwrap() + .0 .is_l1()) } @@ -132,6 +133,7 @@ fn l1_txns_priority_id() { let data = mempool .next_transaction(&L2TxFilter::default()) .unwrap() + .0 .common_data; match data { ExecuteTransactionCommon::L1(data) => { @@ -352,6 +354,7 @@ fn mempool_capacity() { mempool .next_transaction(&L2TxFilter::default()) .unwrap() + .0 .initiator_account(), account0 ); @@ -360,11 +363,45 @@ fn mempool_capacity() { mempool .next_transaction(&L2TxFilter::default()) .unwrap() + .0 .initiator_account(), account1 ); } +// +// #[test] +// fn basic_flow_with_timestamp_filter() { +// let mut mempool = MempoolStore::new(PriorityOpId(0), 100); +// let account0 = Address::random(); +// +// let now = SystemTime::now() +// .duration_since(UNIX_EPOCH) +// .expect("Invalid system time") +// .as_secs() as i64; +// +// #[allow(deprecated)] +// let transactions = vec![ +// (gen_l2_tx(account0, Nonce(0)), TransactionTimeRangeConstraint { +// range_start: Some(NaiveDateTime::from_timestamp(now - 5000, 0)), +// range_end: Some(NaiveDateTime::from_timestamp(now - 1000, 0)), +// }), +// (gen_l2_tx(account0, Nonce(1)), TransactionTimeRangeConstraint { +// range_start: Some(NaiveDateTime::from_timestamp(now - 5000, 0)), +// range_end: Some(NaiveDateTime::from_timestamp(now + 5000, 0)), +// }), +// +// (gen_l2_tx(account0, Nonce(2)), TransactionTimeRangeConstraint::default()), +// ]; +// assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); +// mempool.insert(transactions, HashMap::new()); +// assert_eq!( +// view(mempool.next_transaction(&L2TxFilter::default())), +// (account0, 1) +// ); +// assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); +// } + fn gen_l2_tx(address: Address, nonce: Nonce) -> Transaction { gen_l2_tx_with_timestamp(address, nonce, unix_timestamp_ms()) } @@ -415,8 +452,8 @@ fn gen_l1_tx(priority_id: PriorityOpId) -> Transaction { } } -fn view(transaction: Option) -> (Address, u32) { - let tx = transaction.unwrap(); +fn view(transaction: Option<(Transaction, TransactionTimeRangeConstraint)>) -> (Address, u32) { + let tx = transaction.unwrap().0; (tx.initiator_account(), tx.nonce().unwrap().0) } diff --git a/core/lib/mempool/src/types.rs b/core/lib/mempool/src/types.rs index 8f46318688e6..e67996676a77 100644 --- a/core/lib/mempool/src/types.rs +++ b/core/lib/mempool/src/types.rs @@ -1,8 +1,4 @@ -use std::{ - cmp::Ordering, - collections::HashMap, - time::{SystemTime, UNIX_EPOCH}, -}; +use std::{cmp::Ordering, collections::HashMap}; use zksync_types::{ fee::Fee, fee_model::BatchFeeInput, l2::L2Tx, Address, Nonce, Transaction, @@ -39,11 +35,11 @@ impl AccountTransactions { if nonce < self.nonce { return metadata; } - let new_score = Self::score_for_transaction(&transaction, constraint); + let new_score = Self::score_for_transaction(&transaction); let previous_score = self .transactions .insert(nonce, (transaction, constraint)) - .map(|(tx, constraint)| Self::score_for_transaction(&tx, constraint)); + .map(|x| Self::score_for_transaction(&x.0)); metadata.is_new = previous_score.is_none(); if nonce == self.nonce { metadata.new_score = Some(new_score); @@ -54,7 +50,7 @@ impl AccountTransactions { /// Returns next transaction to be included in block and optional score of its successor /// Panics if no such transaction exists - pub fn next(&mut self) -> (L2Tx, Option) { + pub fn next(&mut self) -> (L2Tx, TransactionTimeRangeConstraint, Option) { let transaction = self .transactions .remove(&self.nonce) @@ -63,12 +59,15 @@ impl AccountTransactions { let score = self .transactions .get(&self.nonce) - .map(|(tx, c)| Self::score_for_transaction(tx, *c)); - (transaction.0, score) + .map(|(tx, _c)| Self::score_for_transaction(tx)); + (transaction.0, transaction.1, score) } /// Handles transaction rejection. Returns optional score of its successor - pub fn reset(&mut self, transaction: &Transaction) -> Option { + pub fn reset( + &mut self, + transaction: &Transaction, + ) -> Option<(MempoolScore, TransactionTimeRangeConstraint)> { // current nonce for the group needs to be reset let tx_nonce = transaction .nonce() @@ -76,22 +75,18 @@ impl AccountTransactions { self.nonce = self.nonce.min(tx_nonce); self.transactions .get(&(tx_nonce + 1)) - .map(|(tx, c)| Self::score_for_transaction(tx, *c)) + .map(|(tx, c)| (Self::score_for_transaction(tx), *c)) } pub fn len(&self) -> usize { self.transactions.len() } - fn score_for_transaction( - transaction: &L2Tx, - constraint: TransactionTimeRangeConstraint, - ) -> MempoolScore { + fn score_for_transaction(transaction: &L2Tx) -> MempoolScore { MempoolScore { account: transaction.initiator_account(), received_at_ms: transaction.received_timestamp_ms, fee_data: transaction.common_data.fee.clone(), - time_range_constraint: constraint, } } } @@ -106,28 +101,12 @@ pub struct MempoolScore { // transactions that have acceptable fee values (so transactions // with fee too low would be ignored until prices go down). pub fee_data: Fee, - pub time_range_constraint: TransactionTimeRangeConstraint, } impl MempoolScore { /// Checks whether transaction matches requirements provided by state keeper. pub fn matches_filter(&self, filter: &L2TxFilter) -> bool { - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Invalid system time") - .as_secs() as i64; - - let matches_range = self - .time_range_constraint - .range_start - .map_or(true, |x| x.and_utc().timestamp() < now) - && self - .time_range_constraint - .range_end - .map_or(true, |x| x.and_utc().timestamp() > now); - - matches_range - && self.fee_data.max_fee_per_gas >= U256::from(filter.fee_per_gas) + self.fee_data.max_fee_per_gas >= U256::from(filter.fee_per_gas) && self.fee_data.gas_per_pubdata_limit >= U256::from(filter.gas_per_pubdata) } } @@ -195,7 +174,6 @@ mod tests { max_priority_fee_per_gas: U256::from(MAX_PRIORITY_FEE_PER_GAS), gas_per_pubdata_limit: U256::from(GAS_PER_PUBDATA_LIMIT), }, - time_range_constraint: TransactionTimeRangeConstraint::default(), }; let noop_filter = filter(0, 0); diff --git a/core/lib/vm_interface/src/types/errors/halt.rs b/core/lib/vm_interface/src/types/errors/halt.rs index 88328e42b812..7789ae7d9c22 100644 --- a/core/lib/vm_interface/src/types/errors/halt.rs +++ b/core/lib/vm_interface/src/types/errors/halt.rs @@ -42,6 +42,7 @@ pub enum Halt { VMPanic, TracerCustom(String), FailedToPublishCompressedBytecodes, + ViolatedBlockTimestampConstraint, } impl fmt::Display for Halt { @@ -116,6 +117,9 @@ impl fmt::Display for Halt { Halt::FailedToPublishCompressedBytecodes => { write!(f, "Failed to publish compressed bytecodes") } + Halt::ViolatedBlockTimestampConstraint => { + write!(f, "Transaction violated block.timestamp constraint") + } } } } diff --git a/core/node/api_server/src/execution_sandbox/error.rs b/core/node/api_server/src/execution_sandbox/error.rs index 5d63d50a3c85..6c7ed19e1c8e 100644 --- a/core/node/api_server/src/execution_sandbox/error.rs +++ b/core/node/api_server/src/execution_sandbox/error.rs @@ -26,6 +26,8 @@ pub(crate) enum SandboxExecutionError { that caused this error. Error description: {0}" )] UnexpectedVMBehavior(String), + #[error("Transaction violated block.timestamp constraint")] + ViolatedBlockTimestampConstraint, } impl From for SandboxExecutionError { @@ -67,6 +69,7 @@ impl From for SandboxExecutionError { Halt::FailedToPublishCompressedBytecodes => { Self::UnexpectedVMBehavior("Failed to publish compressed bytecodes".to_string()) } + Halt::ViolatedBlockTimestampConstraint => Self::ViolatedBlockTimestampConstraint, } } } diff --git a/core/node/api_server/src/tx_sender/result.rs b/core/node/api_server/src/tx_sender/result.rs index a49313f0dd62..03b352776a33 100644 --- a/core/node/api_server/src/tx_sender/result.rs +++ b/core/node/api_server/src/tx_sender/result.rs @@ -75,6 +75,8 @@ pub enum SubmitTxError { /// Catch-all internal error (e.g., database error) that should not be exposed to the caller. #[error("internal error")] Internal(#[from] anyhow::Error), + #[error("transaction violated block.timestamp constraint")] + ViolatedBlockTimestampConstraint, } impl SubmitTxError { @@ -108,6 +110,7 @@ impl SubmitTxError { Self::ProxyError(_) => "proxy-error", Self::FailedToPublishCompressedBytecodes => "failed-to-publish-compressed-bytecodes", Self::Internal(_) => "internal", + Self::ViolatedBlockTimestampConstraint => "violated-block-timestamp-constraint", } } @@ -145,6 +148,9 @@ impl From for SubmitTxError { SandboxExecutionError::FailedToPayForTransaction(reason) => { Self::FailedToChargeFee(reason) } + SandboxExecutionError::ViolatedBlockTimestampConstraint => { + Self::ViolatedBlockTimestampConstraint + } } } } diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index da5fcd19fa9a..c920555b585b 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -2,7 +2,7 @@ use std::{ cmp, collections::HashMap, sync::Arc, - time::{Duration, Instant}, + time::{Duration, Instant, SystemTime, UNIX_EPOCH}, }; use anyhow::Context as _; @@ -285,7 +285,7 @@ impl StateKeeperIO for MempoolIO { let maybe_tx = self.mempool.next_transaction(&self.filter); get_latency.observe(); - if let Some(tx) = maybe_tx { + if let Some((tx, constraint)) = maybe_tx { // Reject transactions with too big gas limit. They are also rejected on the API level, but // we need to secure ourselves in case some tx will somehow get into mempool. if tx.gas_limit() > self.max_allowed_tx_gas_limit { @@ -298,6 +298,31 @@ impl StateKeeperIO for MempoolIO { .await?; continue; } + + // Reject transactions that violate block.timestamp constraints. Such transactions should be + // rejected at the API level, but we need to protect ourselves in case if a transaction + // goes outside of the allowed range while being in the mempool + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Invalid system time") + .as_secs() as i64; + + let matches_range = constraint + .range_start + .map_or(true, |x| x.and_utc().timestamp() < now) + && constraint + .range_end + .map_or(true, |x| x.and_utc().timestamp() > now); + + if !matches_range { + self.reject( + &tx, + UnexecutableReason::Halt(Halt::ViolatedBlockTimestampConstraint), + ) + .await?; + continue; + } + return Ok(Some(tx)); } else { tokio::time::sleep(self.delay_interval).await; diff --git a/core/node/state_keeper/src/seal_criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/mod.rs index 962cc807318b..9fdeecab7107 100644 --- a/core/node/state_keeper/src/seal_criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/mod.rs @@ -54,6 +54,7 @@ fn halt_as_metric_label(halt: &Halt) -> &'static str { Halt::VMPanic => "VMPanic", Halt::TracerCustom(_) => "TracerCustom", Halt::FailedToPublishCompressedBytecodes => "FailedToPublishCompressedBytecodes", + Halt::ViolatedBlockTimestampConstraint => "ViolatedBlockTimestampConstraint", } } diff --git a/core/node/state_keeper/src/types.rs b/core/node/state_keeper/src/types.rs index 6a890f501404..db18e32e0963 100644 --- a/core/node/state_keeper/src/types.rs +++ b/core/node/state_keeper/src/types.rs @@ -65,7 +65,10 @@ impl MempoolGuard { .has_next(filter) } - pub fn next_transaction(&mut self, filter: &L2TxFilter) -> Option { + pub fn next_transaction( + &mut self, + filter: &L2TxFilter, + ) -> Option<(Transaction, TransactionTimeRangeConstraint)> { self.0 .lock() .expect("failed to acquire mempool lock") From f7fb4c26aec46f31ae0c56ffd149c78b977cb179 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 15 Oct 2024 12:46:39 +0100 Subject: [PATCH 29/68] Fix main --- .../config/src/forge_interface/deploy_l2_contracts/output.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkstack_cli/crates/config/src/forge_interface/deploy_l2_contracts/output.rs b/zkstack_cli/crates/config/src/forge_interface/deploy_l2_contracts/output.rs index 799fd06977a4..7b2b56c81548 100644 --- a/zkstack_cli/crates/config/src/forge_interface/deploy_l2_contracts/output.rs +++ b/zkstack_cli/crates/config/src/forge_interface/deploy_l2_contracts/output.rs @@ -8,7 +8,7 @@ impl ZkStackConfig for DefaultL2UpgradeOutput {} impl ZkStackConfig for ConsensusRegistryOutput {} impl ZkStackConfig for Multicall3Output {} -impl ZkToolboxConfig for TimestampAsserterOutput {} +impl ZkStackConfig for TimestampAsserterOutput {} #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InitializeBridgeOutput { From aa23ec1cbfb825b10bdd6914c50763be730677a8 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 15 Oct 2024 14:28:43 +0100 Subject: [PATCH 30/68] Add mempool test --- Cargo.lock | 1 + ...76fb01e6629e8c982c265f2af1d5000090572.json | 20 --- core/lib/dal/src/transactions_dal.rs | 23 +++ core/node/state_keeper/Cargo.toml | 2 + core/node/state_keeper/src/io/tests/mod.rs | 142 +++++++++++++++++- core/node/state_keeper/src/io/tests/tester.rs | 6 +- 6 files changed, 168 insertions(+), 26 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json diff --git a/Cargo.lock b/Cargo.lock index f52a473a9926..bf8234f20ca6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11103,6 +11103,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", + "chrono", "futures 0.3.30", "hex", "itertools 0.10.5", diff --git a/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json b/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json deleted file mode 100644 index 9669622f5cf2..000000000000 --- a/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT COUNT(miniblocks.number) FROM miniblocks WHERE l1_batch_number IS NULL", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "count", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null - ] - }, - "hash": "dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572" -} diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 09a1b4d7f6e4..5b03a42d5a23 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -2231,6 +2231,29 @@ impl TransactionsDal<'_, '_> { .fetch_optional(self.storage) .await } + + pub async fn get_storage_tx_by_hash( + &mut self, + hash: H256, + ) -> DalResult> { + sqlx::query_as!( + StorageTransaction, + r#" + SELECT + * + FROM + transactions + WHERE + hash = $1 + "#, + hash.as_bytes() + ) + .map(Into::into) + .instrument("get_tx_error_by_hash") + .with_arg("hash", &hash) + .fetch_optional(self.storage) + .await + } } #[cfg(test)] diff --git a/core/node/state_keeper/Cargo.toml b/core/node/state_keeper/Cargo.toml index 0e924b9f066d..1bb91a42382d 100644 --- a/core/node/state_keeper/Cargo.toml +++ b/core/node/state_keeper/Cargo.toml @@ -31,6 +31,8 @@ zksync_node_test_utils.workspace = true zksync_vm_executor.workspace = true zksync_system_constants.workspace = true zksync_base_token_adjuster.workspace = true +chrono = { workspace = true, features = ["serde"] } + anyhow.workspace = true async-trait.workspace = true diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 7d9c351fd53b..13ccbe3ee4ab 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -1,8 +1,12 @@ -use std::{collections::HashMap, time::Duration}; +use std::{ + collections::HashMap, + time::{Duration, SystemTime, UNIX_EPOCH}, +}; +use chrono::NaiveDateTime; use test_casing::test_casing; use zksync_contracts::BaseSystemContractsHashes; -use zksync_dal::{ConnectionPool, Core, CoreDal}; +use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; use zksync_mempool::L2TxFilter; use zksync_multivm::{ interface::{ @@ -15,8 +19,9 @@ use zksync_types::{ block::{BlockGasCount, L2BlockHasher}, commitment::L1BatchCommitmentMode, fee_model::{BatchFeeInput, PubdataIndependentBatchFeeModelInput}, + l2::L2Tx, AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, ProtocolVersion, - ProtocolVersionId, StorageKey, H256, U256, + ProtocolVersionId, StorageKey, TransactionTimeRangeConstraint, H256, U256, }; use zksync_utils::time::seconds_since_epoch; @@ -132,6 +137,7 @@ async fn test_filter_with_no_pending_batch(commitment_mode: L1BatchCommitmentMod &mut guard, want_filter.fee_per_gas, want_filter.gas_per_pubdata, + TransactionTimeRangeConstraint::default(), ); // Now, given that there is a transaction matching the expected filter, waiting for the new batch params @@ -171,7 +177,12 @@ async fn test_timestamps_are_distinct( ) .await .unwrap(); - tester.insert_tx(&mut guard, tx_filter.fee_per_gas, tx_filter.gas_per_pubdata); + tester.insert_tx( + &mut guard, + tx_filter.fee_per_gas, + tx_filter.gas_per_pubdata, + TransactionTimeRangeConstraint::default(), + ); let l1_batch_params = mempool .wait_for_new_batch_params(&io_cursor, Duration::from_secs(10)) @@ -431,6 +442,7 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom &mut mempool_guard, tx_filter.fee_per_gas, tx_filter.gas_per_pubdata, + TransactionTimeRangeConstraint::default(), ); storage .transactions_dal() @@ -586,6 +598,7 @@ async fn continue_unsealed_batch_on_restart(commitment_mode: L1BatchCommitmentMo &mut mempool_guard, tx_filter.fee_per_gas, tx_filter.gas_per_pubdata, + TransactionTimeRangeConstraint::default(), ); storage .transactions_dal() @@ -650,3 +663,124 @@ async fn insert_unsealed_batch_on_init(commitment_mode: L1BatchCommitmentMode) { assert_eq!(l1_batch_params.fee_input, fee_input); assert_eq!(l1_batch_params.first_l2_block.timestamp, 2); } + +#[test_casing(2, COMMITMENT_MODES)] +#[tokio::test] +async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmentMode) { + let connection_pool = ConnectionPool::::constrained_test_pool(2).await; + let tester = Tester::new(commitment_mode); + let mut storage = connection_pool.connection().await.unwrap(); + + tester.genesis(&connection_pool).await; + + // Insert a sealed batch so there will be a `prev_l1_batch_state_root`. + // These gas values are random and don't matter for filter calculation. + let tx_result = tester + .insert_l2_block(&connection_pool, 1, 5, BatchFeeInput::l1_pegged(55, 555)) + .await; + tester + .insert_sealed_batch(&connection_pool, 1, &[tx_result]) + .await; + + // Create a copy of the tx filter that the mempool will use. + let want_filter = l2_tx_filter( + &tester.create_batch_fee_input_provider().await, + ProtocolVersionId::latest().into(), + ) + .await + .unwrap(); + + // Create a mempool without pending batch and ensure that filter is not initialized just yet. + let (mut mempool, mut guard) = tester.create_test_mempool_io(connection_pool).await; + mempool.initialize().await.unwrap(); + assert_eq!(mempool.filter(), &L2TxFilter::default()); + + let system_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_secs() as i64; + + // inserting 3 transactions - a good one, sandwiched in between two bad ones. The good one should + // be returned by wait_for_next_tx, while two bad ones should be rejected. + #[allow(deprecated)] + let rejected_tx_1 = tester.insert_tx( + &mut guard, + want_filter.fee_per_gas, + want_filter.gas_per_pubdata, + TransactionTimeRangeConstraint { + range_start: Some(NaiveDateTime::from_timestamp(system_time - 20000, 0)), + range_end: Some(NaiveDateTime::from_timestamp(system_time - 10000, 0)), + }, + ); + #[allow(deprecated)] + let expected_tx = tester.insert_tx( + &mut guard, + want_filter.fee_per_gas, + want_filter.gas_per_pubdata, + TransactionTimeRangeConstraint { + range_start: Some(NaiveDateTime::from_timestamp(system_time - 1000, 0)), + range_end: Some(NaiveDateTime::from_timestamp(system_time + 1000, 0)), + }, + ); + #[allow(deprecated)] + let rejected_tx_2 = tester.insert_tx( + &mut guard, + want_filter.fee_per_gas, + want_filter.gas_per_pubdata, + TransactionTimeRangeConstraint { + range_start: Some(NaiveDateTime::from_timestamp(system_time + 10000, 0)), + range_end: Some(NaiveDateTime::from_timestamp(system_time + 20000, 0)), + }, + ); + insert_l2_transaction(&mut storage, &rejected_tx_1).await; + insert_l2_transaction(&mut storage, &expected_tx).await; + insert_l2_transaction(&mut storage, &rejected_tx_2).await; + + let tx = mempool + .wait_for_next_tx(Duration::from_secs(2)) + .await + .expect("No expected transaction in the mempool") + .unwrap(); + assert_eq!(expected_tx.hash(), tx.hash()); + + let next_tx = mempool + .wait_for_next_tx(Duration::from_secs(2)) + .await + .expect("Should be no more transactions in the mempool"); + assert!(next_tx.is_none()); + + // verify that two transactions have been rejected + let rejected_storage_tx_1 = storage + .transactions_dal() + .get_storage_tx_by_hash(rejected_tx_1.hash()) + .await + .expect("Failed to find transaction") + .unwrap(); + assert_eq!( + "rejected: Transaction violated block.timestamp constraint", + rejected_storage_tx_1.error.unwrap() + ); + + let rejected_storage_tx_2 = storage + .transactions_dal() + .get_storage_tx_by_hash(rejected_tx_2.hash()) + .await + .expect("Failed to find transaction") + .unwrap(); + assert_eq!( + "rejected: Transaction violated block.timestamp constraint", + rejected_storage_tx_2.error.unwrap() + ); +} + +async fn insert_l2_transaction(storage: &mut Connection<'_, Core>, tx: &L2Tx) { + storage + .transactions_dal() + .insert_transaction_l2( + &tx, + TransactionExecutionMetrics::default(), + ValidationTraces::default(), + ) + .await + .unwrap(); +} diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 94a51fb44ae3..1c303f536446 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -31,7 +31,8 @@ use zksync_types::{ l2::L2Tx, protocol_version::{L1VerifierConfig, ProtocolSemanticVersion}, system_contracts::get_system_smart_contracts, - L2BlockNumber, L2ChainId, PriorityOpId, ProtocolVersionId, H256, + L2BlockNumber, L2ChainId, PriorityOpId, ProtocolVersionId, TransactionTimeRangeConstraint, + H256, }; use crate::{MempoolGuard, MempoolIO}; @@ -255,9 +256,10 @@ impl Tester { guard: &mut MempoolGuard, fee_per_gas: u64, gas_per_pubdata: u32, + constraint: TransactionTimeRangeConstraint, ) -> L2Tx { let tx = create_l2_transaction(fee_per_gas, gas_per_pubdata.into()); - guard.insert_without_constraint(vec![tx.clone().into()], Default::default()); + guard.insert(vec![(tx.clone().into(), constraint)], Default::default()); tx } } From b09984147ef0db6af0fa755bc9f667a2ef3f1530 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 15 Oct 2024 14:29:21 +0100 Subject: [PATCH 31/68] Add mempool test --- ...e8fcd809448dfe510eadf965d778c27f94c27.json | 244 ++++++++++++++++++ core/lib/dal/src/transactions_dal.rs | 14 +- 2 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json diff --git a/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json b/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json new file mode 100644 index 000000000000..e24b5fa07f3e --- /dev/null +++ b/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json @@ -0,0 +1,244 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n *\n FROM\n transactions\n WHERE\n hash = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "hash", + "type_info": "Bytea" + }, + { + "ordinal": 1, + "name": "is_priority", + "type_info": "Bool" + }, + { + "ordinal": 2, + "name": "full_fee", + "type_info": "Numeric" + }, + { + "ordinal": 3, + "name": "layer_2_tip_fee", + "type_info": "Numeric" + }, + { + "ordinal": 4, + "name": "initiator_address", + "type_info": "Bytea" + }, + { + "ordinal": 5, + "name": "nonce", + "type_info": "Int8" + }, + { + "ordinal": 6, + "name": "signature", + "type_info": "Bytea" + }, + { + "ordinal": 7, + "name": "input", + "type_info": "Bytea" + }, + { + "ordinal": 8, + "name": "data", + "type_info": "Jsonb" + }, + { + "ordinal": 9, + "name": "received_at", + "type_info": "Timestamp" + }, + { + "ordinal": 10, + "name": "priority_op_id", + "type_info": "Int8" + }, + { + "ordinal": 11, + "name": "l1_batch_number", + "type_info": "Int8" + }, + { + "ordinal": 12, + "name": "index_in_block", + "type_info": "Int4" + }, + { + "ordinal": 13, + "name": "error", + "type_info": "Varchar" + }, + { + "ordinal": 14, + "name": "gas_limit", + "type_info": "Numeric" + }, + { + "ordinal": 15, + "name": "gas_per_storage_limit", + "type_info": "Numeric" + }, + { + "ordinal": 16, + "name": "gas_per_pubdata_limit", + "type_info": "Numeric" + }, + { + "ordinal": 17, + "name": "tx_format", + "type_info": "Int4" + }, + { + "ordinal": 18, + "name": "created_at", + "type_info": "Timestamp" + }, + { + "ordinal": 19, + "name": "updated_at", + "type_info": "Timestamp" + }, + { + "ordinal": 20, + "name": "execution_info", + "type_info": "Jsonb" + }, + { + "ordinal": 21, + "name": "contract_address", + "type_info": "Bytea" + }, + { + "ordinal": 22, + "name": "in_mempool", + "type_info": "Bool" + }, + { + "ordinal": 23, + "name": "l1_block_number", + "type_info": "Int4" + }, + { + "ordinal": 24, + "name": "value", + "type_info": "Numeric" + }, + { + "ordinal": 25, + "name": "paymaster", + "type_info": "Bytea" + }, + { + "ordinal": 26, + "name": "paymaster_input", + "type_info": "Bytea" + }, + { + "ordinal": 27, + "name": "max_fee_per_gas", + "type_info": "Numeric" + }, + { + "ordinal": 28, + "name": "max_priority_fee_per_gas", + "type_info": "Numeric" + }, + { + "ordinal": 29, + "name": "effective_gas_price", + "type_info": "Numeric" + }, + { + "ordinal": 30, + "name": "miniblock_number", + "type_info": "Int8" + }, + { + "ordinal": 31, + "name": "l1_batch_tx_index", + "type_info": "Int4" + }, + { + "ordinal": 32, + "name": "refunded_gas", + "type_info": "Int8" + }, + { + "ordinal": 33, + "name": "l1_tx_mint", + "type_info": "Numeric" + }, + { + "ordinal": 34, + "name": "l1_tx_refund_recipient", + "type_info": "Bytea" + }, + { + "ordinal": 35, + "name": "upgrade_id", + "type_info": "Int4" + }, + { + "ordinal": 36, + "name": "block_timestamp_range_start", + "type_info": "Timestamp" + }, + { + "ordinal": 37, + "name": "block_timestamp_range_end", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Bytea" + ] + }, + "nullable": [ + false, + false, + true, + true, + false, + true, + true, + true, + false, + false, + true, + true, + true, + true, + true, + true, + true, + true, + false, + false, + false, + true, + false, + true, + false, + false, + false, + true, + true, + true, + true, + true, + false, + true, + true, + true, + true, + true + ] + }, + "hash": "f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27" +} diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 5b03a42d5a23..fa46c69d8d5a 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -2239,13 +2239,13 @@ impl TransactionsDal<'_, '_> { sqlx::query_as!( StorageTransaction, r#" - SELECT - * - FROM - transactions - WHERE - hash = $1 - "#, + SELECT + * + FROM + transactions + WHERE + hash = $1 + "#, hash.as_bytes() ) .map(Into::into) From 4716cdde1f939298f1c0b2d68ed7905361d6ed84 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Wed, 16 Oct 2024 10:48:19 +0100 Subject: [PATCH 32/68] Updated contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 69ee5349cdcb..c88da6d261c0 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 69ee5349cdcb95228bb288f8f12470fe466af94d +Subproject commit c88da6d261c0b75f7ca6af155dc50a73df7bac7a From 82841acc6d04d3cbc73daa2acdc6bde1a97b5541 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Wed, 16 Oct 2024 11:10:04 +0100 Subject: [PATCH 33/68] Update to the latest contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index c88da6d261c0..1f4018f1835d 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit c88da6d261c0b75f7ca6af155dc50a73df7bac7a +Subproject commit 1f4018f1835db5f81bcef716f01b18d1e6bc0b6f From 10fff81dad6ac02dc1cfcba9c5179e0238a9bf82 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Wed, 16 Oct 2024 11:44:36 +0100 Subject: [PATCH 34/68] Update contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 1f4018f1835d..cdc6af745649 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 1f4018f1835db5f81bcef716f01b18d1e6bc0b6f +Subproject commit cdc6af745649ba4860563a13b8939997bdb3859e From 8051e0a1e4091c846c9881c7d5227a521b4e9108 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Wed, 16 Oct 2024 11:59:12 +0100 Subject: [PATCH 35/68] Update contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index cdc6af745649..66601e6cc31e 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit cdc6af745649ba4860563a13b8939997bdb3859e +Subproject commit 66601e6cc31e5d919429971ae1e4004746c5b7cf From 623a98e10473f1dc23b947f29eba6eae48ab2155 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Wed, 16 Oct 2024 17:21:36 +0100 Subject: [PATCH 36/68] Add tx_sender test --- ...77a428820fdcea9969aff3b29ca16727357b.json} | 4 +- ...e8fcd809448dfe510eadf965d778c27f94c27.json | 244 ------------------ core/lib/dal/src/transactions_dal.rs | 8 - core/lib/vm_executor/src/oneshot/mock.rs | 21 +- .../api_server/src/tx_sender/tests/send_tx.rs | 82 +++++- .../custom-account/custom-account.sol | 2 +- yarn.lock | 235 +++-------------- 7 files changed, 137 insertions(+), 459 deletions(-) rename core/lib/dal/.sqlx/{query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json => query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json} (84%) delete mode 100644 core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json diff --git a/core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json similarity index 84% rename from core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json rename to core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json index b60cb8b9b47f..83c977551b95 100644 --- a/core/lib/dal/.sqlx/query-cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e.json +++ b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n AND (\n block_timestamp_range_start IS NULL\n OR block_timestamp_range_start <= CURRENT_DATE\n )\n AND (\n block_timestamp_range_end IS NULL\n OR block_timestamp_range_end >= CURRENT_DATE\n )\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", + "query": "\n UPDATE transactions\n SET\n in_mempool = TRUE\n FROM\n (\n SELECT\n hash\n FROM\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n miniblock_number IS NULL\n AND in_mempool = FALSE\n AND error IS NULL\n AND (\n is_priority = TRUE\n OR (\n max_fee_per_gas >= $2\n AND gas_per_pubdata_limit >= $3\n )\n )\n AND tx_format != $4\n ORDER BY\n is_priority DESC,\n priority_op_id,\n received_at\n LIMIT\n $1\n ) AS subquery1\n ORDER BY\n hash\n ) AS subquery2\n WHERE\n transactions.hash = subquery2.hash\n RETURNING\n transactions.*\n ", "describe": { "columns": [ { @@ -243,5 +243,5 @@ true ] }, - "hash": "cdfd1ba13380239e075baab9e7d4f526b631743b18afbcec8e07aef386857f4e" + "hash": "a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b" } diff --git a/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json b/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json deleted file mode 100644 index e24b5fa07f3e..000000000000 --- a/core/lib/dal/.sqlx/query-f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n *\n FROM\n transactions\n WHERE\n hash = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "hash", - "type_info": "Bytea" - }, - { - "ordinal": 1, - "name": "is_priority", - "type_info": "Bool" - }, - { - "ordinal": 2, - "name": "full_fee", - "type_info": "Numeric" - }, - { - "ordinal": 3, - "name": "layer_2_tip_fee", - "type_info": "Numeric" - }, - { - "ordinal": 4, - "name": "initiator_address", - "type_info": "Bytea" - }, - { - "ordinal": 5, - "name": "nonce", - "type_info": "Int8" - }, - { - "ordinal": 6, - "name": "signature", - "type_info": "Bytea" - }, - { - "ordinal": 7, - "name": "input", - "type_info": "Bytea" - }, - { - "ordinal": 8, - "name": "data", - "type_info": "Jsonb" - }, - { - "ordinal": 9, - "name": "received_at", - "type_info": "Timestamp" - }, - { - "ordinal": 10, - "name": "priority_op_id", - "type_info": "Int8" - }, - { - "ordinal": 11, - "name": "l1_batch_number", - "type_info": "Int8" - }, - { - "ordinal": 12, - "name": "index_in_block", - "type_info": "Int4" - }, - { - "ordinal": 13, - "name": "error", - "type_info": "Varchar" - }, - { - "ordinal": 14, - "name": "gas_limit", - "type_info": "Numeric" - }, - { - "ordinal": 15, - "name": "gas_per_storage_limit", - "type_info": "Numeric" - }, - { - "ordinal": 16, - "name": "gas_per_pubdata_limit", - "type_info": "Numeric" - }, - { - "ordinal": 17, - "name": "tx_format", - "type_info": "Int4" - }, - { - "ordinal": 18, - "name": "created_at", - "type_info": "Timestamp" - }, - { - "ordinal": 19, - "name": "updated_at", - "type_info": "Timestamp" - }, - { - "ordinal": 20, - "name": "execution_info", - "type_info": "Jsonb" - }, - { - "ordinal": 21, - "name": "contract_address", - "type_info": "Bytea" - }, - { - "ordinal": 22, - "name": "in_mempool", - "type_info": "Bool" - }, - { - "ordinal": 23, - "name": "l1_block_number", - "type_info": "Int4" - }, - { - "ordinal": 24, - "name": "value", - "type_info": "Numeric" - }, - { - "ordinal": 25, - "name": "paymaster", - "type_info": "Bytea" - }, - { - "ordinal": 26, - "name": "paymaster_input", - "type_info": "Bytea" - }, - { - "ordinal": 27, - "name": "max_fee_per_gas", - "type_info": "Numeric" - }, - { - "ordinal": 28, - "name": "max_priority_fee_per_gas", - "type_info": "Numeric" - }, - { - "ordinal": 29, - "name": "effective_gas_price", - "type_info": "Numeric" - }, - { - "ordinal": 30, - "name": "miniblock_number", - "type_info": "Int8" - }, - { - "ordinal": 31, - "name": "l1_batch_tx_index", - "type_info": "Int4" - }, - { - "ordinal": 32, - "name": "refunded_gas", - "type_info": "Int8" - }, - { - "ordinal": 33, - "name": "l1_tx_mint", - "type_info": "Numeric" - }, - { - "ordinal": 34, - "name": "l1_tx_refund_recipient", - "type_info": "Bytea" - }, - { - "ordinal": 35, - "name": "upgrade_id", - "type_info": "Int4" - }, - { - "ordinal": 36, - "name": "block_timestamp_range_start", - "type_info": "Timestamp" - }, - { - "ordinal": 37, - "name": "block_timestamp_range_end", - "type_info": "Timestamp" - } - ], - "parameters": { - "Left": [ - "Bytea" - ] - }, - "nullable": [ - false, - false, - true, - true, - false, - true, - true, - true, - false, - false, - true, - true, - true, - true, - true, - true, - true, - true, - false, - false, - false, - true, - false, - true, - false, - false, - false, - true, - true, - true, - true, - true, - false, - true, - true, - true, - true, - true - ] - }, - "hash": "f2d5b1389197d2d3becb65caf9ee8fcd809448dfe510eadf965d778c27f94c27" -} diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index fa46c69d8d5a..ec7ebe944ab4 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -1810,14 +1810,6 @@ impl TransactionsDal<'_, '_> { ) ) AND tx_format != $4 - AND ( - block_timestamp_range_start IS NULL - OR block_timestamp_range_start <= CURRENT_DATE - ) - AND ( - block_timestamp_range_end IS NULL - OR block_timestamp_range_end >= CURRENT_DATE - ) ORDER BY is_priority DESC, priority_op_id, diff --git a/core/lib/vm_executor/src/oneshot/mock.rs b/core/lib/vm_executor/src/oneshot/mock.rs index 8a7d03653098..6ab3b1d9c306 100644 --- a/core/lib/vm_executor/src/oneshot/mock.rs +++ b/core/lib/vm_executor/src/oneshot/mock.rs @@ -11,11 +11,14 @@ use zksync_multivm::interface::{ use zksync_types::{l2::L2Tx, Transaction}; type TxResponseFn = dyn Fn(&Transaction, &OneshotEnv) -> VmExecutionResultAndLogs + Send + Sync; +type TxValidationTracesResponseFn = + dyn Fn(&Transaction, &OneshotEnv) -> ValidationTraces + Send + Sync; /// Mock [`OneshotExecutor`] implementation. pub struct MockOneshotExecutor { call_responses: Box, tx_responses: Box, + tx_validation_traces_responses: Box, } impl fmt::Debug for MockOneshotExecutor { @@ -35,6 +38,7 @@ impl Default for MockOneshotExecutor { tx_responses: Box::new(|tx, _| { panic!("Unexpect transaction call: {tx:?}"); }), + tx_validation_traces_responses: Box::new(|_, _| ValidationTraces::default()), } } } @@ -57,6 +61,13 @@ impl MockOneshotExecutor { self.tx_responses = self.wrap_responses(responses); } + pub fn set_tx_validation_traces_responses(&mut self, responses: F) + where + F: Fn(&Transaction, &OneshotEnv) -> ValidationTraces + 'static + Send + Sync, + { + self.tx_validation_traces_responses = Box::new(responses); + } + fn wrap_responses(&mut self, responses: F) -> Box where F: Fn(&Transaction, &OneshotEnv) -> ExecutionResult + 'static + Send + Sync, @@ -82,11 +93,11 @@ impl MockOneshotExecutor { self.tx_responses = Box::new(responses); } - fn mock_inspect(&self, env: OneshotEnv, args: TxExecutionArgs) -> VmExecutionResultAndLogs { + fn mock_inspect(&self, env: &OneshotEnv, args: TxExecutionArgs) -> VmExecutionResultAndLogs { match env.system.execution_mode { TxExecutionMode::EthCall => (self.call_responses)(&args.transaction, &env), TxExecutionMode::VerifyExecute | TxExecutionMode::EstimateFee => { - (self.tx_responses)(&args.transaction, &env) + (self.tx_responses)(&args.transaction, env) } } } @@ -105,7 +116,7 @@ where _params: OneshotTracingParams, ) -> anyhow::Result { Ok(OneshotTransactionExecutionResult { - tx_result: Box::new(self.mock_inspect(env, args)), + tx_result: Box::new(self.mock_inspect(&env, args)), compression_result: Ok(()), call_traces: vec![], }) @@ -126,12 +137,12 @@ where ) -> anyhow::Result> { Ok( match self - .mock_inspect(env, TxExecutionArgs::for_validation(tx)) + .mock_inspect(&env, TxExecutionArgs::for_validation(tx.clone())) .result { ExecutionResult::Halt { reason } => Err(ValidationError::FailedTx(reason)), ExecutionResult::Success { .. } | ExecutionResult::Revert { .. } => { - Ok(ValidationTraces::default()) + Ok((self.tx_validation_traces_responses)(&tx.into(), &env)) } }, ) diff --git a/core/node/api_server/src/tx_sender/tests/send_tx.rs b/core/node/api_server/src/tx_sender/tests/send_tx.rs index fdd63254cf07..f2a301ecbacd 100644 --- a/core/node/api_server/src/tx_sender/tests/send_tx.rs +++ b/core/node/api_server/src/tx_sender/tests/send_tx.rs @@ -2,7 +2,7 @@ use assert_matches::assert_matches; use test_casing::test_casing; -use zksync_multivm::interface::ExecutionResult; +use zksync_multivm::interface::{tracer::ValidationTraces, ExecutionResult}; use zksync_node_fee_model::MockBatchFeeParamsProvider; use zksync_node_test_utils::create_l2_transaction; use zksync_types::K256PrivateKey; @@ -54,6 +54,16 @@ async fn submitting_tx_requires_one_connection() { .await .unwrap() .expect("transaction is not persisted"); + + let storage_tx = storage + .transactions_dal() + .get_storage_tx_by_hash(tx_hash) + .await + .unwrap() + .expect("transaction is not persisted"); + // verify that no validation traces have been persisted + assert!(storage_tx.block_timestamp_range_start.is_none()); + assert!(storage_tx.block_timestamp_range_start.is_none()); } #[tokio::test] @@ -298,3 +308,73 @@ async fn sending_transaction_out_of_gas() { let (_, vm_result) = tx_sender.submit_tx(tx, block_args).await.unwrap(); assert_matches!(vm_result.result, ExecutionResult::Revert { .. }); } + +#[tokio::test] +async fn submitting_tx_with_validation_traces() { + let pool = ConnectionPool::::constrained_test_pool(1).await; + let mut storage = pool.connection().await.unwrap(); + insert_genesis_batch(&mut storage, &GenesisParams::mock()) + .await + .unwrap(); + + let l2_chain_id = L2ChainId::default(); + let fee_input = MockBatchFeeParamsProvider::default() + .get_batch_fee_input_scaled(1.0, 1.0) + .await + .unwrap(); + let (base_fee, gas_per_pubdata) = + derive_base_fee_and_gas_per_pubdata(fee_input, ProtocolVersionId::latest().into()); + let tx = create_l2_transaction(base_fee, gas_per_pubdata); + let tx_hash = tx.hash(); + + // Manually set sufficient balance for the tx initiator. + StateBuilder::default() + .with_balance(tx.initiator_account(), u64::MAX.into()) + .apply(&mut storage) + .await; + drop(storage); + + let mut tx_executor = MockOneshotExecutor::default(); + tx_executor.set_tx_responses(move |received_tx, _| { + assert_eq!(received_tx.hash(), tx_hash); + ExecutionResult::Success { output: vec![] } + }); + tx_executor.set_tx_validation_traces_responses(move |tx, _| { + assert_eq!(tx.hash(), tx_hash); + ValidationTraces { + range_start: Some(U256::from(10)), + range_end: Some(U256::from(20)), + } + }); + + let tx_executor = SandboxExecutor::mock(tx_executor).await; + let (tx_sender, _) = create_test_tx_sender(pool.clone(), l2_chain_id, tx_executor).await; + let block_args = pending_block_args(&tx_sender).await; + + let submission_result = tx_sender.submit_tx(tx, block_args).await.unwrap(); + assert_matches!(submission_result.0, L2TxSubmissionResult::Added); + + let mut storage = pool.connection().await.unwrap(); + let storage_tx = storage + .transactions_dal() + .get_storage_tx_by_hash(tx_hash) + .await + .unwrap() + .expect("transaction is not persisted"); + assert_eq!( + 10, + storage_tx + .block_timestamp_range_start + .unwrap() + .and_utc() + .timestamp() + ); + assert_eq!( + 20, + storage_tx + .block_timestamp_range_end + .unwrap() + .and_utc() + .timestamp() + ); +} diff --git a/core/tests/ts-integration/contracts/custom-account/custom-account.sol b/core/tests/ts-integration/contracts/custom-account/custom-account.sol index 53241aae6063..459bdbbb85df 100644 --- a/core/tests/ts-integration/contracts/custom-account/custom-account.sol +++ b/core/tests/ts-integration/contracts/custom-account/custom-account.sol @@ -34,7 +34,7 @@ contract CustomAccount is IAccount { function validateTransaction(bytes32 _txHash, bytes32 _suggestedSignedTxHash, Transaction calldata _transaction) external payable override returns (bytes4 magic) { ITimestampAsserter timestampAsserter = ITimestampAsserter(timestampAsserterAddress); - // This assertion exists to ensure that block.timestamp can be asserted in AA by using + // This assertion exists to ensure that block.timestamp can be accessed in AA by using // ITimestampAsserter contract // 2555971200 is a number of seconds up to 30/12/2050 timestampAsserter.assertTimestampInRange(0, 2555971200); diff --git a/yarn.lock b/yarn.lock index 255bd901e035..58511dd1b9ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1424,18 +1424,6 @@ resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1727,24 +1715,15 @@ resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-1.5.0.tgz#40cb454fb187da4bb354f3acb48762a6657fcb36" integrity sha512-7LAgYYwoKWHeR+3CyWEvA3NKBKtt7ktcr7SX6ZPgbEYqHAdXH02vxJZGwNADtMWpyYm8h+fEQkpPIgErD4NhmA== dependencies: - "@matterlabs/hardhat-zksync-solc" "^1.0.5" - chalk "4.1.2" - ts-morph "^19.0.0" - -"@matterlabs/hardhat-zksync-deploy@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-1.3.0.tgz#5c2b723318ddf6c4d3929ec225401864ff54557a" - integrity sha512-4UHOgOwIBC4JA3W8DE9GHqbAuBhCPAjtM+Oew1aiYYGkIsPUAMYsH35+4I2FzJsYyE6mD6ATmoS/HfZweQHTlQ== - dependencies: - "@matterlabs/hardhat-zksync-solc" "^1.0.4" - chai "^4.3.6" - chalk "4.1.2" + "@matterlabs/hardhat-zksync-solc" "^1.2.0" + chai "^4.3.4" + chalk "^4.1.2" fs-extra "^11.2.0" - glob "^10.3.10" + glob "^10.4.1" lodash "^4.17.21" - sinon "^17.0.1" + sinon "^18.0.0" sinon-chai "^3.7.0" - ts-morph "^21.0.1" + ts-morph "^22.0.0" "@matterlabs/hardhat-zksync-node@^0.0.1-beta.7": version "0.0.1" @@ -1789,7 +1768,7 @@ chalk "4.1.2" dockerode "^3.3.4" -"@matterlabs/hardhat-zksync-solc@^1.0.4", "@matterlabs/hardhat-zksync-solc@^1.0.5", "@matterlabs/hardhat-zksync-solc@^1.1.4": +"@matterlabs/hardhat-zksync-solc@^1.0.5", "@matterlabs/hardhat-zksync-solc@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.1.4.tgz#04a2fad6fb6b6944c64ad969080ee65b9af3f617" integrity sha512-4/usbogh9neewR2/v8Dn2OzqVblZMUuT/iH2MyPZgPRZYQlL4SlZtMvokU9UQjZT6iSoaKCbbdWESHDHSzfUjA== @@ -1823,10 +1802,10 @@ sinon-chai "^3.7.0" undici "^6.18.2" -"@matterlabs/hardhat-zksync-verify@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-verify/-/hardhat-zksync-verify-0.4.0.tgz#f812c19950022fc36728f3796f6bdae5633e2fcd" - integrity sha512-GPZmAumFl3ZMPKbECX7Qw8CriwZKWd1DlCRhoG/6YYc6mFy4+MXkF1XsHLMs5r34N+GDOfbVZVMeftIlJC96Kg== +"@matterlabs/hardhat-zksync-solc@^1.2.4": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.5.tgz#fbeeabc3fea0dd232fa3c8cb31bd93c103eba11a" + integrity sha512-iZyznWl1Hoe/Z46hnUe1s2drBZBjJOS/eN+Ql2lIBX9B6NevBl9DYzkKzH5HEIMCLGnX9sWpRAJqUQJWy9UB6w== dependencies: "@nomiclabs/hardhat-docker" "^2.0.2" chai "^4.3.4" @@ -1871,20 +1850,20 @@ sinon "^18.0.0" sinon-chai "^3.7.0" -"@matterlabs/hardhat-zksync-vyper@^1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-vyper/-/hardhat-zksync-vyper-1.0.8.tgz#d5bd496715a1e322b0bf3926b4146b4e18ab64ff" - integrity sha512-XR7rbfDuBG5/LZWYfhQTP9gD+U24hSJHDuZ9U55wgIfiQTOxPoztFwEbQNiC39vjT5MjP/Nv8/IDrlEBkaVCgw== +"@matterlabs/hardhat-zksync-vyper@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-vyper/-/hardhat-zksync-vyper-1.1.0.tgz#b3fb304429e88a84b4abc3fe4e5a83b2f5e907bd" + integrity sha512-zDjHPeIuHRpumXiWZUbhoji4UJe09jTDRn4xnxsuVkLH7qLAm0VDFzCXYNMvEuySZSdhbSbekxJsH9Kunc5ycA== dependencies: - "@nomiclabs/hardhat-docker" "^2.0.0" - chai "^4.3.6" - chalk "4.1.2" + "@nomiclabs/hardhat-docker" "^2.0.2" + chai "^4.3.4" + chalk "^4.1.2" dockerode "^4.0.2" - fs-extra "^11.1.1" - semver "^7.5.4" - sinon "^17.0.1" + fs-extra "^11.2.0" + semver "^7.6.2" + sinon "^18.0.0" sinon-chai "^3.7.0" - undici "^5.14.0" + undici "^6.18.2" "@matterlabs/prettier-config@^1.0.3": version "1.0.3" @@ -2324,11 +2303,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@pkgr/core@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" @@ -2659,16 +2633,6 @@ mkdirp "^2.1.6" path-browserify "^1.0.1" -"@ts-morph/common@~0.22.0": - version "0.22.0" - resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.22.0.tgz#8951d451622a26472fbc3a227d6c3a90e687a683" - integrity sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw== - dependencies: - fast-glob "^3.3.2" - minimatch "^9.0.3" - mkdirp "^3.0.1" - path-browserify "^1.0.1" - "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -3341,11 +3305,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -3365,11 +3324,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - antlr4@^4.11.0: version "4.13.1" resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1.tgz#1e0a1830a08faeb86217cb2e6c34716004e4253d" @@ -4481,7 +4435,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4784,11 +4738,6 @@ dotenv@^8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -4855,11 +4804,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - encoding-down@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" @@ -5830,14 +5774,6 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -6126,17 +6062,6 @@ glob@8.1.0, glob@^8.0.3: minimatch "^5.0.1" once "^1.3.0" -glob@^10.3.10: - version "10.3.16" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.16.tgz#bf6679d5d51279c8cfae4febe0d051d2a4bf4c6f" - integrity sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.1" - minipass "^7.0.4" - path-scurry "^1.11.0" - glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -7049,15 +6974,6 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jackspeak@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.1.2.tgz#eada67ea949c6b71de50f1b09c92a961897b90ab" - integrity sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -7961,11 +7877,6 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== -lru-cache@^10.2.0: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -8264,13 +8175,6 @@ minimatch@^7.4.3: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1, minimatch@^9.0.3: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - minimatch@~3.0.4: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -8283,11 +8187,6 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8, minimist@~1. resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: - version "7.1.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481" - integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA== - mkdirp-classic@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" @@ -8310,11 +8209,6 @@ mkdirp@^2.1.6: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== -mkdirp@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== - mnemonist@^0.38.0: version "0.38.5" resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" @@ -8780,16 +8674,6 @@ package-json@^8.1.0: registry-url "^6.0.0" semver "^7.3.7" -package-json@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" - integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== - dependencies: - got "^12.1.0" - registry-auth-token "^5.0.1" - registry-url "^6.0.0" - semver "^7.3.7" - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -8855,14 +8739,6 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-to-regexp@^6.2.1: version "6.2.2" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" @@ -9863,11 +9739,6 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - sinon-chai@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783" @@ -10199,15 +10070,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -10216,14 +10078,14 @@ string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" string.prototype.padend@^3.0.0: version "3.1.6" @@ -10282,13 +10144,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -10303,12 +10158,12 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^6.0.1" + ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" @@ -10413,6 +10268,7 @@ synckit@^0.8.6: fast-glob "^3.3.2" hardhat "=2.22.2" preprocess "^3.2.0" + zksync-ethers "^5.9.0" table-layout@^1.0.2: version "1.0.2" @@ -10664,14 +10520,6 @@ ts-morph@^19.0.0: "@ts-morph/common" "~0.20.0" code-block-writer "^12.0.0" -ts-morph@^21.0.1: - version "21.0.1" - resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-21.0.1.tgz#712302a0f6e9dbf1aa8d9cf33a4386c4b18c2006" - integrity sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg== - dependencies: - "@ts-morph/common" "~0.22.0" - code-block-writer "^12.0.0" - ts-node@^10.1.0, ts-node@^10.7.0: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -11152,7 +11000,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -11161,15 +11009,6 @@ workerpool@6.2.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From b2ea3cbe9777f46696aaa5a5ade55dcf6ae2ded5 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 17 Oct 2024 18:34:55 +0100 Subject: [PATCH 37/68] brush up --- contracts | 2 +- ...a2d505a1aabf52ff4136d2ed1b39c70dd1632.json | 4 +- ...8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json | 42 ----- ...6737ed6b52eb308ebb06c646613be9cc0ce22.json | 42 +++++ ...2826095e9290f0c1157094bd0c44e06012e42.json | 4 +- ...a77a428820fdcea9969aff3b29ca16727357b.json | 4 +- ...64a8e245ecee4866264d38146938595b07f37.json | 4 +- ...7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json | 4 +- ...3940_add_block_timestamp_asserter.down.sql | 4 +- ...073940_add_block_timestamp_asserter.up.sql | 4 +- .../lib/dal/src/models/storage_transaction.rs | 8 +- core/lib/dal/src/transactions_dal.rs | 20 +-- core/lib/mempool/src/tests.rs | 33 ---- core/lib/mempool/src/types.rs | 7 +- .../src/tracers/validator/vm_latest/mod.rs | 22 +-- core/lib/types/src/lib.rs | 4 +- .../lib/vm_interface/src/types/errors/halt.rs | 6 +- core/lib/vm_interface/src/types/tracer.rs | 12 +- .../api_server/src/execution_sandbox/error.rs | 6 +- core/node/api_server/src/tx_sender/result.rs | 10 +- .../api_server/src/tx_sender/tests/send_tx.rs | 14 +- core/node/state_keeper/src/io/mempool.rs | 6 +- core/node/state_keeper/src/io/tests/mod.rs | 34 +++- .../state_keeper/src/seal_criteria/mod.rs | 2 +- .../custom-account/custom-account.sol | 11 +- .../tests/custom-account.test.ts | 161 ++++++++++++------ 26 files changed, 257 insertions(+), 213 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json create mode 100644 core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json diff --git a/contracts b/contracts index 66601e6cc31e..d4dae434ca3b 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 66601e6cc31e5d919429971ae1e4004746c5b7cf +Subproject commit d4dae434ca3bf90a2a4ab32abdfdb731973c9b35 diff --git a/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json b/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json index 371bb33fd6d8..b84cd1bcba89 100644 --- a/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json +++ b/core/lib/dal/.sqlx/query-1689c212d411ebd99a22210519ea2d505a1aabf52ff4136d2ed1b39c70dd1632.json @@ -185,12 +185,12 @@ }, { "ordinal": 36, - "name": "block_timestamp_range_start", + "name": "timestamp_asserter_range_start", "type_info": "Timestamp" }, { "ordinal": 37, - "name": "block_timestamp_range_end", + "name": "timestamp_asserter_range_end", "type_info": "Timestamp" } ], diff --git a/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json b/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json deleted file mode 100644 index 63364370a7dd..000000000000 --- a/core/lib/dal/.sqlx/query-44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at,\n block_timestamp_range_start,\n block_timestamp_range_end\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n NOW(),\n NOW(),\n $20,\n $21\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL,\n block_timestamp_range_start = $20,\n block_timestamp_range_end = $21\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "is_replaced!", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Int8", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Numeric", - "Bytea", - "Jsonb", - "Int4", - "Bytea", - "Numeric", - "Bytea", - "Bytea", - "Int8", - "Int4", - "Int4", - "Timestamp", - "Timestamp", - "Timestamp" - ] - }, - "nullable": [ - null - ] - }, - "hash": "44a45a01a0f59858e106668aa5f8f8ed4af5fbc4eac7ebbdcc3db93f0cc256a8" -} diff --git a/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json b/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json new file mode 100644 index 000000000000..94099dd03285 --- /dev/null +++ b/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at,\n timestamp_asserter_range_start,\n timestamp_asserter_range_end\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n NOW(),\n NOW(),\n $20,\n $21\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL,\n timestamp_asserter_range_start = $20,\n timestamp_asserter_range_end = $21\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "is_replaced!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Bytea", + "Int8", + "Bytea", + "Numeric", + "Numeric", + "Numeric", + "Numeric", + "Bytea", + "Jsonb", + "Int4", + "Bytea", + "Numeric", + "Bytea", + "Bytea", + "Int8", + "Int4", + "Int4", + "Timestamp", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + null + ] + }, + "hash": "529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22" +} diff --git a/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json b/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json index b95878189ce4..2f4203aaa326 100644 --- a/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json +++ b/core/lib/dal/.sqlx/query-72a4f50355324cce85ebaef9fa32826095e9290f0c1157094bd0c44e06012e42.json @@ -185,12 +185,12 @@ }, { "ordinal": 36, - "name": "block_timestamp_range_start", + "name": "timestamp_asserter_range_start", "type_info": "Timestamp" }, { "ordinal": 37, - "name": "block_timestamp_range_end", + "name": "timestamp_asserter_range_end", "type_info": "Timestamp" } ], diff --git a/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json index 83c977551b95..50d3ce5188df 100644 --- a/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json +++ b/core/lib/dal/.sqlx/query-a36135b5908992324c4308f549ea77a428820fdcea9969aff3b29ca16727357b.json @@ -185,12 +185,12 @@ }, { "ordinal": 36, - "name": "block_timestamp_range_start", + "name": "timestamp_asserter_range_start", "type_info": "Timestamp" }, { "ordinal": 37, - "name": "block_timestamp_range_end", + "name": "timestamp_asserter_range_end", "type_info": "Timestamp" } ], diff --git a/core/lib/dal/.sqlx/query-eb27e1b82b8ecbb9711c417888564a8e245ecee4866264d38146938595b07f37.json b/core/lib/dal/.sqlx/query-eb27e1b82b8ecbb9711c417888564a8e245ecee4866264d38146938595b07f37.json index ea7547c5269b..079ce55bd569 100644 --- a/core/lib/dal/.sqlx/query-eb27e1b82b8ecbb9711c417888564a8e245ecee4866264d38146938595b07f37.json +++ b/core/lib/dal/.sqlx/query-eb27e1b82b8ecbb9711c417888564a8e245ecee4866264d38146938595b07f37.json @@ -185,12 +185,12 @@ }, { "ordinal": 36, - "name": "block_timestamp_range_start", + "name": "timestamp_asserter_range_start", "type_info": "Timestamp" }, { "ordinal": 37, - "name": "block_timestamp_range_end", + "name": "timestamp_asserter_range_end", "type_info": "Timestamp" } ], diff --git a/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json b/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json index 8bae63790be7..8c43f8865ac7 100644 --- a/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json +++ b/core/lib/dal/.sqlx/query-f023e5fa599b279acd6ac02dffb7a33a8fea8ab7fdefb7d9210673245a2a6f6c.json @@ -185,12 +185,12 @@ }, { "ordinal": 36, - "name": "block_timestamp_range_start", + "name": "timestamp_asserter_range_start", "type_info": "Timestamp" }, { "ordinal": 37, - "name": "block_timestamp_range_end", + "name": "timestamp_asserter_range_end", "type_info": "Timestamp" } ], diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql index b39ad42a73e8..bb409923da69 100644 --- a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql @@ -1,2 +1,2 @@ -ALTER TABLE transactions DROP COLUMN block_timestamp_range_start; -ALTER TABLE transactions DROP COLUMN block_timestamp_range_end; \ No newline at end of file +ALTER TABLE transactions DROP COLUMN timestamp_asserter_range_start; +ALTER TABLE transactions DROP COLUMN timestamp_asserter_range_end; \ No newline at end of file diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql index f6a9e2970a95..39bd8e1ac9f4 100644 --- a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql @@ -1,2 +1,2 @@ -ALTER TABLE transactions ADD COLUMN block_timestamp_range_start TIMESTAMP DEFAULT NULL; -ALTER TABLE transactions ADD COLUMN block_timestamp_range_end TIMESTAMP DEFAULT NULL; \ No newline at end of file +ALTER TABLE transactions ADD COLUMN timestamp_asserter_range_start TIMESTAMP DEFAULT NULL; +ALTER TABLE transactions ADD COLUMN timestamp_asserter_range_end TIMESTAMP DEFAULT NULL; \ No newline at end of file diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index d23d84c30dda..f2a60e194f74 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -68,8 +68,8 @@ pub struct StorageTransaction { pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, - pub block_timestamp_range_start: Option, - pub block_timestamp_range_end: Option, + pub timestamp_asserter_range_start: Option, + pub timestamp_asserter_range_end: Option, // DEPRECATED. pub l1_block_number: Option, @@ -327,8 +327,8 @@ impl From for Transaction { impl From for TransactionTimeRangeConstraint { fn from(tx: StorageTransaction) -> Self { Self { - range_start: tx.block_timestamp_range_start, - range_end: tx.block_timestamp_range_end, + timestamp_asserter_range_start: tx.timestamp_asserter_range_start, + timestamp_asserter_range_end: tx.timestamp_asserter_range_end, } } } diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index ec7ebe944ab4..6d51f5d58cd1 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -317,12 +317,12 @@ impl TransactionsDal<'_, '_> { #[allow(deprecated)] let received_at = NaiveDateTime::from_timestamp_opt(secs, nanosecs).unwrap(); #[allow(deprecated)] - let block_timestamp_range_start = validation_traces - .range_start + let timestamp_asserter_range_start = validation_traces + .timestamp_asserter_range_start .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); #[allow(deprecated)] - let block_timestamp_range_end = validation_traces - .range_end + let timestamp_asserter_range_end = validation_traces + .timestamp_asserter_range_end .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); // Besides just adding or updating(on conflict) the record, we want to extract some info // from the query below, to indicate what actually happened: @@ -358,8 +358,8 @@ impl TransactionsDal<'_, '_> { received_at, created_at, updated_at, - block_timestamp_range_start, - block_timestamp_range_end + timestamp_asserter_range_start, + timestamp_asserter_range_end ) VALUES ( @@ -423,8 +423,8 @@ impl TransactionsDal<'_, '_> { created_at = NOW(), updated_at = NOW(), error = NULL, - block_timestamp_range_start = $20, - block_timestamp_range_end = $21 + timestamp_asserter_range_start = $20, + timestamp_asserter_range_end = $21 WHERE transactions.is_priority = FALSE AND transactions.miniblock_number IS NULL @@ -458,8 +458,8 @@ impl TransactionsDal<'_, '_> { (exec_info.initial_storage_writes + exec_info.repeated_storage_writes) as i32, exec_info.contracts_used as i32, received_at, - block_timestamp_range_start, - block_timestamp_range_end, + timestamp_asserter_range_start, + timestamp_asserter_range_end, ) .instrument("insert_transaction_l2") .with_arg("tx_hash", &tx_hash) diff --git a/core/lib/mempool/src/tests.rs b/core/lib/mempool/src/tests.rs index 5e53cb4d0014..56b51c239dda 100644 --- a/core/lib/mempool/src/tests.rs +++ b/core/lib/mempool/src/tests.rs @@ -369,39 +369,6 @@ fn mempool_capacity() { ); } -// -// #[test] -// fn basic_flow_with_timestamp_filter() { -// let mut mempool = MempoolStore::new(PriorityOpId(0), 100); -// let account0 = Address::random(); -// -// let now = SystemTime::now() -// .duration_since(UNIX_EPOCH) -// .expect("Invalid system time") -// .as_secs() as i64; -// -// #[allow(deprecated)] -// let transactions = vec![ -// (gen_l2_tx(account0, Nonce(0)), TransactionTimeRangeConstraint { -// range_start: Some(NaiveDateTime::from_timestamp(now - 5000, 0)), -// range_end: Some(NaiveDateTime::from_timestamp(now - 1000, 0)), -// }), -// (gen_l2_tx(account0, Nonce(1)), TransactionTimeRangeConstraint { -// range_start: Some(NaiveDateTime::from_timestamp(now - 5000, 0)), -// range_end: Some(NaiveDateTime::from_timestamp(now + 5000, 0)), -// }), -// -// (gen_l2_tx(account0, Nonce(2)), TransactionTimeRangeConstraint::default()), -// ]; -// assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); -// mempool.insert(transactions, HashMap::new()); -// assert_eq!( -// view(mempool.next_transaction(&L2TxFilter::default())), -// (account0, 1) -// ); -// assert_eq!(mempool.next_transaction(&L2TxFilter::default()), None); -// } - fn gen_l2_tx(address: Address, nonce: Nonce) -> Transaction { gen_l2_tx_with_timestamp(address, nonce, unix_timestamp_ms()) } diff --git a/core/lib/mempool/src/types.rs b/core/lib/mempool/src/types.rs index e67996676a77..f3bc3c6a0a8e 100644 --- a/core/lib/mempool/src/types.rs +++ b/core/lib/mempool/src/types.rs @@ -48,8 +48,8 @@ impl AccountTransactions { metadata } - /// Returns next transaction to be included in block and optional score of its successor - /// Panics if no such transaction exists + /// Returns next transaction to be included in block, its time range constraint and optional + /// score of its successor. Panics if no such transaction exists pub fn next(&mut self) -> (L2Tx, TransactionTimeRangeConstraint, Option) { let transaction = self .transactions @@ -63,7 +63,8 @@ impl AccountTransactions { (transaction.0, transaction.1, score) } - /// Handles transaction rejection. Returns optional score of its successor + /// Handles transaction rejection. Returns optional score of its successor and time range + /// constraint that the transaction has been added to the mempool with pub fn reset( &mut self, transaction: &Transaction, diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 9d98fa9d3257..fd702f8ac787 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -109,7 +109,7 @@ impl ValidationTracer { let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); if start.as_u32() - end.as_u32() < self.timestamp_asserter_min_range_sec { - return Err(ViolatedValidationRule::TimestampAssertionInvalidRange); + return Err(ViolatedValidationRule::TimestampAssertionOutOfRange); } let now = SystemTime::now() @@ -119,19 +119,21 @@ impl ValidationTracer { if end.as_u32() < now as u32 + self.timestamp_asserter_min_time_till_end_sec { - return Err(ViolatedValidationRule::TimestampAssertionInvalidRange); + return Err(ViolatedValidationRule::TimestampAssertionOutOfRange); } { let mut traces_mut = self.traces.lock().unwrap(); - traces_mut.range_start = match traces_mut.range_start { - Some(current_value) => Some(cmp::max(current_value, start)), - None => Some(start), - }; - traces_mut.range_end = match traces_mut.range_end { - Some(current_value) => Some(cmp::min(current_value, end)), - None => Some(end), - }; + traces_mut.timestamp_asserter_range_start = + match traces_mut.timestamp_asserter_range_start { + Some(current_value) => Some(cmp::max(current_value, start)), + None => Some(start), + }; + traces_mut.timestamp_asserter_range_end = + match traces_mut.timestamp_asserter_range_end { + Some(current_value) => Some(cmp::min(current_value, end)), + None => Some(end), + }; } } } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 12445995588c..e92be6f31da7 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -431,6 +431,6 @@ impl Transaction { Copy )] pub struct TransactionTimeRangeConstraint { - pub range_start: Option, - pub range_end: Option, + pub timestamp_asserter_range_start: Option, + pub timestamp_asserter_range_end: Option, } diff --git a/core/lib/vm_interface/src/types/errors/halt.rs b/core/lib/vm_interface/src/types/errors/halt.rs index 7789ae7d9c22..d24f55ab5044 100644 --- a/core/lib/vm_interface/src/types/errors/halt.rs +++ b/core/lib/vm_interface/src/types/errors/halt.rs @@ -42,7 +42,7 @@ pub enum Halt { VMPanic, TracerCustom(String), FailedToPublishCompressedBytecodes, - ViolatedBlockTimestampConstraint, + FailedBlockTimestampAssertion, } impl fmt::Display for Halt { @@ -117,8 +117,8 @@ impl fmt::Display for Halt { Halt::FailedToPublishCompressedBytecodes => { write!(f, "Failed to publish compressed bytecodes") } - Halt::ViolatedBlockTimestampConstraint => { - write!(f, "Transaction violated block.timestamp constraint") + Halt::FailedBlockTimestampAssertion => { + write!(f, "Transaction failed block.timestamp assertion") } } } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index 9a2536a63308..aff788f27478 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -77,8 +77,8 @@ pub enum ViolatedValidationRule { TouchedDisallowedContext, /// The transaction used too much gas during validation. TookTooManyComputationalGas(u32), - /// The transaction passed incorrect parameters into timestamp asserter - TimestampAssertionInvalidRange, + /// The transaction failed block.timestamp assertion + TimestampAssertionOutOfRange, } impl fmt::Display for ViolatedValidationRule { @@ -100,8 +100,8 @@ impl fmt::Display for ViolatedValidationRule { "Took too many computational gas, allowed limit: {gas_limit}" ) } - ViolatedValidationRule::TimestampAssertionInvalidRange => { - write!(f, "Invalid range used with timestamp asserter") + ViolatedValidationRule::TimestampAssertionOutOfRange => { + write!(f, "Transaction failed block.timestamp assertion") } } } @@ -122,8 +122,8 @@ pub enum ValidationError { /// be excluded from the mempool. #[derive(Debug, Clone, Default)] pub struct ValidationTraces { - pub range_start: Option, - pub range_end: Option, + pub timestamp_asserter_range_start: Option, + pub timestamp_asserter_range_end: Option, } impl fmt::Display for ValidationError { diff --git a/core/node/api_server/src/execution_sandbox/error.rs b/core/node/api_server/src/execution_sandbox/error.rs index 6c7ed19e1c8e..4523412ae194 100644 --- a/core/node/api_server/src/execution_sandbox/error.rs +++ b/core/node/api_server/src/execution_sandbox/error.rs @@ -26,8 +26,8 @@ pub(crate) enum SandboxExecutionError { that caused this error. Error description: {0}" )] UnexpectedVMBehavior(String), - #[error("Transaction violated block.timestamp constraint")] - ViolatedBlockTimestampConstraint, + #[error("Transaction failed block.timestamp assertion")] + FailedBlockTimestampAssertion, } impl From for SandboxExecutionError { @@ -69,7 +69,7 @@ impl From for SandboxExecutionError { Halt::FailedToPublishCompressedBytecodes => { Self::UnexpectedVMBehavior("Failed to publish compressed bytecodes".to_string()) } - Halt::ViolatedBlockTimestampConstraint => Self::ViolatedBlockTimestampConstraint, + Halt::FailedBlockTimestampAssertion => Self::FailedBlockTimestampAssertion, } } } diff --git a/core/node/api_server/src/tx_sender/result.rs b/core/node/api_server/src/tx_sender/result.rs index 03b352776a33..003b022072d1 100644 --- a/core/node/api_server/src/tx_sender/result.rs +++ b/core/node/api_server/src/tx_sender/result.rs @@ -75,8 +75,8 @@ pub enum SubmitTxError { /// Catch-all internal error (e.g., database error) that should not be exposed to the caller. #[error("internal error")] Internal(#[from] anyhow::Error), - #[error("transaction violated block.timestamp constraint")] - ViolatedBlockTimestampConstraint, + #[error("transaction failed block.timestamp assertion")] + FailedBlockTimestampAssertion, } impl SubmitTxError { @@ -110,7 +110,7 @@ impl SubmitTxError { Self::ProxyError(_) => "proxy-error", Self::FailedToPublishCompressedBytecodes => "failed-to-publish-compressed-bytecodes", Self::Internal(_) => "internal", - Self::ViolatedBlockTimestampConstraint => "violated-block-timestamp-constraint", + Self::FailedBlockTimestampAssertion => "failed-block-timestamp-assertion", } } @@ -148,8 +148,8 @@ impl From for SubmitTxError { SandboxExecutionError::FailedToPayForTransaction(reason) => { Self::FailedToChargeFee(reason) } - SandboxExecutionError::ViolatedBlockTimestampConstraint => { - Self::ViolatedBlockTimestampConstraint + SandboxExecutionError::FailedBlockTimestampAssertion => { + Self::FailedBlockTimestampAssertion } } } diff --git a/core/node/api_server/src/tx_sender/tests/send_tx.rs b/core/node/api_server/src/tx_sender/tests/send_tx.rs index f2a301ecbacd..85f27bca71ec 100644 --- a/core/node/api_server/src/tx_sender/tests/send_tx.rs +++ b/core/node/api_server/src/tx_sender/tests/send_tx.rs @@ -62,8 +62,8 @@ async fn submitting_tx_requires_one_connection() { .unwrap() .expect("transaction is not persisted"); // verify that no validation traces have been persisted - assert!(storage_tx.block_timestamp_range_start.is_none()); - assert!(storage_tx.block_timestamp_range_start.is_none()); + assert!(storage_tx.timestamp_asserter_range_start.is_none()); + assert!(storage_tx.timestamp_asserter_range_start.is_none()); } #[tokio::test] @@ -311,6 +311,8 @@ async fn sending_transaction_out_of_gas() { #[tokio::test] async fn submitting_tx_with_validation_traces() { + // This test verifies that when a transaction produces ValidationTraces, + // range_start and range_end get persisted in the database let pool = ConnectionPool::::constrained_test_pool(1).await; let mut storage = pool.connection().await.unwrap(); insert_genesis_batch(&mut storage, &GenesisParams::mock()) @@ -342,8 +344,8 @@ async fn submitting_tx_with_validation_traces() { tx_executor.set_tx_validation_traces_responses(move |tx, _| { assert_eq!(tx.hash(), tx_hash); ValidationTraces { - range_start: Some(U256::from(10)), - range_end: Some(U256::from(20)), + timestamp_asserter_range_start: Some(U256::from(10)), + timestamp_asserter_range_end: Some(U256::from(20)), } }); @@ -364,7 +366,7 @@ async fn submitting_tx_with_validation_traces() { assert_eq!( 10, storage_tx - .block_timestamp_range_start + .timestamp_asserter_range_start .unwrap() .and_utc() .timestamp() @@ -372,7 +374,7 @@ async fn submitting_tx_with_validation_traces() { assert_eq!( 20, storage_tx - .block_timestamp_range_end + .timestamp_asserter_range_end .unwrap() .and_utc() .timestamp() diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index 2dea6029cffe..c0f640bf9fe8 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -308,16 +308,16 @@ impl StateKeeperIO for MempoolIO { .as_secs() as i64; let matches_range = constraint - .range_start + .timestamp_asserter_range_start .map_or(true, |x| x.and_utc().timestamp() < now) && constraint - .range_end + .timestamp_asserter_range_end .map_or(true, |x| x.and_utc().timestamp() > now); if !matches_range { self.reject( &tx, - UnexecutableReason::Halt(Halt::ViolatedBlockTimestampConstraint), + UnexecutableReason::Halt(Halt::FailedBlockTimestampAssertion), ) .await?; continue; diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 13ccbe3ee4ab..75b13ee48d49 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -708,8 +708,14 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - range_start: Some(NaiveDateTime::from_timestamp(system_time - 20000, 0)), - range_end: Some(NaiveDateTime::from_timestamp(system_time - 10000, 0)), + timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( + system_time - 20000, + 0, + )), + timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( + system_time - 10000, + 0, + )), }, ); #[allow(deprecated)] @@ -718,8 +724,14 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - range_start: Some(NaiveDateTime::from_timestamp(system_time - 1000, 0)), - range_end: Some(NaiveDateTime::from_timestamp(system_time + 1000, 0)), + timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( + system_time - 1000, + 0, + )), + timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( + system_time + 1000, + 0, + )), }, ); #[allow(deprecated)] @@ -728,8 +740,14 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - range_start: Some(NaiveDateTime::from_timestamp(system_time + 10000, 0)), - range_end: Some(NaiveDateTime::from_timestamp(system_time + 20000, 0)), + timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( + system_time + 10000, + 0, + )), + timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( + system_time + 20000, + 0, + )), }, ); insert_l2_transaction(&mut storage, &rejected_tx_1).await; @@ -757,7 +775,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen .expect("Failed to find transaction") .unwrap(); assert_eq!( - "rejected: Transaction violated block.timestamp constraint", + "rejected: Transaction failed block.timestamp assertion", rejected_storage_tx_1.error.unwrap() ); @@ -768,7 +786,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen .expect("Failed to find transaction") .unwrap(); assert_eq!( - "rejected: Transaction violated block.timestamp constraint", + "rejected: Transaction failed block.timestamp constraint", rejected_storage_tx_2.error.unwrap() ); } diff --git a/core/node/state_keeper/src/seal_criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/mod.rs index 9fdeecab7107..b82d61666fbf 100644 --- a/core/node/state_keeper/src/seal_criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/mod.rs @@ -54,7 +54,7 @@ fn halt_as_metric_label(halt: &Halt) -> &'static str { Halt::VMPanic => "VMPanic", Halt::TracerCustom(_) => "TracerCustom", Halt::FailedToPublishCompressedBytecodes => "FailedToPublishCompressedBytecodes", - Halt::ViolatedBlockTimestampConstraint => "ViolatedBlockTimestampConstraint", + Halt::FailedBlockTimestampAssertion => "FailedBlockTimestampAssertion", } } diff --git a/core/tests/ts-integration/contracts/custom-account/custom-account.sol b/core/tests/ts-integration/contracts/custom-account/custom-account.sol index 459bdbbb85df..991772124771 100644 --- a/core/tests/ts-integration/contracts/custom-account/custom-account.sol +++ b/core/tests/ts-integration/contracts/custom-account/custom-account.sol @@ -23,10 +23,15 @@ contract CustomAccount is IAccount { bytes32 public lastTxHash; address public timestampAsserterAddress; + uint256 public timestampAsserterRangeStart; + uint256 public timestampAsserterRangeEnd; - constructor(bool _violateValidationRules, address _timestampAsserterAddress) { + + constructor(bool _violateValidationRules, address _timestampAsserterAddress, uint256 _timestampAsserterRangeStart, uint256 _timestampAsserterRangeEnd) { violateValidationRules = _violateValidationRules; timestampAsserterAddress = _timestampAsserterAddress; + timestampAsserterRangeStart = _timestampAsserterRangeStart; + timestampAsserterRangeEnd = _timestampAsserterRangeEnd; } // bytes4(keccak256("isValidSignature(bytes32,bytes)") @@ -36,8 +41,8 @@ contract CustomAccount is IAccount { ITimestampAsserter timestampAsserter = ITimestampAsserter(timestampAsserterAddress); // This assertion exists to ensure that block.timestamp can be accessed in AA by using // ITimestampAsserter contract - // 2555971200 is a number of seconds up to 30/12/2050 - timestampAsserter.assertTimestampInRange(0, 2555971200); + + timestampAsserter.assertTimestampInRange(timestampAsserterRangeStart, timestampAsserterRangeEnd); magic = _validateTransaction(_suggestedSignedTxHash, _transaction); lastTxHash = _txHash; diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 6edeb578e94c..9ad1a1f6fde4 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -9,6 +9,9 @@ import * as ethers from 'ethers'; import { deployContract, getTestContract } from '../src/helpers'; import { ERC20_PER_ACCOUNT, L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; import { shouldChangeETHBalances, shouldChangeTokenBalances } from '../src/modifiers/balance-checker'; +import { TransactionResponse } from 'ethers'; +import { MatcherModifier } from '../src/modifiers'; +import { fail } from 'node:assert'; const contracts = { customAccount: getTestContract('CustomAccount'), @@ -18,11 +21,14 @@ const contracts = { // We create multiple custom accounts and we need to fund them with ETH to pay for fees. const ETH_PER_CUSTOM_ACCOUNT = L2_DEFAULT_ETH_PER_ACCOUNT / 8n; const TRANSFER_AMOUNT = 1n; +const DEFAULT_TIMESTAMP_ASSERTER_RANGE_START = 0; +const DEFAULT_TIMESTAMP_ASSERTER_RANGE_END = 2555971200; describe('Tests for the custom account behavior', () => { let testMaster: TestMaster; let alice: zksync.Wallet; let customAccount: zksync.Contract; + let customAccountWithFailingAssertion: zksync.Contract; let erc20Address: string; let erc20: zksync.Contract; let timestampAsserterAddress: string; @@ -41,65 +47,88 @@ describe('Tests for the custom account behavior', () => { }); test('Should deploy custom account', async () => { - const violateRules = false; - customAccount = await deployContract( - alice, - contracts.customAccount, - [violateRules, timestampAsserterAddress], - 'createAccount' - ); - - // Now we need to check that it was correctly marked as an account: - const contractAccountInfo = await alice.provider.getContractAccountInfo(await customAccount.getAddress()); - - // Checking that the version of the account abstraction is correct - expect(contractAccountInfo.supportedAAVersion).toEqual(zksync.types.AccountAbstractionVersion.Version1); - - // Checking that the nonce ordering is correct - expect(contractAccountInfo.nonceOrdering).toEqual(zksync.types.AccountNonceOrdering.Sequential); + const deployFn = async function (rangeStart: number, rangeEnd: number): Promise { + const violateRules = false; + const customAccount = await deployContract( + alice, + contracts.customAccount, + // 2555971200 is a number of seconds up to 30/12/2050 + [violateRules, timestampAsserterAddress, rangeStart, rangeEnd], + 'createAccount' + ); + + // Now we need to check that it was correctly marked as an account: + const contractAccountInfo = await alice.provider.getContractAccountInfo(await customAccount.getAddress()); + + // Checking that the version of the account abstraction is correct + expect(contractAccountInfo.supportedAAVersion).toEqual(zksync.types.AccountAbstractionVersion.Version1); + + // Checking that the nonce ordering is correct + expect(contractAccountInfo.nonceOrdering).toEqual(zksync.types.AccountNonceOrdering.Sequential); + + return customAccount; + }; + + customAccount = await deployFn(DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, DEFAULT_TIMESTAMP_ASSERTER_RANGE_END); + const now = Math.floor(Date.now() / 1000); + customAccountWithFailingAssertion = await deployFn(2 * now, 3 * now); }); test('Should fund the custom account', async () => { - await alice - .transfer({ to: await customAccount.getAddress(), amount: ETH_PER_CUSTOM_ACCOUNT }) - .then((tx) => tx.wait()); - await alice - .transfer({ - to: await customAccount.getAddress(), - token: erc20Address, - amount: ERC20_PER_ACCOUNT / 4n - }) - .then((tx) => tx.wait()); + const fundFn = async function (account: zksync.Contract) { + await alice + .transfer({ to: await account.getAddress(), amount: ETH_PER_CUSTOM_ACCOUNT }) + .then((tx) => tx.wait()); + await alice + .transfer({ + to: await account.getAddress(), + token: erc20Address, + amount: ERC20_PER_ACCOUNT / 4n + }) + .then((tx) => tx.wait()); + }; + await fundFn(customAccount); + await fundFn(customAccountWithFailingAssertion); }); test('Should execute contract by custom account', async () => { - const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); - const customAccountAddress = await customAccount.getAddress(); - - const erc20BalanceChange = await shouldChangeTokenBalances(erc20Address, [ - // Custom account change (sender) - { - addressToCheck: customAccountAddress, - wallet: alice, - change: -TRANSFER_AMOUNT - }, - // Alice change (recipient) - { wallet: alice, change: TRANSFER_AMOUNT } - ]); - const feeCheck = await shouldChangeETHBalances([ - // 0 change would only check for fees. - { addressToCheck: customAccountAddress, wallet: alice, change: 0n } - ]); - + const transferFn = async function ( + account: zksync.Contract + ): Promise<[TransactionResponse, MatcherModifier[]]> { + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); + const customAccountAddress = await account.getAddress(); + + const erc20BalanceChange = await shouldChangeTokenBalances(erc20Address, [ + // Custom account change (sender) + { + addressToCheck: customAccountAddress, + wallet: alice, + change: -TRANSFER_AMOUNT + }, + // Alice change (recipient) + { wallet: alice, change: TRANSFER_AMOUNT } + ]); + const feeCheck = await shouldChangeETHBalances([ + // 0 change would only check for fees. + { addressToCheck: customAccountAddress, wallet: alice, change: 0n } + ]); + + return [ + await sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + customAccountAddress, + testMaster.environment().l2ChainId + ), + [erc20BalanceChange, feeCheck] + ]; + }; + let [transactionResponse, modifiers] = await transferFn(customAccount); // Check that transaction succeeds. - await expect( - sendCustomAccountTransaction( - tx as zksync.types.Transaction, - alice.provider, - customAccountAddress, - testMaster.environment().l2ChainId - ) - ).toBeAccepted([erc20BalanceChange, feeCheck]); + await expect(transactionResponse).toBeAccepted(modifiers); + + [transactionResponse, modifiers] = await transferFn(customAccountWithFailingAssertion); + await expect(transactionResponse).toBeRejected('failed to validate the transaction.'); }); test('Should fail the validation with incorrect signature', async () => { @@ -122,7 +151,12 @@ describe('Tests for the custom account behavior', () => { const badCustomAccount = await deployContract( alice, contracts.customAccount, - [violateRules, timestampAsserterAddress], + [ + violateRules, + timestampAsserterAddress, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_END + ], 'createAccount' ); const badCustomAccountAddress = await badCustomAccount.getAddress(); @@ -160,7 +194,12 @@ describe('Tests for the custom account behavior', () => { const nonAccount = await deployContract( alice, contracts.customAccount, - [violateRules, timestampAsserterAddress], + [ + violateRules, + timestampAsserterAddress, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_END + ], 'create' ); const nonAccountAddress = await nonAccount.getAddress(); @@ -220,7 +259,12 @@ describe('Tests for the custom account behavior', () => { const badCustomAccount = await deployContract( alice, contracts.customAccount, - [violateStorageRules, timestampAsserterAddress], + [ + violateStorageRules, + timestampAsserterAddress, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_END + ], 'createAccount' ); const badCustomAccountAddress = await badCustomAccount.getAddress(); @@ -261,7 +305,12 @@ describe('Tests for the custom account behavior', () => { const badCustomAccount = await deployContract( alice, contracts.customAccount, - [violateStorageRules, timestampAsserterAddress], + [ + violateStorageRules, + timestampAsserterAddress, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_END + ], 'createAccount' ); const badCustomAccountAddress = await badCustomAccount.getAddress(); From 6105694481e0c2bc1a5293fa27dfd8bf69722ae7 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 18 Oct 2024 12:59:35 +0100 Subject: [PATCH 38/68] Fix integration test --- contracts | 2 +- .../tests/custom-account.test.ts | 82 +++++++++++-------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/contracts b/contracts index d4dae434ca3b..b40b2d5f4fe3 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit d4dae434ca3bf90a2a4ab32abdfdb731973c9b35 +Subproject commit b40b2d5f4fe306ccc6d8ffa74b5d49c1e44ec0b8 diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 9ad1a1f6fde4..ae64dd85df91 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -92,43 +92,55 @@ describe('Tests for the custom account behavior', () => { }); test('Should execute contract by custom account', async () => { - const transferFn = async function ( - account: zksync.Contract - ): Promise<[TransactionResponse, MatcherModifier[]]> { - const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); - const customAccountAddress = await account.getAddress(); - - const erc20BalanceChange = await shouldChangeTokenBalances(erc20Address, [ - // Custom account change (sender) - { - addressToCheck: customAccountAddress, - wallet: alice, - change: -TRANSFER_AMOUNT - }, - // Alice change (recipient) - { wallet: alice, change: TRANSFER_AMOUNT } - ]); - const feeCheck = await shouldChangeETHBalances([ - // 0 change would only check for fees. - { addressToCheck: customAccountAddress, wallet: alice, change: 0n } - ]); - - return [ - await sendCustomAccountTransaction( - tx as zksync.types.Transaction, - alice.provider, - customAccountAddress, - testMaster.environment().l2ChainId - ), - [erc20BalanceChange, feeCheck] - ]; - }; - let [transactionResponse, modifiers] = await transferFn(customAccount); + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); + const customAccountAddress = await customAccount.getAddress(); + + const erc20BalanceChange = await shouldChangeTokenBalances(erc20Address, [ + // Custom account change (sender) + { + addressToCheck: customAccountAddress, + wallet: alice, + change: -TRANSFER_AMOUNT + }, + // Alice change (recipient) + { wallet: alice, change: TRANSFER_AMOUNT } + ]); + const feeCheck = await shouldChangeETHBalances([ + // 0 change would only check for fees. + { addressToCheck: customAccountAddress, wallet: alice, change: 0n } + ]); + // Check that transaction succeeds. - await expect(transactionResponse).toBeAccepted(modifiers); + await expect( + sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + customAccountAddress, + testMaster.environment().l2ChainId + ) + ).toBeAccepted([erc20BalanceChange, feeCheck]); + }); + + test('Should fail to estimate fee due to timestamp assertion', async () => { + const promise = alice.provider.estimateGas({ + ...(await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT)), + from: await customAccountWithFailingAssertion.getAddress() + }); - [transactionResponse, modifiers] = await transferFn(customAccountWithFailingAssertion); - await expect(transactionResponse).toBeRejected('failed to validate the transaction.'); + promise + .then((_) => { + fail('The transaction was expected to fail due to timestamp assertion'); + }) + .catch((error) => { + // If it's an error object with the structure you're mentioning, check its properties + if (error.info && error.info.error && error.info.error.message) { + expect(error.info.error.message).toEqual( + 'failed to validate the transaction. reason: Timestamp is out of range' + ); + } else { + fail('The transaction was expected to fail with a different message'); + } + }); }); test('Should fail the validation with incorrect signature', async () => { From ceb6e10391ca624425af9e3ba6c6e9a4a7d00a8d Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 18 Oct 2024 13:19:40 +0100 Subject: [PATCH 39/68] Fix lint --- core/tests/ts-integration/tests/custom-account.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index ae64dd85df91..e147161b20b5 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -9,8 +9,6 @@ import * as ethers from 'ethers'; import { deployContract, getTestContract } from '../src/helpers'; import { ERC20_PER_ACCOUNT, L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; import { shouldChangeETHBalances, shouldChangeTokenBalances } from '../src/modifiers/balance-checker'; -import { TransactionResponse } from 'ethers'; -import { MatcherModifier } from '../src/modifiers'; import { fail } from 'node:assert'; const contracts = { From d93b52d4cc71d502d76e782cf4745c362e6b724b Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 18 Oct 2024 16:26:23 +0100 Subject: [PATCH 40/68] Fix tests --- core/lib/vm_executor/src/oneshot/mock.rs | 2 +- core/node/state_keeper/src/io/tests/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/lib/vm_executor/src/oneshot/mock.rs b/core/lib/vm_executor/src/oneshot/mock.rs index 6ab3b1d9c306..e211328b5eca 100644 --- a/core/lib/vm_executor/src/oneshot/mock.rs +++ b/core/lib/vm_executor/src/oneshot/mock.rs @@ -95,7 +95,7 @@ impl MockOneshotExecutor { fn mock_inspect(&self, env: &OneshotEnv, args: TxExecutionArgs) -> VmExecutionResultAndLogs { match env.system.execution_mode { - TxExecutionMode::EthCall => (self.call_responses)(&args.transaction, &env), + TxExecutionMode::EthCall => (self.call_responses)(&args.transaction, env), TxExecutionMode::VerifyExecute | TxExecutionMode::EstimateFee => { (self.tx_responses)(&args.transaction, env) } diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 75b13ee48d49..437759d2e3b3 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -786,7 +786,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen .expect("Failed to find transaction") .unwrap(); assert_eq!( - "rejected: Transaction failed block.timestamp constraint", + "rejected: Transaction failed block.timestamp assertion", rejected_storage_tx_2.error.unwrap() ); } From d8a3df8ad32cf5b6ceb2d983428f7af9f0ef53fe Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 18 Oct 2024 17:02:51 +0100 Subject: [PATCH 41/68] Add missing sqlx file --- ...76fb01e6629e8c982c265f2af1d5000090572.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json diff --git a/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json b/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json new file mode 100644 index 000000000000..9669622f5cf2 --- /dev/null +++ b/core/lib/dal/.sqlx/query-dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(miniblocks.number) FROM miniblocks WHERE l1_batch_number IS NULL", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null + ] + }, + "hash": "dc16d0fac093a52480b66dfcb5976fb01e6629e8c982c265f2af1d5000090572" +} From a2373d0c8923a25359abde63fdc7c19bf7136049 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Mon, 21 Oct 2024 14:48:30 +0100 Subject: [PATCH 42/68] Add more integration tests --- .../src/tracers/validator/vm_latest/mod.rs | 6 +- core/lib/vm_interface/src/types/tracer.rs | 13 +- .../tests/custom-account.test.ts | 163 ++++++++++++++---- 3 files changed, 137 insertions(+), 45 deletions(-) diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index fd702f8ac787..4fc3c6803589 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -108,8 +108,8 @@ impl ValidationTracer { ); let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); - if start.as_u32() - end.as_u32() < self.timestamp_asserter_min_range_sec { - return Err(ViolatedValidationRule::TimestampAssertionOutOfRange); + if end.as_u32() - start.as_u32() < self.timestamp_asserter_min_range_sec { + return Err(ViolatedValidationRule::TimestampAssertionShortRange); } let now = SystemTime::now() @@ -119,7 +119,7 @@ impl ValidationTracer { if end.as_u32() < now as u32 + self.timestamp_asserter_min_time_till_end_sec { - return Err(ViolatedValidationRule::TimestampAssertionOutOfRange); + return Err(ViolatedValidationRule::TimestampAssertionCloseToRangeEnd); } { diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index aff788f27478..46c7045ae7a0 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -77,8 +77,10 @@ pub enum ViolatedValidationRule { TouchedDisallowedContext, /// The transaction used too much gas during validation. TookTooManyComputationalGas(u32), - /// The transaction failed block.timestamp assertion - TimestampAssertionOutOfRange, + /// The transaction failed block.timestamp assertion because the range is too short + TimestampAssertionShortRange, + /// The transaction failed block.timestamp assertion because the block.timestamp is too close to the range end + TimestampAssertionCloseToRangeEnd, } impl fmt::Display for ViolatedValidationRule { @@ -100,8 +102,11 @@ impl fmt::Display for ViolatedValidationRule { "Took too many computational gas, allowed limit: {gas_limit}" ) } - ViolatedValidationRule::TimestampAssertionOutOfRange => { - write!(f, "Transaction failed block.timestamp assertion") + ViolatedValidationRule::TimestampAssertionShortRange => { + write!(f, "block.timestamp range is too short") + } + ViolatedValidationRule::TimestampAssertionCloseToRangeEnd => { + write!(f, "block.timestamp is too close to the range end") } } } diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index e147161b20b5..81a5535e7915 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -26,7 +26,6 @@ describe('Tests for the custom account behavior', () => { let testMaster: TestMaster; let alice: zksync.Wallet; let customAccount: zksync.Contract; - let customAccountWithFailingAssertion: zksync.Contract; let erc20Address: string; let erc20: zksync.Contract; let timestampAsserterAddress: string; @@ -45,48 +44,43 @@ describe('Tests for the custom account behavior', () => { }); test('Should deploy custom account', async () => { - const deployFn = async function (rangeStart: number, rangeEnd: number): Promise { - const violateRules = false; - const customAccount = await deployContract( - alice, - contracts.customAccount, - // 2555971200 is a number of seconds up to 30/12/2050 - [violateRules, timestampAsserterAddress, rangeStart, rangeEnd], - 'createAccount' - ); - - // Now we need to check that it was correctly marked as an account: - const contractAccountInfo = await alice.provider.getContractAccountInfo(await customAccount.getAddress()); + const violateRules = false; + customAccount = await deployContract( + alice, + contracts.customAccount, + // 2555971200 is a number of seconds up to 30/12/2050 + [ + violateRules, + timestampAsserterAddress, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, + DEFAULT_TIMESTAMP_ASSERTER_RANGE_END + ], + 'createAccount' + ); - // Checking that the version of the account abstraction is correct - expect(contractAccountInfo.supportedAAVersion).toEqual(zksync.types.AccountAbstractionVersion.Version1); + // Now we need to check that it was correctly marked as an account: + const contractAccountInfo = await alice.provider.getContractAccountInfo(await customAccount.getAddress()); - // Checking that the nonce ordering is correct - expect(contractAccountInfo.nonceOrdering).toEqual(zksync.types.AccountNonceOrdering.Sequential); + // Checking that the version of the account abstraction is correct + expect(contractAccountInfo.supportedAAVersion).toEqual(zksync.types.AccountAbstractionVersion.Version1); - return customAccount; - }; + // Checking that the nonce ordering is correct + expect(contractAccountInfo.nonceOrdering).toEqual(zksync.types.AccountNonceOrdering.Sequential); - customAccount = await deployFn(DEFAULT_TIMESTAMP_ASSERTER_RANGE_START, DEFAULT_TIMESTAMP_ASSERTER_RANGE_END); - const now = Math.floor(Date.now() / 1000); - customAccountWithFailingAssertion = await deployFn(2 * now, 3 * now); + return customAccount; }); test('Should fund the custom account', async () => { - const fundFn = async function (account: zksync.Contract) { - await alice - .transfer({ to: await account.getAddress(), amount: ETH_PER_CUSTOM_ACCOUNT }) - .then((tx) => tx.wait()); - await alice - .transfer({ - to: await account.getAddress(), - token: erc20Address, - amount: ERC20_PER_ACCOUNT / 4n - }) - .then((tx) => tx.wait()); - }; - await fundFn(customAccount); - await fundFn(customAccountWithFailingAssertion); + await alice + .transfer({ to: await customAccount.getAddress(), amount: ETH_PER_CUSTOM_ACCOUNT }) + .then((tx) => tx.wait()); + await alice + .transfer({ + to: await customAccount.getAddress(), + token: erc20Address, + amount: ERC20_PER_ACCOUNT / 8n + }) + .then((tx) => tx.wait()); }); test('Should execute contract by custom account', async () => { @@ -119,12 +113,78 @@ describe('Tests for the custom account behavior', () => { ).toBeAccepted([erc20BalanceChange, feeCheck]); }); - test('Should fail to estimate fee due to timestamp assertion', async () => { + test('Should fail transaction validation due to timestamp assertion in the validation tracer - short time window', async () => { + const now = Math.floor(Date.now() / 1000); + const rangeStart = now - 60; + const rangeEnd = now + 60; + + const customAccount = await deployAndFundCustomAccount( + alice, + erc20Address, + timestampAsserterAddress, + rangeStart, + rangeEnd + ); + + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); + await expect( + sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + await customAccount.getAddress(), + testMaster.environment().l2ChainId + ) + ).toBeRejected( + 'failed to validate the transaction. reason: Violated validation rules: block.timestamp range is too short' + ); + }); + + test('Should fail transaction validation due to timestamp assertion in the validation tracer - close to the range end', async () => { + const now = Math.floor(Date.now() / 1000); + const rangeStart = now - 600; + const rangeEnd = now + 30; + + const customAccount = await deployAndFundCustomAccount( + alice, + erc20Address, + timestampAsserterAddress, + rangeStart, + rangeEnd + ); + + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); + + await expect( + sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + await customAccount.getAddress(), + testMaster.environment().l2ChainId + ) + ).toBeRejected( + 'failed to validate the transaction. reason: Violated validation rules: block.timestamp is too close to the range end' + ); + }); + + test('Should fail to estimate fee due to block.timestamp assertion in the smart contract', async () => { + const now = Math.floor(Date.now() / 1000); + const rangeStart = now + 300; + const rangeEnd = now + 1000; + + const customAccount = await deployAndFundCustomAccount( + alice, + erc20Address, + timestampAsserterAddress, + rangeStart, + rangeEnd + ); + const promise = alice.provider.estimateGas({ ...(await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT)), - from: await customAccountWithFailingAssertion.getAddress() + from: await customAccount.getAddress() }); + // requires custom assertion because the transaction would fail in "estimateFee" that is not handled correctly by zksync ethers promise .then((_) => { fail('The transaction was expected to fail due to timestamp assertion'); @@ -421,3 +481,30 @@ async function sendCustomAccountTransaction( return await browserProvider.broadcastTransaction(serializedTx); } + +async function deployAndFundCustomAccount( + richAccount: zksync.Wallet, + erc20Address: string, + timestampAsserterAddress: string, + rangeStart: number, + rangeEnd: number +): Promise { + const customAccount = await deployContract( + richAccount, + contracts.customAccount, + [false, timestampAsserterAddress, rangeStart, rangeEnd], + 'createAccount' + ); + + await richAccount + .transfer({ to: await customAccount.getAddress(), amount: ETH_PER_CUSTOM_ACCOUNT }) + .then((tx) => tx.wait()); + await richAccount + .transfer({ + to: await customAccount.getAddress(), + token: erc20Address, + amount: ERC20_PER_ACCOUNT / 8n + }) + .then((tx) => tx.wait()); + return customAccount; +} From a7adae54c4a1f809f86f6bdbcb104478fa8950a0 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Mon, 21 Oct 2024 15:02:26 +0100 Subject: [PATCH 43/68] Fix unit test --- core/lib/mempool/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/mempool/src/tests.rs b/core/lib/mempool/src/tests.rs index c6c570dd3000..d40158ae9558 100644 --- a/core/lib/mempool/src/tests.rs +++ b/core/lib/mempool/src/tests.rs @@ -374,7 +374,7 @@ fn mempool_does_not_purge_all_accounts() { gen_l2_tx(account0, Nonce(1)), gen_l2_tx(account1, Nonce(1)), ]; - mempool.insert(transactions, HashMap::new()); + mempool.insert_without_constraints(transactions, HashMap::new()); // Mempool is full. Account 1 has tx with non-sequential nonce so it should be purged. // Txs from account 0 have sequential nonces but their number is greater than capacity; they should be kept. assert_eq!(mempool.get_mempool_info().purged_accounts, vec![account1]); From fb31dd96561a104555408819fcbbec467ea58225 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 22 Oct 2024 16:51:53 +0100 Subject: [PATCH 44/68] Review feedback --- ...6737ed6b52eb308ebb06c646613be9cc0ce22.json | 42 ------------ .../lib/dal/src/models/storage_transaction.rs | 25 +++++-- core/lib/dal/src/transactions_dal.rs | 35 +++++----- core/lib/multivm/src/tracers/validator/mod.rs | 23 +++---- .../src/tracers/validator/vm_latest/mod.rs | 67 ++++++++----------- core/lib/types/src/lib.rs | 4 +- core/lib/vm_executor/src/oneshot/mod.rs | 1 + core/lib/vm_interface/src/types/tracer.rs | 28 ++++++-- .../src/execution_sandbox/execute.rs | 20 ++---- .../api_server/src/execution_sandbox/tests.rs | 4 -- .../src/execution_sandbox/validate.rs | 17 ++--- core/node/api_server/src/tx_sender/mod.rs | 15 +++-- .../api_server/src/tx_sender/tests/mod.rs | 2 +- .../api_server/src/tx_sender/tests/send_tx.rs | 3 +- core/node/node_sync/src/external_io.rs | 1 + core/node/state_keeper/src/io/mempool.rs | 18 ++--- core/node/state_keeper/src/io/mod.rs | 7 +- core/node/state_keeper/src/keeper.rs | 3 +- .../src/testonly/test_batch_executor.rs | 1 + 19 files changed, 143 insertions(+), 173 deletions(-) delete mode 100644 core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json diff --git a/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json b/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json deleted file mode 100644 index 94099dd03285..000000000000 --- a/core/lib/dal/.sqlx/query-529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n created_at,\n updated_at,\n timestamp_asserter_range_start,\n timestamp_asserter_range_end\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n NOW(),\n NOW(),\n $20,\n $21\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL,\n timestamp_asserter_range_start = $20,\n timestamp_asserter_range_end = $21\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "is_replaced!", - "type_info": "Bool" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Bytea", - "Int8", - "Bytea", - "Numeric", - "Numeric", - "Numeric", - "Numeric", - "Bytea", - "Jsonb", - "Int4", - "Bytea", - "Numeric", - "Bytea", - "Bytea", - "Int8", - "Int4", - "Int4", - "Timestamp", - "Timestamp", - "Timestamp" - ] - }, - "nullable": [ - null - ] - }, - "hash": "529b1bf08734792959ab1a063bb6737ed6b52eb308ebb06c646613be9cc0ce22" -} diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index f2a60e194f74..dc450bb0d8a3 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -324,11 +324,26 @@ impl From for Transaction { } } -impl From for TransactionTimeRangeConstraint { - fn from(tx: StorageTransaction) -> Self { - Self { - timestamp_asserter_range_start: tx.timestamp_asserter_range_start, - timestamp_asserter_range_end: tx.timestamp_asserter_range_end, +impl From<&StorageTransaction> for TransactionTimeRangeConstraint { + fn from(tx: &StorageTransaction) -> Self { + if tx.timestamp_asserter_range_start.is_some() && tx.timestamp_asserter_range_end.is_some() + { + Self { + timestamp_asserter_range: Some(( + tx.timestamp_asserter_range_start + .unwrap() + .and_utc() + .timestamp(), + tx.timestamp_asserter_range_end + .unwrap() + .and_utc() + .timestamp(), + )), + } + } else { + Self { + timestamp_asserter_range: None, + } } } } diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 437ad03c3539..d7becb99e54a 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -318,12 +318,12 @@ impl TransactionsDal<'_, '_> { let received_at = NaiveDateTime::from_timestamp_opt(secs, nanosecs).unwrap(); #[allow(deprecated)] let timestamp_asserter_range_start = validation_traces - .timestamp_asserter_range_start - .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); + .timestamp_asserter_range + .map(|x| NaiveDateTime::from_timestamp_opt(x.0, 0).unwrap()); #[allow(deprecated)] let timestamp_asserter_range_end = validation_traces - .timestamp_asserter_range_end - .map(|x| NaiveDateTime::from_timestamp_opt(x.as_u64() as i64, 0).unwrap()); + .timestamp_asserter_range + .map(|x| NaiveDateTime::from_timestamp_opt(x.1, 0).unwrap()); // Besides just adding or updating(on conflict) the record, we want to extract some info // from the query below, to indicate what actually happened: // 1) transaction is added @@ -356,10 +356,10 @@ impl TransactionsDal<'_, '_> { paymaster_input, execution_info, received_at, - created_at, - updated_at, timestamp_asserter_range_start, - timestamp_asserter_range_end + timestamp_asserter_range_end, + created_at, + updated_at ) VALUES ( @@ -388,10 +388,10 @@ impl TransactionsDal<'_, '_> { $18::INT ), $19, - NOW(), - NOW(), $20, - $21 + $21, + NOW(), + NOW() ) ON CONFLICT (initiator_address, nonce) DO UPDATE @@ -420,11 +420,11 @@ impl TransactionsDal<'_, '_> { ), in_mempool = FALSE, received_at = $19, + timestamp_asserter_range_start = $20, + timestamp_asserter_range_end = $21, created_at = NOW(), updated_at = NOW(), - error = NULL, - timestamp_asserter_range_start = $20, - timestamp_asserter_range_end = $21 + error = NULL WHERE transactions.is_priority = FALSE AND transactions.miniblock_number IS NULL @@ -1837,11 +1837,14 @@ impl TransactionsDal<'_, '_> { .fetch_all(self.storage) .await?; - let transactions = transactions + let transactions_with_constraints = transactions .into_iter() - .map(|tx| (tx.clone().into(), tx.into())) + .map(|tx| { + let constraint: TransactionTimeRangeConstraint = (&tx).into(); + (tx.into(), constraint) + }) .collect(); - Ok(transactions) + Ok(transactions_with_constraints) } pub async fn reset_mempool(&mut self) -> DalResult<()> { diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index ec8278139bc4..81244bef3355 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -13,7 +13,10 @@ use zksync_types::{ vm::VmVersion, web3::keccak256, AccountTreeId, Address, StorageKey, H256, U256, }; use zksync_utils::{be_bytes_to_safe_address, u256_to_account_address, u256_to_h256}; -use zksync_vm_interface::tracer::ValidationTraces; +use zksync_vm_interface::{ + tracer::{TimestampAsserterParams, ValidationTraces}, + L1BatchEnv, +}; use self::types::{NewTrustedValidationItems, ValidationTracerMode}; use crate::{ @@ -48,10 +51,9 @@ pub struct ValidationTracer { trusted_address_slots: HashSet<(Address, U256)>, computational_gas_used: u32, computational_gas_limit: u32, - timestamp_asserter_address: Option
, - timestamp_asserter_min_range_sec: u32, - timestamp_asserter_min_time_till_end_sec: u32, + timestamp_asserter_params: Option, vm_version: VmVersion, + l1_batch_env: L1BatchEnv, pub result: Arc>, pub traces: Arc>, _marker: PhantomData H>, @@ -63,6 +65,7 @@ impl ValidationTracer { pub fn new( params: ValidationParams, vm_version: VmVersion, + l1_batch_env: L1BatchEnv, ) -> ( Self, Arc>, @@ -83,14 +86,12 @@ impl ValidationTracer { trusted_address_slots: params.trusted_address_slots, computational_gas_used: 0, computational_gas_limit: params.computational_gas_limit, - timestamp_asserter_address: params.timestamp_asserter_address, - timestamp_asserter_min_range_sec: params.timestamp_asserter_min_range_sec, - timestamp_asserter_min_time_till_end_sec: params - .timestamp_asserter_min_time_till_end_sec, + timestamp_asserter_params: params.timestamp_asserter_params.clone(), vm_version, result: result.clone(), traces: traces.clone(), _marker: Default::default(), + l1_batch_env, }, result, traces, @@ -163,7 +164,7 @@ impl ValidationTracer { } // Allow to read any storage slot from the timesttamp asserter contract - if self.timestamp_asserter_address == Some(msg_sender) { + if self.timestamp_asserter_params.as_ref().map(|x| x.address) == Some(msg_sender) { return true; } @@ -214,9 +215,7 @@ impl ValidationTracer { trusted_addresses: self.trusted_addresses.clone(), trusted_address_slots: self.trusted_address_slots.clone(), computational_gas_limit: self.computational_gas_limit, - timestamp_asserter_address: self.timestamp_asserter_address, - timestamp_asserter_min_range_sec: self.timestamp_asserter_min_range_sec, - timestamp_asserter_min_time_till_end_sec: self.timestamp_asserter_min_time_till_end_sec, + timestamp_asserter_params: self.timestamp_asserter_params.clone(), } } } diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 4fc3c6803589..65bf6271ddb6 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -1,8 +1,3 @@ -use std::{ - cmp, - time::{SystemTime, UNIX_EPOCH}, -}; - use zk_evm_1_5_0::{ tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{ContextOpcode, FarCallABI, LogOpcode, Opcode}, @@ -31,6 +26,8 @@ use crate::{ HistoryMode, }; +pub const TIMESTAMP_ASSERTER_FUNCTION_SELECTOR: [u8; 4] = [0x5b, 0x1a, 0x0c, 0x91]; + impl ValidationTracer { fn check_user_restrictions_vm_latest( &mut self, @@ -89,8 +86,8 @@ impl ValidationTracer { // If this is a call to the timestamp asserter, extract the function arguments and store them in ValidationTraces. // These arguments are used by the mempool for transaction filtering. The call data length should be 68 bytes: // a 4-byte function selector followed by two U256 values. - // TODO: if any more functions will be added to the TimestampAsserter contract in the future, verify the function selector too - if Some(called_address) == self.timestamp_asserter_address + let address = self.timestamp_asserter_params.as_ref().map(|x| x.address); + if Some(called_address) == address && far_call_abi.memory_quasi_fat_pointer.length == 68 { let calldata_page = get_calldata_page_via_abi( @@ -103,37 +100,31 @@ impl ValidationTracer { 68, ); - let start = U256::from_big_endian( - &calldata[calldata.len() - 64..calldata.len() - 32], - ); - let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); - - if end.as_u32() - start.as_u32() < self.timestamp_asserter_min_range_sec { - return Err(ViolatedValidationRule::TimestampAssertionShortRange); - } - - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Incorrect system time") - .as_secs(); - - if end.as_u32() < now as u32 + self.timestamp_asserter_min_time_till_end_sec - { - return Err(ViolatedValidationRule::TimestampAssertionCloseToRangeEnd); - } - - { - let mut traces_mut = self.traces.lock().unwrap(); - traces_mut.timestamp_asserter_range_start = - match traces_mut.timestamp_asserter_range_start { - Some(current_value) => Some(cmp::max(current_value, start)), - None => Some(start), - }; - traces_mut.timestamp_asserter_range_end = - match traces_mut.timestamp_asserter_range_end { - Some(current_value) => Some(cmp::min(current_value, end)), - None => Some(end), - }; + if calldata[..4] == TIMESTAMP_ASSERTER_FUNCTION_SELECTOR { + let start = U256::from_big_endian( + &calldata[calldata.len() - 64..calldata.len() - 32], + ); + let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); + + let params = self.timestamp_asserter_params.as_ref().unwrap(); + + if end.as_u32() - start.as_u32() < params.min_range_sec { + return Err(ViolatedValidationRule::TimestampAssertionShortRange); + } + + if end.as_u32() + < self.l1_batch_env.timestamp as u32 + params.min_time_till_end_sec + { + return Err( + ViolatedValidationRule::TimestampAssertionCloseToRangeEnd, + ); + } + + { + let mut traces_mut = self.traces.lock().unwrap(); + traces_mut + .apply_range((start.as_u64() as i64, end.as_u64() as i64)); + } } } } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 4a7cf3d9201d..e58802285bbc 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -8,7 +8,6 @@ use std::fmt; use anyhow::Context as _; -use chrono::NaiveDateTime; use fee::encoding_len; pub use l1::L1TxCommonData; pub use l2::L2TxCommonData; @@ -430,6 +429,5 @@ impl Transaction { Copy )] pub struct TransactionTimeRangeConstraint { - pub timestamp_asserter_range_start: Option, - pub timestamp_asserter_range_end: Option, + pub timestamp_asserter_range: Option<(i64, i64)>, // (start, end) } diff --git a/core/lib/vm_executor/src/oneshot/mod.rs b/core/lib/vm_executor/src/oneshot/mod.rs index c55ad634fcbd..6ca48f184b2e 100644 --- a/core/lib/vm_executor/src/oneshot/mod.rs +++ b/core/lib/vm_executor/src/oneshot/mod.rs @@ -158,6 +158,7 @@ where ValidationTracer::::new( validation_params, env.system.version.into(), + env.l1_batch.clone(), ); let tracers = vec![validation_tracer.into_tracer_pointer()]; diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index 46c7045ae7a0..fe1a31ab47bf 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, fmt}; +use std::{cmp, collections::HashSet, fmt}; use zksync_types::{Address, U256}; @@ -57,13 +57,19 @@ pub struct ValidationParams { pub trusted_address_slots: HashSet<(Address, U256)>, /// Number of computational gas that validation step is allowed to use. pub computational_gas_limit: u32, + /// Parameters of the timestamp asserter if configured + pub timestamp_asserter_params: Option, +} + +#[derive(Debug, Clone)] +pub struct TimestampAsserterParams { /// Address of the timestamp asserter. This contract is allowed to touch block.timestamp regardless /// of the calling context. - pub timestamp_asserter_address: Option
, + pub address: Address, /// Minimum difference in seconds between the range start and range end - pub timestamp_asserter_min_range_sec: u32, + pub min_range_sec: u32, /// Minimum time between current block.timestamp and the end of the asserted range - pub timestamp_asserter_min_time_till_end_sec: u32, + pub min_time_till_end_sec: u32, } /// Rules that can be violated when validating a transaction. @@ -127,8 +133,18 @@ pub enum ValidationError { /// be excluded from the mempool. #[derive(Debug, Clone, Default)] pub struct ValidationTraces { - pub timestamp_asserter_range_start: Option, - pub timestamp_asserter_range_end: Option, + pub timestamp_asserter_range: Option<(i64, i64)>, +} + +impl ValidationTraces { + pub fn apply_range(&mut self, new_range: (i64, i64)) { + if let Some(mut range) = self.timestamp_asserter_range { + range.0 = cmp::max(range.0, new_range.0); + range.1 = cmp::min(range.1, new_range.1); + } else { + self.timestamp_asserter_range = Some(new_range); + } + } } impl fmt::Display for ValidationError { diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index f8336adad6d9..cc0c7843ee54 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -9,13 +9,13 @@ use zksync_dal::{Connection, Core}; use zksync_multivm::interface::{ executor::{OneshotExecutor, TransactionValidator}, storage::ReadStorage, - tracer::{ValidationError, ValidationParams, ValidationTraces}, + tracer::{TimestampAsserterParams, ValidationError, ValidationParams, ValidationTraces}, Call, OneshotEnv, OneshotTracingParams, OneshotTransactionExecutionResult, TransactionExecutionMetrics, TxExecutionArgs, VmExecutionResultAndLogs, }; use zksync_state::{PostgresStorage, PostgresStorageCaches}; use zksync_types::{ - api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Address, Transaction, + api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Transaction, }; use zksync_vm_executor::oneshot::{MainOneshotExecutor, MockOneshotExecutor}; @@ -100,9 +100,7 @@ pub(crate) struct SandboxExecutor { engine: SandboxExecutorEngine, pub(super) options: SandboxExecutorOptions, storage_caches: Option, - pub(super) timestamp_asserter_address: Option
, - pub(super) timestamp_asserter_min_range_sec: u32, - pub(super) timestamp_asserter_min_time_till_end_sec: u32, + pub(super) timestamp_asserter_params: Option, } impl SandboxExecutor { @@ -110,9 +108,7 @@ impl SandboxExecutor { options: SandboxExecutorOptions, caches: PostgresStorageCaches, missed_storage_invocation_limit: usize, - timestamp_asserter_address: Option
, - timestamp_asserter_min_range_sec: u32, - timestamp_asserter_min_time_till_end_sec: u32, + timestamp_asserter_params: Option, ) -> Self { let mut executor = MainOneshotExecutor::new(missed_storage_invocation_limit); executor @@ -121,9 +117,7 @@ impl SandboxExecutor { engine: SandboxExecutorEngine::Real(executor), options, storage_caches: Some(caches), - timestamp_asserter_address, - timestamp_asserter_min_range_sec, - timestamp_asserter_min_time_till_end_sec, + timestamp_asserter_params, } } @@ -139,9 +133,7 @@ impl SandboxExecutor { engine: SandboxExecutorEngine::Mock(executor), options, storage_caches: None, - timestamp_asserter_address: None, - timestamp_asserter_min_range_sec: 0, - timestamp_asserter_min_time_till_end_sec: 0, + timestamp_asserter_params: None, } } diff --git a/core/node/api_server/src/execution_sandbox/tests.rs b/core/node/api_server/src/execution_sandbox/tests.rs index d182fa950a74..0aff15b973e0 100644 --- a/core/node/api_server/src/execution_sandbox/tests.rs +++ b/core/node/api_server/src/execution_sandbox/tests.rs @@ -218,8 +218,6 @@ async fn test_instantiating_vm(connection: Connection<'static, Core>, block_args PostgresStorageCaches::new(1, 1), usize::MAX, None, - 0, - 0, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); @@ -269,8 +267,6 @@ async fn validating_transaction(set_balance: bool) { PostgresStorageCaches::new(1, 1), usize::MAX, None, - 0, - 0, ); let fee_input = BatchFeeInput::l1_pegged(55, 555); diff --git a/core/node/api_server/src/execution_sandbox/validate.rs b/core/node/api_server/src/execution_sandbox/validate.rs index c98e4fed2d82..cf601f77ddfd 100644 --- a/core/node/api_server/src/execution_sandbox/validate.rs +++ b/core/node/api_server/src/execution_sandbox/validate.rs @@ -5,7 +5,10 @@ use tracing::Instrument; use zksync_dal::{Connection, Core, CoreDal}; use zksync_multivm::interface::{ executor::TransactionValidator, - tracer::{ValidationError as RawValidationError, ValidationParams, ValidationTraces}, + tracer::{ + TimestampAsserterParams, ValidationError as RawValidationError, ValidationParams, + ValidationTraces, + }, }; use zksync_types::{ api::state_override::StateOverride, fee_model::BatchFeeInput, l2::L2Tx, Address, @@ -46,9 +49,7 @@ impl SandboxExecutor { &tx, self.options.eth_call.validation_computational_gas_limit(), whitelisted_tokens_for_aa, - self.timestamp_asserter_address, - self.timestamp_asserter_min_range_sec, - self.timestamp_asserter_min_time_till_end_sec, + self.timestamp_asserter_params.clone(), ) .await .context("failed getting validation params")?; @@ -83,9 +84,7 @@ pub(super) async fn get_validation_params( tx: &L2Tx, computational_gas_limit: u32, whitelisted_tokens_for_aa: &[Address], - timestamp_asserter_address: Option
, - timestamp_asserter_min_range_sec: u32, - timestamp_asserter_min_time_till_end_sec: u32, + timestamp_asserter_params: Option, ) -> anyhow::Result { let method_latency = EXECUTION_METRICS.get_validation_params.start(); let user_address = tx.common_data.initiator_address; @@ -132,8 +131,6 @@ pub(super) async fn get_validation_params( trusted_addresses, trusted_address_slots, computational_gas_limit, - timestamp_asserter_address, - timestamp_asserter_min_range_sec, - timestamp_asserter_min_time_till_end_sec, + timestamp_asserter_params, }) } diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 7de043b788d3..bf37179c91ab 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -12,7 +12,10 @@ use zksync_dal::{ transactions_dal::L2TxSubmissionResult, Connection, ConnectionPool, Core, CoreDal, }; use zksync_multivm::{ - interface::{OneshotTracingParams, TransactionExecutionMetrics, VmExecutionResultAndLogs}, + interface::{ + tracer::TimestampAsserterParams, OneshotTracingParams, TransactionExecutionMetrics, + VmExecutionResultAndLogs, + }, utils::{derive_base_fee_and_gas_per_pubdata, get_max_batch_gas_limit}, }; use zksync_node_fee_model::{ApiFeeInputProvider, BatchFeeModelInputProvider}; @@ -200,9 +203,13 @@ impl TxSenderBuilder { executor_options, storage_caches, missed_storage_invocation_limit, - self.config.timestamp_asserter_address, - self.config.timestamp_asserter_min_range_sec, - self.config.timestamp_asserter_min_time_till_end_sec, + self.config + .timestamp_asserter_address + .map(|address| TimestampAsserterParams { + address, + min_range_sec: self.config.timestamp_asserter_min_range_sec, + min_time_till_end_sec: self.config.timestamp_asserter_min_time_till_end_sec, + }), ); TxSender(Arc::new(TxSenderInner { diff --git a/core/node/api_server/src/tx_sender/tests/mod.rs b/core/node/api_server/src/tx_sender/tests/mod.rs index db514f05e4a5..6b46c0463746 100644 --- a/core/node/api_server/src/tx_sender/tests/mod.rs +++ b/core/node/api_server/src/tx_sender/tests/mod.rs @@ -154,7 +154,7 @@ async fn create_real_tx_sender(pool: ConnectionPool) -> TxSender { .unwrap(); let pg_caches = PostgresStorageCaches::new(1, 1); - let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX, None, 0, 0); + let tx_executor = SandboxExecutor::real(executor_options, pg_caches, usize::MAX, None); create_test_tx_sender(pool, genesis_params.config().l2_chain_id, tx_executor) .await .0 diff --git a/core/node/api_server/src/tx_sender/tests/send_tx.rs b/core/node/api_server/src/tx_sender/tests/send_tx.rs index 85f27bca71ec..b08335a0f27e 100644 --- a/core/node/api_server/src/tx_sender/tests/send_tx.rs +++ b/core/node/api_server/src/tx_sender/tests/send_tx.rs @@ -344,8 +344,7 @@ async fn submitting_tx_with_validation_traces() { tx_executor.set_tx_validation_traces_responses(move |tx, _| { assert_eq!(tx.hash(), tx_hash); ValidationTraces { - timestamp_asserter_range_start: Some(U256::from(10)), - timestamp_asserter_range_end: Some(U256::from(20)), + timestamp_asserter_range: Some((10, 20)), } }); diff --git a/core/node/node_sync/src/external_io.rs b/core/node/node_sync/src/external_io.rs index a0be233a002e..755121767b98 100644 --- a/core/node/node_sync/src/external_io.rs +++ b/core/node/node_sync/src/external_io.rs @@ -362,6 +362,7 @@ impl StateKeeperIO for ExternalIO { async fn wait_for_next_tx( &mut self, max_wait: Duration, + _l2_block_timestamp: u64, ) -> anyhow::Result> { tracing::debug!( "Waiting for the new tx, next action is {:?}", diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index c0f640bf9fe8..8e68a38315a8 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -2,7 +2,7 @@ use std::{ cmp, collections::HashMap, sync::Arc, - time::{Duration, Instant, SystemTime, UNIX_EPOCH}, + time::{Duration, Instant}, }; use anyhow::Context as _; @@ -109,6 +109,7 @@ impl StateKeeperIO for MempoolIO { else { return Ok((cursor, None)); }; + let pending_batch_data = load_pending_batch(&mut storage, system_env, l1_batch_env) .await .with_context(|| { @@ -278,6 +279,7 @@ impl StateKeeperIO for MempoolIO { async fn wait_for_next_tx( &mut self, max_wait: Duration, + l2_block_timestamp: u64, ) -> anyhow::Result> { let started_at = Instant::now(); while started_at.elapsed() <= max_wait { @@ -302,17 +304,9 @@ impl StateKeeperIO for MempoolIO { // Reject transactions that violate block.timestamp constraints. Such transactions should be // rejected at the API level, but we need to protect ourselves in case if a transaction // goes outside of the allowed range while being in the mempool - let now = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Invalid system time") - .as_secs() as i64; - - let matches_range = constraint - .timestamp_asserter_range_start - .map_or(true, |x| x.and_utc().timestamp() < now) - && constraint - .timestamp_asserter_range_end - .map_or(true, |x| x.and_utc().timestamp() > now); + let matches_range = constraint.timestamp_asserter_range.map_or(true, |x| { + x.0 < l2_block_timestamp as i64 && x.1 > l2_block_timestamp as i64 + }); if !matches_range { self.reject( diff --git a/core/node/state_keeper/src/io/mod.rs b/core/node/state_keeper/src/io/mod.rs index 0fc5ebb6c082..fff2bac7cd3c 100644 --- a/core/node/state_keeper/src/io/mod.rs +++ b/core/node/state_keeper/src/io/mod.rs @@ -131,8 +131,11 @@ pub trait StateKeeperIO: 'static + Send + Sync + fmt::Debug + IoSealCriteria { /// Blocks for up to `max_wait` until the next transaction is available for execution. /// Returns `None` if no transaction became available until the timeout. - async fn wait_for_next_tx(&mut self, max_wait: Duration) - -> anyhow::Result>; + async fn wait_for_next_tx( + &mut self, + max_wait: Duration, + l2_block_timestamp: u64, + ) -> anyhow::Result>; /// Marks the transaction as "not executed", so it can be retrieved from the IO again. async fn rollback(&mut self, tx: Transaction) -> anyhow::Result<()>; /// Marks the transaction as "rejected", e.g. one that is not correct and can't be executed. diff --git a/core/node/state_keeper/src/keeper.rs b/core/node/state_keeper/src/keeper.rs index bd102daa3080..644b234a9274 100644 --- a/core/node/state_keeper/src/keeper.rs +++ b/core/node/state_keeper/src/keeper.rs @@ -584,11 +584,10 @@ impl ZkSyncStateKeeper { Self::start_next_l2_block(new_l2_block_params, updates_manager, batch_executor) .await?; } - let waiting_latency = KEEPER_METRICS.waiting_for_tx.start(); let Some(tx) = self .io - .wait_for_next_tx(POLL_WAIT_DURATION) + .wait_for_next_tx(POLL_WAIT_DURATION, updates_manager.l2_block.timestamp) .instrument(info_span!("wait_for_next_tx")) .await .context("error waiting for next transaction")? diff --git a/core/node/state_keeper/src/testonly/test_batch_executor.rs b/core/node/state_keeper/src/testonly/test_batch_executor.rs index cb282f3b7d6d..b20396ed49e8 100644 --- a/core/node/state_keeper/src/testonly/test_batch_executor.rs +++ b/core/node/state_keeper/src/testonly/test_batch_executor.rs @@ -728,6 +728,7 @@ impl StateKeeperIO for TestIO { async fn wait_for_next_tx( &mut self, max_wait: Duration, + _l2_block_timestamp: u64, ) -> anyhow::Result> { let action = self.pop_next_item("wait_for_next_tx"); From 222dadae932aad6af5e2f6fd8ea3e73b80207fdf Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 22 Oct 2024 16:59:04 +0100 Subject: [PATCH 45/68] Add missing sqlx file --- ...802690bdd139505ba22be3655e306773abc77.json | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 core/lib/dal/.sqlx/query-ab3f97cf96ef769346703e0c132802690bdd139505ba22be3655e306773abc77.json diff --git a/core/lib/dal/.sqlx/query-ab3f97cf96ef769346703e0c132802690bdd139505ba22be3655e306773abc77.json b/core/lib/dal/.sqlx/query-ab3f97cf96ef769346703e0c132802690bdd139505ba22be3655e306773abc77.json new file mode 100644 index 000000000000..2edb0822ac69 --- /dev/null +++ b/core/lib/dal/.sqlx/query-ab3f97cf96ef769346703e0c132802690bdd139505ba22be3655e306773abc77.json @@ -0,0 +1,42 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n transactions (\n hash,\n is_priority,\n initiator_address,\n nonce,\n signature,\n gas_limit,\n max_fee_per_gas,\n max_priority_fee_per_gas,\n gas_per_pubdata_limit,\n input,\n data,\n tx_format,\n contract_address,\n value,\n paymaster,\n paymaster_input,\n execution_info,\n received_at,\n timestamp_asserter_range_start,\n timestamp_asserter_range_end,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\n FALSE,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7,\n $8,\n $9,\n $10,\n $11,\n $12,\n $13,\n $14,\n $15,\n JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n $19,\n $20,\n $21,\n NOW(),\n NOW()\n )\n ON CONFLICT (initiator_address, nonce) DO\n UPDATE\n SET\n hash = $1,\n signature = $4,\n gas_limit = $5,\n max_fee_per_gas = $6,\n max_priority_fee_per_gas = $7,\n gas_per_pubdata_limit = $8,\n input = $9,\n data = $10,\n tx_format = $11,\n contract_address = $12,\n value = $13,\n paymaster = $14,\n paymaster_input = $15,\n execution_info\n = JSONB_BUILD_OBJECT(\n 'gas_used',\n $16::BIGINT,\n 'storage_writes',\n $17::INT,\n 'contracts_used',\n $18::INT\n ),\n in_mempool = FALSE,\n received_at = $19,\n timestamp_asserter_range_start = $20,\n timestamp_asserter_range_end = $21,\n created_at = NOW(),\n updated_at = NOW(),\n error = NULL\n WHERE\n transactions.is_priority = FALSE\n AND transactions.miniblock_number IS NULL\n RETURNING\n (\n SELECT\n hash\n FROM\n transactions\n WHERE\n transactions.initiator_address = $2\n AND transactions.nonce = $3\n ) IS NOT NULL AS \"is_replaced!\"\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "is_replaced!", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Bytea", + "Int8", + "Bytea", + "Numeric", + "Numeric", + "Numeric", + "Numeric", + "Bytea", + "Jsonb", + "Int4", + "Bytea", + "Numeric", + "Bytea", + "Bytea", + "Int8", + "Int4", + "Int4", + "Timestamp", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + null + ] + }, + "hash": "ab3f97cf96ef769346703e0c132802690bdd139505ba22be3655e306773abc77" +} From 1867ab255d70c7f1de375530ddee8021481e4984 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 22 Oct 2024 17:35:44 +0100 Subject: [PATCH 46/68] Fix lint --- core/node/state_keeper/src/io/tests/mod.rs | 32 ++++------------------ 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 437759d2e3b3..a625ecced288 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -3,7 +3,6 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -use chrono::NaiveDateTime; use test_casing::test_casing; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; @@ -708,14 +707,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( - system_time - 20000, - 0, - )), - timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( - system_time - 10000, - 0, - )), + timestamp_asserter_range: Some((system_time - 20000, system_time - 10000)), }, ); #[allow(deprecated)] @@ -724,14 +716,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( - system_time - 1000, - 0, - )), - timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( - system_time + 1000, - 0, - )), + timestamp_asserter_range: Some((system_time - 1000, system_time + 1000)), }, ); #[allow(deprecated)] @@ -740,14 +725,7 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range_start: Some(NaiveDateTime::from_timestamp( - system_time + 10000, - 0, - )), - timestamp_asserter_range_end: Some(NaiveDateTime::from_timestamp( - system_time + 20000, - 0, - )), + timestamp_asserter_range: Some((system_time + 10000, system_time + 20000)), }, ); insert_l2_transaction(&mut storage, &rejected_tx_1).await; @@ -755,14 +733,14 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen insert_l2_transaction(&mut storage, &rejected_tx_2).await; let tx = mempool - .wait_for_next_tx(Duration::from_secs(2)) + .wait_for_next_tx(Duration::from_secs(2), system_time as u64) .await .expect("No expected transaction in the mempool") .unwrap(); assert_eq!(expected_tx.hash(), tx.hash()); let next_tx = mempool - .wait_for_next_tx(Duration::from_secs(2)) + .wait_for_next_tx(Duration::from_secs(2), system_time as u64) .await .expect("Should be no more transactions in the mempool"); assert!(next_tx.is_none()); From a0a519886731f930ace8d905c60eefe2203f654e Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 22 Oct 2024 18:03:32 +0100 Subject: [PATCH 47/68] Fixed comments --- core/lib/types/src/lib.rs | 3 ++- core/lib/vm_interface/src/types/tracer.rs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index e58802285bbc..f70111ea1797 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -429,5 +429,6 @@ impl Transaction { Copy )] pub struct TransactionTimeRangeConstraint { - pub timestamp_asserter_range: Option<(i64, i64)>, // (start, end) + /// Represents a range from-to. Each field is a number of seconds since the epoch. + pub timestamp_asserter_range: Option<(i64, i64)>, } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index fe1a31ab47bf..e8363ff625ed 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -128,15 +128,18 @@ pub enum ValidationError { } /// Traces the validation of a transaction, providing visibility into the aspects the transaction interacts with. -/// For instance, the `range_start` and `range_end` fields represent the range within which the transaction might make +/// For instance, the `timestamp_asserter_range` represent the range within which the transaction might make /// assertions on `block.timestamp`. This information is crucial for the caller, as expired transactions should /// be excluded from the mempool. #[derive(Debug, Clone, Default)] pub struct ValidationTraces { + /// Represents a range from-to. Each field is a number of seconds since the epoch. pub timestamp_asserter_range: Option<(i64, i64)>, } impl ValidationTraces { + /// Merges two ranges together by taking the maximum of the starts and the minimum of the ends + /// resulting into the narrowest possible time window pub fn apply_range(&mut self, new_range: (i64, i64)) { if let Some(mut range) = self.timestamp_asserter_range { range.0 = cmp::max(range.0, new_range.0); From 6c9094862d4ceedd81bbbad495ddf7e217a8f7f8 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 14:30:33 +0000 Subject: [PATCH 48/68] Review comments --- Cargo.lock | 2 - core/bin/external_node/src/config/mod.rs | 14 +++-- core/bin/zksync_server/src/node_builder.rs | 11 +++- ...3940_add_block_timestamp_asserter.down.sql | 5 +- ...073940_add_block_timestamp_asserter.up.sql | 5 +- .../lib/dal/src/models/storage_transaction.rs | 14 ++--- core/lib/dal/src/transactions_dal.rs | 7 ++- core/lib/mempool/Cargo.toml | 2 - core/lib/mempool/src/types.rs | 2 +- core/lib/multivm/src/tracers/validator/mod.rs | 2 +- .../src/tracers/validator/vm_latest/mod.rs | 18 ++++-- .../protobuf_config/src/timestamp_asserter.rs | 7 ++- core/lib/types/src/lib.rs | 17 +----- core/lib/vm_interface/src/types/tracer.rs | 61 ++++++++++++++++--- core/node/api_server/src/tx_sender/mod.rs | 50 +++++++-------- .../api_server/src/tx_sender/tests/send_tx.rs | 2 +- core/node/api_server/src/web3/testonly.rs | 7 +-- core/node/state_keeper/Cargo.toml | 1 - core/node/state_keeper/src/io/mempool.rs | 6 +- core/node/state_keeper/src/io/tests/mod.rs | 23 +++---- core/tests/ts-integration/src/env.ts | 15 ++++- core/tests/ts-integration/src/types.ts | 2 + .../tests/custom-account.test.ts | 18 +++--- 23 files changed, 171 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e10af775340a..2e3a8a1c3e3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10427,7 +10427,6 @@ dependencies = [ name = "zksync_mempool" version = "0.1.0" dependencies = [ - "chrono", "tracing", "zksync_types", ] @@ -11128,7 +11127,6 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", - "chrono", "futures 0.3.30", "hex", "itertools 0.10.5", diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 83441d0ea1a0..31017d359718 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -24,7 +24,7 @@ use zksync_core_leftovers::temp_config_store::read_yaml_repr; use zksync_dal::{ConnectionPool, Core}; use zksync_metadata_calculator::MetadataCalculatorRecoveryConfig; use zksync_node_api_server::{ - tx_sender::TxSenderConfig, + tx_sender::{TimestampAsserterParams, TxSenderConfig}, web3::{state::InternalApiConfig, Namespace}, }; use zksync_protobuf_config::proto; @@ -1479,11 +1479,13 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { chain_id: config.required.l2_chain_id, // Does not matter for EN. whitelisted_tokens_for_aa: Default::default(), - timestamp_asserter_address: config.remote.l2_timestamp_asserter_addr, - timestamp_asserter_min_range_sec: config.optional.timestamp_asserter_min_range_sec, - timestamp_asserter_min_time_till_end_sec: config - .optional - .timestamp_asserter_min_time_till_end_sec, + timestamp_asserter_params: config.remote.l2_timestamp_asserter_addr.map(|address| { + TimestampAsserterParams { + address, + min_range_sec: config.optional.timestamp_asserter_min_range_sec, + min_time_till_end_sec: config.optional.timestamp_asserter_min_time_till_end_sec, + } + }), } } } diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 9492e28f9c2b..dbc8fb75b2a3 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -12,7 +12,7 @@ use zksync_config::{ use zksync_core_leftovers::Component; use zksync_metadata_calculator::MetadataCalculatorConfig; use zksync_node_api_server::{ - tx_sender::TxSenderConfig, + tx_sender::{TimestampAsserterParams, TxSenderConfig}, web3::{state::InternalApiConfig, Namespace}, }; use zksync_node_framework::{ @@ -323,8 +323,13 @@ impl MainNodeBuilder { .fee_account .address(), self.genesis_config.l2_chain_id, - self.contracts_config.l2_timestamp_asserter_addr, - timestamp_asserter_config, + self.contracts_config + .l2_timestamp_asserter_addr + .map(|address| TimestampAsserterParams { + address, + min_range_sec: timestamp_asserter_config.min_range_sec, + min_time_till_end_sec: timestamp_asserter_config.min_time_till_end_sec, + }), ), postgres_storage_caches_config, rpc_config.vm_concurrency_limit(), diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql index bb409923da69..87f6a8cb75a0 100644 --- a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.down.sql @@ -1,2 +1,3 @@ -ALTER TABLE transactions DROP COLUMN timestamp_asserter_range_start; -ALTER TABLE transactions DROP COLUMN timestamp_asserter_range_end; \ No newline at end of file +ALTER TABLE transactions +DROP COLUMN timestamp_asserter_range_start, +DROP COLUMN timestamp_asserter_range_end; diff --git a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql index 39bd8e1ac9f4..103a22cb8e3c 100644 --- a/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql +++ b/core/lib/dal/migrations/20241008073940_add_block_timestamp_asserter.up.sql @@ -1,2 +1,3 @@ -ALTER TABLE transactions ADD COLUMN timestamp_asserter_range_start TIMESTAMP DEFAULT NULL; -ALTER TABLE transactions ADD COLUMN timestamp_asserter_range_end TIMESTAMP DEFAULT NULL; \ No newline at end of file +ALTER TABLE transactions +ADD COLUMN timestamp_asserter_range_start TIMESTAMP DEFAULT NULL, +ADD COLUMN timestamp_asserter_range_end TIMESTAMP DEFAULT NULL; diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index dc450bb0d8a3..35a9cfede845 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -329,16 +329,16 @@ impl From<&StorageTransaction> for TransactionTimeRangeConstraint { if tx.timestamp_asserter_range_start.is_some() && tx.timestamp_asserter_range_end.is_some() { Self { - timestamp_asserter_range: Some(( + timestamp_asserter_range: Some( tx.timestamp_asserter_range_start .unwrap() .and_utc() - .timestamp(), - tx.timestamp_asserter_range_end - .unwrap() - .and_utc() - .timestamp(), - )), + .timestamp() as u64 + ..tx.timestamp_asserter_range_end + .unwrap() + .and_utc() + .timestamp() as u64, + ), } } else { Self { diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index d7becb99e54a..57766daa4c6e 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -319,11 +319,12 @@ impl TransactionsDal<'_, '_> { #[allow(deprecated)] let timestamp_asserter_range_start = validation_traces .timestamp_asserter_range - .map(|x| NaiveDateTime::from_timestamp_opt(x.0, 0).unwrap()); + .clone() + .map(|x| NaiveDateTime::from_timestamp_opt(x.start as i64, 0).unwrap()); #[allow(deprecated)] let timestamp_asserter_range_end = validation_traces .timestamp_asserter_range - .map(|x| NaiveDateTime::from_timestamp_opt(x.1, 0).unwrap()); + .map(|x| NaiveDateTime::from_timestamp_opt(x.end as i64, 0).unwrap()); // Besides just adding or updating(on conflict) the record, we want to extract some info // from the query below, to indicate what actually happened: // 1) transaction is added @@ -1840,7 +1841,7 @@ impl TransactionsDal<'_, '_> { let transactions_with_constraints = transactions .into_iter() .map(|tx| { - let constraint: TransactionTimeRangeConstraint = (&tx).into(); + let constraint = TransactionTimeRangeConstraint::from(&tx); (tx.into(), constraint) }) .collect(); diff --git a/core/lib/mempool/Cargo.toml b/core/lib/mempool/Cargo.toml index d0354047f8f3..ca2203f174f6 100644 --- a/core/lib/mempool/Cargo.toml +++ b/core/lib/mempool/Cargo.toml @@ -13,5 +13,3 @@ categories.workspace = true [dependencies] zksync_types.workspace = true tracing.workspace = true -chrono = { workspace = true, features = ["serde"] } - diff --git a/core/lib/mempool/src/types.rs b/core/lib/mempool/src/types.rs index f3bc3c6a0a8e..7c2694dff5ef 100644 --- a/core/lib/mempool/src/types.rs +++ b/core/lib/mempool/src/types.rs @@ -76,7 +76,7 @@ impl AccountTransactions { self.nonce = self.nonce.min(tx_nonce); self.transactions .get(&(tx_nonce + 1)) - .map(|(tx, c)| (Self::score_for_transaction(tx), *c)) + .map(|(tx, c)| (Self::score_for_transaction(tx), c.clone())) } pub fn len(&self) -> usize { diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index e86f60138a38..9db15f738a98 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -172,7 +172,7 @@ impl ValidationTracer { } // Allow to read any storage slot from the timesttamp asserter contract - if self.timestamp_asserter_params.as_ref().map(|x| x.address) == Some(msg_sender) { + if self.timestamp_asserter_params.as_ref().map(|x| x.address) == Some(address) { return true; } diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 65bf6271ddb6..5ee27eb05808 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -1,3 +1,5 @@ +use std::u64; + use zk_evm_1_5_0::{ tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{ContextOpcode, FarCallABI, LogOpcode, Opcode}, @@ -108,12 +110,19 @@ impl ValidationTracer { let params = self.timestamp_asserter_params.as_ref().unwrap(); - if end.as_u32() - start.as_u32() < params.min_range_sec { + // end is guaranteed to be greater than the start as + let difference = (end - start) + .try_into() + .unwrap_or(U256::from(u32::MAX)) + .as_u32(); + if difference < params.min_range_sec { return Err(ViolatedValidationRule::TimestampAssertionShortRange); } - if end.as_u32() - < self.l1_batch_env.timestamp as u32 + params.min_time_till_end_sec + // using self.l1_batch_env.timestamp is ok here because the tracer is always + // used in a oneshot execution mode + if end.try_into().unwrap_or(U256::from(u64::MAX)).as_u64() + < self.l1_batch_env.timestamp + params.min_time_till_end_sec as u64 { return Err( ViolatedValidationRule::TimestampAssertionCloseToRangeEnd, @@ -122,8 +131,7 @@ impl ValidationTracer { { let mut traces_mut = self.traces.lock().unwrap(); - traces_mut - .apply_range((start.as_u64() as i64, end.as_u64() as i64)); + traces_mut.apply_range(start.as_u64()..end.as_u64()); } } } diff --git a/core/lib/protobuf_config/src/timestamp_asserter.rs b/core/lib/protobuf_config/src/timestamp_asserter.rs index 80e00c71a383..d2a8a9bf1b8a 100644 --- a/core/lib/protobuf_config/src/timestamp_asserter.rs +++ b/core/lib/protobuf_config/src/timestamp_asserter.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use zksync_config::configs::chain::TimestampAsserterConfig; use zksync_protobuf::{required, ProtoRepr}; @@ -5,8 +6,10 @@ impl ProtoRepr for crate::proto::config::timestamp_asserter::TimestampAsserter { type Type = TimestampAsserterConfig; fn read(&self) -> anyhow::Result { Ok(Self::Type { - min_range_sec: *required(&self.min_range_sec).unwrap_or(&0), - min_time_till_end_sec: *required(&self.min_time_till_end_sec).unwrap_or(&0), + min_range_sec: *required(&self.min_range_sec) + .context("timestamp_asserter_min_range_sec")?, + min_time_till_end_sec: *required(&self.min_time_till_end_sec) + .context("timestamp_asserter_min_time_till_end_sec")?, }) } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index f70111ea1797..320264f28f0a 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -5,7 +5,7 @@ #![allow(clippy::upper_case_acronyms, clippy::derive_partial_eq_without_eq)] -use std::fmt; +use std::{fmt, ops::Range}; use anyhow::Context as _; use fee::encoding_len; @@ -417,18 +417,7 @@ impl Transaction { } } -#[derive( - Clone, - Serialize, - Deserialize, - Debug, - Default, - Eq, - PartialEq, - Hash, - Copy -)] +#[derive(Clone, Serialize, Debug, Default, Eq, PartialEq, Hash)] pub struct TransactionTimeRangeConstraint { - /// Represents a range from-to. Each field is a number of seconds since the epoch. - pub timestamp_asserter_range: Option<(i64, i64)>, + pub timestamp_asserter_range: Option>, } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index e8363ff625ed..fd2cb38194a2 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -1,4 +1,4 @@ -use std::{cmp, collections::HashSet, fmt}; +use std::{collections::HashSet, fmt, ops::Range}; use zksync_types::{Address, U256}; @@ -133,17 +133,18 @@ pub enum ValidationError { /// be excluded from the mempool. #[derive(Debug, Clone, Default)] pub struct ValidationTraces { - /// Represents a range from-to. Each field is a number of seconds since the epoch. - pub timestamp_asserter_range: Option<(i64, i64)>, + pub timestamp_asserter_range: Option>, } impl ValidationTraces { - /// Merges two ranges together by taking the maximum of the starts and the minimum of the ends - /// resulting into the narrowest possible time window - pub fn apply_range(&mut self, new_range: (i64, i64)) { - if let Some(mut range) = self.timestamp_asserter_range { - range.0 = cmp::max(range.0, new_range.0); - range.1 = cmp::min(range.1, new_range.1); + /// Merges two ranges by selecting the maximum of the start values and the minimum of the end values, + /// producing the narrowest possible time window. Note that overlapping ranges are essential; + /// a lack of overlap would have triggered an assertion failure in the `TimestampAsserter` contract, + /// as `block.timestamp` cannot satisfy two non-overlapping ranges. + pub fn apply_range(&mut self, new_range: Range) { + if let Some(ref mut range) = self.timestamp_asserter_range.as_mut() { + range.start = range.start.max(new_range.start); + range.end = range.end.min(new_range.end); } else { self.timestamp_asserter_range = Some(new_range); } @@ -162,3 +163,45 @@ impl fmt::Display for ValidationError { } } } + +#[cfg(test)] +mod tests { + use std::ops::Range; + + use super::*; + + #[test] + fn test_apply_range_when_none() { + let mut validation_traces = ValidationTraces { + timestamp_asserter_range: None, + }; + let new_range = Range { start: 10, end: 20 }; + validation_traces.apply_range(new_range.clone()); + assert_eq!(validation_traces.timestamp_asserter_range, Some(new_range)); + } + + #[test] + fn test_apply_range_with_overlap_narrower_result() { + let mut validation_traces = ValidationTraces { + timestamp_asserter_range: Some(Range { start: 5, end: 25 }), + }; + validation_traces.apply_range(Range { start: 10, end: 20 }); + assert_eq!( + validation_traces.timestamp_asserter_range, + Some(Range { start: 10, end: 20 }) + ); + } + + #[test] + fn test_apply_range_with_partial_overlap() { + let mut validation_traces = ValidationTraces { + timestamp_asserter_range: Some(Range { start: 10, end: 30 }), + ..Default::default() + }; + validation_traces.apply_range(Range { start: 20, end: 40 }); + assert_eq!( + validation_traces.timestamp_asserter_range, + Some(Range { start: 20, end: 30 }) + ); + } +} diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 82cf5aa03dc4..8445902c3a7c 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -4,17 +4,14 @@ use std::sync::Arc; use anyhow::Context as _; use tokio::sync::RwLock; -use zksync_config::configs::{ - api::Web3JsonRpcConfig, - chain::{StateKeeperConfig, TimestampAsserterConfig}, -}; +use zksync_config::configs::{api::Web3JsonRpcConfig, chain::StateKeeperConfig}; use zksync_dal::{ transactions_dal::L2TxSubmissionResult, Connection, ConnectionPool, Core, CoreDal, }; use zksync_multivm::{ interface::{ - tracer::TimestampAsserterParams, OneshotTracingParams, TransactionExecutionMetrics, - VmExecutionResultAndLogs, + tracer::TimestampAsserterParams as TracerTimestampAsserterParams, OneshotTracingParams, + TransactionExecutionMetrics, VmExecutionResultAndLogs, }, utils::{derive_base_fee_and_gas_per_pubdata, get_max_batch_gas_limit}, }; @@ -211,13 +208,13 @@ impl TxSenderBuilder { executor_options, storage_caches, missed_storage_invocation_limit, - self.config - .timestamp_asserter_address - .map(|address| TimestampAsserterParams { - address, - min_range_sec: self.config.timestamp_asserter_min_range_sec, - min_time_till_end_sec: self.config.timestamp_asserter_min_time_till_end_sec, - }), + self.config.timestamp_asserter_params.clone().map(|params| { + TracerTimestampAsserterParams { + address: params.address, + min_range_sec: params.min_range_sec, + min_time_till_end_sec: params.min_time_till_end_sec, + } + }), ); TxSender(Arc::new(TxSenderInner { @@ -247,9 +244,14 @@ pub struct TxSenderConfig { pub validation_computational_gas_limit: u32, pub chain_id: L2ChainId, pub whitelisted_tokens_for_aa: Vec
, - pub timestamp_asserter_address: Option
, - pub timestamp_asserter_min_range_sec: u32, - pub timestamp_asserter_min_time_till_end_sec: u32, + pub timestamp_asserter_params: Option, +} + +#[derive(Debug, Clone)] +pub struct TimestampAsserterParams { + pub address: Address, + pub min_range_sec: u32, + pub min_time_till_end_sec: u32, } impl TxSenderConfig { @@ -258,8 +260,7 @@ impl TxSenderConfig { web3_json_config: &Web3JsonRpcConfig, fee_account_addr: Address, chain_id: L2ChainId, - timestamp_asserter_addr: Option
, - timestamp_asserter_config: TimestampAsserterConfig, + timestamp_asserter_params: Option, ) -> Self { Self { fee_account_addr, @@ -271,10 +272,7 @@ impl TxSenderConfig { .validation_computational_gas_limit, chain_id, whitelisted_tokens_for_aa: web3_json_config.whitelisted_tokens_for_aa.clone(), - timestamp_asserter_address: timestamp_asserter_addr, - timestamp_asserter_min_range_sec: timestamp_asserter_config.min_range_sec, - timestamp_asserter_min_time_till_end_sec: timestamp_asserter_config - .min_time_till_end_sec, + timestamp_asserter_params: timestamp_asserter_params, } } } @@ -377,20 +375,18 @@ impl TxSender { .await; stage_latency.observe(); - if let Err(err) = validation_result { - return Err(err.into()); - } if !execution_output.are_published_bytecodes_ok { return Err(SubmitTxError::FailedToPublishCompressedBytecodes); } - let mut stage_latency = SANDBOX_METRICS.start_tx_submit_stage(tx_hash, SubmitTxStage::DbInsert); self.ensure_tx_executable(&tx.clone().into(), &execution_output.metrics, true)?; + + let validation_traces = validation_result?; let submission_res_handle = self .0 .tx_sink - .submit_tx(&tx, execution_output.metrics, validation_result.unwrap()) + .submit_tx(&tx, execution_output.metrics, validation_traces) .await?; match submission_res_handle { diff --git a/core/node/api_server/src/tx_sender/tests/send_tx.rs b/core/node/api_server/src/tx_sender/tests/send_tx.rs index b08335a0f27e..1add528e0aad 100644 --- a/core/node/api_server/src/tx_sender/tests/send_tx.rs +++ b/core/node/api_server/src/tx_sender/tests/send_tx.rs @@ -344,7 +344,7 @@ async fn submitting_tx_with_validation_traces() { tx_executor.set_tx_validation_traces_responses(move |tx, _| { assert_eq!(tx.hash(), tx_hash); ValidationTraces { - timestamp_asserter_range: Some((10, 20)), + timestamp_asserter_range: Some(10..20), } }); diff --git a/core/node/api_server/src/web3/testonly.rs b/core/node/api_server/src/web3/testonly.rs index 57792cdd2387..540ea085711b 100644 --- a/core/node/api_server/src/web3/testonly.rs +++ b/core/node/api_server/src/web3/testonly.rs @@ -3,11 +3,7 @@ use std::{pin::Pin, time::Instant}; use tokio::sync::watch; -use zksync_config::configs::{ - api::Web3JsonRpcConfig, - chain::{StateKeeperConfig, TimestampAsserterConfig}, - wallets::Wallets, -}; +use zksync_config::configs::{api::Web3JsonRpcConfig, chain::StateKeeperConfig, wallets::Wallets}; use zksync_dal::ConnectionPool; use zksync_health_check::CheckHealth; use zksync_node_fee_model::MockBatchFeeParamsProvider; @@ -39,7 +35,6 @@ pub(crate) async fn create_test_tx_sender( wallets.state_keeper.unwrap().fee_account.address(), l2_chain_id, None, - TimestampAsserterConfig::default(), ); let storage_caches = PostgresStorageCaches::new(1, 1); diff --git a/core/node/state_keeper/Cargo.toml b/core/node/state_keeper/Cargo.toml index 1bb91a42382d..75d7c9f1e943 100644 --- a/core/node/state_keeper/Cargo.toml +++ b/core/node/state_keeper/Cargo.toml @@ -31,7 +31,6 @@ zksync_node_test_utils.workspace = true zksync_vm_executor.workspace = true zksync_system_constants.workspace = true zksync_base_token_adjuster.workspace = true -chrono = { workspace = true, features = ["serde"] } anyhow.workspace = true diff --git a/core/node/state_keeper/src/io/mempool.rs b/core/node/state_keeper/src/io/mempool.rs index 80eaf644952a..370d46fd544c 100644 --- a/core/node/state_keeper/src/io/mempool.rs +++ b/core/node/state_keeper/src/io/mempool.rs @@ -303,9 +303,9 @@ impl StateKeeperIO for MempoolIO { // Reject transactions that violate block.timestamp constraints. Such transactions should be // rejected at the API level, but we need to protect ourselves in case if a transaction // goes outside of the allowed range while being in the mempool - let matches_range = constraint.timestamp_asserter_range.map_or(true, |x| { - x.0 < l2_block_timestamp as i64 && x.1 > l2_block_timestamp as i64 - }); + let matches_range = constraint + .timestamp_asserter_range + .map_or(true, |x| x.contains(&l2_block_timestamp)); if !matches_range { self.reject( diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 145760b2e66a..d0c529ee9b69 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -701,35 +701,32 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen let system_time = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("Time went backwards") - .as_secs() as i64; + .as_secs(); // inserting 3 transactions - a good one, sandwiched in between two bad ones. The good one should // be returned by wait_for_next_tx, while two bad ones should be rejected. - #[allow(deprecated)] let rejected_tx_1 = tester.insert_tx( &mut guard, want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range: Some((system_time - 20000, system_time - 10000)), + timestamp_asserter_range: Some(system_time - 20000..system_time - 10000), }, ); - #[allow(deprecated)] let expected_tx = tester.insert_tx( &mut guard, want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range: Some((system_time - 1000, system_time + 1000)), + timestamp_asserter_range: Some(system_time - 1000..system_time + 1000), }, ); - #[allow(deprecated)] let rejected_tx_2 = tester.insert_tx( &mut guard, want_filter.fee_per_gas, want_filter.gas_per_pubdata, TransactionTimeRangeConstraint { - timestamp_asserter_range: Some((system_time + 10000, system_time + 20000)), + timestamp_asserter_range: Some(system_time + 10000..system_time + 20000), }, ); insert_l2_transaction(&mut storage, &rejected_tx_1).await; @@ -739,8 +736,8 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen let tx = mempool .wait_for_next_tx(Duration::from_secs(2), system_time as u64) .await - .expect("No expected transaction in the mempool") - .unwrap(); + .unwrap() + .expect("No expected transaction in the mempool"); assert_eq!(expected_tx.hash(), tx.hash()); let next_tx = mempool @@ -754,8 +751,8 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen .transactions_dal() .get_storage_tx_by_hash(rejected_tx_1.hash()) .await - .expect("Failed to find transaction") - .unwrap(); + .unwrap() + .expect("Failed to find transaction"); assert_eq!( "rejected: Transaction failed block.timestamp assertion", rejected_storage_tx_1.error.unwrap() @@ -765,8 +762,8 @@ async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmen .transactions_dal() .get_storage_tx_by_hash(rejected_tx_2.hash()) .await - .expect("Failed to find transaction") - .unwrap(); + .unwrap() + .expect("Failed to find transaction"); assert_eq!( "rejected: Transaction failed block.timestamp assertion", rejected_storage_tx_2.error.unwrap() diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 83107be8ea3f..479f6e8cb84f 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -166,6 +166,8 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise { throw new Error('CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR is not defined'); } const timestampAsserterAddress = process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR.toString(); + + const timestampAsserterMinRangeSec = parseInt(process.env.TIMESTAMP_ASSERTER_MIN_RANGE_SEC!); + + const timestampAsserterMinTimeTillEndSec = parseInt(process.env.TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC!); + return { maxLogsLimit, pathToHome, @@ -319,7 +328,9 @@ export async function loadTestEnvironmentFromEnv(): Promise { l1Address: baseToken?.address || token.address, l2Address: baseTokenAddressL2 }, - timestampAsserterAddress + timestampAsserterAddress, + timestampAsserterMinRangeSec, + timestampAsserterMinTimeTillEndSec }; } diff --git a/core/tests/ts-integration/src/types.ts b/core/tests/ts-integration/src/types.ts index 7df8f6337605..1c88a746db7b 100644 --- a/core/tests/ts-integration/src/types.ts +++ b/core/tests/ts-integration/src/types.ts @@ -95,6 +95,8 @@ export interface TestEnvironment { baseToken: Token; healthcheckPort: string; timestampAsserterAddress: string; + timestampAsserterMinRangeSec: number; + timestampAsserterMinTimeTillEndSec: number; } /** diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 81a5535e7915..439046abfc8d 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -20,6 +20,7 @@ const contracts = { const ETH_PER_CUSTOM_ACCOUNT = L2_DEFAULT_ETH_PER_ACCOUNT / 8n; const TRANSFER_AMOUNT = 1n; const DEFAULT_TIMESTAMP_ASSERTER_RANGE_START = 0; +// 2555971200 is a number of seconds up to 30/12/2050 const DEFAULT_TIMESTAMP_ASSERTER_RANGE_END = 2555971200; describe('Tests for the custom account behavior', () => { @@ -48,7 +49,6 @@ describe('Tests for the custom account behavior', () => { customAccount = await deployContract( alice, contracts.customAccount, - // 2555971200 is a number of seconds up to 30/12/2050 [ violateRules, timestampAsserterAddress, @@ -115,8 +115,9 @@ describe('Tests for the custom account behavior', () => { test('Should fail transaction validation due to timestamp assertion in the validation tracer - short time window', async () => { const now = Math.floor(Date.now() / 1000); - const rangeStart = now - 60; - const rangeEnd = now + 60; + const minRange = testMaster.environment().timestampAsserterMinRangeSec; + const rangeStart = now - minRange / 4; + const rangeEnd = now + minRange / 4; const customAccount = await deployAndFundCustomAccount( alice, @@ -141,8 +142,10 @@ describe('Tests for the custom account behavior', () => { test('Should fail transaction validation due to timestamp assertion in the validation tracer - close to the range end', async () => { const now = Math.floor(Date.now() / 1000); - const rangeStart = now - 600; - const rangeEnd = now + 30; + const minRange = testMaster.environment().timestampAsserterMinRangeSec; + const minTimeTillEnd = testMaster.environment().timestampAsserterMinTimeTillEndSec; + const rangeStart = now - minRange; + const rangeEnd = now + minTimeTillEnd / 2; const customAccount = await deployAndFundCustomAccount( alice, @@ -187,16 +190,15 @@ describe('Tests for the custom account behavior', () => { // requires custom assertion because the transaction would fail in "estimateFee" that is not handled correctly by zksync ethers promise .then((_) => { - fail('The transaction was expected to fail due to timestamp assertion'); + expect(null).fail('The transaction was expected to fail due to timestamp assertion'); }) .catch((error) => { - // If it's an error object with the structure you're mentioning, check its properties if (error.info && error.info.error && error.info.error.message) { expect(error.info.error.message).toEqual( 'failed to validate the transaction. reason: Timestamp is out of range' ); } else { - fail('The transaction was expected to fail with a different message'); + expect(null).fail('The transaction was expected to fail with a different message'); } }); }); From f20a68bc3e8ada17a01eab3020f9a6e6cf45e52d Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 14:52:57 +0000 Subject: [PATCH 49/68] lint --- core/lib/multivm/src/tracers/validator/vm_latest/mod.rs | 9 ++------- core/node/api_server/src/tx_sender/mod.rs | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 5ee27eb05808..7cb98796cf2d 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -1,5 +1,3 @@ -use std::u64; - use zk_evm_1_5_0::{ tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{ContextOpcode, FarCallABI, LogOpcode, Opcode}, @@ -111,17 +109,14 @@ impl ValidationTracer { let params = self.timestamp_asserter_params.as_ref().unwrap(); // end is guaranteed to be greater than the start as - let difference = (end - start) - .try_into() - .unwrap_or(U256::from(u32::MAX)) - .as_u32(); + let difference = (end - start).try_into().unwrap_or(u32::MAX); if difference < params.min_range_sec { return Err(ViolatedValidationRule::TimestampAssertionShortRange); } // using self.l1_batch_env.timestamp is ok here because the tracer is always // used in a oneshot execution mode - if end.try_into().unwrap_or(U256::from(u64::MAX)).as_u64() + if end.try_into().unwrap_or(u64::MAX) < self.l1_batch_env.timestamp + params.min_time_till_end_sec as u64 { return Err( diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 8445902c3a7c..fb574f9364fb 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -272,7 +272,7 @@ impl TxSenderConfig { .validation_computational_gas_limit, chain_id, whitelisted_tokens_for_aa: web3_json_config.whitelisted_tokens_for_aa.clone(), - timestamp_asserter_params: timestamp_asserter_params, + timestamp_asserter_params, } } } From 9dea6bd17c7fdabdcc5f1f0abf644dfc3b5e7c61 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 15:07:55 +0000 Subject: [PATCH 50/68] lint --- core/tests/ts-integration/tests/custom-account.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 439046abfc8d..645a547eee12 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -9,7 +9,6 @@ import * as ethers from 'ethers'; import { deployContract, getTestContract } from '../src/helpers'; import { ERC20_PER_ACCOUNT, L2_DEFAULT_ETH_PER_ACCOUNT } from '../src/context-owner'; import { shouldChangeETHBalances, shouldChangeTokenBalances } from '../src/modifiers/balance-checker'; -import { fail } from 'node:assert'; const contracts = { customAccount: getTestContract('CustomAccount'), From d4dcc4c4c576786d3b2bd62a9f525fc02116ba20 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 15:33:01 +0000 Subject: [PATCH 51/68] Fix integration tests --- core/tests/ts-integration/src/env.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 479f6e8cb84f..c541fdebea55 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -166,8 +166,8 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise Date: Tue, 29 Oct 2024 15:55:32 +0000 Subject: [PATCH 52/68] Fix integraiton test --- core/lib/multivm/src/tracers/validator/mod.rs | 2 +- core/tests/ts-integration/src/env.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index 9db15f738a98..e86f60138a38 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -172,7 +172,7 @@ impl ValidationTracer { } // Allow to read any storage slot from the timesttamp asserter contract - if self.timestamp_asserter_params.as_ref().map(|x| x.address) == Some(address) { + if self.timestamp_asserter_params.as_ref().map(|x| x.address) == Some(msg_sender) { return true; } diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index c541fdebea55..e7915305fb62 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -166,8 +166,8 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise Date: Tue, 29 Oct 2024 17:23:29 +0000 Subject: [PATCH 53/68] SWitch to protocol defence branch --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index b40b2d5f4fe3..72a3e8ec1b68 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit b40b2d5f4fe306ccc6d8ffa74b5d49c1e44ec0b8 +Subproject commit 72a3e8ec1b68e3632b0cd37c8589450f3cf4987b From 2d06dab16af83b17427a94d49a99709eca93d29d Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 18:32:49 +0000 Subject: [PATCH 54/68] Fix integration test --- core/node/api_server/src/tx_sender/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index fb574f9364fb..6eb6b481def5 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -375,6 +375,9 @@ impl TxSender { .await; stage_latency.observe(); + if let Err(err) = validation_result { + return Err(err.into()); + } if !execution_output.are_published_bytecodes_ok { return Err(SubmitTxError::FailedToPublishCompressedBytecodes); } From cbe0bbbc302c39b7a4431539b1089a1402229d74 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 19:38:02 +0000 Subject: [PATCH 55/68] Lint fix --- .../crates/zkstack/completion/_zkstack.zsh | 472 +++++++++--------- 1 file changed, 236 insertions(+), 236 deletions(-) diff --git a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh index 4df431754c84..f1cfc9946731 100644 --- a/zkstack_cli/crates/zkstack/completion/_zkstack.zsh +++ b/zkstack_cli/crates/zkstack/completion/_zkstack.zsh @@ -15,7 +15,7 @@ _zkstack() { local context curcontext="$curcontext" state line _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -37,7 +37,7 @@ _arguments "${_arguments_options[@]}" : \ '--generate=[The shell to generate the autocomplete script for]:GENERATOR:(bash elvish fish powershell zsh)' \ '-o+[The out directory to write the autocomplete script to]:OUT:_files' \ '--out=[The out directory to write the autocomplete script to]:OUT:_files' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -47,7 +47,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (ecosystem) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -65,11 +65,11 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (create) _arguments "${_arguments_options[@]}" : \ -'--ecosystem-name=[]:ECOSYSTEM_NAME: ' \ +'--ecosystem-name=[]:ECOSYSTEM_NAME:_default' \ '--l1-network=[L1 Network]:L1_NETWORK:(localhost sepolia holesky mainnet)' \ '--link-to-code=[Code link]:LINK_TO_CODE:_files -/' \ -'--chain-name=[]:CHAIN_NAME: ' \ -'--chain-id=[Chain ID]:CHAIN_ID: ' \ +'--chain-name=[]:CHAIN_NAME:_default' \ +'--chain-id=[Chain ID]:CHAIN_ID:_default' \ '--prover-mode=[Prover options]:PROVER_MODE:(no-proofs gpu)' \ '--wallet-creation=[Wallet options]:WALLET_CREATION:((localhost\:"Load wallets from localhost mnemonic, they are funded for localhost env" random\:"Generate random wallets" @@ -77,13 +77,13 @@ empty\:"Generate placeholder wallets" in-file\:"Specify file with wallets"))' \ '--wallet-path=[Wallet path]:WALLET_PATH:_files' \ '--l1-batch-commit-data-generator-mode=[Commit data generation mode]:L1_BATCH_COMMIT_DATA_GENERATOR_MODE:(rollup validium)' \ -'--base-token-address=[Base token address]:BASE_TOKEN_ADDRESS: ' \ -'--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR: ' \ -'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR: ' \ +'--base-token-address=[Base token address]:BASE_TOKEN_ADDRESS:_default' \ +'--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR:_default' \ +'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR:_default' \ '--set-as-default=[Set as default chain]' \ '--evm-emulator=[Enable EVM emulator]' \ '--start-containers=[Start reth and postgres containers after creation]' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--legacy-bridge[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -94,17 +94,17 @@ in-file\:"Specify file with wallets"))' \ ;; (build-transactions) _arguments "${_arguments_options[@]}" : \ -'--sender=[Address of the transaction sender]:SENDER: ' \ -'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL: ' \ +'--sender=[Address of the transaction sender]:SENDER:_default' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ '-o+[Output directory for the generated files]:OUT:_files' \ '--out=[Output directory for the generated files]:OUT:_files' \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -118,19 +118,19 @@ _arguments "${_arguments_options[@]}" : \ '--deploy-erc20=[Deploy ERC20 contracts]' \ '--deploy-ecosystem=[Deploy ecosystem contracts]' \ '--ecosystem-contracts-path=[Path to ecosystem contracts]:ECOSYSTEM_CONTRACTS_PATH:_files' \ -'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL: ' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ '--deploy-paymaster=[Deploy Paymaster contract]' \ -'--server-db-url=[Server database url without database name]:SERVER_DB_URL: ' \ -'--server-db-name=[Server database name]:SERVER_DB_NAME: ' \ +'--server-db-url=[Server database url without database name]:SERVER_DB_URL:_default' \ +'--server-db-name=[Server database name]:SERVER_DB_NAME:_default' \ '-o+[Enable Grafana]' \ '--observability=[Enable Grafana]' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-d[]' \ '--dont-drop[]' \ @@ -146,18 +146,18 @@ _arguments "${_arguments_options[@]}" : \ ;; (change-default-chain) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ '-h[Print help]' \ '--help[Print help]' \ -'::name:' \ +'::name:_default' \ && ret=0 ;; (setup-observability) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -211,7 +211,7 @@ esac ;; (chain) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -229,8 +229,8 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (create) _arguments "${_arguments_options[@]}" : \ -'--chain-name=[]:CHAIN_NAME: ' \ -'--chain-id=[Chain ID]:CHAIN_ID: ' \ +'--chain-name=[]:CHAIN_NAME:_default' \ +'--chain-id=[Chain ID]:CHAIN_ID:_default' \ '--prover-mode=[Prover options]:PROVER_MODE:(no-proofs gpu)' \ '--wallet-creation=[Wallet options]:WALLET_CREATION:((localhost\:"Load wallets from localhost mnemonic, they are funded for localhost env" random\:"Generate random wallets" @@ -238,12 +238,12 @@ empty\:"Generate placeholder wallets" in-file\:"Specify file with wallets"))' \ '--wallet-path=[Wallet path]:WALLET_PATH:_files' \ '--l1-batch-commit-data-generator-mode=[Commit data generation mode]:L1_BATCH_COMMIT_DATA_GENERATOR_MODE:(rollup validium)' \ -'--base-token-address=[Base token address]:BASE_TOKEN_ADDRESS: ' \ -'--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR: ' \ -'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR: ' \ +'--base-token-address=[Base token address]:BASE_TOKEN_ADDRESS:_default' \ +'--base-token-price-nominator=[Base token nominator]:BASE_TOKEN_PRICE_NOMINATOR:_default' \ +'--base-token-price-denominator=[Base token denominator]:BASE_TOKEN_PRICE_DENOMINATOR:_default' \ '--set-as-default=[Set as default chain]' \ '--evm-emulator=[Enable EVM emulator]' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--legacy-bridge[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -258,12 +258,12 @@ _arguments "${_arguments_options[@]}" : \ '--out=[Output directory for the generated files]:OUT:_files' \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -276,15 +276,15 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--server-db-url=[Server database url without database name]:SERVER_DB_URL: ' \ -'--server-db-name=[Server database name]:SERVER_DB_NAME: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--server-db-url=[Server database url without database name]:SERVER_DB_URL:_default' \ +'--server-db-name=[Server database name]:SERVER_DB_NAME:_default' \ '--deploy-paymaster=[]' \ -'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-d[]' \ '--dont-drop[]' \ @@ -307,10 +307,10 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (configs) _arguments "${_arguments_options[@]}" : \ -'--server-db-url=[Server database url without database name]:SERVER_DB_URL: ' \ -'--server-db-name=[Server database name]:SERVER_DB_NAME: ' \ -'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--server-db-url=[Server database url without database name]:SERVER_DB_URL:_default' \ +'--server-db-name=[Server database name]:SERVER_DB_NAME:_default' \ +'--l1-rpc-url=[L1 RPC URL]:L1_RPC_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-d[Use default database urls and names]' \ '--dev[Use default database urls and names]' \ '-d[]' \ @@ -353,9 +353,9 @@ esac ;; (genesis) _arguments "${_arguments_options[@]}" : \ -'--server-db-url=[Server database url without database name]:SERVER_DB_URL: ' \ -'--server-db-name=[Server database name]:SERVER_DB_NAME: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--server-db-url=[Server database url without database name]:SERVER_DB_URL:_default' \ +'--server-db-name=[Server database name]:SERVER_DB_NAME:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-d[Use default database urls and names]' \ '--dev[Use default database urls and names]' \ '-d[]' \ @@ -377,9 +377,9 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (init-database) _arguments "${_arguments_options[@]}" : \ -'--server-db-url=[Server database url without database name]:SERVER_DB_URL: ' \ -'--server-db-name=[Server database name]:SERVER_DB_NAME: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--server-db-url=[Server database url without database name]:SERVER_DB_URL:_default' \ +'--server-db-name=[Server database name]:SERVER_DB_NAME:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-d[Use default database urls and names]' \ '--dev[Use default database urls and names]' \ '-d[]' \ @@ -393,7 +393,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (server) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -437,11 +437,11 @@ esac _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -454,11 +454,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -471,11 +471,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -488,11 +488,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -505,11 +505,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -522,11 +522,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -539,11 +539,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -556,11 +556,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -573,11 +573,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--verify=[Verify deployed contracts]' \ '--verifier=[Verifier to use]:VERIFIER:(etherscan sourcify blockscout oklink)' \ -'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL: ' \ -'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY: ' \ -'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--verifier-url=[Verifier URL, if using a custom provider]:VERIFIER_URL:_default' \ +'--verifier-api-key=[Verifier API key]:VERIFIER_API_KEY:_default' \ +'*-a+[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[List of additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--resume[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -700,7 +700,7 @@ esac ;; (dev) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -718,7 +718,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (database) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -738,11 +738,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -754,11 +754,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -770,11 +770,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -785,8 +785,8 @@ _arguments "${_arguments_options[@]}" : \ (new-migration) _arguments "${_arguments_options[@]}" : \ '--database=[Database to create new migration for]:DATABASE:(prover core)' \ -'--name=[Migration name]:NAME: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--name=[Migration name]:NAME:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -798,11 +798,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -814,11 +814,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -830,11 +830,11 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '-p+[Prover database]' \ '--prover=[Prover database]' \ -'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL: ' \ +'--prover-url=[URL of the Prover database. If not specified, it is used from the current chain'\''s secrets]:PROVER_URL:_default' \ '-c+[Core database]' \ '--core=[Core database]' \ -'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--core-url=[URL of the Core database. If not specified, it is used from the current chain'\''s secrets.]:CORE_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -896,7 +896,7 @@ esac ;; (test) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -914,9 +914,9 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (integration) _arguments "${_arguments_options[@]}" : \ -'-t+[Run just the tests matching a pattern. Same as the -t flag on jest.]:TEST_PATTERN: ' \ -'--test-pattern=[Run just the tests matching a pattern. Same as the -t flag on jest.]:TEST_PATTERN: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'-t+[Run just the tests matching a pattern. Same as the -t flag on jest.]:TEST_PATTERN:_default' \ +'--test-pattern=[Run just the tests matching a pattern. Same as the -t flag on jest.]:TEST_PATTERN:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-e[Run tests for external node]' \ '--external-node[Run tests for external node]' \ '-n[Do not install or build dependencies]' \ @@ -930,7 +930,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (fees) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-n[Do not install or build dependencies]' \ '--no-deps[Do not install or build dependencies]' \ '--no-kill[The test will not kill all the nodes during execution]' \ @@ -943,7 +943,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (revert) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--enable-consensus[Enable consensus]' \ '-e[Run tests for external node]' \ '--external-node[Run tests for external node]' \ @@ -959,7 +959,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (recovery) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-s[Run recovery from a snapshot instead of genesis]' \ '--snapshot[Run recovery from a snapshot instead of genesis]' \ '-n[Do not install or build dependencies]' \ @@ -974,7 +974,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (upgrade) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-n[Do not install or build dependencies]' \ '--no-deps[Do not install or build dependencies]' \ '-v[Verbose mode]' \ @@ -986,7 +986,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (build) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -996,8 +996,8 @@ _arguments "${_arguments_options[@]}" : \ ;; (rust) _arguments "${_arguments_options[@]}" : \ -'--options=[Cargo test flags]:OPTIONS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--options=[Cargo test flags]:OPTIONS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1007,7 +1007,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (l1-contracts) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1017,7 +1017,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (prover) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1027,7 +1027,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (wallet) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1037,7 +1037,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (loadtest) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1115,7 +1115,7 @@ esac ;; (clean) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1133,7 +1133,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (all) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1143,7 +1143,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (containers) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1153,7 +1153,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (contracts-cache) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1199,7 +1199,7 @@ esac ;; (snapshot) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1217,7 +1217,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (create) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1257,7 +1257,7 @@ esac _arguments "${_arguments_options[@]}" : \ '*-t+[]:TARGETS:(md sol js ts rs contracts autocompletion)' \ '*--targets=[]:TARGETS:(md sol js ts rs contracts autocompletion)' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-c[]' \ '--check[]' \ '-v[Verbose mode]' \ @@ -1269,7 +1269,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (fmt) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-c[]' \ '--check[]' \ '-v[Verbose mode]' \ @@ -1289,7 +1289,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (rustfmt) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1299,7 +1299,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (contract) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1311,7 +1311,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*-t+[]:TARGETS:(md sol js ts rs contracts autocompletion)' \ '*--targets=[]:TARGETS:(md sol js ts rs contracts autocompletion)' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1357,7 +1357,7 @@ esac ;; (prover) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1375,7 +1375,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (info) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1385,9 +1385,9 @@ _arguments "${_arguments_options[@]}" : \ ;; (insert-batch) _arguments "${_arguments_options[@]}" : \ -'--number=[]:NUMBER: ' \ -'--version=[]:VERSION: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--number=[]:NUMBER:_default' \ +'--version=[]:VERSION:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--default[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -1398,9 +1398,9 @@ _arguments "${_arguments_options[@]}" : \ ;; (insert-version) _arguments "${_arguments_options[@]}" : \ -'--version=[]:VERSION: ' \ -'--snark-wrapper=[]:SNARK_WRAPPER: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--version=[]:VERSION:_default' \ +'--snark-wrapper=[]:SNARK_WRAPPER:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--default[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -1451,7 +1451,7 @@ _arguments "${_arguments_options[@]}" : \ '--l2-contracts=[Build L2 contracts]' \ '--system-contracts=[Build system contracts]' \ '--test-contracts=[Build test contracts]' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1461,9 +1461,9 @@ _arguments "${_arguments_options[@]}" : \ ;; (config-writer) _arguments "${_arguments_options[@]}" : \ -'-p+[Path to the config file to override]:PATH: ' \ -'--path=[Path to the config file to override]:PATH: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'-p+[Path to the config file to override]:PATH:_default' \ +'--path=[Path to the config file to override]:PATH:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1474,10 +1474,10 @@ _arguments "${_arguments_options[@]}" : \ (send-transactions) _arguments "${_arguments_options[@]}" : \ '--file=[]:FILE:_files' \ -'--private-key=[]:PRIVATE_KEY: ' \ -'--l1-rpc-url=[]:L1_RPC_URL: ' \ -'--confirmations=[]:CONFIRMATIONS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--private-key=[]:PRIVATE_KEY:_default' \ +'--l1-rpc-url=[]:L1_RPC_URL:_default' \ +'--confirmations=[]:CONFIRMATIONS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1487,9 +1487,9 @@ _arguments "${_arguments_options[@]}" : \ ;; (status) _arguments "${_arguments_options[@]}" : \ -'-u+[URL of the health check endpoint]:URL: ' \ -'--url=[URL of the health check endpoint]:URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'-u+[URL of the health check endpoint]:URL:_default' \ +'--url=[URL of the health check endpoint]:URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1507,7 +1507,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (ports) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1545,7 +1545,7 @@ esac ;; (generate-genesis) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1827,7 +1827,7 @@ esac ;; (prover) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1845,35 +1845,35 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (init) _arguments "${_arguments_options[@]}" : \ -'--proof-store-dir=[]:PROOF_STORE_DIR: ' \ -'--bucket-base-url=[]:BUCKET_BASE_URL: ' \ -'--credentials-file=[]:CREDENTIALS_FILE: ' \ -'--bucket-name=[]:BUCKET_NAME: ' \ -'--location=[]:LOCATION: ' \ -'--project-id=[]:PROJECT_ID: ' \ +'--proof-store-dir=[]:PROOF_STORE_DIR:_default' \ +'--bucket-base-url=[]:BUCKET_BASE_URL:_default' \ +'--credentials-file=[]:CREDENTIALS_FILE:_default' \ +'--bucket-name=[]:BUCKET_NAME:_default' \ +'--location=[]:LOCATION:_default' \ +'--project-id=[]:PROJECT_ID:_default' \ '--shall-save-to-public-bucket=[]:SHALL_SAVE_TO_PUBLIC_BUCKET:(true false)' \ -'--public-store-dir=[]:PUBLIC_STORE_DIR: ' \ -'--public-bucket-base-url=[]:PUBLIC_BUCKET_BASE_URL: ' \ -'--public-credentials-file=[]:PUBLIC_CREDENTIALS_FILE: ' \ -'--public-bucket-name=[]:PUBLIC_BUCKET_NAME: ' \ -'--public-location=[]:PUBLIC_LOCATION: ' \ -'--public-project-id=[]:PUBLIC_PROJECT_ID: ' \ -'(--clone)--bellman-cuda-dir=[]:BELLMAN_CUDA_DIR: ' \ +'--public-store-dir=[]:PUBLIC_STORE_DIR:_default' \ +'--public-bucket-base-url=[]:PUBLIC_BUCKET_BASE_URL:_default' \ +'--public-credentials-file=[]:PUBLIC_CREDENTIALS_FILE:_default' \ +'--public-bucket-name=[]:PUBLIC_BUCKET_NAME:_default' \ +'--public-location=[]:PUBLIC_LOCATION:_default' \ +'--public-project-id=[]:PUBLIC_PROJECT_ID:_default' \ +'(--clone)--bellman-cuda-dir=[]:BELLMAN_CUDA_DIR:_default' \ '--bellman-cuda=[]' \ '--setup-compressor-key=[]' \ -'--path=[]:PATH: ' \ +'--path=[]:PATH:_default' \ '--region=[]:REGION:(us europe asia)' \ '--mode=[]:MODE:(download generate)' \ '--setup-keys=[]' \ '--setup-database=[]:SETUP_DATABASE:(true false)' \ -'--prover-db-url=[Prover database url without database name]:PROVER_DB_URL: ' \ -'--prover-db-name=[Prover database name]:PROVER_DB_NAME: ' \ +'--prover-db-url=[Prover database url without database name]:PROVER_DB_URL:_default' \ +'--prover-db-name=[Prover database name]:PROVER_DB_NAME:_default' \ '-u+[Use default database urls and names]:USE_DEFAULT:(true false)' \ '--use-default=[Use default database urls and names]:USE_DEFAULT:(true false)' \ '-d+[]:DONT_DROP:(true false)' \ '--dont-drop=[]:DONT_DROP:(true false)' \ '--cloud-type=[]:CLOUD_TYPE:(gcp local)' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--dev[]' \ '(--bellman-cuda-dir)--clone[]' \ '-v[Verbose mode]' \ @@ -1887,7 +1887,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--region=[]:REGION:(us europe asia)' \ '--mode=[]:MODE:(download generate)' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1899,13 +1899,13 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--component=[]:COMPONENT:(gateway witness-generator witness-vector-generator prover circuit-prover compressor prover-job-monitor)' \ '--round=[]:ROUND:(all-rounds basic-circuits leaf-aggregation node-aggregation recursion-tip scheduler)' \ -'--threads=[]:THREADS: ' \ -'--max-allocation=[Memory allocation limit in bytes (for prover component)]:MAX_ALLOCATION: ' \ -'--witness-vector-generator-count=[]:WITNESS_VECTOR_GENERATOR_COUNT: ' \ -'--max-allocation=[]:MAX_ALLOCATION: ' \ +'--threads=[]:THREADS:_default' \ +'--max-allocation=[Memory allocation limit in bytes (for prover component)]:MAX_ALLOCATION:_default' \ +'--witness-vector-generator-count=[]:WITNESS_VECTOR_GENERATOR_COUNT:_default' \ +'--max-allocation=[]:MAX_ALLOCATION:_default' \ '--docker=[]:DOCKER:(true false)' \ -'--tag=[]:TAG: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--tag=[]:TAG:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1915,8 +1915,8 @@ _arguments "${_arguments_options[@]}" : \ ;; (init-bellman-cuda) _arguments "${_arguments_options[@]}" : \ -'(--clone)--bellman-cuda-dir=[]:BELLMAN_CUDA_DIR: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'(--clone)--bellman-cuda-dir=[]:BELLMAN_CUDA_DIR:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '(--bellman-cuda-dir)--clone[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -1927,8 +1927,8 @@ _arguments "${_arguments_options[@]}" : \ ;; (compressor-keys) _arguments "${_arguments_options[@]}" : \ -'--path=[]:PATH: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--path=[]:PATH:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -1982,10 +1982,10 @@ esac ;; (server) _arguments "${_arguments_options[@]}" : \ -'*--components=[Components of server to run]:COMPONENTS: ' \ -'*-a+[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'*--components=[Components of server to run]:COMPONENTS:_default' \ +'*-a+[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--genesis[Run server in genesis mode]' \ '--build[Build server but don'\''t run it]' \ '--uring[Enables uring support for RocksDB]' \ @@ -1998,7 +1998,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (external-node) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2016,10 +2016,10 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (configs) _arguments "${_arguments_options[@]}" : \ -'--db-url=[]:DB_URL: ' \ -'--db-name=[]:DB_NAME: ' \ -'--l1-rpc-url=[]:L1_RPC_URL: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--db-url=[]:DB_URL:_default' \ +'--db-name=[]:DB_NAME:_default' \ +'--l1-rpc-url=[]:L1_RPC_URL:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-u[Use default database urls and names]' \ '--use-default[Use default database urls and names]' \ '-v[Verbose mode]' \ @@ -2031,7 +2031,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (init) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2041,11 +2041,11 @@ _arguments "${_arguments_options[@]}" : \ ;; (run) _arguments "${_arguments_options[@]}" : \ -'*--components=[Components of server to run]:COMPONENTS: ' \ +'*--components=[Components of server to run]:COMPONENTS:_default' \ '--enable-consensus=[Enable consensus]' \ -'*-a+[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'*--additional-args=[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'*-a+[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'*--additional-args=[Additional arguments that can be passed through the CLI]:ADDITIONAL_ARGS:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--reinit[]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -2094,7 +2094,7 @@ esac _arguments "${_arguments_options[@]}" : \ '-o+[Enable Grafana]' \ '--observability=[Enable Grafana]' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2104,7 +2104,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (contract-verifier) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2122,7 +2122,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (run) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2132,12 +2132,12 @@ _arguments "${_arguments_options[@]}" : \ ;; (init) _arguments "${_arguments_options[@]}" : \ -'--zksolc-version=[Version of zksolc to install]:ZKSOLC_VERSION: ' \ -'--zkvyper-version=[Version of zkvyper to install]:ZKVYPER_VERSION: ' \ -'--solc-version=[Version of solc to install]:SOLC_VERSION: ' \ -'--era-vm-solc-version=[Version of era vm solc to install]:ERA_VM_SOLC_VERSION: ' \ -'--vyper-version=[Version of vyper to install]:VYPER_VERSION: ' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--zksolc-version=[Version of zksolc to install]:ZKSOLC_VERSION:_default' \ +'--zkvyper-version=[Version of zkvyper to install]:ZKVYPER_VERSION:_default' \ +'--solc-version=[Version of solc to install]:SOLC_VERSION:_default' \ +'--era-vm-solc-version=[Version of era vm solc to install]:ERA_VM_SOLC_VERSION:_default' \ +'--vyper-version=[Version of vyper to install]:VYPER_VERSION:_default' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--only[Install only provided compilers]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -2180,7 +2180,7 @@ esac ;; (portal) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2190,7 +2190,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (explorer) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2208,7 +2208,7 @@ _arguments "${_arguments_options[@]}" : \ case $line[1] in (init) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2218,7 +2218,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (run-backend) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2228,7 +2228,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (run) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2274,7 +2274,7 @@ esac ;; (consensus) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2293,7 +2293,7 @@ _arguments "${_arguments_options[@]}" : \ (set-attester-committee) _arguments "${_arguments_options[@]}" : \ '--from-file=[Sets the attester committee in the consensus registry contract to the committee in the yaml file. File format is definied in \`commands/consensus/proto/mod.proto\`]:FROM_FILE:_files' \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '--from-genesis[Sets the attester committee in the consensus registry contract to \`consensus.genesis_spec.attesters\` in general.yaml]' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ @@ -2304,7 +2304,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (get-attester-committee) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ @@ -2346,7 +2346,7 @@ esac ;; (update) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-c[Update only the config files]' \ '--only-config[Update only the config files]' \ '-v[Verbose mode]' \ @@ -2358,7 +2358,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (markdown) _arguments "${_arguments_options[@]}" : \ -'--chain=[Chain to use]:CHAIN: ' \ +'--chain=[Chain to use]:CHAIN:_default' \ '-v[Verbose mode]' \ '--verbose[Verbose mode]' \ '--ignore-prerequisites[Ignores prerequisites checks]' \ From 8ec0c3eff496e05bd35c52f973353c6498394ffb Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 20:08:33 +0000 Subject: [PATCH 56/68] Removed window range check --- core/bin/external_node/src/config/mod.rs | 17 ++--------- core/bin/external_node/src/config/tests.rs | 1 - core/bin/zksync_server/src/node_builder.rs | 1 - core/lib/config/src/configs/chain.rs | 2 -- core/lib/config/src/testonly.rs | 1 - core/lib/env_config/src/timestamp_asserter.rs | 2 -- .../src/tracers/validator/vm_latest/mod.rs | 7 ----- .../src/proto/config/timestamp_asserter.proto | 3 +- .../protobuf_config/src/timestamp_asserter.rs | 3 -- core/lib/vm_interface/src/types/tracer.rs | 7 ----- core/node/api_server/src/tx_sender/mod.rs | 2 -- core/tests/ts-integration/src/env.ts | 5 ---- core/tests/ts-integration/src/types.ts | 1 - .../tests/custom-account.test.ts | 30 +------------------ etc/env/file_based/general.yaml | 1 - 15 files changed, 4 insertions(+), 79 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 31017d359718..f221c9069c11 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -461,9 +461,6 @@ pub(crate) struct OptionalENConfig { pub gateway_url: Option, /// Interval for bridge addresses refreshing in seconds. bridge_addresses_refresh_interval_sec: Option, - /// Minimum difference in seconds between the range start and range end for TimestampAsserter - #[serde(default = "OptionalENConfig::default_timestamp_asserter_min_range_sec")] - pub timestamp_asserter_min_range_sec: u32, /// Minimum time between current block.timestamp and the end of the asserted range for TimestampAsserter #[serde(default = "OptionalENConfig::default_timestamp_asserter_min_time_till_end_sec")] pub timestamp_asserter_min_time_till_end_sec: u32, @@ -698,16 +695,11 @@ impl OptionalENConfig { contracts_diamond_proxy_addr: None, gateway_url: enconfig.gateway_url.clone(), bridge_addresses_refresh_interval_sec: enconfig.bridge_addresses_refresh_interval_sec, - timestamp_asserter_min_range_sec: general_config - .timestamp_asserter_config - .as_ref() - .map(|x| x.min_range_sec) - .unwrap_or(0), timestamp_asserter_min_time_till_end_sec: general_config .timestamp_asserter_config .as_ref() .map(|x| x.min_time_till_end_sec) - .unwrap_or(0), + .unwrap_or_else(Self::default_timestamp_asserter_min_time_till_end_sec), }) } @@ -842,12 +834,8 @@ impl OptionalENConfig { 3_600 * 24 * 7 // 7 days } - const fn default_timestamp_asserter_min_range_sec() -> u32 { - 10 * 60 - } - const fn default_timestamp_asserter_min_time_till_end_sec() -> u32 { - 2 * 60 + 60 } fn from_env() -> anyhow::Result { @@ -1482,7 +1470,6 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { timestamp_asserter_params: config.remote.l2_timestamp_asserter_addr.map(|address| { TimestampAsserterParams { address, - min_range_sec: config.optional.timestamp_asserter_min_range_sec, min_time_till_end_sec: config.optional.timestamp_asserter_min_time_till_end_sec, } }), diff --git a/core/bin/external_node/src/config/tests.rs b/core/bin/external_node/src/config/tests.rs index 34ca89637369..dc74d124b18e 100644 --- a/core/bin/external_node/src/config/tests.rs +++ b/core/bin/external_node/src/config/tests.rs @@ -128,7 +128,6 @@ fn parsing_optional_config_from_env() { "zks_getProof=100,eth_call=2", ), ("EN_L1_BATCH_COMMIT_DATA_GENERATOR_MODE", "Validium"), - ("EN_TIMESTAMP_ASSERTER_MIN_RANGE_SEC", "1"), ("EN_TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC", "2"), ]; let env_vars = env_vars diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 20ef6de9b49f..17519f77a1ad 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -327,7 +327,6 @@ impl MainNodeBuilder { .l2_timestamp_asserter_addr .map(|address| TimestampAsserterParams { address, - min_range_sec: timestamp_asserter_config.min_range_sec, min_time_till_end_sec: timestamp_asserter_config.min_time_till_end_sec, }), ), diff --git a/core/lib/config/src/configs/chain.rs b/core/lib/config/src/configs/chain.rs index a1ea47bddcf3..d73dce81b13a 100644 --- a/core/lib/config/src/configs/chain.rs +++ b/core/lib/config/src/configs/chain.rs @@ -247,8 +247,6 @@ impl MempoolConfig { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)] pub struct TimestampAsserterConfig { - /// Minimum difference in seconds between the range start and range end - pub min_range_sec: u32, /// Minimum time between current block.timestamp and the end of the asserted range pub min_time_till_end_sec: u32, } diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index b363d1220327..d5a9b2780323 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -1190,7 +1190,6 @@ impl Distribution for EncodeDist { impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> TimestampAsserterConfig { TimestampAsserterConfig { - min_range_sec: self.sample(rng), min_time_till_end_sec: self.sample(rng), } } diff --git a/core/lib/env_config/src/timestamp_asserter.rs b/core/lib/env_config/src/timestamp_asserter.rs index 3d22d89d9c82..df586f5925ee 100644 --- a/core/lib/env_config/src/timestamp_asserter.rs +++ b/core/lib/env_config/src/timestamp_asserter.rs @@ -19,7 +19,6 @@ mod tests { fn from_env_timestamp_asserter() { let mut lock = MUTEX.lock(); let config = r#" - TIMESTAMP_ASSERTER_MIN_RANGE_SEC=1 TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC=2 "#; lock.set_env(config); @@ -28,7 +27,6 @@ mod tests { assert_eq!( actual, TimestampAsserterConfig { - min_range_sec: 1, min_time_till_end_sec: 2, } ); diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 7cb98796cf2d..054a2b94af7b 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -105,15 +105,8 @@ impl ValidationTracer { &calldata[calldata.len() - 64..calldata.len() - 32], ); let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); - let params = self.timestamp_asserter_params.as_ref().unwrap(); - // end is guaranteed to be greater than the start as - let difference = (end - start).try_into().unwrap_or(u32::MAX); - if difference < params.min_range_sec { - return Err(ViolatedValidationRule::TimestampAssertionShortRange); - } - // using self.l1_batch_env.timestamp is ok here because the tracer is always // used in a oneshot execution mode if end.try_into().unwrap_or(u64::MAX) diff --git a/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto b/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto index 85b7590ca595..c8d0b9d1fec7 100644 --- a/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto +++ b/core/lib/protobuf_config/src/proto/config/timestamp_asserter.proto @@ -3,6 +3,5 @@ syntax = "proto3"; package zksync.config.timestamp_asserter; message TimestampAsserter { - optional uint32 min_range_sec = 1; // required; u32 - optional uint32 min_time_till_end_sec = 2; // required; u32 + optional uint32 min_time_till_end_sec = 1; // required; u32 } diff --git a/core/lib/protobuf_config/src/timestamp_asserter.rs b/core/lib/protobuf_config/src/timestamp_asserter.rs index d2a8a9bf1b8a..5984caff8c6f 100644 --- a/core/lib/protobuf_config/src/timestamp_asserter.rs +++ b/core/lib/protobuf_config/src/timestamp_asserter.rs @@ -6,8 +6,6 @@ impl ProtoRepr for crate::proto::config::timestamp_asserter::TimestampAsserter { type Type = TimestampAsserterConfig; fn read(&self) -> anyhow::Result { Ok(Self::Type { - min_range_sec: *required(&self.min_range_sec) - .context("timestamp_asserter_min_range_sec")?, min_time_till_end_sec: *required(&self.min_time_till_end_sec) .context("timestamp_asserter_min_time_till_end_sec")?, }) @@ -15,7 +13,6 @@ impl ProtoRepr for crate::proto::config::timestamp_asserter::TimestampAsserter { fn build(this: &Self::Type) -> Self { Self { - min_range_sec: Some(this.min_range_sec), min_time_till_end_sec: Some(this.min_time_till_end_sec), } } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index fd2cb38194a2..bc0a228d21cc 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -66,8 +66,6 @@ pub struct TimestampAsserterParams { /// Address of the timestamp asserter. This contract is allowed to touch block.timestamp regardless /// of the calling context. pub address: Address, - /// Minimum difference in seconds between the range start and range end - pub min_range_sec: u32, /// Minimum time between current block.timestamp and the end of the asserted range pub min_time_till_end_sec: u32, } @@ -83,8 +81,6 @@ pub enum ViolatedValidationRule { TouchedDisallowedContext, /// The transaction used too much gas during validation. TookTooManyComputationalGas(u32), - /// The transaction failed block.timestamp assertion because the range is too short - TimestampAssertionShortRange, /// The transaction failed block.timestamp assertion because the block.timestamp is too close to the range end TimestampAssertionCloseToRangeEnd, } @@ -108,9 +104,6 @@ impl fmt::Display for ViolatedValidationRule { "Took too many computational gas, allowed limit: {gas_limit}" ) } - ViolatedValidationRule::TimestampAssertionShortRange => { - write!(f, "block.timestamp range is too short") - } ViolatedValidationRule::TimestampAssertionCloseToRangeEnd => { write!(f, "block.timestamp is too close to the range end") } diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 6eb6b481def5..0e452e025218 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -211,7 +211,6 @@ impl TxSenderBuilder { self.config.timestamp_asserter_params.clone().map(|params| { TracerTimestampAsserterParams { address: params.address, - min_range_sec: params.min_range_sec, min_time_till_end_sec: params.min_time_till_end_sec, } }), @@ -250,7 +249,6 @@ pub struct TxSenderConfig { #[derive(Debug, Clone)] pub struct TimestampAsserterParams { pub address: Address, - pub min_range_sec: u32, pub min_time_till_end_sec: u32, } diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index e7915305fb62..d663fe6a5fed 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -166,7 +166,6 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise { } const timestampAsserterAddress = process.env.CONTRACTS_L2_TIMESTAMP_ASSERTER_ADDR.toString(); - const timestampAsserterMinRangeSec = parseInt(process.env.TIMESTAMP_ASSERTER_MIN_RANGE_SEC!); - const timestampAsserterMinTimeTillEndSec = parseInt(process.env.TIMESTAMP_ASSERTER_MIN_TIME_TILL_END_SEC!); return { @@ -329,7 +325,6 @@ export async function loadTestEnvironmentFromEnv(): Promise { l2Address: baseTokenAddressL2 }, timestampAsserterAddress, - timestampAsserterMinRangeSec, timestampAsserterMinTimeTillEndSec }; } diff --git a/core/tests/ts-integration/src/types.ts b/core/tests/ts-integration/src/types.ts index 1c88a746db7b..014031a3dd7e 100644 --- a/core/tests/ts-integration/src/types.ts +++ b/core/tests/ts-integration/src/types.ts @@ -95,7 +95,6 @@ export interface TestEnvironment { baseToken: Token; healthcheckPort: string; timestampAsserterAddress: string; - timestampAsserterMinRangeSec: number; timestampAsserterMinTimeTillEndSec: number; } diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 645a547eee12..daf43617826d 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -112,38 +112,10 @@ describe('Tests for the custom account behavior', () => { ).toBeAccepted([erc20BalanceChange, feeCheck]); }); - test('Should fail transaction validation due to timestamp assertion in the validation tracer - short time window', async () => { - const now = Math.floor(Date.now() / 1000); - const minRange = testMaster.environment().timestampAsserterMinRangeSec; - const rangeStart = now - minRange / 4; - const rangeEnd = now + minRange / 4; - - const customAccount = await deployAndFundCustomAccount( - alice, - erc20Address, - timestampAsserterAddress, - rangeStart, - rangeEnd - ); - - const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); - await expect( - sendCustomAccountTransaction( - tx as zksync.types.Transaction, - alice.provider, - await customAccount.getAddress(), - testMaster.environment().l2ChainId - ) - ).toBeRejected( - 'failed to validate the transaction. reason: Violated validation rules: block.timestamp range is too short' - ); - }); - test('Should fail transaction validation due to timestamp assertion in the validation tracer - close to the range end', async () => { const now = Math.floor(Date.now() / 1000); - const minRange = testMaster.environment().timestampAsserterMinRangeSec; const minTimeTillEnd = testMaster.environment().timestampAsserterMinTimeTillEndSec; - const rangeStart = now - minRange; + const rangeStart = now - 10; const rangeEnd = now + minTimeTillEnd / 2; const customAccount = await deployAndFundCustomAccount( diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 89c3817dc58b..1f13cebea290 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -378,7 +378,6 @@ external_proof_integration_api: http_port: 3073 timestamp_asserter: - min_range_sec: 300 min_time_till_end_sec: 60 consensus: From acd55a62529ee8dee024136945437e9c427ebef1 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 21:20:06 +0000 Subject: [PATCH 57/68] Review feedback --- .../lib/dal/src/models/storage_transaction.rs | 26 +++----- core/lib/multivm/src/tracers/validator/mod.rs | 62 +++++++++---------- core/lib/vm_executor/src/oneshot/mod.rs | 13 ++-- core/lib/vm_interface/src/types/tracer.rs | 24 +++---- core/node/state_keeper/src/io/tests/mod.rs | 6 +- core/node/state_keeper/src/mempool_actor.rs | 5 +- 6 files changed, 55 insertions(+), 81 deletions(-) diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 8b9442084ed9..f6f9742b0d74 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -1,4 +1,4 @@ -use std::{convert::TryInto, str::FromStr}; +use std::{convert::TryInto, ops::Range, str::FromStr}; use bigdecimal::Zero; use serde_json::Value; @@ -326,24 +326,12 @@ impl From for Transaction { impl From<&StorageTransaction> for TransactionTimeRangeConstraint { fn from(tx: &StorageTransaction) -> Self { - if tx.timestamp_asserter_range_start.is_some() && tx.timestamp_asserter_range_end.is_some() - { - Self { - timestamp_asserter_range: Some( - tx.timestamp_asserter_range_start - .unwrap() - .and_utc() - .timestamp() as u64 - ..tx.timestamp_asserter_range_end - .unwrap() - .and_utc() - .timestamp() as u64, - ), - } - } else { - Self { - timestamp_asserter_range: None, - } + Self { + timestamp_asserter_range: tx.timestamp_asserter_range_start.and_then(|start| { + tx.timestamp_asserter_range_end.map(|end| { + (start.and_utc().timestamp() as u64)..(end.and_utc().timestamp() as u64) + }) + }), } } } diff --git a/core/lib/multivm/src/tracers/validator/mod.rs b/core/lib/multivm/src/tracers/validator/mod.rs index e86f60138a38..a095be9f3748 100644 --- a/core/lib/multivm/src/tracers/validator/mod.rs +++ b/core/lib/multivm/src/tracers/validator/mod.rs @@ -64,40 +64,34 @@ type ValidationRoundResult = Result ValidationTracer { const MAX_ALLOWED_SLOT_OFFSET: u32 = 127; - pub fn new( - params: ValidationParams, - vm_version: VmVersion, - l1_batch_env: L1BatchEnv, - ) -> ( - Self, - Arc>, - Arc>, - ) { - let result = Arc::new(OnceCell::new()); - let traces = Arc::new(Mutex::new(ValidationTraces::default())); - ( - Self { - validation_mode: ValidationTracerMode::NoValidation, - auxilary_allowed_slots: Default::default(), - - should_stop_execution: false, - user_address: params.user_address, - paymaster_address: params.paymaster_address, - trusted_slots: params.trusted_slots, - trusted_addresses: params.trusted_addresses, - trusted_address_slots: params.trusted_address_slots, - computational_gas_used: 0, - computational_gas_limit: params.computational_gas_limit, - timestamp_asserter_params: params.timestamp_asserter_params.clone(), - vm_version, - result: result.clone(), - traces: traces.clone(), - _marker: Default::default(), - l1_batch_env, - }, - result, - traces, - ) + pub fn new(params: ValidationParams, vm_version: VmVersion, l1_batch_env: L1BatchEnv) -> Self { + Self { + validation_mode: ValidationTracerMode::NoValidation, + auxilary_allowed_slots: Default::default(), + + should_stop_execution: false, + user_address: params.user_address, + paymaster_address: params.paymaster_address, + trusted_slots: params.trusted_slots, + trusted_addresses: params.trusted_addresses, + trusted_address_slots: params.trusted_address_slots, + computational_gas_used: 0, + computational_gas_limit: params.computational_gas_limit, + timestamp_asserter_params: params.timestamp_asserter_params.clone(), + vm_version, + result: Arc::new(OnceCell::new()), + traces: Arc::new(Mutex::new(ValidationTraces::default())), + _marker: Default::default(), + l1_batch_env, + } + } + + pub fn get_result(&self) -> Arc> { + self.result.clone() + } + + pub fn get_traces(&self) -> Arc> { + self.traces.clone() } fn process_validation_round_result(&mut self, result: ValidationRoundResult) { diff --git a/core/lib/vm_executor/src/oneshot/mod.rs b/core/lib/vm_executor/src/oneshot/mod.rs index 5070f302343e..7d45dcca8cd3 100644 --- a/core/lib/vm_executor/src/oneshot/mod.rs +++ b/core/lib/vm_executor/src/oneshot/mod.rs @@ -189,12 +189,13 @@ where }; tokio::task::spawn_blocking(move || { - let (validation_tracer, mut validation_result, validation_traces) = - ValidationTracer::::new( - validation_params, - sandbox.env.system.version.into(), - l1_batch_env, - ); + let validation_tracer = ValidationTracer::::new( + validation_params, + sandbox.env.system.version.into(), + l1_batch_env, + ); + let mut validation_result = validation_tracer.get_result(); + let validation_traces = validation_tracer.get_traces(); let tracers = vec![validation_tracer.into_tracer_pointer()]; let exec_result = sandbox.execute_in_vm(|vm, transaction| { diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index bc0a228d21cc..083803f08c35 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -135,7 +135,7 @@ impl ValidationTraces { /// a lack of overlap would have triggered an assertion failure in the `TimestampAsserter` contract, /// as `block.timestamp` cannot satisfy two non-overlapping ranges. pub fn apply_range(&mut self, new_range: Range) { - if let Some(ref mut range) = self.timestamp_asserter_range.as_mut() { + if let Some(range) = &mut self.timestamp_asserter_range { range.start = range.start.max(new_range.start); range.end = range.end.min(new_range.end); } else { @@ -159,8 +159,6 @@ impl fmt::Display for ValidationError { #[cfg(test)] mod tests { - use std::ops::Range; - use super::*; #[test] @@ -168,7 +166,7 @@ mod tests { let mut validation_traces = ValidationTraces { timestamp_asserter_range: None, }; - let new_range = Range { start: 10, end: 20 }; + let new_range = 10..20; validation_traces.apply_range(new_range.clone()); assert_eq!(validation_traces.timestamp_asserter_range, Some(new_range)); } @@ -176,25 +174,19 @@ mod tests { #[test] fn test_apply_range_with_overlap_narrower_result() { let mut validation_traces = ValidationTraces { - timestamp_asserter_range: Some(Range { start: 5, end: 25 }), + timestamp_asserter_range: Some(5..25), }; - validation_traces.apply_range(Range { start: 10, end: 20 }); - assert_eq!( - validation_traces.timestamp_asserter_range, - Some(Range { start: 10, end: 20 }) - ); + validation_traces.apply_range(10..20); + assert_eq!(validation_traces.timestamp_asserter_range, Some(10..20)); } #[test] fn test_apply_range_with_partial_overlap() { let mut validation_traces = ValidationTraces { - timestamp_asserter_range: Some(Range { start: 10, end: 30 }), + timestamp_asserter_range: Some(10..30), ..Default::default() }; - validation_traces.apply_range(Range { start: 20, end: 40 }); - assert_eq!( - validation_traces.timestamp_asserter_range, - Some(Range { start: 20, end: 30 }) - ); + validation_traces.apply_range(20..40); + assert_eq!(validation_traces.timestamp_asserter_range, Some(20..30)); } } diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index d0c529ee9b69..101809e0f075 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -667,11 +667,11 @@ async fn insert_unsealed_batch_on_init(commitment_mode: L1BatchCommitmentMode) { assert_eq!(l1_batch_params.first_l2_block.timestamp, 2); } -#[test_casing(2, COMMITMENT_MODES)] #[tokio::test] -async fn test_mempool_with_timestamp_assertion(commitment_mode: L1BatchCommitmentMode) { +async fn test_mempool_with_timestamp_assertion() { let connection_pool = ConnectionPool::::constrained_test_pool(2).await; - let tester = Tester::new(commitment_mode); + // what commitment mode to use is irrelevant here + let tester = Tester::new(L1BatchCommitmentMode::Rollup); let mut storage = connection_pool.connection().await.unwrap(); tester.genesis(&connection_pool).await; diff --git a/core/node/state_keeper/src/mempool_actor.rs b/core/node/state_keeper/src/mempool_actor.rs index ab764117b039..8e9d674f8787 100644 --- a/core/node/state_keeper/src/mempool_actor.rs +++ b/core/node/state_keeper/src/mempool_actor.rs @@ -1,7 +1,6 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; use anyhow::Context as _; -use itertools::Itertools; #[cfg(test)] use tokio::sync::mpsc; use tokio::sync::watch; @@ -124,10 +123,10 @@ impl MempoolFetcher { .await .context("failed syncing mempool")?; - let transactions = transactions_with_constraints + let transactions: Vec<_> = transactions_with_constraints .iter() .map(|(t, _c)| t) - .collect_vec(); + .collect(); let nonces = get_transaction_nonces(&mut storage, &transactions).await?; drop(storage); From 56ea9153efced4f51130a6ea06b8127b80b60504 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 21:26:30 +0000 Subject: [PATCH 58/68] lint fix --- core/lib/dal/src/models/storage_transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index f6f9742b0d74..459a3ec0c0fb 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -1,4 +1,4 @@ -use std::{convert::TryInto, ops::Range, str::FromStr}; +use std::{convert::TryInto, str::FromStr}; use bigdecimal::Zero; use serde_json::Value; From 14b506d9bd65a49aee72c21b1836369bac9649bc Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 22:30:24 +0000 Subject: [PATCH 59/68] add test for range overflow --- core/bin/external_node/src/config/mod.rs | 4 +- core/bin/zksync_server/src/node_builder.rs | 6 +- .../src/tracers/validator/vm_latest/mod.rs | 70 ++++++++++--------- core/lib/vm_interface/src/types/tracer.rs | 5 +- core/node/api_server/src/tx_sender/mod.rs | 6 +- core/node/state_keeper/src/io/tests/mod.rs | 6 +- .../tests/custom-account.test.ts | 40 ++++++++++- 7 files changed, 92 insertions(+), 45 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index f221c9069c11..9bf8141294fa 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1470,7 +1470,9 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { timestamp_asserter_params: config.remote.l2_timestamp_asserter_addr.map(|address| { TimestampAsserterParams { address, - min_time_till_end_sec: config.optional.timestamp_asserter_min_time_till_end_sec, + min_time_till_end: Duration::from_secs( + config.optional.timestamp_asserter_min_time_till_end_sec as u64, + ), } }), } diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 17519f77a1ad..ac03e9b7f282 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -1,6 +1,8 @@ //! This module provides a "builder" for the main node, //! as well as an interface to run the node with the specified components. +use std::time::Duration; + use anyhow::{bail, Context}; use zksync_config::{ configs::{ @@ -327,7 +329,9 @@ impl MainNodeBuilder { .l2_timestamp_asserter_addr .map(|address| TimestampAsserterParams { address, - min_time_till_end_sec: timestamp_asserter_config.min_time_till_end_sec, + min_time_till_end: Duration::from_secs( + timestamp_asserter_config.min_time_till_end_sec as u64, + ), }), ), postgres_storage_caches_config, diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index 054a2b94af7b..e5ee3794dee6 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -86,40 +86,46 @@ impl ValidationTracer { // If this is a call to the timestamp asserter, extract the function arguments and store them in ValidationTraces. // These arguments are used by the mempool for transaction filtering. The call data length should be 68 bytes: // a 4-byte function selector followed by two U256 values. - let address = self.timestamp_asserter_params.as_ref().map(|x| x.address); - if Some(called_address) == address - && far_call_abi.memory_quasi_fat_pointer.length == 68 - { - let calldata_page = get_calldata_page_via_abi( - &far_call_abi, - state.vm_local_state.callstack.current.base_memory_page, - ); - let calldata = memory.read_unaligned_bytes( - calldata_page as usize, - far_call_abi.memory_quasi_fat_pointer.start as usize, - 68, - ); - - if calldata[..4] == TIMESTAMP_ASSERTER_FUNCTION_SELECTOR { - let start = U256::from_big_endian( - &calldata[calldata.len() - 64..calldata.len() - 32], + if let Some(params) = &self.timestamp_asserter_params { + if called_address == params.address + && far_call_abi.memory_quasi_fat_pointer.length == 68 + { + let calldata_page = get_calldata_page_via_abi( + &far_call_abi, + state.vm_local_state.callstack.current.base_memory_page, + ); + let calldata = memory.read_unaligned_bytes( + calldata_page as usize, + far_call_abi.memory_quasi_fat_pointer.start as usize, + 68, ); - let end = U256::from_big_endian(&calldata[calldata.len() - 32..]); - let params = self.timestamp_asserter_params.as_ref().unwrap(); - - // using self.l1_batch_env.timestamp is ok here because the tracer is always - // used in a oneshot execution mode - if end.try_into().unwrap_or(u64::MAX) - < self.l1_batch_env.timestamp + params.min_time_till_end_sec as u64 - { - return Err( - ViolatedValidationRule::TimestampAssertionCloseToRangeEnd, - ); - } - { - let mut traces_mut = self.traces.lock().unwrap(); - traces_mut.apply_range(start.as_u64()..end.as_u64()); + if calldata[..4] == TIMESTAMP_ASSERTER_FUNCTION_SELECTOR { + // start and end need to be capped to u64::MAX to avoid overflow + let start = U256::from_big_endian( + &calldata[calldata.len() - 64..calldata.len() - 32], + ) + .try_into() + .unwrap_or(u64::MAX); + let end = U256::from_big_endian(&calldata[calldata.len() - 32..]) + .try_into() + .unwrap_or(u64::MAX); + + // using self.l1_batch_env.timestamp is ok here because the tracer is always + // used in a oneshot execution mode + if end + < self.l1_batch_env.timestamp + + params.min_time_till_end.as_secs() + { + return Err( + ViolatedValidationRule::TimestampAssertionCloseToRangeEnd, + ); + } + + { + let mut traces_mut = self.traces.lock().unwrap(); + traces_mut.apply_range(start..end); + } } } } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index 083803f08c35..bddf4bffb9ea 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, fmt, ops::Range}; +use std::{collections::HashSet, fmt, ops::Range, time}; use zksync_types::{Address, U256}; @@ -67,7 +67,7 @@ pub struct TimestampAsserterParams { /// of the calling context. pub address: Address, /// Minimum time between current block.timestamp and the end of the asserted range - pub min_time_till_end_sec: u32, + pub min_time_till_end: time::Duration, } /// Rules that can be violated when validating a transaction. @@ -184,7 +184,6 @@ mod tests { fn test_apply_range_with_partial_overlap() { let mut validation_traces = ValidationTraces { timestamp_asserter_range: Some(10..30), - ..Default::default() }; validation_traces.apply_range(20..40); assert_eq!(validation_traces.timestamp_asserter_range, Some(20..30)); diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 0e452e025218..011d9e4e2b2f 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -1,6 +1,6 @@ //! Helper module to submit transactions into the ZKsync Network. -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use anyhow::Context as _; use tokio::sync::RwLock; @@ -211,7 +211,7 @@ impl TxSenderBuilder { self.config.timestamp_asserter_params.clone().map(|params| { TracerTimestampAsserterParams { address: params.address, - min_time_till_end_sec: params.min_time_till_end_sec, + min_time_till_end: params.min_time_till_end, } }), ); @@ -249,7 +249,7 @@ pub struct TxSenderConfig { #[derive(Debug, Clone)] pub struct TimestampAsserterParams { pub address: Address, - pub min_time_till_end_sec: u32, + pub min_time_till_end: Duration, } impl TxSenderConfig { diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 101809e0f075..adef238fe928 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -734,14 +734,14 @@ async fn test_mempool_with_timestamp_assertion() { insert_l2_transaction(&mut storage, &rejected_tx_2).await; let tx = mempool - .wait_for_next_tx(Duration::from_secs(2), system_time as u64) + .wait_for_next_tx(Duration::from_secs(2), system_time) .await .unwrap() .expect("No expected transaction in the mempool"); assert_eq!(expected_tx.hash(), tx.hash()); let next_tx = mempool - .wait_for_next_tx(Duration::from_secs(2), system_time as u64) + .wait_for_next_tx(Duration::from_secs(2), system_time) .await .expect("Should be no more transactions in the mempool"); assert!(next_tx.is_none()); @@ -774,7 +774,7 @@ async fn insert_l2_transaction(storage: &mut Connection<'_, Core>, tx: &L2Tx) { storage .transactions_dal() .insert_transaction_l2( - &tx, + tx, TransactionExecutionMetrics::default(), ValidationTraces::default(), ) diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index daf43617826d..4ec9c7e19a9e 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -140,6 +140,42 @@ describe('Tests for the custom account behavior', () => { ); }); + test('Should execute contract by custom account when timestamp asserter range end overflows', async () => { + // This test ensures that a custom account transaction completes successfully + // even when the timestamp asserter's range end exceeds `u64::MAX`. In such cases, + // the range is capped at `u64::MAX` and processed as expected. + const customAccount = await deployAndFundCustomAccount( + alice, + erc20Address, + timestampAsserterAddress, + 0, + BigInt('3402823669209384634633746074317682') // u128::MAX + ); + + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); + const customAccountAddress = await customAccount.getAddress(); + const erc20BalanceChange = await shouldChangeTokenBalances(erc20Address, [ + { + addressToCheck: customAccountAddress, + wallet: alice, + change: -TRANSFER_AMOUNT + }, + { wallet: alice, change: TRANSFER_AMOUNT } + ]); + const feeCheck = await shouldChangeETHBalances([ + { addressToCheck: customAccountAddress, wallet: alice, change: 0n } + ]); + + await expect( + sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + await customAccount.getAddress(), + testMaster.environment().l2ChainId + ) + ).toBeAccepted([erc20BalanceChange, feeCheck]); + }); + test('Should fail to estimate fee due to block.timestamp assertion in the smart contract', async () => { const now = Math.floor(Date.now() / 1000); const rangeStart = now + 300; @@ -459,8 +495,8 @@ async function deployAndFundCustomAccount( richAccount: zksync.Wallet, erc20Address: string, timestampAsserterAddress: string, - rangeStart: number, - rangeEnd: number + rangeStart: any, + rangeEnd: any ): Promise { const customAccount = await deployContract( richAccount, From 5fa2f063f056965b2b0cb2409ccb9c8d5518e878 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Tue, 29 Oct 2024 23:24:42 +0000 Subject: [PATCH 60/68] Update integration test --- .../tests/custom-account.test.ts | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 4ec9c7e19a9e..d9128598e8da 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -188,26 +188,23 @@ describe('Tests for the custom account behavior', () => { rangeStart, rangeEnd ); + const customAccountAddress = await customAccount.getAddress(); - const promise = alice.provider.estimateGas({ - ...(await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT)), - from: await customAccount.getAddress() - }); + const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); - // requires custom assertion because the transaction would fail in "estimateFee" that is not handled correctly by zksync ethers - promise - .then((_) => { - expect(null).fail('The transaction was expected to fail due to timestamp assertion'); - }) - .catch((error) => { - if (error.info && error.info.error && error.info.error.message) { - expect(error.info.error.message).toEqual( - 'failed to validate the transaction. reason: Timestamp is out of range' - ); - } else { - expect(null).fail('The transaction was expected to fail with a different message'); - } - }); + await expect( + sendCustomAccountTransaction( + tx as zksync.types.Transaction, + alice.provider, + customAccountAddress, + testMaster.environment().l2ChainId, + undefined, + undefined, + false + ) + ).toBeRejected( + 'failed to validate the transaction. reason: Validation revert: Account validation error: Timestamp is out of range' + ); }); test('Should fail the validation with incorrect signature', async () => { @@ -461,12 +458,11 @@ async function sendCustomAccountTransaction( accountAddress: string, chainId: bigint, customSignature?: Uint8Array, - nonce?: number + nonce?: number, + estimateGas: boolean = true ) { - const gasLimit = await browserProvider.estimateGas({ - ...tx, - from: accountAddress - }); + const gasLimit = estimateGas ? await browserProvider.estimateGas({ ...tx, from: accountAddress }) : BigInt(100_000); // Enough gas to invoke AA contract + const gasPrice = await browserProvider.getGasPrice(); tx.gasLimit = gasLimit; From 53e9ec8cc1bdef85903a9d59ffe0f92a5cd6a422 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 09:33:55 +0000 Subject: [PATCH 61/68] Updated contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 72a3e8ec1b68..26bcdbed3c10 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 72a3e8ec1b68e3632b0cd37c8589450f3cf4987b +Subproject commit 26bcdbed3c1077f1e55dd3ccbb2ac7e12479b724 From 125ff973fccce9c1cec527b3ba68c72992e7ed47 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 09:36:59 +0000 Subject: [PATCH 62/68] Updated contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 26bcdbed3c10..9f3f710d67d6 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 26bcdbed3c1077f1e55dd3ccbb2ac7e12479b724 +Subproject commit 9f3f710d67d6dd759a303b9f716c8e20dc2800c5 From bd954a36f140332d91bce09c3a677f285c06d4c9 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 12:08:35 +0000 Subject: [PATCH 63/68] Update to the last contracts --- contracts | 2 +- core/bin/zksync_server/src/node_builder.rs | 24 ++++++++----- core/lib/dal/src/transactions_dal.rs | 17 +++++----- .../api_server/src/tx_sender/tests/send_tx.rs | 27 ++++++++++++--- .../tests/custom-account.test.ts | 34 +++++++++++++++---- 5 files changed, 75 insertions(+), 29 deletions(-) diff --git a/contracts b/contracts index 9f3f710d67d6..9fb1264fce8c 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 9f3f710d67d6dd759a303b9f716c8e20dc2800c5 +Subproject commit 9fb1264fce8c0ebeefe8bf1846e89876027161d2 diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index ac03e9b7f282..4a903bd9d502 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -305,7 +305,20 @@ impl MainNodeBuilder { fn add_tx_sender_layer(mut self) -> anyhow::Result { let sk_config = try_load_config!(self.configs.state_keeper_config); let rpc_config = try_load_config!(self.configs.api_config).web3_json_rpc; - let timestamp_asserter_config = try_load_config!(self.configs.timestamp_asserter_config); + + let timestamp_asserter_params = match self.contracts_config.l2_timestamp_asserter_addr { + Some(address) => { + let timestamp_asserter_config = + try_load_config!(self.configs.timestamp_asserter_config); + Some(TimestampAsserterParams { + address, + min_time_till_end: Duration::from_secs( + timestamp_asserter_config.min_time_till_end_sec as u64, + ), + }) + } + None => None, + }; let postgres_storage_caches_config = PostgresStorageCachesConfig { factory_deps_cache_size: rpc_config.factory_deps_cache_size() as u64, initial_writes_cache_size: rpc_config.initial_writes_cache_size() as u64, @@ -325,14 +338,7 @@ impl MainNodeBuilder { .fee_account .address(), self.genesis_config.l2_chain_id, - self.contracts_config - .l2_timestamp_asserter_addr - .map(|address| TimestampAsserterParams { - address, - min_time_till_end: Duration::from_secs( - timestamp_asserter_config.min_time_till_end_sec as u64, - ), - }), + timestamp_asserter_params, ), postgres_storage_caches_config, rpc_config.vm_concurrency_limit(), diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 57766daa4c6e..9d05921d9894 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt, time::Duration}; +use std::{cmp::min, collections::HashMap, fmt, time::Duration}; use bigdecimal::BigDecimal; use itertools::Itertools; @@ -316,15 +316,16 @@ impl TransactionsDal<'_, '_> { let nanosecs = ((tx.received_timestamp_ms % 1000) * 1_000_000) as u32; #[allow(deprecated)] let received_at = NaiveDateTime::from_timestamp_opt(secs, nanosecs).unwrap(); + let max_timestamp = NaiveDateTime::MAX.and_utc().timestamp() as u64; #[allow(deprecated)] - let timestamp_asserter_range_start = validation_traces - .timestamp_asserter_range - .clone() - .map(|x| NaiveDateTime::from_timestamp_opt(x.start as i64, 0).unwrap()); + let timestamp_asserter_range_start = + validation_traces.timestamp_asserter_range.clone().map(|x| { + NaiveDateTime::from_timestamp_opt(min(x.start, max_timestamp) as i64, 0).unwrap() + }); #[allow(deprecated)] - let timestamp_asserter_range_end = validation_traces - .timestamp_asserter_range - .map(|x| NaiveDateTime::from_timestamp_opt(x.end as i64, 0).unwrap()); + let timestamp_asserter_range_end = validation_traces.timestamp_asserter_range.map(|x| { + NaiveDateTime::from_timestamp_opt(min(x.end, max_timestamp) as i64, 0).unwrap() + }); // Besides just adding or updating(on conflict) the record, we want to extract some info // from the query below, to indicate what actually happened: // 1) transaction is added diff --git a/core/node/api_server/src/tx_sender/tests/send_tx.rs b/core/node/api_server/src/tx_sender/tests/send_tx.rs index 1add528e0aad..c861f04a832e 100644 --- a/core/node/api_server/src/tx_sender/tests/send_tx.rs +++ b/core/node/api_server/src/tx_sender/tests/send_tx.rs @@ -1,6 +1,9 @@ //! Tests for sending raw transactions. +use std::ops::Range; + use assert_matches::assert_matches; +use chrono::NaiveDateTime; use test_casing::test_casing; use zksync_multivm::interface::{tracer::ValidationTraces, ExecutionResult}; use zksync_node_fee_model::MockBatchFeeParamsProvider; @@ -309,8 +312,7 @@ async fn sending_transaction_out_of_gas() { assert_matches!(vm_result.result, ExecutionResult::Revert { .. }); } -#[tokio::test] -async fn submitting_tx_with_validation_traces() { +async fn submit_tx_with_validation_traces(actual_range: Range, expected_range: Range) { // This test verifies that when a transaction produces ValidationTraces, // range_start and range_end get persisted in the database let pool = ConnectionPool::::constrained_test_pool(1).await; @@ -344,7 +346,7 @@ async fn submitting_tx_with_validation_traces() { tx_executor.set_tx_validation_traces_responses(move |tx, _| { assert_eq!(tx.hash(), tx_hash); ValidationTraces { - timestamp_asserter_range: Some(10..20), + timestamp_asserter_range: Some(actual_range.clone()), } }); @@ -363,7 +365,7 @@ async fn submitting_tx_with_validation_traces() { .unwrap() .expect("transaction is not persisted"); assert_eq!( - 10, + expected_range.start, storage_tx .timestamp_asserter_range_start .unwrap() @@ -371,7 +373,7 @@ async fn submitting_tx_with_validation_traces() { .timestamp() ); assert_eq!( - 20, + expected_range.end, storage_tx .timestamp_asserter_range_end .unwrap() @@ -379,3 +381,18 @@ async fn submitting_tx_with_validation_traces() { .timestamp() ); } + +#[tokio::test] +async fn submitting_tx_with_validation_traces() { + // This test verifies that when a transaction produces ValidationTraces, + // range_start and range_end get persisted in the database + submit_tx_with_validation_traces(10..20, 10..20).await; +} + +#[tokio::test] +async fn submitting_tx_with_validation_traces_resulting_into_overflow() { + // This test verifies that the timestamp in ValidationTraces is capped at + // the maximum value supported by the NaiveDateTime type + submit_tx_with_validation_traces(10..u64::MAX, 10..NaiveDateTime::MAX.and_utc().timestamp()) + .await; +} diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index d9128598e8da..5543a4792a03 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -192,8 +192,8 @@ describe('Tests for the custom account behavior', () => { const tx = await erc20.transfer.populateTransaction(alice.address, TRANSFER_AMOUNT); - await expect( - sendCustomAccountTransaction( + try { + await sendCustomAccountTransaction( tx as zksync.types.Transaction, alice.provider, customAccountAddress, @@ -201,10 +201,32 @@ describe('Tests for the custom account behavior', () => { undefined, undefined, false - ) - ).toBeRejected( - 'failed to validate the transaction. reason: Validation revert: Account validation error: Timestamp is out of range' - ); + ); + expect(null).fail('The transaction was expected to fail'); + } catch (e) { + const err = e as Error; + expect(err.message).toContain( + 'failed to validate the transaction. reason: Validation revert: Account validation error' + ); + const functionSelectorMatch = err.message.match(/function_selector\s=\s(0x[0-9a-fA-F]{8})/); + const calldataMatch = err.message.match(/data\s=\s(0x[0-9a-fA-F]+)/); + + if (!functionSelectorMatch || !calldataMatch) { + expect(null).fail('Function selector or calldata not found in the error message'); + } + + const functionSelector = functionSelectorMatch![1]; + const calldata = calldataMatch![1]; + + const startHex = calldata.slice(74, 138); + const endHex = calldata.slice(138); + const start = BigInt(`0x${startHex}`); + const end = BigInt(`0x${endHex}`); + + expect(functionSelector).toBe('0x3d5740d9'); + expect(start).toBe(BigInt(rangeStart)); + expect(end).toBe(BigInt(rangeEnd)); + } }); test('Should fail the validation with incorrect signature', async () => { From 29d99d407b0aead79c390f26c28ab9befd7644b8 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 16:53:30 +0000 Subject: [PATCH 64/68] Review feedback --- core/bin/external_node/src/config/mod.rs | 64 +++++++++++++------ core/lib/dal/src/transactions_dal.rs | 2 +- .../src/tracers/validator/vm_latest/mod.rs | 8 +-- core/lib/vm_interface/src/types/tracer.rs | 8 +-- .../tests/custom-account.test.ts | 7 +- 5 files changed, 55 insertions(+), 34 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 9bf8141294fa..46389c2e08d8 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -1,6 +1,7 @@ use std::{ env, ffi::OsString, + future::Future, num::{NonZeroU32, NonZeroU64, NonZeroUsize}, path::PathBuf, time::Duration, @@ -147,26 +148,19 @@ impl RemoteENConfig { .get_main_contract() .rpc_context("get_main_contract") .await?; - let timestamp_asserter_address = client - .get_timestamp_asserter() - .rpc_context("get_timestamp_asserter") - .await?; - let base_token_addr = match client.get_base_token_l1_address().await { - Err(ClientError::Call(err)) - if [ - ErrorCode::MethodNotFound.code(), - // This what `Web3Error::NotImplemented` gets - // `casted` into in the `api` server. - ErrorCode::InternalError.code(), - ] - .contains(&(err.code())) => - { - // This is the fallback case for when the EN tries to interact - // with a node that does not implement the `zks_baseTokenL1Address` endpoint. - ETHEREUM_ADDRESS - } - response => response.context("Failed to fetch base token address")?, - }; + + let timestamp_asserter_address = handle_rpc_response_with_fallback( + client.get_timestamp_asserter(), + None, + "Failed to fetch timestamp asserter address", + ) + .await?; + let base_token_addr = handle_rpc_response_with_fallback( + client.get_base_token_l1_address(), + Some(ETHEREUM_ADDRESS), + "Failed to fetch base token address", + ) + .await?; // These two config variables should always have the same value. // TODO(EVM-578): double check and potentially forbid both of them being `None`. @@ -238,6 +232,31 @@ impl RemoteENConfig { } } +async fn handle_rpc_response_with_fallback( + rpc_call: F, + fallback: Option, + context: &str, +) -> anyhow::Result +where + F: Future>, + T: Clone, +{ + match rpc_call.await { + Err(ClientError::Call(err)) + if [ + ErrorCode::MethodNotFound.code(), + // This what `Web3Error::NotImplemented` gets + // `casted` into in the `api` server. + ErrorCode::InternalError.code(), + ] + .contains(&(err.code())) => + { + fallback.ok_or_else(|| anyhow::anyhow!("RPC method not found or internal error")) + } + response => response.context(context), + } +} + /// This part of the external node config is completely optional to provide. /// It can tweak limits of the API, delay intervals of certain components, etc. /// If any of the fields are not provided, the default values will be used. @@ -1471,7 +1490,10 @@ impl From<&ExternalNodeConfig> for TxSenderConfig { TimestampAsserterParams { address, min_time_till_end: Duration::from_secs( - config.optional.timestamp_asserter_min_time_till_end_sec as u64, + config + .optional + .timestamp_asserter_min_time_till_end_sec + .into(), ), } }), diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 9d05921d9894..9c0889ebfc75 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -2256,7 +2256,7 @@ impl TransactionsDal<'_, '_> { hash.as_bytes() ) .map(Into::into) - .instrument("get_tx_error_by_hash") + .instrument("get_storage_tx_by_hash") .with_arg("hash", &hash) .fetch_optional(self.storage) .await diff --git a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs index e5ee3794dee6..d3dc7fd87c42 100644 --- a/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs +++ b/core/lib/multivm/src/tracers/validator/vm_latest/mod.rs @@ -122,10 +122,10 @@ impl ValidationTracer { ); } - { - let mut traces_mut = self.traces.lock().unwrap(); - traces_mut.apply_range(start..end); - } + self.traces + .lock() + .unwrap() + .apply_timestamp_asserter_range(start..end); } } } diff --git a/core/lib/vm_interface/src/types/tracer.rs b/core/lib/vm_interface/src/types/tracer.rs index bddf4bffb9ea..1c3f65f443ef 100644 --- a/core/lib/vm_interface/src/types/tracer.rs +++ b/core/lib/vm_interface/src/types/tracer.rs @@ -134,7 +134,7 @@ impl ValidationTraces { /// producing the narrowest possible time window. Note that overlapping ranges are essential; /// a lack of overlap would have triggered an assertion failure in the `TimestampAsserter` contract, /// as `block.timestamp` cannot satisfy two non-overlapping ranges. - pub fn apply_range(&mut self, new_range: Range) { + pub fn apply_timestamp_asserter_range(&mut self, new_range: Range) { if let Some(range) = &mut self.timestamp_asserter_range { range.start = range.start.max(new_range.start); range.end = range.end.min(new_range.end); @@ -167,7 +167,7 @@ mod tests { timestamp_asserter_range: None, }; let new_range = 10..20; - validation_traces.apply_range(new_range.clone()); + validation_traces.apply_timestamp_asserter_range(new_range.clone()); assert_eq!(validation_traces.timestamp_asserter_range, Some(new_range)); } @@ -176,7 +176,7 @@ mod tests { let mut validation_traces = ValidationTraces { timestamp_asserter_range: Some(5..25), }; - validation_traces.apply_range(10..20); + validation_traces.apply_timestamp_asserter_range(10..20); assert_eq!(validation_traces.timestamp_asserter_range, Some(10..20)); } @@ -185,7 +185,7 @@ mod tests { let mut validation_traces = ValidationTraces { timestamp_asserter_range: Some(10..30), }; - validation_traces.apply_range(20..40); + validation_traces.apply_timestamp_asserter_range(20..40); assert_eq!(validation_traces.timestamp_asserter_range, Some(20..30)); } } diff --git a/core/tests/ts-integration/tests/custom-account.test.ts b/core/tests/ts-integration/tests/custom-account.test.ts index 5543a4792a03..ebbe11b87195 100644 --- a/core/tests/ts-integration/tests/custom-account.test.ts +++ b/core/tests/ts-integration/tests/custom-account.test.ts @@ -211,11 +211,11 @@ describe('Tests for the custom account behavior', () => { const functionSelectorMatch = err.message.match(/function_selector\s=\s(0x[0-9a-fA-F]{8})/); const calldataMatch = err.message.match(/data\s=\s(0x[0-9a-fA-F]+)/); - if (!functionSelectorMatch || !calldataMatch) { - expect(null).fail('Function selector or calldata not found in the error message'); - } + expect(functionSelectorMatch && calldataMatch).toBeTruthy(); const functionSelector = functionSelectorMatch![1]; + expect(functionSelector).toBe('0x3d5740d9'); + const calldata = calldataMatch![1]; const startHex = calldata.slice(74, 138); @@ -223,7 +223,6 @@ describe('Tests for the custom account behavior', () => { const start = BigInt(`0x${startHex}`); const end = BigInt(`0x${endHex}`); - expect(functionSelector).toBe('0x3d5740d9'); expect(start).toBe(BigInt(rangeStart)); expect(end).toBe(BigInt(rangeEnd)); } From bd395d208839cd012d14736874c065821ef3611d Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 16:59:55 +0000 Subject: [PATCH 65/68] Review feedback --- core/bin/external_node/src/config/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 46389c2e08d8..16851220eec4 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -152,13 +152,13 @@ impl RemoteENConfig { let timestamp_asserter_address = handle_rpc_response_with_fallback( client.get_timestamp_asserter(), None, - "Failed to fetch timestamp asserter address", + "Failed to fetch timestamp asserter address".to_string(), ) .await?; let base_token_addr = handle_rpc_response_with_fallback( client.get_base_token_l1_address(), Some(ETHEREUM_ADDRESS), - "Failed to fetch base token address", + "Failed to fetch base token address".to_string(), ) .await?; @@ -235,7 +235,7 @@ impl RemoteENConfig { async fn handle_rpc_response_with_fallback( rpc_call: F, fallback: Option, - context: &str, + context: String, ) -> anyhow::Result where F: Future>, From 56e93754885eaa2cd9853850424f8273e7612d05 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 31 Oct 2024 18:47:49 +0000 Subject: [PATCH 66/68] Review feedback --- core/bin/external_node/src/config/mod.rs | 6 +++--- core/bin/zksync_server/src/node_builder.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index 16851220eec4..0a94f993656a 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -157,7 +157,7 @@ impl RemoteENConfig { .await?; let base_token_addr = handle_rpc_response_with_fallback( client.get_base_token_l1_address(), - Some(ETHEREUM_ADDRESS), + ETHEREUM_ADDRESS, "Failed to fetch base token address".to_string(), ) .await?; @@ -234,7 +234,7 @@ impl RemoteENConfig { async fn handle_rpc_response_with_fallback( rpc_call: F, - fallback: Option, + fallback: T, context: String, ) -> anyhow::Result where @@ -251,7 +251,7 @@ where ] .contains(&(err.code())) => { - fallback.ok_or_else(|| anyhow::anyhow!("RPC method not found or internal error")) + Ok(fallback) } response => response.context(context), } diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 4a903bd9d502..32478ede5bf8 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -313,7 +313,7 @@ impl MainNodeBuilder { Some(TimestampAsserterParams { address, min_time_till_end: Duration::from_secs( - timestamp_asserter_config.min_time_till_end_sec as u64, + timestamp_asserter_config.min_time_till_end_sec.into(), ), }) } From 42cc5f7d86cb0632726eb27b4d13b6c8cf8a0876 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 1 Nov 2024 10:23:02 +0000 Subject: [PATCH 67/68] Remove unnecessary workflows change --- .github/workflows/new-build-core-template.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index 8d7911e0c355..db0b21e0c12c 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -77,8 +77,6 @@ jobs: tar -C ./contracts -zxf l1-contracts.tar.gz tar -C ./contracts -zxf l2-contracts.tar.gz tar -C ./contracts -zxf system-contracts.tar.gz - # TODO Remove mkdir once we use foundry inside contracts repo - mkdir -p contracts/l1-contracts/out - name: Install Apt dependencies if: env.BUILD_CONTRACTS == 'true' @@ -211,14 +209,6 @@ jobs: path: | ./contracts - # TODO Remove it when we migrate to foundry inside contracts repository - - name: Create necessary artefacts - shell: bash - run: | - mkdir -p contracts/l1-contracts/artifacts/ - mkdir -p contracts/l1-contracts/out - - - name: login to Docker registries if: ${{ inputs.action == 'push' }} shell: bash From 4a7adb12ea4d861a18ad6e4995898b57e74821cf Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 1 Nov 2024 10:25:43 +0000 Subject: [PATCH 68/68] Remove unnecessary workflows change --- .github/workflows/new-build-core-template.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/new-build-core-template.yml b/.github/workflows/new-build-core-template.yml index db0b21e0c12c..c4aeb9180fda 100644 --- a/.github/workflows/new-build-core-template.yml +++ b/.github/workflows/new-build-core-template.yml @@ -142,7 +142,6 @@ jobs: cp etc/tokens/{test,localhost}.json zkstack dev contracts - - name: Upload contracts uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: