From bbd7db9bf064c6e683e7ed57a42f5899cf3748a4 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 12:48:56 -0300 Subject: [PATCH 01/72] Make address optional in transaction data --- .../system-constants-generator/src/utils.rs | 4 +- core/lib/dal/src/consensus/mod.rs | 16 +++- core/lib/dal/src/models/tests.rs | 2 +- core/lib/dal/src/tests/mod.rs | 6 +- core/lib/dal/src/transactions_dal.rs | 74 +++++++++++++++---- core/lib/mempool/src/tests.rs | 4 +- .../src/versions/vm_1_3_2/test_utils.rs | 2 +- .../src/versions/vm_1_3_2/transaction_data.rs | 6 +- .../types/internals/transaction_data.rs | 6 +- .../types/internals/transaction_data.rs | 6 +- .../types/internals/transaction_data.rs | 6 +- .../src/versions/vm_fast/tests/block_tip.rs | 2 +- .../src/versions/vm_fast/tests/circuits.rs | 2 +- .../src/versions/vm_fast/tests/code_oracle.rs | 8 +- .../vm_fast/tests/get_used_contracts.rs | 6 +- .../versions/vm_fast/tests/l1_tx_execution.rs | 2 +- .../src/versions/vm_fast/tests/l2_blocks.rs | 2 +- .../versions/vm_fast/tests/nonce_holder.rs | 2 +- .../src/versions/vm_fast/tests/precompiles.rs | 6 +- .../src/versions/vm_fast/tests/refunds.rs | 4 +- .../versions/vm_fast/tests/require_eip712.rs | 4 +- .../src/versions/vm_fast/tests/rollbacks.rs | 4 +- .../src/versions/vm_fast/tests/sekp256r1.rs | 2 +- .../src/versions/vm_fast/tests/storage.rs | 4 +- .../vm_fast/tests/tracing_execution_error.rs | 2 +- .../src/versions/vm_fast/tests/transfer.rs | 6 +- .../src/versions/vm_fast/tests/upgrade.rs | 4 +- .../src/versions/vm_fast/transaction_data.rs | 6 +- .../src/versions/vm_latest/tests/block_tip.rs | 2 +- .../versions/vm_latest/tests/call_tracer.rs | 4 +- .../src/versions/vm_latest/tests/circuits.rs | 2 +- .../versions/vm_latest/tests/code_oracle.rs | 8 +- .../vm_latest/tests/get_used_contracts.rs | 4 +- .../vm_latest/tests/l1_tx_execution.rs | 2 +- .../versions/vm_latest/tests/nonce_holder.rs | 2 +- .../versions/vm_latest/tests/precompiles.rs | 6 +- .../vm_latest/tests/prestate_tracer.rs | 4 +- .../src/versions/vm_latest/tests/refunds.rs | 4 +- .../vm_latest/tests/require_eip712.rs | 4 +- .../src/versions/vm_latest/tests/rollbacks.rs | 4 +- .../src/versions/vm_latest/tests/sekp256r1.rs | 2 +- .../src/versions/vm_latest/tests/storage.rs | 2 +- .../tests/tracing_execution_error.rs | 2 +- .../src/versions/vm_latest/tests/transfer.rs | 6 +- .../src/versions/vm_latest/tests/upgrade.rs | 4 +- .../types/internals/transaction_data.rs | 6 +- .../multivm/src/versions/vm_m5/test_utils.rs | 2 +- .../src/versions/vm_m5/transaction_data.rs | 6 +- .../multivm/src/versions/vm_m6/test_utils.rs | 2 +- .../src/versions/vm_m6/transaction_data.rs | 6 +- .../types/internals/transaction_data.rs | 6 +- .../types/internals/transaction_data.rs | 6 +- core/lib/types/src/l1/mod.rs | 4 +- core/lib/types/src/l2/mod.rs | 6 +- core/lib/types/src/lib.rs | 8 +- core/lib/types/src/transaction_request.rs | 8 +- core/lib/types/src/tx/execute.rs | 9 ++- .../api_server/src/execution_sandbox/tests.rs | 2 +- core/node/consensus/src/registry/testonly.rs | 2 +- core/node/consensus/src/vm.rs | 2 +- core/node/eth_watch/src/tests.rs | 4 +- .../state_keeper/src/executor/tests/tester.rs | 4 +- core/node/state_keeper/src/testonly/mod.rs | 4 +- core/node/test_utils/src/lib.rs | 2 +- core/node/vm_runner/src/tests/mod.rs | 2 +- .../src/sdk/operations/deploy_contract.rs | 2 +- .../src/sdk/operations/execute_contract.rs | 2 +- .../loadnext/src/sdk/operations/transfer.rs | 4 +- core/tests/loadnext/src/sdk/signer.rs | 6 +- core/tests/test_account/src/lib.rs | 8 +- core/tests/vm-benchmark/src/transaction.rs | 8 +- prover/crates/lib/keystore/src/utils.rs | 1 + 72 files changed, 219 insertions(+), 163 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 3775b3c0e243..664ae0ebdb16 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -89,7 +89,7 @@ pub(super) fn get_l2_tx( pubdata_price: u32, ) -> L2Tx { L2Tx::new_signed( - contract_address, + Some(contract_address), vec![], Nonce(0), Fee { @@ -134,7 +134,7 @@ pub(super) fn get_l1_tx( ) -> L1Tx { L1Tx { execute: Execute { - contract_address, + contract_address: Some(contract_address), calldata: custom_calldata.unwrap_or_default(), value: U256::from(0), factory_deps, diff --git a/core/lib/dal/src/consensus/mod.rs b/core/lib/dal/src/consensus/mod.rs index f0ef336bc543..88620575c88a 100644 --- a/core/lib/dal/src/consensus/mod.rs +++ b/core/lib/dal/src/consensus/mod.rs @@ -401,9 +401,11 @@ impl ProtoRepr for proto::Transaction { } }, execute: Execute { - contract_address: required(&execute.contract_address) - .and_then(|x| parse_h160(x)) - .context("execute.contract_address")?, + contract_address: Some( + required(&execute.contract_address) + .and_then(|x| parse_h160(x)) + .context("execute.contract_address")?, + ), calldata: required(&execute.calldata).context("calldata")?.clone(), value: required(&execute.value) .and_then(|x| parse_h256(x)) @@ -487,7 +489,13 @@ impl ProtoRepr for proto::Transaction { } }; let execute = proto::Execute { - contract_address: Some(this.execute.contract_address.as_bytes().into()), + contract_address: Some( + this.execute + .contract_address + .unwrap_or_default() + .as_bytes() + .into(), + ), calldata: Some(this.execute.calldata.clone()), value: Some(u256_to_h256(this.execute.value).as_bytes().into()), factory_deps: this.execute.factory_deps.clone(), diff --git a/core/lib/dal/src/models/tests.rs b/core/lib/dal/src/models/tests.rs index 34cfde108f19..b4949dc101d6 100644 --- a/core/lib/dal/src/models/tests.rs +++ b/core/lib/dal/src/models/tests.rs @@ -13,7 +13,7 @@ use crate::{models::storage_transaction::StorageTransaction, BigDecimal}; fn default_execute() -> Execute { Execute { - contract_address: H160::random(), + contract_address: Some(H160::random()), value: U256::from(10i32), calldata: hex::decode( "a9059cbb00000000000000000000000058d595f318167d5af45d9e44ade4348dd4e\ diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index c17e8c5d1fe3..dc672fa1f807 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -74,7 +74,7 @@ pub(crate) fn mock_l2_transaction() -> L2Tx { gas_per_pubdata_limit: U256::from(DEFAULT_GAS_PER_PUBDATA), }; let mut l2_tx = L2Tx::new_signed( - Address::random(), + Some(Address::random()), vec![], zksync_types::Nonce(0), fee, @@ -110,7 +110,7 @@ pub(crate) fn mock_l1_execute() -> L1Tx { }; let execute = Execute { - contract_address: H160::random(), + contract_address: Some(H160::random()), value: Default::default(), calldata: vec![], factory_deps: vec![], @@ -138,7 +138,7 @@ pub(crate) fn mock_protocol_upgrade_transaction() -> ProtocolUpgradeTx { }; let execute = Execute { - contract_address: H160::random(), + contract_address: Some(H160::random()), value: Default::default(), calldata: vec![], factory_deps: vec![], diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index 49791f776e08..bc44083ea319 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -58,7 +58,13 @@ impl TransactionsDal<'_, '_> { tx: &L1Tx, l1_block_number: L1BlockNumber, ) -> DalResult<()> { - let contract_address = tx.execute.contract_address.as_bytes(); + let contract_address = tx.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: &[u8] = if contract_address.is_none() { + &[] + } else { + unwrapped_contract_address.as_bytes() + }; let tx_hash = tx.hash(); let tx_hash_bytes = tx_hash.as_bytes(); let json_data = serde_json::to_value(&tx.execute) @@ -143,7 +149,7 @@ impl TransactionsDal<'_, '_> { serial_id, full_fee, layer_2_tip_fee, - contract_address, + contract_address_b, l1_block_number.0 as i32, value, empty_address.as_bytes(), @@ -161,7 +167,13 @@ impl TransactionsDal<'_, '_> { } pub async fn insert_system_transaction(&mut self, tx: &ProtocolUpgradeTx) -> DalResult<()> { - let contract_address = tx.execute.contract_address.as_bytes().to_vec(); + let contract_address = tx.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: &[u8] = if contract_address.is_none() { + &[] + } else { + unwrapped_contract_address.as_bytes() + }; let tx_hash = tx.common_data.hash().0.to_vec(); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.common_data.hash())); @@ -238,7 +250,7 @@ impl TransactionsDal<'_, '_> { gas_per_pubdata_limit, json_data, upgrade_id, - contract_address, + contract_address_b, l1_block_number, value, &Address::default().0.to_vec(), @@ -284,7 +296,13 @@ impl TransactionsDal<'_, '_> { } let initiator_address = tx.initiator_account(); - let contract_address = tx.execute.contract_address.as_bytes(); + let contract_address = tx.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: &[u8] = if contract_address.is_none() { + &[] + } else { + unwrapped_contract_address.as_bytes() + }; let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())); let gas_limit = u256_to_big_decimal(tx.common_data.fee.gas_limit); @@ -413,7 +431,7 @@ impl TransactionsDal<'_, '_> { input_data, &json_data, tx_format, - contract_address, + contract_address_b, value, &paymaster, &paymaster_input, @@ -697,8 +715,15 @@ impl TransactionsDal<'_, '_> { .arg_error(&format!("transactions[{index_in_block}].refunded_gas"), err) })?; + let contract_address = transaction.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: Vec = if contract_address.is_none() { + Vec::new() + } else { + unwrapped_contract_address.as_bytes().to_vec() + }; l2_values.push(u256_to_big_decimal(transaction.execute.value)); - l2_contract_addresses.push(transaction.execute.contract_address.as_bytes()); + l2_contract_addresses.push(contract_address_b); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); l2_paymaster.push(common_data.paymaster_params.paymaster.as_bytes()); l2_hashes.push(tx_res.hash.as_bytes()); @@ -818,7 +843,7 @@ impl TransactionsDal<'_, '_> { &l2_inputs as &[&[u8]], &l2_datas, &l2_tx_formats, - &l2_contract_addresses as &[&[u8]], + &l2_contract_addresses, &l2_values, &l2_paymaster as &[&[u8]], &l2_paymaster_input as &[&[u8]], @@ -901,8 +926,15 @@ impl TransactionsDal<'_, '_> { .arg_error(&format!("transactions[{index_in_block}].refunded_gas"), err) })?; + let contract_address = transaction.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: Vec = if contract_address.is_none() { + Vec::new() + } else { + unwrapped_contract_address.as_bytes().to_vec() + }; l2_values.push(u256_to_big_decimal(transaction.execute.value)); - l2_contract_addresses.push(transaction.execute.contract_address.as_bytes()); + l2_contract_addresses.push(contract_address_b); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); l2_paymaster.push(common_data.paymaster_params.paymaster.as_bytes()); l2_hashes.push(tx_res.hash.as_bytes()); @@ -1013,7 +1045,7 @@ impl TransactionsDal<'_, '_> { &l2_datas, &l2_refunded_gas, &l2_values, - &l2_contract_addresses as &[&[u8]], + &l2_contract_addresses, &l2_paymaster as &[&[u8]], &l2_paymaster_input as &[&[u8]], l2_block_number.0 as i32, @@ -1083,6 +1115,13 @@ impl TransactionsDal<'_, '_> { .arg_error(&format!("transactions[{index_in_block}].refunded_gas"), err) })?; + let contract_address = transaction.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: Vec = if contract_address.is_none() { + Vec::new() + } else { + unwrapped_contract_address.as_bytes().to_vec() + }; let tx = &tx_res.transaction; l1_hashes.push(tx_res.hash.as_bytes()); l1_initiator_address.push(common_data.sender.as_bytes()); @@ -1096,7 +1135,7 @@ impl TransactionsDal<'_, '_> { l1_priority_op_id.push(common_data.serial_id.0 as i64); l1_full_fee.push(u256_to_big_decimal(common_data.full_fee)); l1_layer_2_tip_fee.push(u256_to_big_decimal(common_data.layer_2_tip_fee)); - l1_contract_address.push(tx.execute.contract_address.as_bytes()); + l1_contract_address.push(contract_address_b); l1_l1_block_number.push(common_data.eth_block as i32); l1_value.push(u256_to_big_decimal(tx.execute.value)); l1_tx_format.push(common_data.tx_format() as i32); @@ -1203,7 +1242,7 @@ impl TransactionsDal<'_, '_> { &l1_priority_op_id, &l1_full_fee, &l1_layer_2_tip_fee, - &l1_contract_address as &[&[u8]], + &l1_contract_address, &l1_l1_block_number, &l1_value, &l1_tx_format, @@ -1373,6 +1412,13 @@ impl TransactionsDal<'_, '_> { .arg_error(&format!("transactions[{index_in_block}].refunded_gas"), err) })?; + let contract_address = transaction.execute.contract_address; + let unwrapped_contract_address = contract_address.unwrap_or_default(); + let contract_address_b: Vec = if contract_address.is_none() { + Vec::new() + } else { + unwrapped_contract_address.as_bytes().to_vec() + }; let tx = &tx_res.transaction; upgrade_hashes.push(tx_res.hash.as_bytes()); upgrade_initiator_address.push(common_data.sender.as_bytes()); @@ -1385,7 +1431,7 @@ impl TransactionsDal<'_, '_> { .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())), ); upgrade_upgrade_id.push(common_data.upgrade_id as i32); - upgrade_contract_address.push(tx.execute.contract_address.as_bytes()); + upgrade_contract_address.push(contract_address_b); upgrade_l1_block_number.push(common_data.eth_block as i32); upgrade_value.push(u256_to_big_decimal(tx.execute.value)); upgrade_tx_format.push(common_data.tx_format() as i32); @@ -1484,7 +1530,7 @@ impl TransactionsDal<'_, '_> { &upgrade_gas_per_pubdata_limit, &upgrade_data, &upgrade_upgrade_id, - &upgrade_contract_address as &[&[u8]], + &upgrade_contract_address, &upgrade_l1_block_number, &upgrade_value, &upgrade_tx_format, diff --git a/core/lib/mempool/src/tests.rs b/core/lib/mempool/src/tests.rs index 6ea1be3b514b..96ef600984f9 100644 --- a/core/lib/mempool/src/tests.rs +++ b/core/lib/mempool/src/tests.rs @@ -371,7 +371,7 @@ fn gen_l2_tx(address: Address, nonce: Nonce) -> Transaction { fn gen_l2_tx_with_timestamp(address: Address, nonce: Nonce, received_at_ms: u64) -> Transaction { let mut txn = L2Tx::new( - Address::default(), + Some(Address::default()), Vec::new(), nonce, Fee::default(), @@ -386,7 +386,7 @@ fn gen_l2_tx_with_timestamp(address: Address, nonce: Nonce, received_at_ms: u64) fn gen_l1_tx(priority_id: PriorityOpId) -> Transaction { let execute = Execute { - contract_address: Address::repeat_byte(0x11), + contract_address: Some(Address::repeat_byte(0x11)), calldata: vec![1, 2, 3], factory_deps: vec![], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs b/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs index a29e1101d520..34c70e0f9c45 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/test_utils.rs @@ -153,7 +153,7 @@ pub fn get_create_execute(code: &[u8], calldata: &[u8]) -> Execute { .expect("failed to encode parameters"); Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps: vec![code.to_vec()], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_1_3_2/transaction_data.rs b/core/lib/multivm/src/versions/vm_1_3_2/transaction_data.rs index 788a52206e80..0285320daa30 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_1_3_2::vm_with_bootloader::{ pub struct TransactionData { pub tx_type: u8, pub from: Address, - pub to: Address, + pub to: Option
, pub gas_limit: U256, pub pubdata_price_limit: U256, pub max_fee_per_gas: U256, @@ -170,7 +170,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -593,7 +593,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs index 1379b853a542..f7384da76d0d 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_1_4_1::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -311,7 +311,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs index 3498e51ec308..38280aa80513 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_1_4_2::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -311,7 +311,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs index ad740a279dcd..8bf575effe06 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_boojum_integration::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -325,7 +325,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_fast/tests/block_tip.rs b/core/lib/multivm/src/versions/vm_fast/tests/block_tip.rs index 15af9d868adc..a96045141380 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/block_tip.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/block_tip.rs @@ -147,7 +147,7 @@ fn execute_test(test_data: L1MessengerTestData) -> TestStatistics { for (i, data) in txs_data.into_iter().enumerate() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: CONTRACT_FORCE_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_FORCE_DEPLOYER_ADDRESS), calldata: data, value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/circuits.rs b/core/lib/multivm/src/versions/vm_fast/tests/circuits.rs index 0270ac35475b..a119a31618e9 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/circuits.rs @@ -21,7 +21,7 @@ fn test_circuits() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: Address::random(), + contract_address: Some(Address::random()), calldata: Vec::new(), value: U256::from(1u8), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/code_oracle.rs b/core/lib/multivm/src/versions/vm_fast/tests/code_oracle.rs index 836603d77d87..f29684260051 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/code_oracle.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/code_oracle.rs @@ -58,7 +58,7 @@ fn test_code_oracle() { // Firstly, let's ensure that the contract works. let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), @@ -82,7 +82,7 @@ fn test_code_oracle() { // the decommitted bytecode gets erased (it shouldn't). let tx2 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), @@ -152,7 +152,7 @@ fn test_code_oracle_big_bytecode() { // Firstly, let's ensure that the contract works. let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(big_zkevm_bytecode_hash.0.to_vec()), @@ -220,7 +220,7 @@ fn refunds_in_code_oracle() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), diff --git a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs index 3fcef71add07..746e9be923f2 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs @@ -65,7 +65,7 @@ fn test_get_used_contracts() { let account2 = Account::random(); let tx2 = account2.get_l1_tx( Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata: big_calldata, value: Default::default(), factory_deps: vec![vec![1; 32]], @@ -150,7 +150,7 @@ fn execute_proxy_counter(gas: u32) -> (VmTester, ProxyCounterData, VmExecutionRe let increment = proxy_counter_abi.function("increment").unwrap(); let increment_tx = account.get_l2_tx_for_execute( Execute { - contract_address: deploy_tx.address, + contract_address: Some(deploy_tx.address), calldata: increment .encode_input(&[Token::Uint(1.into()), Token::Uint(gas.into())]) .unwrap(), @@ -197,7 +197,7 @@ fn get_used_contracts_with_out_of_gas_far_call() { let increment = proxy_counter_abi.function("increment").unwrap(); let increment_tx = account.get_l2_tx_for_execute( Execute { - contract_address: data.proxy_counter_address, + contract_address: Some(data.proxy_counter_address), calldata: increment .encode_input(&[Token::Uint(1.into()), Token::Uint(u64::MAX.into())]) .unwrap(), diff --git a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs index f1399a1b4e68..ea3613b0fe79 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs @@ -176,7 +176,7 @@ fn test_l1_tx_execution_high_gas_limit() { let mut tx = account.get_l1_tx( Execute { - contract_address: L1_MESSENGER_ADDRESS, + contract_address: Some(L1_MESSENGER_ADDRESS), value: 0.into(), factory_deps: vec![], calldata, diff --git a/core/lib/multivm/src/versions/vm_fast/tests/l2_blocks.rs b/core/lib/multivm/src/versions/vm_fast/tests/l2_blocks.rs index a374f63608bc..a43bb7c0309e 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/l2_blocks.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/l2_blocks.rs @@ -37,7 +37,7 @@ fn get_l1_noop() -> Transaction { ..Default::default() }), execute: Execute { - contract_address: H160::zero(), + contract_address: Some(H160::zero()), calldata: vec![], value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs index 122b38601175..2ae43869d7f6 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs @@ -59,7 +59,7 @@ fn test_nonce_holder() { vm.reset_state(true); let mut transaction = account.get_l2_tx_for_execute_with_nonce( Execute { - contract_address: account.address, + contract_address: Some(account.address), calldata: vec![12], value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/precompiles.rs b/core/lib/multivm/src/versions/vm_fast/tests/precompiles.rs index f77eeb4f126e..28d3ea82da31 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/precompiles.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/precompiles.rs @@ -28,7 +28,7 @@ fn test_keccak() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: hex::decode(keccak1000_calldata).unwrap(), value: 0.into(), factory_deps: vec![], @@ -65,7 +65,7 @@ fn test_sha256() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: hex::decode(sha1000_calldata).unwrap(), value: 0.into(), factory_deps: vec![], @@ -95,7 +95,7 @@ fn test_ecrecover() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: account.address, + contract_address: Some(account.address), calldata: vec![], value: 0.into(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/refunds.rs b/core/lib/multivm/src/versions/vm_fast/tests/refunds.rs index 5ad6e3fa4f3d..1d276533898e 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/refunds.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/refunds.rs @@ -181,7 +181,7 @@ fn negative_pubdata_for_transaction() { let expensive_tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: expensive_contract_address, + contract_address: Some(expensive_contract_address), calldata: expensive_function .encode_input(&[Token::Uint(10.into())]) .unwrap(), @@ -200,7 +200,7 @@ fn negative_pubdata_for_transaction() { // This transaction cleans all initial writes in the contract, thus having negative `pubdata` impact. let clean_up_tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: expensive_contract_address, + contract_address: Some(expensive_contract_address), calldata: cleanup_function.encode_input(&[]).unwrap(), value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs b/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs index fe94189ed7cf..89b8788f52fe 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs @@ -68,7 +68,7 @@ async fn test_require_eip712() { let tx = private_account.get_l2_tx_for_execute( Execute { - contract_address: account_abstraction.address, + contract_address: Some(account_abstraction.address), calldata: encoded_input, value: Default::default(), factory_deps: vec![], @@ -125,7 +125,7 @@ async fn test_require_eip712() { // // Now send the 'classic' EIP712 transaction let tx_712 = L2Tx::new( - beneficiary.address, + Some(beneficiary.address), vec![], Nonce(1), Fee { diff --git a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs index c530c5af18ea..4419aaeedfaa 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs @@ -83,7 +83,7 @@ fn test_vm_loadnext_rollbacks() { let loadnext_tx_1 = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: LoadnextContractExecutionParams { reads: 100, writes: 100, @@ -101,7 +101,7 @@ fn test_vm_loadnext_rollbacks() { let loadnext_tx_2 = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: LoadnextContractExecutionParams { reads: 100, writes: 100, diff --git a/core/lib/multivm/src/versions/vm_fast/tests/sekp256r1.rs b/core/lib/multivm/src/versions/vm_fast/tests/sekp256r1.rs index a61a0a2bd91c..55ca372c4a9f 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/sekp256r1.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/sekp256r1.rs @@ -48,7 +48,7 @@ fn test_sekp256r1() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: P256VERIFY_PRECOMPILE_ADDRESS, + contract_address: Some(P256VERIFY_PRECOMPILE_ADDRESS), calldata: [digest, encoded_r, encoded_s, x, y].concat(), value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/storage.rs b/core/lib/multivm/src/versions/vm_fast/tests/storage.rs index 7fe15ca7bcd2..8258e21366ce 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/storage.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/storage.rs @@ -30,7 +30,7 @@ fn test_storage(first_tx_calldata: Vec, second_tx_calldata: Vec) -> u32 let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata: first_tx_calldata, value: 0.into(), factory_deps: vec![], @@ -40,7 +40,7 @@ fn test_storage(first_tx_calldata: Vec, second_tx_calldata: Vec) -> u32 let tx2 = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata: second_tx_calldata, value: 0.into(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/tracing_execution_error.rs b/core/lib/multivm/src/versions/vm_fast/tests/tracing_execution_error.rs index 75144839006e..efa64ea17708 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/tracing_execution_error.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/tracing_execution_error.rs @@ -24,7 +24,7 @@ fn test_tracing_of_execution_errors() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address, + contract_address: Some(contract_address), calldata: get_execute_error_calldata(), value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/transfer.rs b/core/lib/multivm/src/versions/vm_fast/tests/transfer.rs index 3327012801ce..3370f8bce354 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/transfer.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/transfer.rs @@ -70,7 +70,7 @@ fn test_send_or_transfer(test_option: TestOptions) { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata, value: U256::zero(), factory_deps: vec![], @@ -167,7 +167,7 @@ fn test_reentrancy_protection_send_or_transfer(test_option: TestOptions) { let account = &mut vm.rich_accounts[0]; let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: reentrant_recipeint_address, + contract_address: Some(reentrant_recipeint_address), calldata: reentrant_recipient_abi .function("setX") .unwrap() @@ -188,7 +188,7 @@ fn test_reentrancy_protection_send_or_transfer(test_option: TestOptions) { let tx2 = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata, value, factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_fast/tests/upgrade.rs b/core/lib/multivm/src/versions/vm_fast/tests/upgrade.rs index f972b29cda8a..f0ed2fb30c87 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/upgrade.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/upgrade.rs @@ -265,7 +265,7 @@ fn get_forced_deploy_tx(deployment: &[ForceDeployment]) -> Transaction { .expect("failed to encode parameters"); let execute = Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps: vec![], value: U256::zero(), @@ -315,7 +315,7 @@ fn get_complex_upgrade_tx( .unwrap(); let execute = Execute { - contract_address: COMPLEX_UPGRADER_ADDRESS, + contract_address: Some(COMPLEX_UPGRADER_ADDRESS), calldata: complex_upgrader_calldata, factory_deps: vec![], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_fast/transaction_data.rs b/core/lib/multivm/src/versions/vm_fast/transaction_data.rs index 502be0dc22cc..2ec86eb3ceaf 100644 --- a/core/lib/multivm/src/versions/vm_fast/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_fast/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_latest::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -305,7 +305,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs b/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs index bed348afd2d9..02c73344a543 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/block_tip.rs @@ -164,7 +164,7 @@ fn execute_test(test_data: L1MessengerTestData) -> TestStatistics { for (i, data) in txs_data.into_iter().enumerate() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: CONTRACT_FORCE_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_FORCE_DEPLOYER_ADDRESS), calldata: data, value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/call_tracer.rs b/core/lib/multivm/src/versions/vm_latest/tests/call_tracer.rs index a4d0eb2d17e2..df7a78855426 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/call_tracer.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/call_tracer.rs @@ -34,7 +34,7 @@ fn test_max_depth() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: vec![], value: Default::default(), factory_deps: vec![], @@ -69,7 +69,7 @@ fn test_basic_behavior() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: hex::decode(increment_by_6_calldata).unwrap(), value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs index 02ec2dc58aaa..35412ee4d1bd 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs @@ -22,7 +22,7 @@ fn test_circuits() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: Address::random(), + contract_address: Some(Address::random()), calldata: Vec::new(), value: U256::from(1u8), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs b/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs index 0708d67e27a3..b15ef7fde2bf 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/code_oracle.rs @@ -69,7 +69,7 @@ fn test_code_oracle() { // Firstly, let's ensure that the contract works. let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), @@ -93,7 +93,7 @@ fn test_code_oracle() { // the decommitted bytecode gets erased (it shouldn't). let tx2 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), @@ -169,7 +169,7 @@ fn test_code_oracle_big_bytecode() { // Firstly, let's ensure that the contract works. let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(big_zkevm_bytecode_hash.0.to_vec()), @@ -251,7 +251,7 @@ fn refunds_in_code_oracle() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: precompiles_contract_address, + contract_address: Some(precompiles_contract_address), calldata: call_code_oracle_function .encode_input(&[ Token::FixedBytes(normal_zkevm_bytecode_hash.0.to_vec()), diff --git a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs index a42037a7f5be..ef19717a627c 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs @@ -82,7 +82,7 @@ fn test_get_used_contracts() { let account2 = Account::random(); let tx2 = account2.get_l1_tx( Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata: big_calldata, value: Default::default(), factory_deps: vec![vec![1; 32]], @@ -208,7 +208,7 @@ fn execute_proxy_counter(gas: u32) -> (VmTester, U256, VmExecut let increment = proxy_counter_abi.function("increment").unwrap(); let increment_tx = account.get_l2_tx_for_execute( Execute { - contract_address: deploy_tx.address, + contract_address: Some(deploy_tx.address), calldata: increment .encode_input(&[Token::Uint(1.into()), Token::Uint(gas.into())]) .unwrap(), diff --git a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs index dcb1bff06d09..0fc12848227e 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs @@ -173,7 +173,7 @@ fn test_l1_tx_execution_high_gas_limit() { let mut tx = account.get_l1_tx( Execute { - contract_address: L1_MESSENGER_ADDRESS, + contract_address: Some(L1_MESSENGER_ADDRESS), value: 0.into(), factory_deps: vec![], calldata, diff --git a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs index 661286ca9697..91d78c69a931 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs @@ -64,7 +64,7 @@ fn test_nonce_holder() { let mut transaction_data: TransactionData = account .get_l2_tx_for_execute_with_nonce( Execute { - contract_address: account.address, + contract_address: Some(account.address), calldata: vec![12], value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/precompiles.rs b/core/lib/multivm/src/versions/vm_latest/tests/precompiles.rs index 2ab40faf22ca..9388d0161846 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/precompiles.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/precompiles.rs @@ -31,7 +31,7 @@ fn test_keccak() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: hex::decode(keccak1000_calldata).unwrap(), value: Default::default(), factory_deps: vec![], @@ -75,7 +75,7 @@ fn test_sha256() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: hex::decode(sha1000_calldata).unwrap(), value: Default::default(), factory_deps: vec![], @@ -112,7 +112,7 @@ fn test_ecrecover() { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: account.address, + contract_address: Some(account.address), calldata: Vec::new(), value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/prestate_tracer.rs b/core/lib/multivm/src/versions/vm_latest/tests/prestate_tracer.rs index eb3104fd637a..8bf5e9919889 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/prestate_tracer.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/prestate_tracer.rs @@ -88,7 +88,7 @@ fn test_prestate_tracer_diff_mode() { //enter ether to contract to see difference in the balance post execution let tx0 = Execute { - contract_address: vm.test_contract.unwrap(), + contract_address: Some(vm.test_contract.unwrap()), calldata: Default::default(), value: U256::from(100000), factory_deps: vec![], @@ -98,7 +98,7 @@ fn test_prestate_tracer_diff_mode() { .push_transaction(account.get_l2_tx_for_execute(tx0.clone(), None)); let tx1 = Execute { - contract_address: deployed_address2, + contract_address: Some(deployed_address2), calldata: Default::default(), value: U256::from(200000), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs b/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs index ca058d672d2e..cc0085f20252 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs @@ -188,7 +188,7 @@ fn negative_pubdata_for_transaction() { let expensive_tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: expensive_contract_address, + contract_address: Some(expensive_contract_address), calldata: expensive_function .encode_input(&[Token::Uint(10.into())]) .unwrap(), @@ -207,7 +207,7 @@ fn negative_pubdata_for_transaction() { // This transaction cleans all initial writes in the contract, thus having negative `pubdata` impact. let clean_up_tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: expensive_contract_address, + contract_address: Some(expensive_contract_address), calldata: cleanup_function.encode_input(&[]).unwrap(), value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs b/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs index 779e9b5c629d..cdd71354c8de 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs @@ -63,7 +63,7 @@ async fn test_require_eip712() { let tx = private_account.get_l2_tx_for_execute( Execute { - contract_address: account_abstraction.address, + contract_address: Some(account_abstraction.address), calldata: encoded_input, value: Default::default(), factory_deps: vec![], @@ -120,7 +120,7 @@ async fn test_require_eip712() { // // Now send the 'classic' EIP712 transaction let tx_712 = L2Tx::new( - beneficiary.address, + Some(beneficiary.address), vec![], Nonce(1), Fee { diff --git a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs index 43e7baae3b2d..52e4d24bc0b4 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs @@ -92,7 +92,7 @@ fn test_vm_loadnext_rollbacks() { let loadnext_tx_1 = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: LoadnextContractExecutionParams { reads: 100, writes: 100, @@ -110,7 +110,7 @@ fn test_vm_loadnext_rollbacks() { let loadnext_tx_2 = account.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: LoadnextContractExecutionParams { reads: 100, writes: 100, diff --git a/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs b/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs index 6cc731a1387c..93be9506a3b0 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/sekp256r1.rs @@ -48,7 +48,7 @@ fn test_sekp256r1() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: P256VERIFY_PRECOMPILE_ADDRESS, + contract_address: Some(P256VERIFY_PRECOMPILE_ADDRESS), calldata: [digest, encoded_r, encoded_s, x, y].concat(), value: U256::zero(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/storage.rs b/core/lib/multivm/src/versions/vm_latest/tests/storage.rs index 0fe0b0220fae..126d174a6468 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/storage.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/storage.rs @@ -50,7 +50,7 @@ fn test_storage(txs: Vec) -> u32 { let tx = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata, value: 0.into(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/tracing_execution_error.rs b/core/lib/multivm/src/versions/vm_latest/tests/tracing_execution_error.rs index 58c5ef77dc42..2db37881352f 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/tracing_execution_error.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/tracing_execution_error.rs @@ -27,7 +27,7 @@ fn test_tracing_of_execution_errors() { let tx = account.get_l2_tx_for_execute( Execute { - contract_address, + contract_address: Some(contract_address), calldata: get_execute_error_calldata(), value: Default::default(), factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/transfer.rs b/core/lib/multivm/src/versions/vm_latest/tests/transfer.rs index 31f6c3291ef6..2c380623636a 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/transfer.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/transfer.rs @@ -73,7 +73,7 @@ fn test_send_or_transfer(test_option: TestOptions) { let account = &mut vm.rich_accounts[0]; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata, value: U256::zero(), factory_deps: vec![], @@ -169,7 +169,7 @@ fn test_reentrancy_protection_send_or_transfer(test_option: TestOptions) { let account = &mut vm.rich_accounts[0]; let tx1 = account.get_l2_tx_for_execute( Execute { - contract_address: reentrant_recipeint_address, + contract_address: Some(reentrant_recipeint_address), calldata: reentrant_recipient_abi .function("setX") .unwrap() @@ -190,7 +190,7 @@ fn test_reentrancy_protection_send_or_transfer(test_option: TestOptions) { let tx2 = account.get_l2_tx_for_execute( Execute { - contract_address: test_contract_address, + contract_address: Some(test_contract_address), calldata, value, factory_deps: vec![], diff --git a/core/lib/multivm/src/versions/vm_latest/tests/upgrade.rs b/core/lib/multivm/src/versions/vm_latest/tests/upgrade.rs index 7c3ebff4a77d..d85a504de40f 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/upgrade.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/upgrade.rs @@ -276,7 +276,7 @@ fn get_forced_deploy_tx(deployment: &[ForceDeployment]) -> Transaction { .expect("failed to encode parameters"); let execute = Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps: vec![], value: U256::zero(), @@ -326,7 +326,7 @@ fn get_complex_upgrade_tx( .unwrap(); let execute = Execute { - contract_address: COMPLEX_UPGRADER_ADDRESS, + contract_address: Some(COMPLEX_UPGRADER_ADDRESS), calldata: complex_upgrader_calldata, factory_deps: vec![], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs index 502be0dc22cc..2ec86eb3ceaf 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_latest::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -305,7 +305,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_m5/test_utils.rs b/core/lib/multivm/src/versions/vm_m5/test_utils.rs index 785eb49835f1..d7c0dfb9f6d0 100644 --- a/core/lib/multivm/src/versions/vm_m5/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_m5/test_utils.rs @@ -151,7 +151,7 @@ pub fn get_create_execute(code: &[u8], calldata: &[u8]) -> Execute { .expect("failed to encode parameters"); Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps: vec![code.to_vec()], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_m5/transaction_data.rs b/core/lib/multivm/src/versions/vm_m5/transaction_data.rs index 7ef739fd5bf5..b64e3f770185 100644 --- a/core/lib/multivm/src/versions/vm_m5/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_m5/transaction_data.rs @@ -22,7 +22,7 @@ const L1_TX_TYPE: u8 = 255; pub struct TransactionData { pub tx_type: u8, pub from: Address, - pub to: Address, + pub to: Option
, pub gas_limit: U256, pub pubdata_price_limit: U256, pub max_fee_per_gas: U256, @@ -144,7 +144,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -479,7 +479,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_m6/test_utils.rs b/core/lib/multivm/src/versions/vm_m6/test_utils.rs index ecad7d911b40..4bd39bc56dd4 100644 --- a/core/lib/multivm/src/versions/vm_m6/test_utils.rs +++ b/core/lib/multivm/src/versions/vm_m6/test_utils.rs @@ -151,7 +151,7 @@ pub fn get_create_execute(code: &[u8], calldata: &[u8]) -> Execute { .expect("failed to encode parameters"); Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps: vec![code.to_vec()], value: U256::zero(), diff --git a/core/lib/multivm/src/versions/vm_m6/transaction_data.rs b/core/lib/multivm/src/versions/vm_m6/transaction_data.rs index 99ce4671c29b..a8f80ea3255e 100644 --- a/core/lib/multivm/src/versions/vm_m6/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_m6/transaction_data.rs @@ -23,7 +23,7 @@ pub(crate) const L1_TX_TYPE: u8 = 255; pub struct TransactionData { pub tx_type: u8, pub from: Address, - pub to: Address, + pub to: Option
, pub gas_limit: U256, pub pubdata_price_limit: U256, pub max_fee_per_gas: U256, @@ -171,7 +171,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -592,7 +592,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs index 205090ba633e..22ab09296c91 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_refunds_enhancement::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -325,7 +325,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs index b42950399f61..c96004163a65 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/types/internals/transaction_data.rs @@ -22,7 +22,7 @@ use crate::vm_virtual_blocks::{ pub(crate) struct TransactionData { pub(crate) tx_type: u8, pub(crate) from: Address, - pub(crate) to: Address, + pub(crate) to: Option
, pub(crate) gas_limit: U256, pub(crate) pubdata_price_limit: U256, pub(crate) max_fee_per_gas: U256, @@ -169,7 +169,7 @@ impl TransactionData { encode(&[Token::Tuple(vec![ Token::Uint(U256::from_big_endian(&self.tx_type.to_be_bytes())), Token::Address(self.from), - Token::Address(self.to), + Token::Address(self.to.unwrap_or_default()), Token::Uint(self.gas_limit), Token::Uint(self.pubdata_price_limit), Token::Uint(self.max_fee_per_gas), @@ -325,7 +325,7 @@ mod tests { let transaction = TransactionData { tx_type: 113, from: Address::random(), - to: Address::random(), + to: Some(Address::random()), gas_limit: U256::from(1u32), pubdata_price_limit: U256::from(1u32), max_fee_per_gas: U256::from(1u32), diff --git a/core/lib/types/src/l1/mod.rs b/core/lib/types/src/l1/mod.rs index 05f08987a2d3..215836cb52f5 100644 --- a/core/lib/types/src/l1/mod.rs +++ b/core/lib/types/src/l1/mod.rs @@ -274,7 +274,7 @@ impl From for abi::NewPriorityRequest { transaction: abi::L2CanonicalTransaction { tx_type: PRIORITY_OPERATION_L2_TX_TYPE.into(), from: address_to_u256(&t.common_data.sender), - to: address_to_u256(&t.execute.contract_address), + to: address_to_u256(&t.execute.contract_address.unwrap_or_default()), gas_limit: t.common_data.gas_limit, gas_per_pubdata_byte_limit: t.common_data.gas_per_pubdata_limit, max_fee_per_gas: t.common_data.max_fee_per_gas, @@ -345,7 +345,7 @@ impl TryFrom for L1Tx { }; let execute = Execute { - contract_address: u256_to_account_address(&req.transaction.to), + contract_address: Some(u256_to_account_address(&req.transaction.to)), calldata: req.transaction.data, factory_deps: req.factory_deps, value: req.transaction.value, diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index 5a5276407529..abd60491af38 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -153,7 +153,7 @@ pub struct L2Tx { impl L2Tx { #[allow(clippy::too_many_arguments)] pub fn new( - contract_address: Address, + contract_address: Option
, calldata: Vec, nonce: Nonce, fee: Fee, @@ -185,7 +185,7 @@ impl L2Tx { #[allow(clippy::too_many_arguments)] pub fn new_signed( - contract_address: Address, + contract_address: Option
, calldata: Vec, nonce: Nonce, fee: Fee, @@ -233,7 +233,7 @@ impl L2Tx { /// Returns recipient account of the transaction. pub fn recipient_account(&self) -> Address { - self.execute.contract_address + self.execute.contract_address.unwrap_or_default() } /// Returns the account nonce associated with transaction. diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 402e16afd435..54e1b40b5b33 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -105,7 +105,7 @@ impl Eq for Transaction {} impl Transaction { /// Returns recipient account of the transaction. pub fn recipient_account(&self) -> Address { - self.execute.contract_address + self.execute.contract_address.unwrap_or_default() } pub fn nonce(&self) -> Option { @@ -253,7 +253,7 @@ impl TryFrom for abi::Transaction { tx: abi::L2CanonicalTransaction { tx_type: PRIORITY_OPERATION_L2_TX_TYPE.into(), from: address_to_u256(&data.sender), - to: address_to_u256(&tx.execute.contract_address), + to: address_to_u256(&tx.execute.contract_address.unwrap_or_default()), gas_limit: data.gas_limit, gas_per_pubdata_byte_limit: data.gas_per_pubdata_limit, max_fee_per_gas: data.max_fee_per_gas, @@ -284,7 +284,7 @@ impl TryFrom for abi::Transaction { tx: abi::L2CanonicalTransaction { tx_type: PROTOCOL_UPGRADE_TX_TYPE.into(), from: address_to_u256(&data.sender), - to: address_to_u256(&tx.execute.contract_address), + to: address_to_u256(&tx.execute.contract_address.unwrap_or_default()), gas_limit: data.gas_limit, gas_per_pubdata_byte_limit: data.gas_per_pubdata_limit, max_fee_per_gas: data.max_fee_per_gas, @@ -377,7 +377,7 @@ impl TryFrom for Transaction { unknown_type => anyhow::bail!("unknown tx type {unknown_type}"), }, execute: Execute { - contract_address: u256_to_account_address(&tx.to), + contract_address: Some(u256_to_account_address(&tx.to)), calldata: tx.data, factory_deps, value: tx.value, diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index c71e6e4206c5..057c905d1c66 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -108,8 +108,8 @@ impl CallRequestBuilder { } /// Set to address (None allowed for eth_estimateGas) - pub fn to(mut self, to: Address) -> Self { - self.call_request.to = Some(to); + pub fn to(mut self, to: Option
) -> Self { + self.call_request.to = to; self } @@ -818,9 +818,7 @@ impl L2Tx { validate_factory_deps(&meta.factory_deps)?; let mut tx = L2Tx::new( - value - .to - .ok_or(SerializationTransactionError::ToAddressIsNull)?, + value.to, value.input.0.clone(), nonce, fee, diff --git a/core/lib/types/src/tx/execute.rs b/core/lib/types/src/tx/execute.rs index 03762040a6b8..c5d31c0f8a03 100644 --- a/core/lib/types/src/tx/execute.rs +++ b/core/lib/types/src/tx/execute.rs @@ -15,7 +15,7 @@ use crate::{ethabi, Address, EIP712TypedStructure, StructBuilder, H256, U256}; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct ExecuteSerde { - contract_address: Address, + contract_address: Option
, #[serde(with = "ZeroPrefixHexSerde")] calldata: Vec, value: U256, @@ -25,7 +25,7 @@ struct ExecuteSerde { /// `Execute` transaction executes a previously deployed smart contract in the L2 rollup. #[derive(Clone, Default, PartialEq)] pub struct Execute { - pub contract_address: Address, + pub contract_address: Option
, pub calldata: Vec, pub value: U256, /// Factory dependencies: list of contract bytecodes associated with the deploy transaction. @@ -72,7 +72,10 @@ impl EIP712TypedStructure for Execute { const TYPE_NAME: &'static str = "Transaction"; fn build_structure(&self, builder: &mut BUILDER) { - builder.add_member("to", &U256::from(self.contract_address.as_bytes())); + builder.add_member( + "to", + &U256::from(self.contract_address.unwrap_or_default().as_bytes()), + ); builder.add_member("value", &self.value); builder.add_member("data", &self.calldata.as_slice()); // Factory deps are not included into the transaction signature, since they are parsed from the diff --git a/core/node/api_server/src/execution_sandbox/tests.rs b/core/node/api_server/src/execution_sandbox/tests.rs index 35103779a49e..79c5a7330384 100644 --- a/core/node/api_server/src/execution_sandbox/tests.rs +++ b/core/node/api_server/src/execution_sandbox/tests.rs @@ -236,7 +236,7 @@ fn create_transfer(fee_per_gas: u64, gas_per_pubdata: u64) -> L2Tx { gas_per_pubdata_limit: gas_per_pubdata.into(), }; L2Tx::new_signed( - Address::random(), + Some(Address::random()), vec![], Nonce(0), fee, diff --git a/core/node/consensus/src/registry/testonly.rs b/core/node/consensus/src/registry/testonly.rs index a0c55a557feb..07a87e3b676e 100644 --- a/core/node/consensus/src/registry/testonly.rs +++ b/core/node/consensus/src/registry/testonly.rs @@ -13,7 +13,7 @@ pub(crate) fn make_tx( ) -> Transaction { account.get_l2_tx_for_execute( Execute { - contract_address: *address, + contract_address: Some(*address), calldata: call.calldata().unwrap(), value: U256::zero(), factory_deps: vec![], diff --git a/core/node/consensus/src/vm.rs b/core/node/consensus/src/vm.rs index 11b6b5c67e3b..c93cafc09f9c 100644 --- a/core/node/consensus/src/vm.rs +++ b/core/node/consensus/src/vm.rs @@ -56,7 +56,7 @@ impl VM { call: abi::Call, ) -> ctx::Result { let tx = L2Tx::new( - *address, + Some(*address), call.calldata().context("call.calldata()")?, Nonce(0), Fee { diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index 7ae3b5494e98..e6e343f50bca 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -147,7 +147,7 @@ impl EthClient for MockEthClient { fn build_l1_tx(serial_id: u64, eth_block: u64) -> L1Tx { let tx = L1Tx { execute: Execute { - contract_address: Address::repeat_byte(0x11), + contract_address: Some(Address::repeat_byte(0x11)), calldata: vec![1, 2, 3], factory_deps: vec![], value: U256::zero(), @@ -178,7 +178,7 @@ fn build_l1_tx(serial_id: u64, eth_block: u64) -> L1Tx { fn build_upgrade_tx(id: ProtocolVersionId, eth_block: u64) -> ProtocolUpgradeTx { let tx = ProtocolUpgradeTx { execute: Execute { - contract_address: Address::repeat_byte(0x11), + contract_address: Some(Address::repeat_byte(0x11)), calldata: vec![1, 2, 3], factory_deps: vec![], value: U256::zero(), diff --git a/core/node/state_keeper/src/executor/tests/tester.rs b/core/node/state_keeper/src/executor/tests/tester.rs index 8256435f2f5b..d524d1a20dd7 100644 --- a/core/node/state_keeper/src/executor/tests/tester.rs +++ b/core/node/state_keeper/src/executor/tests/tester.rs @@ -396,7 +396,7 @@ impl AccountLoadNextExecutable for Account { self.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata: LoadnextContractExecutionParams { reads: 100, writes: writes as usize, @@ -432,7 +432,7 @@ impl AccountLoadNextExecutable for Account { self.get_l2_tx_for_execute( Execute { - contract_address: address, + contract_address: Some(address), calldata, value: Default::default(), factory_deps: vec![], diff --git a/core/node/state_keeper/src/testonly/mod.rs b/core/node/state_keeper/src/testonly/mod.rs index 23aec8af49fb..edcf3ccc4f5c 100644 --- a/core/node/state_keeper/src/testonly/mod.rs +++ b/core/node/state_keeper/src/testonly/mod.rs @@ -131,7 +131,7 @@ pub fn fee(gas_limit: u32) -> Fee { pub fn l2_transaction(account: &mut Account, gas_limit: u32) -> Transaction { account.get_l2_tx_for_execute( Execute { - contract_address: Address::random(), + contract_address: Some(Address::random()), calldata: vec![], value: Default::default(), factory_deps: vec![], @@ -143,7 +143,7 @@ pub fn l2_transaction(account: &mut Account, gas_limit: u32) -> Transaction { pub fn l1_transaction(account: &mut Account, serial_id: PriorityOpId) -> Transaction { account.get_l1_tx( Execute { - contract_address: Address::random(), + contract_address: Some(Address::random()), value: Default::default(), calldata: vec![], factory_deps: vec![], diff --git a/core/node/test_utils/src/lib.rs b/core/node/test_utils/src/lib.rs index acb65bf1634d..b9984b782111 100644 --- a/core/node/test_utils/src/lib.rs +++ b/core/node/test_utils/src/lib.rs @@ -138,7 +138,7 @@ pub fn create_l2_transaction(fee_per_gas: u64, gas_per_pubdata: u64) -> L2Tx { gas_per_pubdata_limit: gas_per_pubdata.into(), }; let mut tx = L2Tx::new_signed( - Address::random(), + Some(Address::random()), vec![], Nonce(0), fee, diff --git a/core/node/vm_runner/src/tests/mod.rs b/core/node/vm_runner/src/tests/mod.rs index 530016408140..928da3b93157 100644 --- a/core/node/vm_runner/src/tests/mod.rs +++ b/core/node/vm_runner/src/tests/mod.rs @@ -202,7 +202,7 @@ pub fn create_l2_transaction( }; let tx = account.get_l2_tx_for_execute( Execute { - contract_address: Address::random(), + contract_address: Some(Address::random()), calldata: vec![], value: Default::default(), factory_deps: vec![], diff --git a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs index 161d156a53e9..67e877ae8efb 100644 --- a/core/tests/loadnext/src/sdk/operations/deploy_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/deploy_contract.rs @@ -145,7 +145,7 @@ where let mut factory_deps = self.factory_deps.clone().unwrap_or_default(); factory_deps.push(bytecode); let l2_tx = L2Tx::new( - CONTRACT_DEPLOYER_ADDRESS, + Some(CONTRACT_DEPLOYER_ADDRESS), Execute::encode_deploy_params_create(Default::default(), main_contract_hash, calldata), Nonce(0), Default::default(), diff --git a/core/tests/loadnext/src/sdk/operations/execute_contract.rs b/core/tests/loadnext/src/sdk/operations/execute_contract.rs index d5fe57c7b79f..627e889ed012 100644 --- a/core/tests/loadnext/src/sdk/operations/execute_contract.rs +++ b/core/tests/loadnext/src/sdk/operations/execute_contract.rs @@ -144,7 +144,7 @@ where .unwrap_or_default(); let execute = L2Tx::new( - contract_address, + Some(contract_address), calldata, Nonce(0), Default::default(), diff --git a/core/tests/loadnext/src/sdk/operations/transfer.rs b/core/tests/loadnext/src/sdk/operations/transfer.rs index 94ee3aeb6082..651fabeb788b 100644 --- a/core/tests/loadnext/src/sdk/operations/transfer.rs +++ b/core/tests/loadnext/src/sdk/operations/transfer.rs @@ -153,7 +153,7 @@ where let tx = if token.is_zero() || token == L2_BASE_TOKEN_ADDRESS { // ETH estimate Execute { - contract_address: to, + contract_address: Some(to), calldata: Default::default(), factory_deps: vec![], value: amount, @@ -161,7 +161,7 @@ where } else { // ERC-20 estimate Execute { - contract_address: token, + contract_address: Some(token), calldata: create_transfer_calldata(to, amount), factory_deps: vec![], value: Default::default(), diff --git a/core/tests/loadnext/src/sdk/signer.rs b/core/tests/loadnext/src/sdk/signer.rs index 0f4b1cf29717..6f98f674ed95 100644 --- a/core/tests/loadnext/src/sdk/signer.rs +++ b/core/tests/loadnext/src/sdk/signer.rs @@ -51,7 +51,7 @@ impl Signer { // Sign Ether transfer if token.is_zero() || token == L2_BASE_TOKEN_ADDRESS { let mut transfer = L2Tx::new( - to, + Some(to), Default::default(), nonce, fee, @@ -73,7 +73,7 @@ impl Signer { // Sign ERC-20 transfer let data = create_transfer_calldata(to, amount); let mut transfer = L2Tx::new( - token, + Some(token), data, nonce, fee, @@ -122,7 +122,7 @@ impl Signer { paymaster_params: PaymasterParams, ) -> Result { let mut execute_contract = L2Tx::new( - contract, + Some(contract), calldata, nonce, fee, diff --git a/core/tests/test_account/src/lib.rs b/core/tests/test_account/src/lib.rs index 28e3d609e63d..d0c97abab729 100644 --- a/core/tests/test_account/src/lib.rs +++ b/core/tests/test_account/src/lib.rs @@ -129,7 +129,7 @@ impl Account { .expect("failed to encode parameters"); let execute = Execute { - contract_address: CONTRACT_DEPLOYER_ADDRESS, + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), calldata, factory_deps, value: U256::zero(), @@ -158,7 +158,7 @@ impl Account { tx: abi::L2CanonicalTransaction { tx_type: PRIORITY_OPERATION_L2_TX_TYPE.into(), from: address_to_u256(&self.address), - to: address_to_u256(&execute.contract_address), + to: address_to_u256(&execute.contract_address.unwrap_or_default()), gas_limit, gas_per_pubdata_byte_limit: REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE.into(), max_fee_per_gas, @@ -216,7 +216,7 @@ impl Account { .expect("failed to encode parameters"); let execute = Execute { - contract_address: address, + contract_address: Some(address), calldata, value: value.unwrap_or_default(), factory_deps: vec![], @@ -235,7 +235,7 @@ impl Account { ) -> Transaction { let calldata = params.to_bytes(); let execute = Execute { - contract_address: address, + contract_address: Some(address), calldata, value: U256::zero(), factory_deps: vec![], diff --git a/core/tests/vm-benchmark/src/transaction.rs b/core/tests/vm-benchmark/src/transaction.rs index 90e1c6360b81..d5fedfa4df94 100644 --- a/core/tests/vm-benchmark/src/transaction.rs +++ b/core/tests/vm-benchmark/src/transaction.rs @@ -47,7 +47,7 @@ pub fn get_deploy_tx_with_gas_limit(code: &[u8], gas_limit: u32, nonce: u32) -> .collect(); let mut signed = L2Tx::new_signed( - CONTRACT_DEPLOYER_ADDRESS, + Some(CONTRACT_DEPLOYER_ADDRESS), calldata, Nonce(nonce), tx_fee(gas_limit), @@ -76,7 +76,7 @@ fn tx_fee(gas_limit: u32) -> Fee { pub fn get_transfer_tx(nonce: u32) -> Transaction { let mut signed = L2Tx::new_signed( - PRIVATE_KEY.address(), + Some(PRIVATE_KEY.address()), vec![], // calldata Nonce(nonce), tx_fee(1_000_000), @@ -109,7 +109,7 @@ pub fn get_load_test_deploy_tx() -> Transaction { factory_deps.push(LOAD_TEST_CONTRACT.bytecode.clone()); let mut signed = L2Tx::new_signed( - CONTRACT_DEPLOYER_ADDRESS, + Some(CONTRACT_DEPLOYER_ADDRESS), create_calldata, Nonce(0), tx_fee(100_000_000), @@ -147,7 +147,7 @@ pub fn get_load_test_tx(nonce: u32, gas_limit: u32, params: LoadTestParams) -> T .expect("cannot encode `execute` inputs"); let mut signed = L2Tx::new_signed( - *LOAD_TEST_CONTRACT_ADDRESS, + Some(*LOAD_TEST_CONTRACT_ADDRESS), calldata, Nonce(nonce), tx_fee(gas_limit), diff --git a/prover/crates/lib/keystore/src/utils.rs b/prover/crates/lib/keystore/src/utils.rs index d9bb3b47dbb0..10504292d64f 100644 --- a/prover/crates/lib/keystore/src/utils.rs +++ b/prover/crates/lib/keystore/src/utils.rs @@ -115,6 +115,7 @@ pub fn calculate_snark_vk_hash(keystore: &Keystore) -> anyhow::Result { #[cfg(test)] mod tests { use std::str::FromStr; + use zksync_utils::env::Workspace; use super::*; From 4e6bed2507f600223b4fdf3d47f82d93723bf43f Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 16:47:42 -0300 Subject: [PATCH 02/72] Add migrations and update queries with evm simulator --- ...af26470206d43fedf44c1a348b13865dbc0f.json} | 12 +++++-- ...0bf5f89e96ab4e6c199fccd17d38eaec77a7.json} | 28 ++++++++++------- ...4a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json} | 12 +++++-- ...927c5f5b88725987e82cf3ec5d499c5addbb.json} | 16 +++++++--- ...e9afe0ead3d435d166a3116551502a730731.json} | 26 ++++++++++------ ...6d3bc76cabe8b0c616ed13dd139327c4cc34.json} | 26 ++++++++++------ ...3a6f0a2de9a615e50a94d98d18e47621c709.json} | 18 +++++++---- ...87dde392c0efa13ecd42becfd0e5db79f059.json} | 14 ++++++--- ...884ca664431997692e4af804ecf5ff8b819a.json} | 5 +-- ...dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b.json} | 26 ++++++++++------ ...08525bf32965ca06e847082c0fc3c54a1dde.json} | 10 ++++-- ...b7ce70b4aaa5c810c79d5bf854fe30c28fd4.json} | 26 ++++++++++------ ...bbb0aa11d1c974d6ae7c99d83560bb37357e.json} | 18 +++++++---- ...0ff9894b1de204599f4a4fd39cfde1020a3e.json} | 26 ++++++++++------ ...00ff851252dd9da2df5ab7da51324f9258400.json | 31 +++++++++++++++++++ ...686d545c780b37430bdcf70fc55e80588b6b.json} | 30 +++++++++++------- ...ba3af74e8e7b5944cb2943b5badb906167046.json | 30 ------------------ ...a68e5e5cf16897de4b6e3211d5e1c07e9294.json} | 10 ++++-- ...412e502df24849331486c604fb0d36d99554.json} | 12 +++++-- ...1bc51d4f949f0941156021a4844ed8c959ca.json} | 26 ++++++++++------ ...85d2efa5902269f3b5ad17b0259c3526877f.json} | 5 +-- .../20240911161714_evm-simulator.down.sql | 3 ++ .../20240911161714_evm-simulator.up.sql | 3 ++ core/lib/dal/src/blocks_dal.rs | 20 ++++++++++++ core/lib/dal/src/blocks_web3_dal.rs | 4 ++- core/lib/dal/src/factory_deps_dal.rs | 14 +++++++++ core/lib/dal/src/models/storage_block.rs | 19 ++++++++++++ .../src/models/storage_protocol_version.rs | 12 +++++++ core/lib/dal/src/models/storage_sync.rs | 3 ++ .../lib/dal/src/models/storage_transaction.rs | 16 ++++++---- core/lib/dal/src/protocol_versions_dal.rs | 12 +++++-- .../lib/dal/src/protocol_versions_web3_dal.rs | 1 + core/lib/dal/src/sync_dal.rs | 1 + core/lib/dal/src/tests/mod.rs | 1 + 34 files changed, 356 insertions(+), 160 deletions(-) rename core/lib/dal/.sqlx/{query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json => query-0631be0bcabdb1697510ecbe6019af26470206d43fedf44c1a348b13865dbc0f.json} (62%) rename core/lib/dal/.sqlx/{query-05b0050aa9d2944542abbcef31af3fe8d35800340d1c6e9d02c15226b699c93b.json => query-08313f09d890c7158bb1ab8158e10bf5f89e96ab4e6c199fccd17d38eaec77a7.json} (83%) rename core/lib/dal/.sqlx/{query-ef70506e90e8add3b95940a7333f8222bd9fbe8ce82d8963f7da03fe6fcf9225.json => query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json} (74%) rename core/lib/dal/.sqlx/{query-778f92b1ac91e1ae279f588053d75a9ac877fdd28bda99661e423405e695223d.json => query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json} (81%) rename core/lib/dal/.sqlx/{query-38dea171e4c49f54bf1db5ac9bfb3be9cf3928755be5f5fcfcdc086e73fb15e2.json => query-2cfcd25a9e0a51c509baafcf8611e9afe0ead3d435d166a3116551502a730731.json} (78%) rename core/lib/dal/.sqlx/{query-2486f8404e8cfcb9c178acd6dccae32e8812becbe5ce85e63694385f015f2cfe.json => query-2f0d3e88282af17374c549e650756d3bc76cabe8b0c616ed13dd139327c4cc34.json} (80%) rename core/lib/dal/.sqlx/{query-39a105cba1be0ec8f2b2b88d2f10c6286fcc824e84bb40a6e9f289c34b85fded.json => query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json} (81%) rename core/lib/dal/.sqlx/{query-454e16ddb5e85285d0c4b9013bcce5d464ecc55c80b54bc16040226df7e297bd.json => query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json} (82%) rename core/lib/dal/.sqlx/{query-9f2c06e6b14434ac4f3b556dc97994cc05ebeb4e5aeeaee50b7c4d8baf58ca44.json => query-49f300dde6f37c283bd99596c290884ca664431997692e4af804ecf5ff8b819a.json} (50%) rename core/lib/dal/.sqlx/{query-659f616d3af4a79f898e84f890e06de9633d1086da972a467d89831e7a07c67e.json => query-535ca6ef0f2b47fe36a6a2c59861dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b.json} (73%) rename core/lib/dal/.sqlx/{query-5556ebdb040428b42c04ea9121b3c2a3d0a09c5ee88bdd671462904d4d27a355.json => query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json} (71%) rename core/lib/dal/.sqlx/{query-63f95c6cdcfd933e2cf8f62c0d408f2dce89f7b700896fcc0f242e0e15ba058e.json => query-7f5993b00c1270d80e6081c3304fb7ce70b4aaa5c810c79d5bf854fe30c28fd4.json} (69%) rename core/lib/dal/.sqlx/{query-45e52d05a4483def84c141e3529bab30553732953e589cd237595227044f438d.json => query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json} (83%) rename core/lib/dal/.sqlx/{query-de255be5d2e5ef215428e9a886e7c9dc036873c60b8b916ce8c446e310447b66.json => query-92d3a7d8c32c4575d6a225f0440b0ff9894b1de204599f4a4fd39cfde1020a3e.json} (80%) create mode 100644 core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json rename core/lib/dal/.sqlx/{query-52bb6de515e1edf4dcf34a31600edb31cfd855014dfca5041833b9d5d9f7a55e.json => query-acf497b952de2d8f83cf2b96f2eb686d545c780b37430bdcf70fc55e80588b6b.json} (80%) delete mode 100644 core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json rename core/lib/dal/.sqlx/{query-1074d0a2e4a4afb9a92f3822e133db7a71aca15698bafba051a8d9a91a4dbc76.json => query-d7ee8998bdc54b0a68dadb79aae3a68e5e5cf16897de4b6e3211d5e1c07e9294.json} (75%) rename core/lib/dal/.sqlx/{query-5d493cbce749cc5b56d4069423597b16599abaf51df0f19effe1a536376cf6a6.json => query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json} (52%) rename core/lib/dal/.sqlx/{query-b7cd7c40282c2ca2287eef93ee79c69a9e494bf1f873291b4ae7bf68b7e3c549.json => query-ebb6c005f99d144963d487841d6e1bc51d4f949f0941156021a4844ed8c959ca.json} (74%) rename core/lib/dal/.sqlx/{query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json => query-ff68458acd9c98120bf4a6814c1985d2efa5902269f3b5ad17b0259c3526877f.json} (52%) create mode 100644 core/lib/dal/migrations/20240911161714_evm-simulator.down.sql create mode 100644 core/lib/dal/migrations/20240911161714_evm-simulator.up.sql diff --git a/core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json b/core/lib/dal/.sqlx/query-0631be0bcabdb1697510ecbe6019af26470206d43fedf44c1a348b13865dbc0f.json similarity index 62% rename from core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json rename to core/lib/dal/.sqlx/query-0631be0bcabdb1697510ecbe6019af26470206d43fedf44c1a348b13865dbc0f.json index 3297d411d8a7..ec5b6c771ff0 100644 --- a/core/lib/dal/.sqlx/query-85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc.json +++ b/core/lib/dal/.sqlx/query-0631be0bcabdb1697510ecbe6019af26470206d43fedf44c1a348b13865dbc0f.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_versions.evm_simulator_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": [ { @@ -25,11 +25,16 @@ }, { "ordinal": 4, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 5, "name": "patch", "type_info": "Int4" }, { - "ordinal": 5, + "ordinal": 6, "name": "snark_wrapper_vk_hash", "type_info": "Bytea" } @@ -44,9 +49,10 @@ false, false, false, + true, false, false ] }, - "hash": "85576fdbb4bd6e3a6e43511c065a2e3eaf72dfe0fa96b335b76c9506cb1ebdcc" + "hash": "0631be0bcabdb1697510ecbe6019af26470206d43fedf44c1a348b13865dbc0f" } diff --git a/core/lib/dal/.sqlx/query-05b0050aa9d2944542abbcef31af3fe8d35800340d1c6e9d02c15226b699c93b.json b/core/lib/dal/.sqlx/query-08313f09d890c7158bb1ab8158e10bf5f89e96ab4e6c199fccd17d38eaec77a7.json similarity index 83% rename from core/lib/dal/.sqlx/query-05b0050aa9d2944542abbcef31af3fe8d35800340d1c6e9d02c15226b699c93b.json rename to core/lib/dal/.sqlx/query-08313f09d890c7158bb1ab8158e10bf5f89e96ab4e6c199fccd17d38eaec77a7.json index b577e7535eb0..abd12214c197 100644 --- a/core/lib/dal/.sqlx/query-05b0050aa9d2944542abbcef31af3fe8d35800340d1c6e9d02c15226b699c93b.json +++ b/core/lib/dal/.sqlx/query-08313f09d890c7158bb1ab8158e10bf5f89e96ab4e6c199fccd17d38eaec77a7.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND eth_prove_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n system_logs,\n compressed_state_diffs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -90,28 +90,28 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, - "name": "protocol_version", - "type_info": "Int4" + "name": "meta_parameters_hash", + "type_info": "Bytea" }, { "ordinal": 21, - "name": "compressed_state_diffs", - "type_info": "Bytea" + "name": "protocol_version", + "type_info": "Int4" }, { "ordinal": 22, @@ -120,16 +120,21 @@ }, { "ordinal": 23, - "name": "events_queue_commitment", + "name": "compressed_state_diffs", "type_info": "Bytea" }, { "ordinal": 24, - "name": "bootloader_initial_content_commitment", + "name": "events_queue_commitment", "type_info": "Bytea" }, { "ordinal": 25, + "name": "bootloader_initial_content_commitment", + "type_info": "Bytea" + }, + { + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -165,8 +170,9 @@ false, true, true, + true, true ] }, - "hash": "05b0050aa9d2944542abbcef31af3fe8d35800340d1c6e9d02c15226b699c93b" + "hash": "08313f09d890c7158bb1ab8158e10bf5f89e96ab4e6c199fccd17d38eaec77a7" } diff --git a/core/lib/dal/.sqlx/query-ef70506e90e8add3b95940a7333f8222bd9fbe8ce82d8963f7da03fe6fcf9225.json b/core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json similarity index 74% rename from core/lib/dal/.sqlx/query-ef70506e90e8add3b95940a7333f8222bd9fbe8ce82d8963f7da03fe6fcf9225.json rename to core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json index cf102b828aa8..12ddbfbc4211 100644 --- a/core/lib/dal/.sqlx/query-ef70506e90e8add3b95940a7333f8222bd9fbe8ce82d8963f7da03fe6fcf9225.json +++ b/core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", "describe": { "columns": [ { @@ -90,11 +90,16 @@ }, { "ordinal": 17, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 18, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 18, + "ordinal": 19, "name": "fee_account_address", "type_info": "Bytea" } @@ -123,8 +128,9 @@ true, true, true, + true, false ] }, - "hash": "ef70506e90e8add3b95940a7333f8222bd9fbe8ce82d8963f7da03fe6fcf9225" + "hash": "1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a" } diff --git a/core/lib/dal/.sqlx/query-778f92b1ac91e1ae279f588053d75a9ac877fdd28bda99661e423405e695223d.json b/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json similarity index 81% rename from core/lib/dal/.sqlx/query-778f92b1ac91e1ae279f588053d75a9ac877fdd28bda99661e423405e695223d.json rename to core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json index aa7d4c65a39d..7b4fa2793dba 100644 --- a/core/lib/dal/.sqlx/query-778f92b1ac91e1ae279f588053d75a9ac877fdd28bda99661e423405e695223d.json +++ b/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", "describe": { "columns": [ { @@ -50,21 +50,26 @@ }, { "ordinal": 9, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 10, "name": "virtual_blocks", "type_info": "Int8" }, { - "ordinal": 10, + "ordinal": 11, "name": "hash", "type_info": "Bytea" }, { - "ordinal": 11, + "ordinal": 12, "name": "protocol_version!", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 13, "name": "fee_account_address!", "type_info": "Bytea" } @@ -85,11 +90,12 @@ true, true, true, + true, false, false, true, false ] }, - "hash": "778f92b1ac91e1ae279f588053d75a9ac877fdd28bda99661e423405e695223d" + "hash": "2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb" } diff --git a/core/lib/dal/.sqlx/query-38dea171e4c49f54bf1db5ac9bfb3be9cf3928755be5f5fcfcdc086e73fb15e2.json b/core/lib/dal/.sqlx/query-2cfcd25a9e0a51c509baafcf8611e9afe0ead3d435d166a3116551502a730731.json similarity index 78% rename from core/lib/dal/.sqlx/query-38dea171e4c49f54bf1db5ac9bfb3be9cf3928755be5f5fcfcdc086e73fb15e2.json rename to core/lib/dal/.sqlx/query-2cfcd25a9e0a51c509baafcf8611e9afe0ead3d435d166a3116551502a730731.json index 7ac6785d8e64..5d5785ddc36f 100644 --- a/core/lib/dal/.sqlx/query-38dea171e4c49f54bf1db5ac9bfb3be9cf3928755be5f5fcfcdc086e73fb15e2.json +++ b/core/lib/dal/.sqlx/query-2cfcd25a9e0a51c509baafcf8611e9afe0ead3d435d166a3116551502a730731.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_prove_tx_id IS NOT NULL\n AND eth_execute_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_prove_tx_id IS NOT NULL\n AND eth_execute_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -162,11 +167,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "38dea171e4c49f54bf1db5ac9bfb3be9cf3928755be5f5fcfcdc086e73fb15e2" + "hash": "2cfcd25a9e0a51c509baafcf8611e9afe0ead3d435d166a3116551502a730731" } diff --git a/core/lib/dal/.sqlx/query-2486f8404e8cfcb9c178acd6dccae32e8812becbe5ce85e63694385f015f2cfe.json b/core/lib/dal/.sqlx/query-2f0d3e88282af17374c549e650756d3bc76cabe8b0c616ed13dd139327c4cc34.json similarity index 80% rename from core/lib/dal/.sqlx/query-2486f8404e8cfcb9c178acd6dccae32e8812becbe5ce85e63694385f015f2cfe.json rename to core/lib/dal/.sqlx/query-2f0d3e88282af17374c549e650756d3bc76cabe8b0c616ed13dd139327c4cc34.json index f28e3d044ccc..43d5f009cf0b 100644 --- a/core/lib/dal/.sqlx/query-2486f8404e8cfcb9c178acd6dccae32e8812becbe5ce85e63694385f015f2cfe.json +++ b/core/lib/dal/.sqlx/query-2f0d3e88282af17374c549e650756d3bc76cabe8b0c616ed13dd139327c4cc34.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number BETWEEN $1 AND $2\n ORDER BY\n number\n LIMIT\n $3\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number BETWEEN $1 AND $2\n ORDER BY\n number\n LIMIT\n $3\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -164,11 +169,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "2486f8404e8cfcb9c178acd6dccae32e8812becbe5ce85e63694385f015f2cfe" + "hash": "2f0d3e88282af17374c549e650756d3bc76cabe8b0c616ed13dd139327c4cc34" } diff --git a/core/lib/dal/.sqlx/query-39a105cba1be0ec8f2b2b88d2f10c6286fcc824e84bb40a6e9f289c34b85fded.json b/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json similarity index 81% rename from core/lib/dal/.sqlx/query-39a105cba1be0ec8f2b2b88d2f10c6286fcc824e84bb40a6e9f289c34b85fded.json rename to core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json index 26a3458bff9b..16f258cf3047 100644 --- a/core/lib/dal/.sqlx/query-39a105cba1be0ec8f2b2b88d2f10c6286fcc824e84bb40a6e9f289c34b85fded.json +++ b/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -65,26 +65,31 @@ }, { "ordinal": 12, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 13, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 13, + "ordinal": 14, "name": "virtual_blocks", "type_info": "Int8" }, { - "ordinal": 14, + "ordinal": 15, "name": "fair_pubdata_price", "type_info": "Int8" }, { - "ordinal": 15, + "ordinal": 16, "name": "gas_limit", "type_info": "Int8" }, { - "ordinal": 16, + "ordinal": 17, "name": "logs_bloom", "type_info": "Bytea" } @@ -106,11 +111,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "39a105cba1be0ec8f2b2b88d2f10c6286fcc824e84bb40a6e9f289c34b85fded" + "hash": "3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709" } diff --git a/core/lib/dal/.sqlx/query-454e16ddb5e85285d0c4b9013bcce5d464ecc55c80b54bc16040226df7e297bd.json b/core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json similarity index 82% rename from core/lib/dal/.sqlx/query-454e16ddb5e85285d0c4b9013bcce5d464ecc55c80b54bc16040226df7e297bd.json rename to core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json index 4a73fde57e29..cff8a75aeb98 100644 --- a/core/lib/dal/.sqlx/query-454e16ddb5e85285d0c4b9013bcce5d464ecc55c80b54bc16040226df7e297bd.json +++ b/core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n system_logs,\n pubdata_input\n FROM\n l1_batches\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n system_logs,\n pubdata_input\n FROM\n l1_batches\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -55,16 +55,21 @@ }, { "ordinal": 10, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 11, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 12, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 12, + "ordinal": 13, "name": "pubdata_input", "type_info": "Bytea" } @@ -86,9 +91,10 @@ true, true, true, + true, false, true ] }, - "hash": "454e16ddb5e85285d0c4b9013bcce5d464ecc55c80b54bc16040226df7e297bd" + "hash": "42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059" } diff --git a/core/lib/dal/.sqlx/query-9f2c06e6b14434ac4f3b556dc97994cc05ebeb4e5aeeaee50b7c4d8baf58ca44.json b/core/lib/dal/.sqlx/query-49f300dde6f37c283bd99596c290884ca664431997692e4af804ecf5ff8b819a.json similarity index 50% rename from core/lib/dal/.sqlx/query-9f2c06e6b14434ac4f3b556dc97994cc05ebeb4e5aeeaee50b7c4d8baf58ca44.json rename to core/lib/dal/.sqlx/query-49f300dde6f37c283bd99596c290884ca664431997692e4af804ecf5ff8b819a.json index 54f0d27bab26..e5b14af2fedb 100644 --- a/core/lib/dal/.sqlx/query-9f2c06e6b14434ac4f3b556dc97994cc05ebeb4e5aeeaee50b7c4d8baf58ca44.json +++ b/core/lib/dal/.sqlx/query-49f300dde6f37c283bd99596c290884ca664431997692e4af804ecf5ff8b819a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n l1_batches (\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n predicted_commit_gas_cost,\n predicted_prove_gas_cost,\n predicted_execute_gas_cost,\n initial_bootloader_heap_content,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n system_logs,\n storage_refunds,\n pubdata_costs,\n pubdata_input,\n predicted_circuits_by_type,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 $19,\n $20,\n NOW(),\n NOW()\n )\n ", + "query": "\n INSERT INTO\n l1_batches (\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n predicted_commit_gas_cost,\n predicted_prove_gas_cost,\n predicted_execute_gas_cost,\n initial_bootloader_heap_content,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n system_logs,\n storage_refunds,\n pubdata_costs,\n pubdata_input,\n predicted_circuits_by_type,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 $19,\n $20,\n $21,\n NOW(),\n NOW()\n )\n ", "describe": { "columns": [], "parameters": { @@ -19,6 +19,7 @@ "Jsonb", "Bytea", "Bytea", + "Bytea", "Int4", "ByteaArray", "Int8Array", @@ -29,5 +30,5 @@ }, "nullable": [] }, - "hash": "9f2c06e6b14434ac4f3b556dc97994cc05ebeb4e5aeeaee50b7c4d8baf58ca44" + "hash": "49f300dde6f37c283bd99596c290884ca664431997692e4af804ecf5ff8b819a" } diff --git a/core/lib/dal/.sqlx/query-659f616d3af4a79f898e84f890e06de9633d1086da972a467d89831e7a07c67e.json b/core/lib/dal/.sqlx/query-535ca6ef0f2b47fe36a6a2c59861dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b.json similarity index 73% rename from core/lib/dal/.sqlx/query-659f616d3af4a79f898e84f890e06de9633d1086da972a467d89831e7a07c67e.json rename to core/lib/dal/.sqlx/query-535ca6ef0f2b47fe36a6a2c59861dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b.json index 9116a25c1673..6678ad05301f 100644 --- a/core/lib/dal/.sqlx/query-659f616d3af4a79f898e84f890e06de9633d1086da972a467d89831e7a07c67e.json +++ b/core/lib/dal/.sqlx/query-535ca6ef0f2b47fe36a6a2c59861dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n system_logs,\n compressed_state_diffs,\n protocol_version,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n (\n SELECT\n l1_batches.*,\n ROW_NUMBER() OVER (\n ORDER BY\n number ASC\n ) AS ROW_NUMBER\n FROM\n l1_batches\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND l1_batches.skip_proof = TRUE\n AND l1_batches.number > $1\n ORDER BY\n number\n LIMIT\n $2\n ) inn\n LEFT JOIN commitments ON commitments.l1_batch_number = inn.number\n WHERE\n number - ROW_NUMBER = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n system_logs,\n compressed_state_diffs,\n protocol_version,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n (\n SELECT\n l1_batches.*,\n ROW_NUMBER() OVER (\n ORDER BY\n number ASC\n ) AS ROW_NUMBER\n FROM\n l1_batches\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND l1_batches.skip_proof = TRUE\n AND l1_batches.number > $1\n ORDER BY\n number\n LIMIT\n $2\n ) inn\n LEFT JOIN commitments ON commitments.l1_batch_number = inn.number\n WHERE\n number - ROW_NUMBER = $1\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -161,6 +166,7 @@ true, true, true, + true, false, true, true, @@ -169,5 +175,5 @@ true ] }, - "hash": "659f616d3af4a79f898e84f890e06de9633d1086da972a467d89831e7a07c67e" + "hash": "535ca6ef0f2b47fe36a6a2c59861dfa954eaf93e6ab5b64bdaa8ef9984ccdf6b" } diff --git a/core/lib/dal/.sqlx/query-5556ebdb040428b42c04ea9121b3c2a3d0a09c5ee88bdd671462904d4d27a355.json b/core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json similarity index 71% rename from core/lib/dal/.sqlx/query-5556ebdb040428b42c04ea9121b3c2a3d0a09c5ee88bdd671462904d4d27a355.json rename to core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json index 5e9051587bb9..56a31f74b835 100644 --- a/core/lib/dal/.sqlx/query-5556ebdb040428b42c04ea9121b3c2a3d0a09c5ee88bdd671462904d4d27a355.json +++ b/core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n id AS \"minor!\",\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n upgrade_tx_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", + "query": "\n SELECT\n id AS \"minor!\",\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash,\n upgrade_tx_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", "describe": { "columns": [ { @@ -25,6 +25,11 @@ }, { "ordinal": 4, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 5, "name": "upgrade_tx_hash", "type_info": "Bytea" } @@ -39,8 +44,9 @@ false, false, false, + true, true ] }, - "hash": "5556ebdb040428b42c04ea9121b3c2a3d0a09c5ee88bdd671462904d4d27a355" + "hash": "5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde" } diff --git a/core/lib/dal/.sqlx/query-63f95c6cdcfd933e2cf8f62c0d408f2dce89f7b700896fcc0f242e0e15ba058e.json b/core/lib/dal/.sqlx/query-7f5993b00c1270d80e6081c3304fb7ce70b4aaa5c810c79d5bf854fe30c28fd4.json similarity index 69% rename from core/lib/dal/.sqlx/query-63f95c6cdcfd933e2cf8f62c0d408f2dce89f7b700896fcc0f242e0e15ba058e.json rename to core/lib/dal/.sqlx/query-7f5993b00c1270d80e6081c3304fb7ce70b4aaa5c810c79d5bf854fe30c28fd4.json index cb68e7622524..a2e9f4500961 100644 --- a/core/lib/dal/.sqlx/query-63f95c6cdcfd933e2cf8f62c0d408f2dce89f7b700896fcc0f242e0e15ba058e.json +++ b/core/lib/dal/.sqlx/query-7f5993b00c1270d80e6081c3304fb7ce70b4aaa5c810c79d5bf854fe30c28fd4.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n LEFT JOIN data_availability ON data_availability.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n AND events_queue_commitment IS NOT NULL\n AND bootloader_initial_content_commitment IS NOT NULL\n AND (\n data_availability.inclusion_data IS NOT NULL\n OR $4 IS FALSE\n )\n ORDER BY\n number\n LIMIT\n $5\n ", + "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n LEFT JOIN data_availability ON data_availability.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n AND events_queue_commitment IS NOT NULL\n AND bootloader_initial_content_commitment IS NOT NULL\n AND (\n data_availability.inclusion_data IS NOT NULL\n OR $4 IS FALSE\n )\n ORDER BY\n number\n LIMIT\n $5\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -166,11 +171,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "63f95c6cdcfd933e2cf8f62c0d408f2dce89f7b700896fcc0f242e0e15ba058e" + "hash": "7f5993b00c1270d80e6081c3304fb7ce70b4aaa5c810c79d5bf854fe30c28fd4" } diff --git a/core/lib/dal/.sqlx/query-45e52d05a4483def84c141e3529bab30553732953e589cd237595227044f438d.json b/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json similarity index 83% rename from core/lib/dal/.sqlx/query-45e52d05a4483def84c141e3529bab30553732953e589cd237595227044f438d.json rename to core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json index 74a6187e6444..287c69687e53 100644 --- a/core/lib/dal/.sqlx/query-45e52d05a4483def84c141e3529bab30553732953e589cd237595227044f438d.json +++ b/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -65,26 +65,31 @@ }, { "ordinal": 12, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" + }, + { + "ordinal": 13, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 13, + "ordinal": 14, "name": "virtual_blocks", "type_info": "Int8" }, { - "ordinal": 14, + "ordinal": 15, "name": "fair_pubdata_price", "type_info": "Int8" }, { - "ordinal": 15, + "ordinal": 16, "name": "gas_limit", "type_info": "Int8" }, { - "ordinal": 16, + "ordinal": 17, "name": "logs_bloom", "type_info": "Bytea" } @@ -108,11 +113,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "45e52d05a4483def84c141e3529bab30553732953e589cd237595227044f438d" + "hash": "922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e" } diff --git a/core/lib/dal/.sqlx/query-de255be5d2e5ef215428e9a886e7c9dc036873c60b8b916ce8c446e310447b66.json b/core/lib/dal/.sqlx/query-92d3a7d8c32c4575d6a225f0440b0ff9894b1de204599f4a4fd39cfde1020a3e.json similarity index 80% rename from core/lib/dal/.sqlx/query-de255be5d2e5ef215428e9a886e7c9dc036873c60b8b916ce8c446e310447b66.json rename to core/lib/dal/.sqlx/query-92d3a7d8c32c4575d6a225f0440b0ff9894b1de204599f4a4fd39cfde1020a3e.json index 8a492376557b..4a0c6ce38596 100644 --- a/core/lib/dal/.sqlx/query-de255be5d2e5ef215428e9a886e7c9dc036873c60b8b916ce8c446e310447b66.json +++ b/core/lib/dal/.sqlx/query-92d3a7d8c32c4575d6a225f0440b0ff9894b1de204599f4a4fd39cfde1020a3e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = 0\n OR eth_commit_tx_id IS NOT NULL\n AND commitment IS NOT NULL\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = 0\n OR eth_commit_tx_id IS NOT NULL\n AND commitment IS NOT NULL\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -160,11 +165,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "de255be5d2e5ef215428e9a886e7c9dc036873c60b8b916ce8c446e310447b66" + "hash": "92d3a7d8c32c4575d6a225f0440b0ff9894b1de204599f4a4fd39cfde1020a3e" } diff --git a/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json b/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json new file mode 100644 index 000000000000..52ef95716470 --- /dev/null +++ b/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json @@ -0,0 +1,31 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Bytea", + "Int4", + "Int4", + "Bytea", + "Numeric", + "Int8", + "Int8", + "Int8", + "Bytea", + "Bytea", + "Bytea", + "Int4", + "Int8", + "Int8", + "Int8", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400" +} diff --git a/core/lib/dal/.sqlx/query-52bb6de515e1edf4dcf34a31600edb31cfd855014dfca5041833b9d5d9f7a55e.json b/core/lib/dal/.sqlx/query-acf497b952de2d8f83cf2b96f2eb686d545c780b37430bdcf70fc55e80588b6b.json similarity index 80% rename from core/lib/dal/.sqlx/query-52bb6de515e1edf4dcf34a31600edb31cfd855014dfca5041833b9d5d9f7a55e.json rename to core/lib/dal/.sqlx/query-acf497b952de2d8f83cf2b96f2eb686d545c780b37430bdcf70fc55e80588b6b.json index b872e2ce6297..bfd2202608f4 100644 --- a/core/lib/dal/.sqlx/query-52bb6de515e1edf4dcf34a31600edb31cfd855014dfca5041833b9d5d9f7a55e.json +++ b/core/lib/dal/.sqlx/query-acf497b952de2d8f83cf2b96f2eb686d545c780b37430bdcf70fc55e80588b6b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n system_logs,\n compressed_state_diffs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND eth_prove_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", "describe": { "columns": [ { @@ -90,28 +90,28 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, - "name": "protocol_version", - "type_info": "Int4" + "name": "meta_parameters_hash", + "type_info": "Bytea" }, { "ordinal": 21, - "name": "system_logs", - "type_info": "ByteaArray" + "name": "protocol_version", + "type_info": "Int4" }, { "ordinal": 22, @@ -120,16 +120,21 @@ }, { "ordinal": 23, + "name": "system_logs", + "type_info": "ByteaArray" + }, + { + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -161,12 +166,13 @@ true, true, true, - false, true, true, + false, + true, true, true ] }, - "hash": "52bb6de515e1edf4dcf34a31600edb31cfd855014dfca5041833b9d5d9f7a55e" + "hash": "acf497b952de2d8f83cf2b96f2eb686d545c780b37430bdcf70fc55e80588b6b" } diff --git a/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json b/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json deleted file mode 100644 index 9ae9d2e50cde..000000000000 --- a/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 NOW(),\n NOW()\n )\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Bytea", - "Int4", - "Int4", - "Bytea", - "Numeric", - "Int8", - "Int8", - "Int8", - "Bytea", - "Bytea", - "Int4", - "Int8", - "Int8", - "Int8", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046" -} diff --git a/core/lib/dal/.sqlx/query-1074d0a2e4a4afb9a92f3822e133db7a71aca15698bafba051a8d9a91a4dbc76.json b/core/lib/dal/.sqlx/query-d7ee8998bdc54b0a68dadb79aae3a68e5e5cf16897de4b6e3211d5e1c07e9294.json similarity index 75% rename from core/lib/dal/.sqlx/query-1074d0a2e4a4afb9a92f3822e133db7a71aca15698bafba051a8d9a91a4dbc76.json rename to core/lib/dal/.sqlx/query-d7ee8998bdc54b0a68dadb79aae3a68e5e5cf16897de4b6e3211d5e1c07e9294.json index 13e4cdb9431d..b87cf7e99100 100644 --- a/core/lib/dal/.sqlx/query-1074d0a2e4a4afb9a92f3822e133db7a71aca15698bafba051a8d9a91a4dbc76.json +++ b/core/lib/dal/.sqlx/query-d7ee8998bdc54b0a68dadb79aae3a68e5e5cf16897de4b6e3211d5e1c07e9294.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH\n mb AS (\n SELECT\n l1_gas_price,\n l2_fair_gas_price,\n fair_pubdata_price\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n LIMIT\n 1\n )\n SELECT\n l1_batches.number,\n l1_batches.timestamp,\n l1_batches.l1_tx_count,\n l1_batches.l2_tx_count,\n l1_batches.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n mb.l1_gas_price,\n mb.l2_fair_gas_price,\n mb.fair_pubdata_price,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash\n FROM\n l1_batches\n INNER JOIN mb ON TRUE\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n l1_batches.number = $1\n ", + "query": "\n WITH\n mb AS (\n SELECT\n l1_gas_price,\n l2_fair_gas_price,\n fair_pubdata_price\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n LIMIT\n 1\n )\n SELECT\n l1_batches.number,\n l1_batches.timestamp,\n l1_batches.l1_tx_count,\n l1_batches.l2_tx_count,\n l1_batches.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n mb.l1_gas_price,\n mb.l2_fair_gas_price,\n mb.fair_pubdata_price,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash\n FROM\n l1_batches\n INNER JOIN mb ON TRUE\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n l1_batches.number = $1\n ", "describe": { "columns": [ { @@ -82,6 +82,11 @@ "ordinal": 15, "name": "default_aa_code_hash", "type_info": "Bytea" + }, + { + "ordinal": 16, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" } ], "parameters": { @@ -105,8 +110,9 @@ false, true, true, + true, true ] }, - "hash": "1074d0a2e4a4afb9a92f3822e133db7a71aca15698bafba051a8d9a91a4dbc76" + "hash": "d7ee8998bdc54b0a68dadb79aae3a68e5e5cf16897de4b6e3211d5e1c07e9294" } diff --git a/core/lib/dal/.sqlx/query-5d493cbce749cc5b56d4069423597b16599abaf51df0f19effe1a536376cf6a6.json b/core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json similarity index 52% rename from core/lib/dal/.sqlx/query-5d493cbce749cc5b56d4069423597b16599abaf51df0f19effe1a536376cf6a6.json rename to core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json index eba36994fb34..57e92a2dfa3f 100644 --- a/core/lib/dal/.sqlx/query-5d493cbce749cc5b56d4069423597b16599abaf51df0f19effe1a536376cf6a6.json +++ b/core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n bootloader_code_hash,\n default_account_code_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", + "query": "\n SELECT\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", "describe": { "columns": [ { @@ -12,6 +12,11 @@ "ordinal": 1, "name": "default_account_code_hash", "type_info": "Bytea" + }, + { + "ordinal": 2, + "name": "evm_simulator_code_hash", + "type_info": "Bytea" } ], "parameters": { @@ -21,8 +26,9 @@ }, "nullable": [ false, - false + false, + true ] }, - "hash": "5d493cbce749cc5b56d4069423597b16599abaf51df0f19effe1a536376cf6a6" + "hash": "e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554" } diff --git a/core/lib/dal/.sqlx/query-b7cd7c40282c2ca2287eef93ee79c69a9e494bf1f873291b4ae7bf68b7e3c549.json b/core/lib/dal/.sqlx/query-ebb6c005f99d144963d487841d6e1bc51d4f949f0941156021a4844ed8c959ca.json similarity index 74% rename from core/lib/dal/.sqlx/query-b7cd7c40282c2ca2287eef93ee79c69a9e494bf1f873291b4ae7bf68b7e3c549.json rename to core/lib/dal/.sqlx/query-ebb6c005f99d144963d487841d6e1bc51d4f949f0941156021a4844ed8c959ca.json index ed4744206a48..a9f43d749df1 100644 --- a/core/lib/dal/.sqlx/query-b7cd7c40282c2ca2287eef93ee79c69a9e494bf1f873291b4ae7bf68b7e3c549.json +++ b/core/lib/dal/.sqlx/query-ebb6c005f99d144963d487841d6e1bc51d4f949f0941156021a4844ed8c959ca.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n ORDER BY\n number\n LIMIT\n $4\n ", + "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n ORDER BY\n number\n LIMIT\n $4\n ", "describe": { "columns": [ { @@ -90,46 +90,51 @@ }, { "ordinal": 17, - "name": "aux_data_hash", + "name": "evm_simulator_code_hash", "type_info": "Bytea" }, { "ordinal": 18, - "name": "pass_through_data_hash", + "name": "aux_data_hash", "type_info": "Bytea" }, { "ordinal": 19, - "name": "meta_parameters_hash", + "name": "pass_through_data_hash", "type_info": "Bytea" }, { "ordinal": 20, + "name": "meta_parameters_hash", + "type_info": "Bytea" + }, + { + "ordinal": 21, "name": "protocol_version", "type_info": "Int4" }, { - "ordinal": 21, + "ordinal": 22, "name": "compressed_state_diffs", "type_info": "Bytea" }, { - "ordinal": 22, + "ordinal": 23, "name": "system_logs", "type_info": "ByteaArray" }, { - "ordinal": 23, + "ordinal": 24, "name": "events_queue_commitment", "type_info": "Bytea" }, { - "ordinal": 24, + "ordinal": 25, "name": "bootloader_initial_content_commitment", "type_info": "Bytea" }, { - "ordinal": 25, + "ordinal": 26, "name": "pubdata_input", "type_info": "Bytea" } @@ -165,11 +170,12 @@ true, true, true, + true, false, true, true, true ] }, - "hash": "b7cd7c40282c2ca2287eef93ee79c69a9e494bf1f873291b4ae7bf68b7e3c549" + "hash": "ebb6c005f99d144963d487841d6e1bc51d4f949f0941156021a4844ed8c959ca" } diff --git a/core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json b/core/lib/dal/.sqlx/query-ff68458acd9c98120bf4a6814c1985d2efa5902269f3b5ad17b0259c3526877f.json similarity index 52% rename from core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json rename to core/lib/dal/.sqlx/query-ff68458acd9c98120bf4a6814c1985d2efa5902269f3b5ad17b0259c3526877f.json index ee88bcdf39bd..5d8b7ffae83f 100644 --- a/core/lib/dal/.sqlx/query-25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633.json +++ b/core/lib/dal/.sqlx/query-ff68458acd9c98120bf4a6814c1985d2efa5902269f3b5ad17b0259c3526877f.json @@ -1,6 +1,6 @@ { "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 ", + "query": "\n INSERT INTO\n protocol_versions (\n id,\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash,\n upgrade_tx_hash,\n created_at\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, NOW())\n ON CONFLICT DO NOTHING\n ", "describe": { "columns": [], "parameters": { @@ -9,10 +9,11 @@ "Int8", "Bytea", "Bytea", + "Bytea", "Bytea" ] }, "nullable": [] }, - "hash": "25fb31277591dd7d5d783bd8777f1a855e76b37b6ed36ae612b551f9a6a55633" + "hash": "ff68458acd9c98120bf4a6814c1985d2efa5902269f3b5ad17b0259c3526877f" } diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql new file mode 100644 index 000000000000..999728809a5e --- /dev/null +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE protocol_versions DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; +ALTER TABLE l1_batches DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; +ALTER TABLE miniblocks DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql new file mode 100644 index 000000000000..ea8e0a83d20c --- /dev/null +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE protocol_versions ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; +ALTER TABLE l1_batches ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; +ALTER TABLE miniblocks ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 1f4cc3b0b98c..5d82dc18d48c 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -325,6 +325,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -366,6 +367,7 @@ impl BlocksDal<'_, '_> { used_contract_hashes, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, system_logs, pubdata_input @@ -610,6 +612,7 @@ impl BlocksDal<'_, '_> { used_contract_hashes, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, system_logs, storage_refunds, @@ -641,6 +644,7 @@ impl BlocksDal<'_, '_> { $18, $19, $20, + $21, NOW(), NOW() ) @@ -659,6 +663,7 @@ impl BlocksDal<'_, '_> { used_contract_hashes, header.base_system_contracts_hashes.bootloader.as_bytes(), header.base_system_contracts_hashes.default_aa.as_bytes(), + header.base_system_contracts_hashes.evm_simulator.as_bytes(), header.protocol_version.map(|v| v as i32), &system_logs, &storage_refunds, @@ -703,6 +708,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -730,6 +736,7 @@ impl BlocksDal<'_, '_> { $15, $16, $17, + $18, NOW(), NOW() ) @@ -752,6 +759,10 @@ impl BlocksDal<'_, '_> { .base_system_contracts_hashes .default_aa .as_bytes(), + l2_block_header + .base_system_contracts_hashes + .evm_simulator + .as_bytes(), l2_block_header.protocol_version.map(|v| v as i32), i64::from(l2_block_header.virtual_blocks), l2_block_header.batch_fee_input.fair_pubdata_price() as i64, @@ -780,6 +791,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -820,6 +832,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -1031,6 +1044,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1211,6 +1225,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1291,6 +1306,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1364,6 +1380,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1489,6 +1506,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1553,6 +1571,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, l1_batches.bootloader_code_hash, l1_batches.default_aa_code_hash, + l1_batches.evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1631,6 +1650,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, l1_batches.bootloader_code_hash, l1_batches.default_aa_code_hash, + l1_batches.evm_simulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 36a4acc0a6db..78c01dc1f6b0 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -663,6 +663,7 @@ impl BlocksWeb3Dal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, + miniblocks.evm_simulator_code_hash, miniblocks.protocol_version, miniblocks.fee_account_address FROM @@ -730,7 +731,8 @@ impl BlocksWeb3Dal<'_, '_> { mb.l2_fair_gas_price, mb.fair_pubdata_price, l1_batches.bootloader_code_hash, - l1_batches.default_aa_code_hash + l1_batches.default_aa_code_hash, + l1_batches.evm_simulator_code_hash FROM l1_batches INNER JOIN mb ON TRUE diff --git a/core/lib/dal/src/factory_deps_dal.rs b/core/lib/dal/src/factory_deps_dal.rs index 02ce32306cfb..6731b05166dc 100644 --- a/core/lib/dal/src/factory_deps_dal.rs +++ b/core/lib/dal/src/factory_deps_dal.rs @@ -94,6 +94,7 @@ impl FactoryDepsDal<'_, '_> { &mut self, bootloader_hash: H256, default_aa_hash: H256, + evm_simulator_hash: H256, ) -> anyhow::Result { let bootloader_bytecode = self .get_sealed_factory_dep(bootloader_hash) @@ -115,9 +116,22 @@ impl FactoryDepsDal<'_, '_> { code: bytes_to_be_words(default_aa_bytecode), hash: default_aa_hash, }; + + let evm_simulator_bytecode = self + .get_sealed_factory_dep(evm_simulator_hash) + .await + .context("failed loading evm simulator code")? + .with_context(|| format!("evm simulator code with hash {default_aa_hash:?} should be present in the database"))?; + + let evm_simulator_code = SystemContractCode { + code: bytes_to_be_words(evm_simulator_bytecode), + hash: evm_simulator_hash, + }; + Ok(BaseSystemContracts { bootloader: bootloader_code, default_aa: default_aa_code, + evm_simulator: evm_simulator_code, }) } diff --git a/core/lib/dal/src/models/storage_block.rs b/core/lib/dal/src/models/storage_block.rs index 34e14387ca61..a98049e8ac6d 100644 --- a/core/lib/dal/src/models/storage_block.rs +++ b/core/lib/dal/src/models/storage_block.rs @@ -44,6 +44,7 @@ pub(crate) struct StorageL1BatchHeader { pub used_contract_hashes: serde_json::Value, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, pub protocol_version: Option, // `system_logs` are introduced as part of boojum and will be absent in all batches generated prior to boojum. @@ -82,6 +83,7 @@ impl StorageL1BatchHeader { base_system_contracts_hashes: convert_base_system_contracts_hashes( self.bootloader_code_hash, self.default_aa_code_hash, + self.evm_simulator_code_hash, ), system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: self @@ -103,6 +105,7 @@ fn convert_l2_to_l1_logs(raw_logs: Vec>) -> Vec { fn convert_base_system_contracts_hashes( bootloader_code_hash: Option>, default_aa_code_hash: Option>, + evm_simulator_code_hash: Option>, ) -> BaseSystemContractsHashes { BaseSystemContractsHashes { bootloader: bootloader_code_hash @@ -111,6 +114,9 @@ fn convert_base_system_contracts_hashes( default_aa: default_aa_code_hash .map(|hash| H256::from_slice(&hash)) .expect("should not be none"), + evm_simulator: evm_simulator_code_hash + .map(|hash| H256::from_slice(&hash)) + .expect("should not be none"), } } @@ -134,6 +140,7 @@ pub(crate) struct StorageL1Batch { pub zkporter_is_available: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, pub l2_to_l1_messages: Vec>, pub l2_l1_merkle_root: Option>, @@ -177,6 +184,7 @@ impl StorageL1Batch { base_system_contracts_hashes: convert_base_system_contracts_hashes( self.bootloader_code_hash, self.default_aa_code_hash, + self.evm_simulator_code_hash, ), system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: self @@ -240,6 +248,11 @@ impl TryFrom for L1BatchMetadata { .default_aa_code_hash .ok_or(L1BatchMetadataError::Incomplete("default_aa_code_hash"))?, ), + evm_simulator_code_hash: H256::from_slice( + &batch + .evm_simulator_code_hash + .ok_or(L1BatchMetadataError::Incomplete("evm_simulator_code_hash"))?, + ), protocol_version: batch .protocol_version .map(|v| (v as u16).try_into().unwrap()), @@ -275,6 +288,7 @@ pub(crate) struct StorageBlockDetails { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, pub fee_account_address: Vec, pub protocol_version: Option, } @@ -320,6 +334,7 @@ impl From for api::BlockDetails { base_system_contracts_hashes: convert_base_system_contracts_hashes( details.bootloader_code_hash, details.default_aa_code_hash, + details.evm_simulator_code_hash, ), }; api::BlockDetails { @@ -352,6 +367,7 @@ pub(crate) struct StorageL1BatchDetails { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, } impl From for api::L1BatchDetails { @@ -395,6 +411,7 @@ impl From for api::L1BatchDetails { base_system_contracts_hashes: convert_base_system_contracts_hashes( details.bootloader_code_hash, details.default_aa_code_hash, + details.evm_simulator_code_hash, ), }; api::L1BatchDetails { @@ -418,6 +435,7 @@ pub(crate) struct StorageL2BlockHeader { // L2 gas price assumed in the corresponding batch pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, pub protocol_version: Option, pub fair_pubdata_price: Option, @@ -471,6 +489,7 @@ impl From for L2BlockHeader { base_system_contracts_hashes: convert_base_system_contracts_hashes( row.bootloader_code_hash, row.default_aa_code_hash, + row.evm_simulator_code_hash, ), gas_per_pubdata_limit: row.gas_per_pubdata_limit as u64, protocol_version, diff --git a/core/lib/dal/src/models/storage_protocol_version.rs b/core/lib/dal/src/models/storage_protocol_version.rs index e53bf7b9d0a4..a1a61bd0670f 100644 --- a/core/lib/dal/src/models/storage_protocol_version.rs +++ b/core/lib/dal/src/models/storage_protocol_version.rs @@ -16,6 +16,7 @@ pub struct StorageProtocolVersion { pub snark_wrapper_vk_hash: Vec, pub bootloader_code_hash: Vec, pub default_account_code_hash: Vec, + pub evm_simulator_code_hash: Option>, } pub(crate) fn protocol_version_from_storage( @@ -34,6 +35,11 @@ pub(crate) fn protocol_version_from_storage( base_system_contracts_hashes: BaseSystemContractsHashes { bootloader: H256::from_slice(&storage_version.bootloader_code_hash), default_aa: H256::from_slice(&storage_version.default_account_code_hash), + evm_simulator: H256::from_slice( + &storage_version + .evm_simulator_code_hash + .unwrap_or(H256::zero().as_bytes().to_vec()), + ), }, tx, } @@ -45,6 +51,7 @@ pub struct StorageApiProtocolVersion { pub timestamp: i64, pub bootloader_code_hash: Vec, pub default_account_code_hash: Vec, + pub evm_simulator_code_hash: Option>, pub upgrade_tx_hash: Option>, } @@ -60,6 +67,11 @@ impl From for api::ProtocolVersion { storage_protocol_version.timestamp as u64, H256::from_slice(&storage_protocol_version.bootloader_code_hash), H256::from_slice(&storage_protocol_version.default_account_code_hash), + H256::from_slice( + &storage_protocol_version + .evm_simulator_code_hash + .unwrap_or(H256::zero().as_bytes().to_vec()), + ), l2_system_upgrade_tx_hash, ) } diff --git a/core/lib/dal/src/models/storage_sync.rs b/core/lib/dal/src/models/storage_sync.rs index 688a6f997904..0fb7527aa42a 100644 --- a/core/lib/dal/src/models/storage_sync.rs +++ b/core/lib/dal/src/models/storage_sync.rs @@ -22,6 +22,7 @@ pub(crate) struct StorageSyncBlock { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, + pub evm_simulator_code_hash: Option>, pub fee_account_address: Vec, pub protocol_version: i32, pub virtual_blocks: i64, @@ -75,6 +76,8 @@ impl TryFrom for SyncBlock { .decode_column("bootloader_code_hash")?, default_aa: parse_h256_opt(block.default_aa_code_hash.as_deref()) .decode_column("default_aa_code_hash")?, + evm_simulator: parse_h256_opt(block.evm_simulator_code_hash.as_deref()) + .decode_column("evm_simulator_code_hash")?, }, fee_account_address: parse_h160(&block.fee_account_address) .decode_column("fee_account_address")?, diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 9f67e9025e0c..746026af73e5 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -364,12 +364,10 @@ impl From for TransactionReceipt { to: storage_receipt .transfer_to .or(storage_receipt.execute_contract_address) - .map(|addr| { - serde_json::from_value::
(addr) + .and_then(|addr| { + serde_json::from_value::>(addr) .expect("invalid address value in the database") - }) - // For better compatibility with various clients, we never return null. - .or_else(|| Some(Address::default())), + }), cumulative_gas_used: Default::default(), // TODO: Should be actually calculated (SMA-1183). gas_used: { let refunded_gas: U256 = storage_receipt.refunded_gas.into(); @@ -508,6 +506,12 @@ impl StorageApiTransaction { .signature .and_then(|signature| PackedEthSignature::deserialize_packed(&signature).ok()); + let to = if let Ok(address) = serde_json::from_value(self.execute_contract_address) { + Some(address) + } else { + Some(Address::zero()) + }; + // For legacy and EIP-2930 transactions it is gas price willing to be paid by the sender in wei. // For other transactions it should be the effective gas price if transaction is included in block, // otherwise this value should be set equal to the max fee per gas. @@ -528,7 +532,7 @@ impl StorageApiTransaction { block_number: self.block_number.map(|number| U64::from(number as u64)), transaction_index: self.index_in_block.map(|idx| U64::from(idx as u64)), from: Some(Address::from_slice(&self.initiator_address)), - to: Some(serde_json::from_value(self.execute_contract_address).unwrap()), + to, value: bigdecimal_to_u256(self.value), gas_price: Some(bigdecimal_to_u256(gas_price)), gas: bigdecimal_to_u256(self.gas_limit.unwrap_or_else(BigDecimal::zero)), diff --git a/core/lib/dal/src/protocol_versions_dal.rs b/core/lib/dal/src/protocol_versions_dal.rs index 8cb5094fd49e..d01ae3a52ac8 100644 --- a/core/lib/dal/src/protocol_versions_dal.rs +++ b/core/lib/dal/src/protocol_versions_dal.rs @@ -45,17 +45,19 @@ impl ProtocolVersionsDal<'_, '_> { timestamp, bootloader_code_hash, default_account_code_hash, + evm_simulator_code_hash, upgrade_tx_hash, created_at ) VALUES - ($1, $2, $3, $4, $5, NOW()) + ($1, $2, $3, $4, $5, $6, NOW()) ON CONFLICT DO NOTHING "#, version.minor as i32, timestamp as i64, base_system_contracts_hashes.bootloader.as_bytes(), base_system_contracts_hashes.default_aa.as_bytes(), + base_system_contracts_hashes.evm_simulator.as_bytes(), tx_hash.as_ref().map(H256::as_bytes), ) .instrument("save_protocol_version#minor") @@ -193,7 +195,8 @@ impl ProtocolVersionsDal<'_, '_> { r#" SELECT bootloader_code_hash, - default_account_code_hash + default_account_code_hash, + evm_simulator_code_hash FROM protocol_versions WHERE @@ -212,6 +215,10 @@ impl ProtocolVersionsDal<'_, '_> { .get_base_system_contracts( H256::from_slice(&row.bootloader_code_hash), H256::from_slice(&row.default_account_code_hash), + H256::from_slice( + &row.evm_simulator_code_hash + .unwrap_or(H256::zero().as_bytes().to_vec()), + ), ) .await?; Some(contracts) @@ -232,6 +239,7 @@ impl ProtocolVersionsDal<'_, '_> { protocol_versions.timestamp, protocol_versions.bootloader_code_hash, protocol_versions.default_account_code_hash, + protocol_versions.evm_simulator_code_hash, protocol_patches.patch, protocol_patches.snark_wrapper_vk_hash FROM diff --git a/core/lib/dal/src/protocol_versions_web3_dal.rs b/core/lib/dal/src/protocol_versions_web3_dal.rs index a3a7a162c3dd..05a93ea1b098 100644 --- a/core/lib/dal/src/protocol_versions_web3_dal.rs +++ b/core/lib/dal/src/protocol_versions_web3_dal.rs @@ -21,6 +21,7 @@ impl ProtocolVersionsWeb3Dal<'_, '_> { timestamp, bootloader_code_hash, default_account_code_hash, + evm_simulator_code_hash, upgrade_tx_hash FROM protocol_versions diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index ec6ee0f92812..22c72fc4d152 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -50,6 +50,7 @@ impl SyncDal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, + miniblocks.evm_simulator_code_hash, miniblocks.virtual_blocks, miniblocks.hash, miniblocks.protocol_version AS "protocol_version!", diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index dc672fa1f807..dd725aeda3ee 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -61,6 +61,7 @@ pub(crate) fn create_l1_batch_header(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), + evm_simulator: H256::repeat_byte(43), }, ProtocolVersionId::latest(), ) From 723c5e3ab18cd294b3d92606bf410642f436685e Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 16:49:44 -0300 Subject: [PATCH 03/72] Add evm simulator as base system contract and update callers --- core/bin/genesis_generator/src/main.rs | 1 + .../system-constants-generator/src/utils.rs | 16 ++ core/lib/config/src/configs/chain.rs | 3 + core/lib/config/src/configs/genesis.rs | 2 + core/lib/config/src/testonly.rs | 2 + core/lib/constants/src/contracts.rs | 5 + core/lib/contracts/Cargo.toml | 2 + core/lib/contracts/src/lib.rs | 18 ++ core/lib/env_config/src/chain.rs | 11 +- core/lib/env_config/src/genesis.rs | 1 + core/lib/multivm/Cargo.toml | 2 + .../src/glue/types/vm/vm_block_result.rs | 6 + .../types/vm/vm_partial_execution_result.rs | 3 + .../glue/types/vm/vm_tx_execution_result.rs | 5 + .../vm_1_4_1/implementation/execution.rs | 1 + .../vm_1_4_1/tests/get_used_contracts.rs | 14 +- .../vm_1_4_2/implementation/execution.rs | 1 + .../src/versions/vm_1_4_2/tests/circuits.rs | 2 +- .../vm_1_4_2/tests/get_used_contracts.rs | 18 +- .../implementation/execution.rs | 1 + .../tests/get_used_contracts.rs | 18 +- .../vm_fast/tests/get_used_contracts.rs | 17 +- .../versions/vm_fast/tests/l1_tx_execution.rs | 7 +- .../versions/vm_fast/tests/nonce_holder.rs | 11 +- .../src/versions/vm_fast/tests/rollbacks.rs | 46 ++- .../tests/tester/transaction_test_info.rs | 71 ++--- core/lib/multivm/src/versions/vm_fast/vm.rs | 24 +- .../vm_latest/implementation/execution.rs | 8 + .../vm_latest/old_vm/oracles/decommitter.rs | 76 +++-- .../src/versions/vm_latest/tests/circuits.rs | 2 +- .../vm_latest/tests/get_used_contracts.rs | 17 +- .../vm_latest/tests/l1_tx_execution.rs | 7 +- .../src/versions/vm_latest/tests/migration.rs | 51 ---- .../src/versions/vm_latest/tests/mod.rs | 1 - .../versions/vm_latest/tests/nonce_holder.rs | 11 +- .../src/versions/vm_latest/tests/rollbacks.rs | 47 +++- .../tests/tester/transaction_test_info.rs | 73 +++-- .../vm_latest/tracers/default_tracers.rs | 13 +- .../vm_latest/tracers/evm_deploy_tracer.rs | 106 +++++++ .../src/versions/vm_latest/tracers/mod.rs | 2 + .../types/internals/transaction_data.rs | 8 +- .../vm_latest/types/internals/vm_state.rs | 16 +- .../src/versions/vm_latest/utils/mod.rs | 52 ++++ core/lib/multivm/src/versions/vm_latest/vm.rs | 20 +- .../implementation/execution.rs | 1 + .../tests/get_used_contracts.rs | 16 +- .../implementation/execution.rs | 1 + .../tests/get_used_contracts.rs | 18 +- core/lib/protobuf_config/src/chain.rs | 1 + core/lib/protobuf_config/src/genesis.rs | 6 + .../src/proto/config/genesis.proto | 1 + core/lib/prover_interface/src/inputs.rs | 1 + core/lib/tee_verifier/src/lib.rs | 4 + core/lib/types/src/abi.rs | 9 +- core/lib/types/src/api/mod.rs | 16 +- core/lib/types/src/commitment/mod.rs | 13 +- .../tests/post_boojum_1_4_1_test.json | 6 +- .../tests/post_boojum_1_4_2_test.json | 6 +- .../tests/post_boojum_1_5_0_test.json | 6 +- .../src/commitment/tests/pre_boojum_test.json | 6 +- core/lib/types/src/protocol_upgrade.rs | 8 + core/lib/types/src/storage/mod.rs | 11 +- core/lib/types/src/system_contracts.rs | 26 +- core/lib/vm_executor/src/oneshot/mock.rs | 1 + core/lib/vm_executor/src/storage.rs | 6 +- core/lib/vm_interface/Cargo.toml | 1 + .../lib/vm_interface/src/storage/in_memory.rs | 12 +- .../src/types/outputs/execution_result.rs | 1 + .../src/types/outputs/finished_l1batch.rs | 1 + .../node/api_server/src/web3/namespaces/en.rs | 6 + core/node/api_server/src/web3/tests/vm.rs | 1 + core/node/commitment_generator/src/lib.rs | 1 + core/node/eth_sender/src/eth_tx_aggregator.rs | 27 +- core/node/eth_sender/src/tests.rs | 6 +- core/node/eth_sender/src/zksync_functions.rs | 4 + core/node/eth_watch/src/tests.rs | 1 + core/node/genesis/src/lib.rs | 8 + core/node/genesis/src/utils.rs | 12 +- core/node/node_sync/src/external_io.rs | 9 + core/node/node_sync/src/genesis.rs | 11 + core/node/node_sync/src/tests.rs | 8 + core/node/proof_data_handler/src/tests.rs | 4 + core/node/state_keeper/src/executor/mod.rs | 2 +- core/node/state_keeper/src/io/persistence.rs | 1 + core/node/state_keeper/src/io/tests/mod.rs | 4 + core/node/state_keeper/src/keeper.rs | 9 +- .../state_keeper/src/seal_criteria/mod.rs | 1 + core/node/state_keeper/src/testonly/mod.rs | 1 + .../src/testonly/test_batch_executor.rs | 2 + core/node/state_keeper/src/tests/mod.rs | 1 + .../src/updates/l1_batch_updates.rs | 1 + .../src/updates/l2_block_updates.rs | 40 +-- core/node/state_keeper/src/updates/mod.rs | 6 +- core/node/test_utils/src/lib.rs | 14 +- core/node/vm_runner/src/impls/bwip.rs | 17 ++ core/node/vm_runner/src/tests/mod.rs | 4 + .../vm_runner/src/tests/output_handler.rs | 4 + etc/env/base/chain.toml | 5 +- etc/env/base/contracts.toml | 6 +- etc/env/file_based/genesis.yaml | 5 +- .../src/l2upgrade/deployer.ts | 4 + prover/Cargo.lock | 266 ++++++++++++++++++ .../witness_generator/src/basic_circuits.rs | 3 +- .../forge_interface/deploy_ecosystem/input.rs | 2 + 104 files changed, 1149 insertions(+), 343 deletions(-) delete mode 100644 core/lib/multivm/src/versions/vm_latest/tests/migration.rs create mode 100644 core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs diff --git a/core/bin/genesis_generator/src/main.rs b/core/bin/genesis_generator/src/main.rs index abdd6091ed73..c90daac46b1c 100644 --- a/core/bin/genesis_generator/src/main.rs +++ b/core/bin/genesis_generator/src/main.rs @@ -91,6 +91,7 @@ async fn generate_new_config( genesis_commitment: None, bootloader_hash: Some(base_system_contracts.bootloader), default_aa_hash: Some(base_system_contracts.default_aa), + evm_simulator_hash: Some(base_system_contracts.evm_simulator), ..genesis_config }; diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 664ae0ebdb16..989b235de61c 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -71,12 +71,19 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); BaseSystemContracts { default_aa: SystemContractCode { code: bytes_to_be_words(bytecode), hash, }, bootloader, + evm_simulator: SystemContractCode { + code: bytes_to_be_words(evm_simulator_bytecode), + hash: evm_simulator_hash, + }, } }); @@ -219,9 +226,18 @@ pub(super) fn execute_internal_transfer_test() -> u32 { hash, }; + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + let evm_simulator = SystemContractCode { + code: bytes_to_be_words(evm_simulator_bytecode), + hash: evm_simulator_hash, + }; + let base_system_smart_contracts = BaseSystemContracts { bootloader, default_aa, + evm_simulator, }; let system_env = SystemEnv { diff --git a/core/lib/config/src/configs/chain.rs b/core/lib/config/src/configs/chain.rs index 7e33f6964bb7..e24865fabbbd 100644 --- a/core/lib/config/src/configs/chain.rs +++ b/core/lib/config/src/configs/chain.rs @@ -138,6 +138,8 @@ pub struct StateKeeperConfig { pub bootloader_hash: Option, #[deprecated(note = "Use GenesisConfig::default_aa_hash instead")] pub default_aa_hash: Option, + #[deprecated(note = "Use GenesisConfig::evm_simulator_hash instead")] + pub evm_simulator_hash: Option, #[deprecated(note = "Use GenesisConfig::l1_batch_commit_data_generator_mode instead")] #[serde(default)] pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, @@ -178,6 +180,7 @@ impl StateKeeperConfig { protective_reads_persistence_enabled: true, bootloader_hash: None, default_aa_hash: None, + evm_simulator_hash: None, l1_batch_commit_data_generator_mode: L1BatchCommitmentMode::Rollup, } } diff --git a/core/lib/config/src/configs/genesis.rs b/core/lib/config/src/configs/genesis.rs index 6c4bacc3a6e2..3a962b18410d 100644 --- a/core/lib/config/src/configs/genesis.rs +++ b/core/lib/config/src/configs/genesis.rs @@ -17,6 +17,7 @@ pub struct GenesisConfig { pub genesis_commitment: Option, pub bootloader_hash: Option, pub default_aa_hash: Option, + pub evm_simulator_hash: Option, pub l1_chain_id: L1ChainId, pub sl_chain_id: Option, pub l2_chain_id: L2ChainId, @@ -49,6 +50,7 @@ impl GenesisConfig { genesis_commitment: Some(H256::repeat_byte(0x17)), bootloader_hash: Default::default(), default_aa_hash: Default::default(), + evm_simulator_hash: Default::default(), l1_chain_id: L1ChainId(9), sl_chain_id: None, protocol_version: Some(ProtocolSemanticVersion { diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index bc3b6025b15a..f6e6fcafdb5e 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -185,6 +185,7 @@ impl Distribution for EncodeDist { fee_account_addr: None, bootloader_hash: None, default_aa_hash: None, + evm_simulator_hash: None, l1_batch_commit_data_generator_mode: Default::default(), } } @@ -724,6 +725,7 @@ impl Distribution for EncodeDist { genesis_commitment: Some(rng.gen()), bootloader_hash: Some(rng.gen()), default_aa_hash: Some(rng.gen()), + evm_simulator_hash: Some(rng.gen()), fee_account: rng.gen(), l1_chain_id: L1ChainId(self.sample(rng)), sl_chain_id: None, diff --git a/core/lib/constants/src/contracts.rs b/core/lib/constants/src/contracts.rs index 44bb05a89764..3edfc3585d92 100644 --- a/core/lib/constants/src/contracts.rs +++ b/core/lib/constants/src/contracts.rs @@ -125,6 +125,11 @@ pub const CODE_ORACLE_ADDRESS: Address = H160([ 0x00, 0x00, 0x80, 0x12, ]); +pub const EVM_GAS_MANAGER_ADDRESS: Address = H160([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x13, +]); + /// Note, that the `Create2Factory` is explicitly deployed on a non-system-contract address. pub const CREATE2_FACTORY_ADDRESS: Address = H160([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/core/lib/contracts/Cargo.toml b/core/lib/contracts/Cargo.toml index 2b80295cf440..26372a02a096 100644 --- a/core/lib/contracts/Cargo.toml +++ b/core/lib/contracts/Cargo.toml @@ -12,6 +12,8 @@ categories.workspace = true [dependencies] zksync_utils.workspace = true +zksync_config.workspace = true +zksync_env_config.workspace = true ethabi.workspace = true serde_json.workspace = true diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index f57649c9d695..5ab977a5dfd5 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -193,6 +193,10 @@ pub fn deployer_contract() -> Contract { load_sys_contract("ContractDeployer") } +pub fn known_code_storage_contract() -> Contract { + load_sys_contract("KnownCodesStorage") +} + pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } @@ -303,18 +307,21 @@ pub struct SystemContractCode { pub struct BaseSystemContracts { pub bootloader: SystemContractCode, pub default_aa: SystemContractCode, + pub evm_simulator: SystemContractCode, } #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)] pub struct BaseSystemContractsHashes { pub bootloader: H256, pub default_aa: H256, + pub evm_simulator: H256, } impl PartialEq for BaseSystemContracts { fn eq(&self, other: &Self) -> bool { self.bootloader.hash == other.bootloader.hash && self.default_aa.hash == other.default_aa.hash + && self.evm_simulator.hash == other.evm_simulator.hash } } @@ -335,9 +342,19 @@ impl BaseSystemContracts { hash, }; + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + + let evm_simulator = SystemContractCode { + code: bytes_to_be_words(evm_simulator_bytecode), + hash: evm_simulator_hash, + }; + BaseSystemContracts { bootloader, default_aa, + evm_simulator, } } // BaseSystemContracts with proved bootloader - for handling transactions. @@ -474,6 +491,7 @@ impl BaseSystemContracts { BaseSystemContractsHashes { bootloader: self.bootloader.hash, default_aa: self.default_aa.hash, + evm_simulator: self.evm_simulator.hash, } } } diff --git a/core/lib/env_config/src/chain.rs b/core/lib/env_config/src/chain.rs index a25c593bd881..ca2c51803ba2 100644 --- a/core/lib/env_config/src/chain.rs +++ b/core/lib/env_config/src/chain.rs @@ -97,10 +97,13 @@ mod tests { validation_computational_gas_limit: 10_000_000, save_call_traces: false, bootloader_hash: Some(hash( - "0x010007ede999d096c84553fb514d3d6ca76fbf39789dda76bfeda9f3ae06236e", + "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1", )), default_aa_hash: Some(hash( - "0x0100055b041eb28aff6e3a6e0f37c31fd053fc9ef142683b05e5f0aee6934066", + "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2", + )), + evm_simulator_hash: Some(hash( + "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", )), l1_batch_commit_data_generator_mode, max_circuits_per_batch: 24100, @@ -135,8 +138,8 @@ mod tests { CHAIN_STATE_KEEPER_FEE_MODEL_VERSION="V2" CHAIN_STATE_KEEPER_VALIDATION_COMPUTATIONAL_GAS_LIMIT="10000000" CHAIN_STATE_KEEPER_SAVE_CALL_TRACES="false" - CHAIN_STATE_KEEPER_BOOTLOADER_HASH=0x010007ede999d096c84553fb514d3d6ca76fbf39789dda76bfeda9f3ae06236e - CHAIN_STATE_KEEPER_DEFAULT_AA_HASH=0x0100055b041eb28aff6e3a6e0f37c31fd053fc9ef142683b05e5f0aee6934066 + CHAIN_STATE_KEEPER_BOOTLOADER_HASH=0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1 + CHAIN_STATE_KEEPER_DEFAULT_AA_HASH=0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2 CHAIN_STATE_KEEPER_PROTECTIVE_READS_PERSISTENCE_ENABLED=true CHAIN_STATE_KEEPER_L1_BATCH_COMMIT_DATA_GENERATOR_MODE="{l1_batch_commit_data_generator_mode}" "# diff --git a/core/lib/env_config/src/genesis.rs b/core/lib/env_config/src/genesis.rs index bf30fd4cc339..6d1927828641 100644 --- a/core/lib/env_config/src/genesis.rs +++ b/core/lib/env_config/src/genesis.rs @@ -68,6 +68,7 @@ impl FromEnv for GenesisConfig { genesis_commitment: contracts_config.genesis_batch_commitment, bootloader_hash: state_keeper.bootloader_hash, default_aa_hash: state_keeper.default_aa_hash, + evm_simulator_hash: state_keeper.evm_simulator_hash, // TODO(EVM-676): for now, the settlement layer is always the same as the L1 network l1_chain_id: L1ChainId(network_config.network.chain_id().0), sl_chain_id: Some(network_config.network.chain_id()), diff --git a/core/lib/multivm/Cargo.toml b/core/lib/multivm/Cargo.toml index 4711eefa0d6c..28495da33021 100644 --- a/core/lib/multivm/Cargo.toml +++ b/core/lib/multivm/Cargo.toml @@ -29,6 +29,7 @@ zksync_contracts.workspace = true zksync_utils.workspace = true zksync_system_constants.workspace = true zksync_vm_interface.workspace = true +zksync_state.workspace = true anyhow.workspace = true hex.workspace = true @@ -38,6 +39,7 @@ pretty_assertions.workspace = true thiserror.workspace = true tracing.workspace = true vise.workspace = true +ethabi.workspace = true [dev-dependencies] assert_matches.workspace = true diff --git a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs index ce928e652d76..6ef9b2947746 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs @@ -47,6 +47,7 @@ impl GlueFrom for crate::interface::Fi circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -103,6 +104,7 @@ impl GlueFrom for crate::interface::Fi circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -158,6 +160,7 @@ impl GlueFrom for crate::interface: circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -227,6 +230,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), } } } @@ -259,6 +263,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), } } } @@ -307,6 +312,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), } } } diff --git a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs index 3cb61b461a42..1891330b6d29 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs @@ -22,6 +22,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, + new_known_factory_deps: Default::default(), } } } @@ -48,6 +49,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, + new_known_factory_deps: Default::default(), } } } @@ -74,6 +76,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, + new_known_factory_deps: Default::default(), } } } diff --git a/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs index 2dc680ba77d9..2ea1e3984c47 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs @@ -66,12 +66,14 @@ impl GlueFrom VmExecutionResultAndLogs { result: ExecutionResult::Halt { reason: halt }, logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }, } } @@ -100,12 +102,14 @@ impl logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }, TxRevertReason::Halt(halt) => VmExecutionResultAndLogs { result: ExecutionResult::Halt { reason: halt }, logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }, } } @@ -129,6 +133,7 @@ impl GlueFrom { unreachable!("Halt is the only revert reason for VM 5") diff --git a/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs b/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs index db5aaa783df5..61b99cb676ed 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs @@ -96,6 +96,7 @@ impl Vm { logs, statistics, refunds, + new_known_factory_deps: Default::default(), }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_1_4_1/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_1_4_1/tests/get_used_contracts.rs index a7cbcd8e2953..b6b22c866a3f 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/tests/get_used_contracts.rs @@ -26,7 +26,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that `get_used_contracts()` updates @@ -48,7 +48,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -84,26 +84,26 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps.unwrap() { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts } diff --git a/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs b/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs index d42d18809331..f49eb10e26bc 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs @@ -96,6 +96,7 @@ impl Vm { logs, statistics, refunds, + new_known_factory_deps: Default::default(), }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs b/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs index 7d0dfd1ed0ea..3e2b23999182 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs @@ -33,7 +33,7 @@ fn test_circuits() { let s = res.statistics.circuit_statistic; // Check `circuit_statistic`. const EXPECTED: [f32; 11] = [ - 1.1979, 0.1390, 1.5455, 0.0031, 1.0573, 0.00059, 0.003438, 0.00077, 0.1195, 0.1429, 0.0, + 1.1979, 0.1390, 1.5455, 0.0031, 1.1799649, 0.00059, 0.003438, 0.00077, 0.1195, 0.1429, 0.0, ]; let actual = [ (s.main_vm, "main_vm"), diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs index cfe3e1bfc235..2054bf6a0fc6 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs @@ -26,7 +26,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that `get_used_contracts()` updates @@ -48,7 +48,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -84,26 +84,30 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps.unwrap() { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)) + .unwrap(); + + known_bytecodes_without_base_system_contracts } diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs index a7c790a4bc30..73f122c701dc 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs @@ -90,6 +90,7 @@ impl Vm { logs, statistics, refunds, + new_known_factory_deps: Default::default(), }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_boojum_integration/tests/get_used_contracts.rs index 658bcd75b059..ad26db9f9a78 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/tests/get_used_contracts.rs @@ -26,7 +26,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that get_used_contracts() updates @@ -48,7 +48,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -84,26 +84,30 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps.unwrap() { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)) + .unwrap(); + + known_bytecodes_without_base_system_contracts } diff --git a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs index 746e9be923f2..50ee14a2f56c 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs @@ -30,7 +30,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that `get_decommitted_hashes()` updates @@ -49,7 +49,7 @@ fn test_get_used_contracts() { // Note: `Default_AA` will be in the list of used contracts if L2 tx is used assert_eq!( vm.vm.decommitted_hashes().collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) ); // create push and execute some non-empty factory deps transaction that fails @@ -82,20 +82,23 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm).contains(&hash_to_u256)); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).contains(&hash_to_u256)); assert!(!vm.vm.decommitted_hashes().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code(vm: &Vm) -> HashSet { - let mut known_bytecodes_without_aa_code = vm +fn known_bytecodes_without_base_system_contracts(vm: &Vm) -> HashSet { + let mut known_bytecodes_without_base_system_contracts = vm .world .bytecode_cache .keys() .cloned() .collect::>(); - known_bytecodes_without_aa_code.remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)); + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)); + known_bytecodes_without_base_system_contracts } /// Counter test contract bytecode inflated by appending lots of `NOP` opcodes at the end. This leads to non-trivial diff --git a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs index ea3613b0fe79..2079629fadc9 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs @@ -117,9 +117,8 @@ fn test_l1_tx_execution() { let res = vm.vm.execute(VmExecutionMode::OneTx); let storage_logs = res.logs.storage_logs; let res = StorageWritesDeduplicator::apply_on_empty_state(&storage_logs); - // We changed one slot inside contract. However, the rewrite of the `basePubdataSpent` didn't happen, since it was the same - // as the start of the previous tx. Thus we have `+1` slot for the changed counter and `-1` slot for base pubdata spent - assert_eq!(res.initial_storage_writes, basic_initial_writes); + // We changed one slot inside contract. + assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); // No repeated writes let repeated_writes = res.repeated_storage_writes; @@ -146,7 +145,7 @@ fn test_l1_tx_execution() { assert!(result.result.is_failed(), "The transaction should fail"); let res = StorageWritesDeduplicator::apply_on_empty_state(&result.logs.storage_logs); - assert_eq!(res.initial_storage_writes, basic_initial_writes); + assert_eq!(res.initial_storage_writes, basic_initial_writes + 1); assert_eq!(res.repeated_storage_writes, 1); } diff --git a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs index 2ae43869d7f6..3db779601383 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs @@ -36,6 +36,7 @@ impl From for u8 { #[test] fn test_nonce_holder() { let mut account = Account::random(); + let hex_addr = hex::encode(account.address.to_fixed_bytes()); let mut vm = VmTesterBuilder::new() .with_empty_in_memory_storage() @@ -92,7 +93,7 @@ fn test_nonce_holder() { run_nonce_test( 1u32, NonceHolderTestMode::SetValueUnderNonce, - Some("Previous nonce has not been used".to_string()), + Some("Error function_selector = 0x13595475, data = 0x13595475".to_string()), "Allowed to set value under non sequential value", ); @@ -133,7 +134,7 @@ fn test_nonce_holder() { run_nonce_test( 10u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some("Reusing the same nonce twice".to_string()), + Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000a")), "Allowed to reuse nonce below the minimal one", ); @@ -149,7 +150,7 @@ fn test_nonce_holder() { run_nonce_test( 13u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some("Reusing the same nonce twice".to_string()), + Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000d")), "Allowed to reuse the same nonce twice", ); @@ -165,7 +166,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::IncreaseMinNonceTooMuch, - Some("The value for incrementing the nonce is too high".to_string()), + Some("Error function_selector = 0x45ac24a6, data = 0x45ac24a600000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000".to_string()), "Allowed for incrementing min nonce too much", ); @@ -173,7 +174,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::LeaveNonceUnused, - Some("The nonce was not set as used".to_string()), + Some(format!("Error function_selector = 0x1f2f8478, data = 0x1f2f8478000000000000000000000000{hex_addr}0000000000000000000000000000000000000000000000000000000000000010")), "Allowed to leave nonce as unused", ); } diff --git a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs index 4419aaeedfaa..446de84b19cb 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs @@ -1,6 +1,6 @@ use ethabi::Token; use zksync_contracts::{get_loadnext_contract, test_contracts::LoadnextContractExecutionParams}; -use zksync_types::{Execute, U256}; +use zksync_types::{Execute, Nonce, U256}; use crate::{ interface::TxExecutionMode, @@ -38,22 +38,40 @@ fn test_vm_rollbacks() { TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongMagicValue.into()), TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongSignature.into()), // The correct nonce is 0, this tx will fail - TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(0)).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_0.clone(), false), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(1)).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_1, false), // The correct nonce is 2, this tx will fail - TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_2.clone(), false), // This tx will fail - TransactionTestInfo::new_rejected(tx_2, TxModifier::NonceReused.into()), - TransactionTestInfo::new_rejected(tx_0, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::NonceReused(tx_2.initiator_account(), tx_2.nonce().unwrap()).into(), + ), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), ]); assert_eq!(result_without_rollbacks, result_with_rollbacks); @@ -131,12 +149,22 @@ fn test_vm_loadnext_rollbacks() { TransactionTestInfo::new_processed(loadnext_tx_1.clone(), true), TransactionTestInfo::new_rejected( loadnext_deploy_tx.clone(), - TxModifier::NonceReused.into(), + TxModifier::NonceReused( + loadnext_deploy_tx.initiator_account(), + loadnext_deploy_tx.nonce().unwrap(), + ), ), TransactionTestInfo::new_processed(loadnext_tx_1, false), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), - TransactionTestInfo::new_rejected(loadnext_deploy_tx, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + loadnext_deploy_tx.clone(), + TxModifier::NonceReused( + loadnext_deploy_tx.initiator_account(), + loadnext_deploy_tx.nonce().unwrap(), + ) + .into(), + ), TransactionTestInfo::new_processed(loadnext_tx_2, false), ]); diff --git a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs index 105bc5f2fd43..359ba38d07a5 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs @@ -15,8 +15,8 @@ pub(crate) enum TxModifier { WrongSignatureLength, WrongSignature, WrongMagicValue, - WrongNonce, - NonceReused, + WrongNonce(Nonce, Nonce), + NonceReused(H160, Nonce), } #[derive(Debug, Clone)] @@ -41,15 +41,9 @@ impl From for ExpectedError { fn from(value: TxModifier) -> Self { let revert_reason = match value { TxModifier::WrongSignatureLength => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Signature length is incorrect".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 83, 105, 103, 110, 97, 116, 117, 114, 101, 32, - 108, 101, 110, 103, 116, 104, 32, 105, 115, 32, 105, 110, 99, 111, 114, 114, 101, 99, - 116, 0, 0, 0, - ], + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector: vec![144, 240, 73, 201], + data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45], }) } TxModifier::WrongSignature => { @@ -59,38 +53,35 @@ impl From for ExpectedError { }) } TxModifier::WrongMagicValue => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "v is neither 27 nor 28".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 118, 32, 105, 115, 32, 110, 101, 105, 116, 104, - 101, 114, 32, 50, 55, 32, 110, 111, 114, 32, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector: vec![144, 240, 73, 201], + data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], }) } - TxModifier::WrongNonce => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Incorrect nonce".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 73, 110, 99, 111, 114, 114, 101, 99, 116, 32, 110, - 111, 110, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], + TxModifier::WrongNonce(expected, actual) => { + let function_selector = vec![98, 106, 222, 48]; + let expected_nonce_bytes = expected.0.to_be_bytes().to_vec(); + let actual_nonce_bytes = actual.0.to_be_bytes().to_vec(); + // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field + let nonce_padding = vec![0u8; 28]; + let data = [function_selector.clone(), nonce_padding.clone(), expected_nonce_bytes, nonce_padding.clone(), actual_nonce_bytes].concat(); + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector, + data }) } - TxModifier::NonceReused => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Reusing the same nonce twice".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 82, 101, 117, 115, 105, 110, 103, 32, 116, 104, - 101, 32, 115, 97, 109, 101, 32, 110, 111, 110, 99, 101, 32, 116, 119, 105, 99, 101, 0, - 0, 0, 0, - ], + TxModifier::NonceReused(addr, nonce) => { + let function_selector = vec![233, 10, 222, 212]; + let addr = addr.as_bytes().to_vec(); + // padding is 12 because an address takes up 20 bytes and we need it to fill a 32 byte field + let addr_padding = vec![0u8; 12]; + // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field + let nonce_padding = vec![0u8; 28]; + let data = [function_selector.clone(), addr_padding, addr, nonce_padding, nonce.0.to_be_bytes().to_vec()].concat(); + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector, + data, }) } }; @@ -116,10 +107,10 @@ impl TransactionTestInfo { } TxModifier::WrongSignature => data.signature = vec![27u8; 65], TxModifier::WrongMagicValue => data.signature = vec![1u8; 65], - TxModifier::WrongNonce => { + TxModifier::WrongNonce(_, _) => { // Do not need to modify signature for nonce error } - TxModifier::NonceReused => { + TxModifier::NonceReused(_, _) => { // Do not need to modify signature for nonce error } } diff --git a/core/lib/multivm/src/versions/vm_fast/vm.rs b/core/lib/multivm/src/versions/vm_fast/vm.rs index d8816cfaf2a6..0cc6f1baa688 100644 --- a/core/lib/multivm/src/versions/vm_fast/vm.rs +++ b/core/lib/multivm/src/versions/vm_fast/vm.rs @@ -393,10 +393,22 @@ impl Vm { .hash .into(); - let program_cache = HashMap::from([World::convert_system_contract_code( - &system_env.base_system_smart_contracts.default_aa, - false, - )]); + let evm_simulator_code_hash = system_env + .base_system_smart_contracts + .evm_simulator + .hash + .into(); + + let program_cache = HashMap::from([ + World::convert_system_contract_code( + &system_env.base_system_smart_contracts.default_aa, + false, + ), + World::convert_system_contract_code( + &system_env.base_system_smart_contracts.evm_simulator, + false, + ), + ]); let (_, bootloader) = World::convert_system_contract_code( &system_env.base_system_smart_contracts.bootloader, @@ -412,8 +424,7 @@ impl Vm { system_env.bootloader_gas_limit, Settings { default_aa_code_hash, - // this will change after 1.5 - evm_interpreter_code_hash: default_aa_code_hash, + evm_interpreter_code_hash: evm_simulator_code_hash, hook_address: get_vm_hook_position(VM_VERSION) * 32, }, ); @@ -577,6 +588,7 @@ impl VmInterface for Vm { circuit_statistic, }, refunds, + new_known_factory_deps: Default::default(), } } diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index 66fc1a8bfd71..8242041b98fb 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -12,6 +12,7 @@ use crate::{ circuits_capacity::circuit_statistic_from_cycles, dispatcher::TracerDispatcher, DefaultExecutionTracer, PubdataTracer, RefundsTracer, }, + utils::extract_bytecodes_marked_as_known, vm::Vm, }, HistoryMode, @@ -93,12 +94,19 @@ impl Vm { circuit_statistic_from_cycles(tx_tracer.circuits_tracer.statistics), ); let result = tx_tracer.result_tracer.into_result(); + let factory_deps_marked_as_known = extract_bytecodes_marked_as_known(&logs.events); + let preimages = self.ask_decommitter(factory_deps_marked_as_known.clone()); + let new_known_factory_deps = factory_deps_marked_as_known + .into_iter() + .zip(preimages) + .collect(); let result = VmExecutionResultAndLogs { result, logs, statistics, refunds, + new_known_factory_deps: Some(new_known_factory_deps), }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_latest/old_vm/oracles/decommitter.rs b/core/lib/multivm/src/versions/vm_latest/old_vm/oracles/decommitter.rs index 0315aa38327d..d91fbfdb24df 100644 --- a/core/lib/multivm/src/versions/vm_latest/old_vm/oracles/decommitter.rs +++ b/core/lib/multivm/src/versions/vm_latest/old_vm/oracles/decommitter.rs @@ -5,9 +5,7 @@ use zk_evm_1_5_0::{ aux_structures::{ DecommittmentQuery, MemoryIndex, MemoryLocation, MemoryPage, MemoryQuery, Timestamp, }, - zkevm_opcode_defs::{ - ContractCodeSha256, VersionedHashDef, VersionedHashHeader, VersionedHashNormalizedPreimage, - }, + zkevm_opcode_defs::{VersionedHashHeader, VersionedHashNormalizedPreimage}, }; use zksync_types::{H256, U256}; use zksync_utils::{bytes_to_be_words, h256_to_u256, u256_to_h256}; @@ -166,8 +164,8 @@ impl DecommittmentProcess _monotonic_cycle_counter: u32, mut partial_query: DecommittmentQuery, ) -> anyhow::Result { - let (stored_hash, length) = stored_hash_from_query(&partial_query); - partial_query.decommitted_length = length; + let versioned_hash = VersionedCodeHash::from_query(&partial_query); + let stored_hash = versioned_hash.to_stored_hash(); if let Some(memory_page) = self .decommitted_code_hashes @@ -178,10 +176,10 @@ impl DecommittmentProcess { partial_query.is_fresh = false; partial_query.memory_page = MemoryPage(memory_page); + partial_query.decommitted_length = versioned_hash.get_preimage_length() as u16; Ok(partial_query) } else { - partial_query.is_fresh = true; if self .decommitted_code_hashes .inner() @@ -190,7 +188,9 @@ impl DecommittmentProcess { self.decommitted_code_hashes .insert(stored_hash, None, partial_query.timestamp); - } + }; + partial_query.is_fresh = true; + partial_query.decommitted_length = versioned_hash.get_preimage_length() as u16; Ok(partial_query) } @@ -204,11 +204,10 @@ impl DecommittmentProcess memory: &mut M, ) -> anyhow::Result>> { assert!(partial_query.is_fresh); - self.decommitment_requests.push((), partial_query.timestamp); - let stored_hash = stored_hash_from_query(&partial_query).0; - + let versioned_hash = VersionedCodeHash::from_query(&partial_query); + let stored_hash = versioned_hash.to_stored_hash(); // We are fetching a fresh bytecode that we didn't read before. let values = self.get_bytecode(stored_hash, partial_query.timestamp); let page_to_use = partial_query.memory_page; @@ -251,28 +250,49 @@ impl DecommittmentProcess } } -fn concat_header_and_preimage( - header: VersionedHashHeader, - normalized_preimage: VersionedHashNormalizedPreimage, -) -> [u8; 32] { - let mut buffer = [0u8; 32]; +#[derive(Debug)] +// TODO: consider moving this to the zk-evm crate +enum VersionedCodeHash { + ZkEVM(VersionedHashHeader, VersionedHashNormalizedPreimage), + Evm(VersionedHashHeader, VersionedHashNormalizedPreimage), +} - buffer[0..4].copy_from_slice(&header.0); - buffer[4..32].copy_from_slice(&normalized_preimage.0); +impl VersionedCodeHash { + fn from_query(query: &DecommittmentQuery) -> Self { + match query.header.0[0] { + 1 => Self::ZkEVM(query.header, query.normalized_preimage), + 2 => Self::Evm(query.header, query.normalized_preimage), + _ => panic!("Unsupported hash version"), + } + } - buffer -} + /// Returns the hash in the format it is stored in the DB. + fn to_stored_hash(&self) -> U256 { + let (header, preimage) = match self { + Self::ZkEVM(header, preimage) => (header, preimage), + Self::Evm(header, preimage) => (header, preimage), + }; -/// For a given decommitment query, returns a pair of the stored hash as U256 and the length of the preimage in 32-byte words. -fn stored_hash_from_query(partial_query: &DecommittmentQuery) -> (U256, u16) { - let full_hash = - concat_header_and_preimage(partial_query.header, partial_query.normalized_preimage); + let mut hash = [0u8; 32]; + hash[0..4].copy_from_slice(&header.0); + hash[4..32].copy_from_slice(&preimage.0); - let versioned_hash = - ContractCodeSha256::try_deserialize(full_hash).expect("Invalid ContractCodeSha256 hash"); + // Hash[1] is used in both of the versions to denote whether the bytecode is being constructed. + // We ignore this param. + hash[1] = 0; - let stored_hash = H256(ContractCodeSha256::serialize_to_stored(versioned_hash).unwrap()); - let length = versioned_hash.code_length_in_words; + h256_to_u256(H256(hash)) + } - (h256_to_u256(stored_hash), length) + fn get_preimage_length(&self) -> u32 { + // In zkEVM the hash[2..3] denotes the length of the preimage in words, while + // in EVM the hash[2..3] denotes the length of the preimage in bytes. + match self { + Self::ZkEVM(header, _) => { + let length_in_words = header.0[2] as u32 * 256 + header.0[3] as u32; + length_in_words * 32 + } + Self::Evm(header, _) => header.0[2] as u32 * 256 + header.0[3] as u32, + } + } } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs index 35412ee4d1bd..74d77484d682 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs @@ -35,7 +35,7 @@ fn test_circuits() { let s = res.statistics.circuit_statistic; // Check `circuit_statistic`. const EXPECTED: [f32; 13] = [ - 1.34935, 0.15026, 1.66666, 0.00315, 1.0594, 0.00058, 0.00348, 0.00076, 0.11945, 0.14285, + 1.34935, 0.15026, 1.66666, 0.00315, 1.1799649, 0.00058, 0.00348, 0.00076, 0.11945, 0.14285, 0.0, 0.0, 0.0, ]; let actual = [ diff --git a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs index ef19717a627c..10f4bff22635 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs @@ -41,7 +41,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that `get_used_contracts()` updates @@ -63,7 +63,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -99,7 +99,7 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); @@ -147,19 +147,22 @@ fn test_contract_is_used_right_after_prepare_to_decommit() { assert_eq!(vm.vm.get_used_contracts(), vec![bytecode_hash]); } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)) + .unwrap(); + known_bytecodes_without_base_system_contracts } /// Counter test contract bytecode inflated by appending lots of `NOP` opcodes at the end. This leads to non-trivial diff --git a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs index 0fc12848227e..b424567aab02 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs @@ -112,9 +112,8 @@ fn test_l1_tx_execution() { let res = vm.vm.execute(VmExecutionMode::OneTx); let storage_logs = res.logs.storage_logs; let res = StorageWritesDeduplicator::apply_on_empty_state(&storage_logs); - // We changed one slot inside contract. However, the rewrite of the `basePubdataSpent` didn't happen, since it was the same - // as the start of the previous tx. Thus we have `+1` slot for the changed counter and `-1` slot for base pubdata spent - assert_eq!(res.initial_storage_writes - basic_initial_writes, 0); + // We changed one slot inside contract. + assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); // No repeated writes let repeated_writes = res.repeated_storage_writes; @@ -142,7 +141,7 @@ fn test_l1_tx_execution() { let res = StorageWritesDeduplicator::apply_on_empty_state(&result.logs.storage_logs); // There are only basic initial writes - assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); + assert_eq!(res.initial_storage_writes - basic_initial_writes, 2); } #[test] diff --git a/core/lib/multivm/src/versions/vm_latest/tests/migration.rs b/core/lib/multivm/src/versions/vm_latest/tests/migration.rs deleted file mode 100644 index 5b8da2551808..000000000000 --- a/core/lib/multivm/src/versions/vm_latest/tests/migration.rs +++ /dev/null @@ -1,51 +0,0 @@ -use zksync_types::{get_code_key, H256, SYSTEM_CONTEXT_ADDRESS}; - -use crate::{ - interface::{TxExecutionMode, VmExecutionMode, VmInterface, VmInterfaceExt}, - vm_latest::{ - tests::{ - tester::{get_empty_storage, DeployContractsTx, TxType, VmTesterBuilder}, - utils::read_test_contract, - }, - HistoryEnabled, - }, -}; - -/// This test checks that the new bootloader will work fine even if the previous system context contract is not -/// compatible with it, i.e. the bootloader will upgrade it before starting any transaction. -#[test] -fn test_migration_for_system_context_aa_interaction() { - let mut storage = get_empty_storage(); - // We will set the system context bytecode to zero. - storage.set_value(get_code_key(&SYSTEM_CONTEXT_ADDRESS), H256::zero()); - - // In this test, we aim to test whether a simple account interaction (without any fee logic) - // will work. The account will try to deploy a simple contract from integration tests. - let mut vm = VmTesterBuilder::new(HistoryEnabled) - .with_storage(storage) - .with_execution_mode(TxExecutionMode::VerifyExecute) - .with_random_rich_accounts(1) - .build(); - - // Now, we will just proceed with standard transaction execution. - // The bootloader should be able to update system context regardless of whether - // the upgrade transaction is there or not. - let account = &mut vm.rich_accounts[0]; - let counter = read_test_contract(); - let DeployContractsTx { tx, .. } = account.get_deploy_tx(&counter, None, TxType::L2); - - vm.vm.push_transaction(tx); - let result = vm.vm.execute(VmExecutionMode::OneTx); - assert!( - !result.result.is_failed(), - "Transaction wasn't successful {:#?}", - result.result - ); - - let batch_result = vm.vm.execute(VmExecutionMode::Batch); - assert!( - !batch_result.result.is_failed(), - "Batch transaction wasn't successful {:#?}", - batch_result.result - ); -} diff --git a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs index 1203d61b80b7..bc6d5b0144f1 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs @@ -13,7 +13,6 @@ mod get_used_contracts; mod is_write_initial; mod l1_tx_execution; mod l2_blocks; -mod migration; mod nonce_holder; mod precompiles; mod prestate_tracer; diff --git a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs index 91d78c69a931..86d03970f5c3 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs @@ -40,6 +40,7 @@ impl From for u8 { #[test] fn test_nonce_holder() { let mut account = Account::random(); + let hex_addr = hex::encode(account.address.to_fixed_bytes()); let mut vm = VmTesterBuilder::new(HistoryEnabled) .with_empty_in_memory_storage() @@ -101,7 +102,7 @@ fn test_nonce_holder() { run_nonce_test( 1u32, NonceHolderTestMode::SetValueUnderNonce, - Some("Previous nonce has not been used".to_string()), + Some("Error function_selector = 0x13595475, data = 0x13595475".to_string()), "Allowed to set value under non sequential value", ); @@ -142,7 +143,7 @@ fn test_nonce_holder() { run_nonce_test( 10u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some("Reusing the same nonce twice".to_string()), + Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000a")), "Allowed to reuse nonce below the minimal one", ); @@ -158,7 +159,7 @@ fn test_nonce_holder() { run_nonce_test( 13u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some("Reusing the same nonce twice".to_string()), + Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000d")), "Allowed to reuse the same nonce twice", ); @@ -174,7 +175,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::IncreaseMinNonceTooMuch, - Some("The value for incrementing the nonce is too high".to_string()), + Some("Error function_selector = 0x45ac24a6, data = 0x45ac24a600000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000".to_string()), "Allowed for incrementing min nonce too much", ); @@ -182,7 +183,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::LeaveNonceUnused, - Some("The nonce was not set as used".to_string()), + Some(format!("Error function_selector = 0x1f2f8478, data = 0x1f2f8478000000000000000000000000{hex_addr}0000000000000000000000000000000000000000000000000000000000000010")), "Allowed to leave nonce as unused", ); } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs index 52e4d24bc0b4..6b665fa555e0 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs @@ -1,6 +1,6 @@ use ethabi::Token; use zksync_contracts::{get_loadnext_contract, test_contracts::LoadnextContractExecutionParams}; -use zksync_types::{get_nonce_key, Execute, U256}; +use zksync_types::{get_nonce_key, Execute, Nonce, U256}; use crate::{ interface::{ @@ -47,22 +47,40 @@ fn test_vm_rollbacks() { TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongMagicValue.into()), TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongSignature.into()), // The correct nonce is 0, this tx will fail - TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(0)).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_0.clone(), false), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(1)).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_1, false), // The correct nonce is 2, this tx will fail - TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), // This tx will succeed TransactionTestInfo::new_processed(tx_2.clone(), false), // This tx will fail - TransactionTestInfo::new_rejected(tx_2, TxModifier::NonceReused.into()), - TransactionTestInfo::new_rejected(tx_0, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + tx_2.clone(), + TxModifier::NonceReused(tx_2.initiator_account(), tx_2.nonce().unwrap()).into(), + ), + TransactionTestInfo::new_rejected( + tx_0.clone(), + TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), + ), ]); assert_eq!(result_without_rollbacks, result_with_rollbacks); @@ -140,12 +158,23 @@ fn test_vm_loadnext_rollbacks() { TransactionTestInfo::new_processed(loadnext_tx_1.clone(), true), TransactionTestInfo::new_rejected( loadnext_deploy_tx.clone(), - TxModifier::NonceReused.into(), + TxModifier::NonceReused( + loadnext_deploy_tx.initiator_account(), + loadnext_deploy_tx.nonce().unwrap(), + ) + .into(), ), TransactionTestInfo::new_processed(loadnext_tx_1, false), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), - TransactionTestInfo::new_rejected(loadnext_deploy_tx, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected( + loadnext_deploy_tx.clone(), + TxModifier::NonceReused( + loadnext_deploy_tx.initiator_account(), + loadnext_deploy_tx.nonce().unwrap(), + ) + .into(), + ), TransactionTestInfo::new_processed(loadnext_tx_2, false), ]); diff --git a/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs b/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs index 08667ccc625f..f07d1602d300 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs @@ -1,4 +1,4 @@ -use zksync_types::{ExecuteTransactionCommon, Transaction}; +use zksync_types::{ExecuteTransactionCommon, Nonce, Transaction, H160}; use crate::{ interface::{ @@ -14,8 +14,8 @@ pub(crate) enum TxModifier { WrongSignatureLength, WrongSignature, WrongMagicValue, - WrongNonce, - NonceReused, + WrongNonce(Nonce, Nonce), + NonceReused(H160, Nonce), } #[derive(Debug, Clone)] @@ -40,14 +40,11 @@ impl From for ExpectedError { fn from(value: TxModifier) -> Self { let revert_reason = match value { TxModifier::WrongSignatureLength => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Signature length is incorrect".to_string(), + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector: vec![144, 240, 73, 201], data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 83, 105, 103, 110, 97, 116, 117, 114, 101, 32, - 108, 101, 110, 103, 116, 104, 32, 105, 115, 32, 105, 110, 99, 111, 114, 114, 101, 99, - 116, 0, 0, 0, + 144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45 ], }) } @@ -58,38 +55,34 @@ impl From for ExpectedError { }) } TxModifier::WrongMagicValue => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "v is neither 27 nor 28".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 118, 32, 105, 115, 32, 110, 101, 105, 116, 104, - 101, 114, 32, 50, 55, 32, 110, 111, 114, 32, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector: vec![144, 240, 73, 201], + data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], }) - } - TxModifier::WrongNonce => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Incorrect nonce".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 73, 110, 99, 111, 114, 114, 101, 99, 116, 32, 110, - 111, 110, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], + TxModifier::WrongNonce(expected, actual) => { + let function_selector = vec![98, 106, 222, 48]; + let expected_nonce_bytes = expected.0.to_be_bytes().to_vec(); + let actual_nonce_bytes = actual.0.to_be_bytes().to_vec(); + // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field + let nonce_padding = vec![0u8; 28]; + let data = [function_selector.clone(), nonce_padding.clone(), expected_nonce_bytes, nonce_padding.clone(), actual_nonce_bytes].concat(); + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector, + data }) } - TxModifier::NonceReused => { - Halt::ValidationFailed(VmRevertReason::General { - msg: "Reusing the same nonce twice".to_string(), - data: vec![ - 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 82, 101, 117, 115, 105, 110, 103, 32, 116, 104, - 101, 32, 115, 97, 109, 101, 32, 110, 111, 110, 99, 101, 32, 116, 119, 105, 99, 101, 0, - 0, 0, 0, - ], + TxModifier::NonceReused(addr, nonce) => { + let function_selector = vec![233, 10, 222, 212]; + let addr = addr.as_bytes().to_vec(); + // padding is 12 because an address takes up 20 bytes and we need it to fill a 32 byte field + let addr_padding = vec![0u8; 12]; + // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field + let nonce_padding = vec![0u8; 28]; + let data = [function_selector.clone(), addr_padding, addr, nonce_padding, nonce.0.to_be_bytes().to_vec()].concat(); + Halt::ValidationFailed(VmRevertReason::Unknown { + function_selector, + data, }) } }; @@ -115,10 +108,10 @@ impl TransactionTestInfo { } TxModifier::WrongSignature => data.signature = vec![27u8; 65], TxModifier::WrongMagicValue => data.signature = vec![1u8; 65], - TxModifier::WrongNonce => { + TxModifier::WrongNonce(_, _) => { // Do not need to modify signature for nonce error } - TxModifier::NonceReused => { + TxModifier::NonceReused(_, _) => { // Do not need to modify signature for nonce error } } diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index 6a908c2a73ed..f7def2a66106 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -13,7 +13,7 @@ use zk_evm_1_5_0::{ zkevm_opcode_defs::{decoding::EncodingModeProduction, Opcode, RetOpcode}, }; -use super::PubdataTracer; +use super::{EvmDeployTracer, PubdataTracer}; use crate::{ glue::GlueInto, interface::{ @@ -38,7 +38,7 @@ use crate::{ }; /// Default tracer for the VM. It manages the other tracers execution and stop the vm when needed. -pub(crate) struct DefaultExecutionTracer { +pub struct DefaultExecutionTracer { tx_has_been_processed: bool, execution_mode: VmExecutionMode, @@ -63,6 +63,8 @@ pub(crate) struct DefaultExecutionTracer { // It only takes into account circuits that are generated for actual execution. It doesn't // take into account e.g circuits produced by the initial bootloader memory commitment. pub(crate) circuits_tracer: CircuitsTracer, + // This tracer is responsible for handling EVM deployments and providing the data to the code decommitter. + pub(crate) evm_deploy_tracer: EvmDeployTracer, subversion: MultiVMSubversion, storage: StoragePtr, _phantom: PhantomData, @@ -92,6 +94,7 @@ impl DefaultExecutionTracer { pubdata_tracer, ret_from_the_bootloader: None, circuits_tracer: CircuitsTracer::new(), + evm_deploy_tracer: EvmDeployTracer::new(), storage, _phantom: PhantomData, } @@ -172,6 +175,7 @@ macro_rules! dispatch_tracers { tracer.$function($( $params ),*); } $self.circuits_tracer.$function($( $params ),*); + $self.evm_deploy_tracer.$function($( $params ),*); }; } @@ -289,6 +293,11 @@ impl DefaultExecutionTracer { .finish_cycle(state, bootloader_state) .stricter(&result); + result = self + .evm_deploy_tracer + .finish_cycle(state, bootloader_state) + .stricter(&result); + result.stricter(&self.should_stop_execution()) } diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs b/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs new file mode 100644 index 000000000000..7cd32cea96fa --- /dev/null +++ b/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs @@ -0,0 +1,106 @@ +use std::marker::PhantomData; + +use zk_evm_1_5_0::{ + aux_structures::Timestamp, + zkevm_opcode_defs::{FatPointer, CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER}, +}; +use zksync_contracts::known_codes_contract; +use zksync_state::interface::WriteStorage; +use zksync_types::{CONTRACT_DEPLOYER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS}; +use zksync_utils::{bytes_to_be_words, h256_to_u256}; + +use super::{traits::VmTracer, utils::read_pointer}; +use crate::{ + interface::tracer::TracerExecutionStatus, + tracers::dynamic::vm_1_5_0::DynTracer, + vm_latest::{ + utils::hash_evm_bytecode, BootloaderState, HistoryMode, SimpleMemory, ZkSyncVmState, + }, +}; + +/// Tracer responsible for collecting information about EVM deploys and providing those +/// to the code decommitter. +#[derive(Debug, Clone)] +pub(crate) struct EvmDeployTracer { + _phantom: PhantomData, +} + +impl EvmDeployTracer { + pub(crate) fn new() -> Self { + Self { + _phantom: PhantomData, + } + } +} + +impl DynTracer> for EvmDeployTracer {} + +impl VmTracer for EvmDeployTracer { + fn finish_cycle( + &mut self, + state: &mut ZkSyncVmState, + _bootloader_state: &mut BootloaderState, + ) -> TracerExecutionStatus { + // We check if ContractDeployer was called with provided evm bytecode. + // It is assumed that by that time the user has already paid for its size. + // So even if we do not revert the addition of the this bytecode it is not a ddos vector, since + // the payment is the same as if the bytecode publication was reverted. + let current_callstack = &state.local_state.callstack.current; + + // Here we assume that the only case when PC is 0 at the start of the execution of the contract. + let known_code_storage_call = current_callstack.this_address == KNOWN_CODES_STORAGE_ADDRESS + && current_callstack.pc == 0 + && current_callstack.msg_sender == CONTRACT_DEPLOYER_ADDRESS; + + if !known_code_storage_call { + // Just continue executing + return TracerExecutionStatus::Continue; + } + + // Now, we need to check whether it is indeed a call to publish EVM code. + let calldata_ptr = + state.local_state.registers[CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER as usize]; + + let data = read_pointer(&state.memory, FatPointer::from_u256(calldata_ptr.value)); + + let contract = known_codes_contract(); + + if data.len() < 4 { + // Not interested + return TracerExecutionStatus::Continue; + } + + let (signature, data) = data.split_at(4); + + if signature + != contract + .function("publishEVMBytecode") + .unwrap() + .short_signature() + { + // Not interested + return TracerExecutionStatus::Continue; + } + + let Ok(call_params) = contract + .function("publishEVMBytecode") + .unwrap() + .decode_input(data) + else { + // Not interested + return TracerExecutionStatus::Continue; + }; + + let published_bytecode = call_params[0].clone().into_bytes().unwrap(); + + let hash = hash_evm_bytecode(&published_bytecode); + let as_words = bytes_to_be_words(published_bytecode); + + state.decommittment_processor.populate( + vec![(h256_to_u256(hash), as_words)], + Timestamp(state.local_state.timestamp), + ); + + TracerExecutionStatus::Continue + } +} diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/mod.rs b/core/lib/multivm/src/versions/vm_latest/tracers/mod.rs index fe916e19e8ca..82721a322640 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/mod.rs @@ -1,11 +1,13 @@ pub(crate) use circuits_tracer::CircuitsTracer; pub(crate) use default_tracers::DefaultExecutionTracer; +pub(crate) use evm_deploy_tracer::EvmDeployTracer; pub(crate) use pubdata_tracer::PubdataTracer; pub(crate) use refunds::RefundsTracer; pub(crate) use result_tracer::ResultTracer; pub(crate) mod circuits_tracer; pub(crate) mod default_tracers; +pub(crate) mod evm_deploy_tracer; pub(crate) mod pubdata_tracer; pub(crate) mod refunds; pub(crate) mod result_tracer; diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs index 2ec86eb3ceaf..0a5ebb37360e 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs @@ -62,6 +62,12 @@ impl From for TransactionData { U256::zero() }; + let should_deploy_contract = if execute_tx.execute.contract_address.is_none() { + U256([1, 0, 0, 0]) + } else { + U256::zero() + }; + // Ethereum transactions do not sign gas per pubdata limit, and so for them we need to use // some default value. We use the maximum possible value that is allowed by the bootloader // (i.e. we can not use u64::MAX, because the bootloader requires gas per pubdata for such @@ -85,7 +91,7 @@ impl From for TransactionData { value: execute_tx.execute.value, reserved: [ should_check_chain_id, - U256::zero(), + should_deploy_contract, U256::zero(), U256::zero(), ], diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs index 6f9522572ad8..16353f5c2f7e 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs @@ -98,6 +98,18 @@ pub(crate) fn new_vm_state( Timestamp(0), ); + decommittment_processor.populate( + vec![( + h256_to_u256(system_env.base_system_smart_contracts.evm_simulator.hash), + system_env + .base_system_smart_contracts + .evm_simulator + .code + .clone(), + )], + Timestamp(0), + ); + memory.populate( vec![( BOOTLOADER_CODE_PAGE, @@ -128,10 +140,8 @@ pub(crate) fn new_vm_state( default_aa_code_hash: h256_to_u256( system_env.base_system_smart_contracts.default_aa.hash, ), - // For now, the default account hash is used as the code hash for the EVM simulator. - // In the 1.5.0 version, it is not possible to instantiate EVM bytecode. evm_simulator_code_hash: h256_to_u256( - system_env.base_system_smart_contracts.default_aa.hash, + system_env.base_system_smart_contracts.evm_simulator.hash, ), zkporter_is_available: system_env.zk_porter_available, }, diff --git a/core/lib/multivm/src/versions/vm_latest/utils/mod.rs b/core/lib/multivm/src/versions/vm_latest/utils/mod.rs index 0fb803de5d4e..742434b68970 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/mod.rs @@ -1,6 +1,58 @@ /// Utility functions for the VM. +use ethabi; +use once_cell::sync::Lazy; +use zk_evm_1_4_1::sha2; +use zk_evm_1_5_0::{ + aux_structures::MemoryPage, + zkevm_opcode_defs::{BlobSha256Format, VersionedHashLen32}, +}; +use zksync_types::{H256, KNOWN_CODES_STORAGE_ADDRESS}; +use zksync_vm_interface::VmEvent; + pub mod fee; pub mod l2_blocks; pub(crate) mod logs; pub mod overhead; pub mod transaction_encoding; + +/// TODO: maybe move to a different folder +pub(crate) fn hash_evm_bytecode(bytecode: &[u8]) -> H256 { + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + let len = bytecode.len() as u16; + hasher.update(bytecode); + let result = hasher.finalize(); + + let mut output = [0u8; 32]; + output[..].copy_from_slice(result.as_slice()); + output[0] = BlobSha256Format::VERSION_BYTE; + output[1] = 0; + output[2..4].copy_from_slice(&len.to_be_bytes()); + + H256(output) +} + +pub const fn heap_page_from_base(base: MemoryPage) -> MemoryPage { + MemoryPage(base.0 + 2) +} + +/// Extracts all bytecodes marked as known on the system contracts. +pub fn extract_bytecodes_marked_as_known(all_generated_events: &[VmEvent]) -> Vec { + static PUBLISHED_BYTECODE_SIGNATURE: Lazy = Lazy::new(|| { + ethabi::long_signature( + "MarkedAsKnown", + &[ethabi::ParamType::FixedBytes(32), ethabi::ParamType::Bool], + ) + }); + + all_generated_events + .iter() + .filter(|event| { + // Filter events from the deployer contract that match the expected signature. + event.address == KNOWN_CODES_STORAGE_ADDRESS + && event.indexed_topics.len() == 3 + && event.indexed_topics[0] == *PUBLISHED_BYTECODE_SIGNATURE + }) + .map(|event| event.indexed_topics[1]) + .collect() +} diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index a445a1d51402..d3e8964bcd32 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -2,8 +2,9 @@ use circuit_sequencer_api_1_5_0::sort_storage_access::sort_storage_access_querie use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, vm::VmVersion, - Transaction, + Transaction, H256, }; +use zksync_utils::{be_words_to_bytes, h256_to_u256}; use crate::{ glue::GlueInto, @@ -78,6 +79,23 @@ impl Vm { self.state.local_state.callstack.current.ergs_remaining } + pub(crate) fn ask_decommitter(&self, hashes: Vec) -> Vec> { + let mut result = vec![]; + for hash in hashes { + let bytecode = self + .state + .decommittment_processor + .known_bytecodes + .inner() + .get(&h256_to_u256(hash)) + .expect("Bytecode not found") + .clone(); + result.push(be_words_to_bytes(&bytecode)); + } + + result + } + // visible for testing pub(super) fn get_current_execution_state(&self) -> CurrentExecutionState { let (raw_events, l1_messages) = self.state.event_sink.flatten(); diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs index cadd183735e6..bb43dc3ffb61 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs @@ -87,6 +87,7 @@ impl Vm { logs, statistics, refunds, + new_known_factory_deps: Default::default(), }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs index 8c121db3e43e..8f8678167667 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs @@ -21,7 +21,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that get_used_contracts() updates @@ -43,7 +43,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -79,26 +79,26 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps.unwrap() { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code - .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts } diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs index 42709c345ea6..8ad917353863 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs @@ -86,6 +86,7 @@ impl Vm { .refund_tracer .map(|r| r.get_refunds()) .unwrap_or_default(), + new_known_factory_deps: Default::default(), }; tx_tracer.dispatcher.save_results(&mut result); diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/tests/get_used_contracts.rs index 06d8191310bc..c4fe148d7ad6 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/tests/get_used_contracts.rs @@ -23,7 +23,7 @@ fn test_get_used_contracts() { .with_execution_mode(TxExecutionMode::VerifyExecute) .build(); - assert!(known_bytecodes_without_aa_code(&vm.vm).is_empty()); + assert!(known_bytecodes_without_base_system_contracts(&vm.vm).is_empty()); // create and push and execute some not-empty factory deps transaction with success status // to check that get_used_contracts() updates @@ -45,7 +45,7 @@ fn test_get_used_contracts() { .get_used_contracts() .into_iter() .collect::>(), - known_bytecodes_without_aa_code(&vm.vm) + known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .cloned() .collect::>() @@ -81,26 +81,30 @@ fn test_get_used_contracts() { for factory_dep in tx2.execute.factory_deps.unwrap() { let hash = hash_bytecode(&factory_dep); let hash_to_u256 = h256_to_u256(hash); - assert!(known_bytecodes_without_aa_code(&vm.vm) + assert!(known_bytecodes_without_base_system_contracts(&vm.vm) .keys() .contains(&hash_to_u256)); assert!(!vm.vm.get_used_contracts().contains(&hash_to_u256)); } } -fn known_bytecodes_without_aa_code( +fn known_bytecodes_without_base_system_contracts( vm: &Vm, ) -> HashMap> { - let mut known_bytecodes_without_aa_code = vm + let mut known_bytecodes_without_base_system_contracts = vm .state .decommittment_processor .known_bytecodes .inner() .clone(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)) .unwrap(); - known_bytecodes_without_aa_code + known_bytecodes_without_base_system_contracts + .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)) + .unwrap(); + + known_bytecodes_without_base_system_contracts } diff --git a/core/lib/protobuf_config/src/chain.rs b/core/lib/protobuf_config/src/chain.rs index f91bf07e43f8..169d09a2caa3 100644 --- a/core/lib/protobuf_config/src/chain.rs +++ b/core/lib/protobuf_config/src/chain.rs @@ -86,6 +86,7 @@ impl ProtoRepr for proto::StateKeeper { // needed during the initialization from files bootloader_hash: None, default_aa_hash: None, + evm_simulator_hash: None, fee_account_addr: None, l1_batch_commit_data_generator_mode: Default::default(), }) diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 59896aa244d8..42215cda9533 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -75,6 +75,11 @@ impl ProtoRepr for proto::Genesis { .and_then(|x| parse_h256(x)) .context("default_aa_hash")?, ), + evm_simulator_hash: Some( + required(&self.evm_simulator_hash) + .and_then(|x| parse_h256(x)) + .context("evm_simulator_hash")?, + ), l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, @@ -105,6 +110,7 @@ impl ProtoRepr for proto::Genesis { genesis_protocol_semantic_version: this.protocol_version.map(|x| x.to_string()), default_aa_hash: this.default_aa_hash.map(|x| format!("{:?}", x)), bootloader_hash: this.bootloader_hash.map(|x| format!("{:?}", x)), + evm_simulator_hash: this.evm_simulator_hash.map(|x| format!("{:?}", x)), fee_account: Some(format!("{:?}", this.fee_account)), l1_chain_id: Some(this.l1_chain_id.0), l2_chain_id: Some(this.l2_chain_id.as_u64()), diff --git a/core/lib/protobuf_config/src/proto/config/genesis.proto b/core/lib/protobuf_config/src/proto/config/genesis.proto index 08cbb954fcbc..5e955bf4f00d 100644 --- a/core/lib/protobuf_config/src/proto/config/genesis.proto +++ b/core/lib/protobuf_config/src/proto/config/genesis.proto @@ -28,5 +28,6 @@ message Genesis { optional Prover prover = 10; optional L1BatchCommitDataGeneratorMode l1_batch_commit_data_generator_mode = 29; // optional, default to rollup optional string genesis_protocol_semantic_version = 12; // optional; + optional string evm_simulator_hash = 13; // required; h256 reserved 11; reserved "shared_bridge"; } diff --git a/core/lib/prover_interface/src/inputs.rs b/core/lib/prover_interface/src/inputs.rs index 22a20223c8b4..776ca516aa3b 100644 --- a/core/lib/prover_interface/src/inputs.rs +++ b/core/lib/prover_interface/src/inputs.rs @@ -144,6 +144,7 @@ pub struct VMRunWitnessInputData { pub protocol_version: ProtocolVersionId, pub bootloader_code: Vec<[u8; 32]>, pub default_account_code_hash: U256, + pub evm_simulator_code_hash: U256, pub storage_refunds: Vec, pub pubdata_costs: Vec, pub witness_block_state: WitnessStorageState, diff --git a/core/lib/tee_verifier/src/lib.rs b/core/lib/tee_verifier/src/lib.rs index 8728a4e52749..7da20637a6c1 100644 --- a/core/lib/tee_verifier/src/lib.rs +++ b/core/lib/tee_verifier/src/lib.rs @@ -305,6 +305,10 @@ mod tests { code: vec![U256([1; 4])], hash: H256([1; 32]), }, + evm_simulator: SystemContractCode { + code: vec![U256([1; 4])], + hash: H256([1; 32]), + }, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/lib/types/src/abi.rs b/core/lib/types/src/abi.rs index 84f8aba64869..c1c0efa66e4c 100644 --- a/core/lib/types/src/abi.rs +++ b/core/lib/types/src/abi.rs @@ -198,6 +198,7 @@ pub struct ProposedUpgrade { pub factory_deps: Vec>, pub bootloader_hash: [u8; 32], pub default_account_hash: [u8; 32], + pub evm_simulator_hash: [u8; 32], pub verifier: Address, pub verifier_params: VerifierParams, pub l1_contracts_upgrade_calldata: Vec, @@ -257,6 +258,7 @@ impl ProposedUpgrade { ParamType::Array(ParamType::Bytes.into()), // factory deps ParamType::FixedBytes(32), // bootloader code hash ParamType::FixedBytes(32), // default account code hash + ParamType::FixedBytes(32), // evm simulator code hash ParamType::Address, // verifier address VerifierParams::schema(), // verifier params ParamType::Bytes, // l1 custom data @@ -278,6 +280,7 @@ impl ProposedUpgrade { ), Token::FixedBytes(self.bootloader_hash.into()), Token::FixedBytes(self.default_account_hash.into()), + Token::FixedBytes(self.evm_simulator_hash.into()), Token::Address(self.verifier), self.verifier_params.encode(), Token::Bytes(self.l1_contracts_upgrade_calldata.clone()), @@ -291,7 +294,7 @@ impl ProposedUpgrade { /// Returns an error if token doesn't match the `schema()`. pub fn decode(token: Token) -> anyhow::Result { let tokens = token.into_tuple().context("not a tuple")?; - anyhow::ensure!(tokens.len() == 10); + anyhow::ensure!(tokens.len() == 11); let mut t = tokens.into_iter(); let mut next = || t.next().unwrap(); Ok(Self { @@ -314,6 +317,10 @@ impl ProposedUpgrade { .into_fixed_bytes() .and_then(|b| b.try_into().ok()) .context("default_account_hash")?, + evm_simulator_hash: next() + .into_fixed_bytes() + .and_then(|b| b.try_into().ok()) + .context("evm_simulator_hash")?, verifier: next().into_address().context("verifier")?, verifier_params: VerifierParams::decode(next()).context("verifier_params")?, l1_contracts_upgrade_calldata: next() diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index 916fae6a35bc..e72884340252 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -638,7 +638,7 @@ pub struct ProtocolVersion { /// Verifier configuration #[deprecated] pub verification_keys_hashes: Option, - /// Hashes of base system contracts (bootloader and default account) + /// Hashes of base system contracts (bootloader, default account and evm simulator) #[deprecated] pub base_system_contracts: Option, /// Bootloader code hash @@ -647,6 +647,9 @@ pub struct ProtocolVersion { /// Default account code hash #[serde(rename = "defaultAccountCodeHash")] pub default_account_code_hash: Option, + /// Evm simulator code hash + #[serde(rename = "evmSimulatorCodeHash")] + pub evm_simulator_code_hash: Option, /// L2 Upgrade transaction hash #[deprecated] pub l2_system_upgrade_tx_hash: Option, @@ -662,6 +665,7 @@ impl ProtocolVersion { timestamp: u64, bootloader_code_hash: H256, default_account_code_hash: H256, + evm_simulator_code_hash: H256, l2_system_upgrade_tx_hash: Option, ) -> Self { Self { @@ -672,9 +676,11 @@ impl ProtocolVersion { base_system_contracts: Some(BaseSystemContractsHashes { bootloader: bootloader_code_hash, default_aa: default_account_code_hash, + evm_simulator: evm_simulator_code_hash, }), bootloader_code_hash: Some(bootloader_code_hash), default_account_code_hash: Some(default_account_code_hash), + evm_simulator_code_hash: Some(evm_simulator_code_hash), l2_system_upgrade_tx_hash, l2_system_upgrade_tx_hash_new: l2_system_upgrade_tx_hash, } @@ -690,6 +696,13 @@ impl ProtocolVersion { .or_else(|| self.base_system_contracts.map(|hashes| hashes.default_aa)) } + pub fn evm_simulator_code_hash(&self) -> Option { + self.evm_simulator_code_hash.or_else(|| { + self.base_system_contracts + .map(|hashes| hashes.evm_simulator) + }) + } + pub fn minor_version(&self) -> Option { self.minor_version.or(self.version_id) } @@ -847,6 +860,7 @@ mod tests { base_system_contracts: Some(Default::default()), bootloader_code_hash: Some(Default::default()), default_account_code_hash: Some(Default::default()), + evm_simulator_code_hash: Some(Default::default()), l2_system_upgrade_tx_hash: Default::default(), l2_system_upgrade_tx_hash_new: Default::default(), }; diff --git a/core/lib/types/src/commitment/mod.rs b/core/lib/types/src/commitment/mod.rs index 63d1bad486f3..944c0705f4f8 100644 --- a/core/lib/types/src/commitment/mod.rs +++ b/core/lib/types/src/commitment/mod.rs @@ -467,6 +467,7 @@ pub struct L1BatchMetaParameters { pub zkporter_is_available: bool, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, + pub evm_simulator_code_hash: H256, pub protocol_version: Option, } @@ -478,14 +479,7 @@ impl L1BatchMetaParameters { result.extend(self.bootloader_code_hash.as_bytes()); result.extend(self.default_aa_code_hash.as_bytes()); - if self - .protocol_version - .map_or(false, |ver| ver.is_post_1_5_0()) - { - // EVM simulator hash for now is the same as the default AA hash. - result.extend(self.default_aa_code_hash.as_bytes()); - } - + result.extend(self.evm_simulator_code_hash.as_bytes()); result } @@ -551,6 +545,7 @@ impl L1BatchCommitment { zkporter_is_available: ZKPORTER_IS_AVAILABLE, bootloader_code_hash: input.common().bootloader_code_hash, default_aa_code_hash: input.common().default_aa_code_hash, + evm_simulator_code_hash: input.common().evm_simulator_code_hash, protocol_version: Some(input.common().protocol_version), }; @@ -653,6 +648,7 @@ pub struct CommitmentCommonInput { pub rollup_root_hash: H256, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, + pub evm_simulator_code_hash: H256, pub protocol_version: ProtocolVersionId, } @@ -693,6 +689,7 @@ impl CommitmentInput { rollup_root_hash, bootloader_code_hash: base_system_contracts_hashes.bootloader, default_aa_code_hash: base_system_contracts_hashes.default_aa, + evm_simulator_code_hash: base_system_contracts_hashes.evm_simulator, protocol_version, }; if protocol_version.is_pre_boojum() { diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json index c5eccbce038a..74af90ce98f6 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json @@ -16,6 +16,7 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version20" }, "system_logs": [ @@ -212,6 +213,7 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version20" }, "auxiliary_output": { @@ -261,7 +263,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0x1759d3eff5b7f03b5207418548d2735fd8f70930c2726812f0b077581eb0832f", - "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", - "commitment": "0xde52fb0a4b41aa857b0b18a8e5932846a955f60e0921fb99974a9786369e8503" + "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", + "commitment": "0xfe674b8b0ca1602cf37cedd7bc1fd88ea36fd7a69eeda94c5ee13b2cf3496662" } } diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json index 4983bbeca143..17744c562fc2 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json @@ -16,6 +16,7 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version21" }, "system_logs": [ @@ -228,6 +229,7 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version21" }, "auxiliary_output": { @@ -277,7 +279,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0xa6410b9d726740cc0e3309565816ed7a929fb2ad7ab69b46cde006e7ea60dd5b", - "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", - "commitment": "0x3b2e443dd853fb0c15c5956db1deb2527661c2b2b64011ab345120c620bc5faa" + "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", + "commitment": "0x5885a3c69a01beb06a795f78269c2cc092919e3202f38ac57c2bd498cb1c3f74" } } diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json index 59a24b7c90ce..15d34a21b0f7 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json @@ -16,6 +16,7 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "system_logs": [ @@ -274,6 +275,7 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "auxiliary_output": { @@ -351,7 +353,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0xadc63d9c45f85598f3e3c232970315d1f6ac96222e379e16ced7a204524a4061", - "meta_parameters": "0xffdee3e679310760e0320a3f9dea3fa863b0771e4424193752ed803fc2d53d20", - "commitment": "0xbbac3e74f007f28453294acb27e3b5c85e67be1208203bb31db9065fe4305dea" + "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", + "commitment": "0x4fdd8c5b231dfc9fc81aba744a90fbec78627f529ac29f9fc758a7b9e62fa321" } } diff --git a/core/lib/types/src/commitment/tests/pre_boojum_test.json b/core/lib/types/src/commitment/tests/pre_boojum_test.json index 3aa163830330..eccd843c08a3 100644 --- a/core/lib/types/src/commitment/tests/pre_boojum_test.json +++ b/core/lib/types/src/commitment/tests/pre_boojum_test.json @@ -16,6 +16,7 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version17" }, "initial_writes": [ @@ -80,6 +81,7 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version17" }, "auxiliary_output": { @@ -564,7 +566,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0x688566b1fe957584256b3bbdc9f9862a7c98cd0a3fa542b3e73600e7bfcd63a3", - "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", - "commitment": "0x8e0a1f1f866df7d53f0648dc6e642eabd452a1319e4acae8cdf58d364d25ee59" + "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", + "commitment": "0xebf93d8addf13e664e78fc287468b8783954d9d92572a734f96f0aa63c536da2" } } diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 1afb108a0536..3766bda51ef3 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -62,6 +62,8 @@ pub struct ProtocolUpgrade { pub bootloader_code_hash: Option, /// New default account code hash. pub default_account_code_hash: Option, + /// New evm simulator code hash + pub evm_simulator_code_hash: Option, /// New verifier params. pub verifier_params: Option, /// New verifier address. @@ -112,12 +114,15 @@ impl ProtocolUpgrade { let upgrade = abi::ProposedUpgrade::decode(upgrade.into_iter().next().unwrap()).unwrap(); let bootloader_hash = H256::from_slice(&upgrade.bootloader_hash); let default_account_hash = H256::from_slice(&upgrade.default_account_hash); + let evm_simulator_hash = H256::from_slice(&upgrade.evm_simulator_hash); Ok(Self { version: ProtocolSemanticVersion::try_from_packed(upgrade.new_protocol_version) .map_err(|err| anyhow::format_err!("Version is not supported: {err}"))?, bootloader_code_hash: (bootloader_hash != H256::zero()).then_some(bootloader_hash), default_account_code_hash: (default_account_hash != H256::zero()) .then_some(default_account_hash), + evm_simulator_code_hash: (evm_simulator_hash != H256::zero()) + .then_some(evm_simulator_hash), verifier_params: (upgrade.verifier_params != abi::VerifierParams::default()) .then_some(upgrade.verifier_params.into()), verifier_address: (upgrade.verifier != Address::zero()).then_some(upgrade.verifier), @@ -298,6 +303,9 @@ impl ProtocolVersion { default_aa: upgrade .default_account_code_hash .unwrap_or(self.base_system_contracts_hashes.default_aa), + evm_simulator: upgrade + .evm_simulator_code_hash + .unwrap_or(self.base_system_contracts_hashes.evm_simulator), }, tx: upgrade.tx, } diff --git a/core/lib/types/src/storage/mod.rs b/core/lib/types/src/storage/mod.rs index a30a57bffa51..9ef037dc29b2 100644 --- a/core/lib/types/src/storage/mod.rs +++ b/core/lib/types/src/storage/mod.rs @@ -5,7 +5,7 @@ pub use log::*; use serde::{Deserialize, Serialize}; use zksync_basic_types::{web3::keccak256, L2ChainId}; pub use zksync_system_constants::*; -use zksync_utils::address_to_h256; +use zksync_utils::{address_to_h256, u256_to_h256}; use crate::{AccountTreeId, Address, H160, H256, U256}; @@ -78,6 +78,10 @@ pub fn get_code_key(account: &Address) -> StorageKey { StorageKey::new(account_code_storage, address_to_h256(account)) } +pub fn get_evm_code_hash_key(account: &Address) -> StorageKey { + get_deployer_key(get_address_mapping_key(account, u256_to_h256(1.into()))) +} + pub fn get_known_code_key(hash: &H256) -> StorageKey { let known_codes_storage = AccountTreeId::new(KNOWN_CODES_STORAGE_ADDRESS); StorageKey::new(known_codes_storage, *hash) @@ -88,6 +92,11 @@ pub fn get_system_context_key(key: H256) -> StorageKey { StorageKey::new(system_context, key) } +pub fn get_deployer_key(key: H256) -> StorageKey { + let deployer_contract = AccountTreeId::new(CONTRACT_DEPLOYER_ADDRESS); + StorageKey::new(deployer_contract, key) +} + pub fn get_is_account_key(account: &Address) -> StorageKey { let deployer = AccountTreeId::new(CONTRACT_DEPLOYER_ADDRESS); diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index a28c45b8feae..57ca0150f7f4 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -1,12 +1,14 @@ use std::path::PathBuf; use once_cell::sync::Lazy; -use zksync_basic_types::{AccountTreeId, Address, U256}; +use zksync_basic_types::{AccountTreeId, Address, H256, U256}; use zksync_contracts::{read_sys_contract_bytecode, ContractLanguage, SystemContractsRepo}; use zksync_system_constants::{ BOOTLOADER_UTILITIES_ADDRESS, CODE_ORACLE_ADDRESS, COMPRESSOR_ADDRESS, CREATE2_FACTORY_ADDRESS, - EVENT_WRITER_ADDRESS, P256VERIFY_PRECOMPILE_ADDRESS, PUBDATA_CHUNK_PUBLISHER_ADDRESS, + EVENT_WRITER_ADDRESS, EVM_GAS_MANAGER_ADDRESS, P256VERIFY_PRECOMPILE_ADDRESS, + PUBDATA_CHUNK_PUBLISHER_ADDRESS, }; +use zksync_utils::bytecode::hash_bytecode; use crate::{ block::DeployedContract, ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS, @@ -25,7 +27,7 @@ use crate::{ pub const TX_NONCE_INCREMENT: U256 = U256([1, 0, 0, 0]); // 1 pub const DEPLOYMENT_NONCE_INCREMENT: U256 = U256([0, 0, 1, 0]); // 2^128 -static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 25] = [ +static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 26] = [ ( "", "AccountCodeStorage", @@ -147,6 +149,12 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 25] = [ COMPLEX_UPGRADER_ADDRESS, ContractLanguage::Sol, ), + ( + "", + "EvmGasManager", + EVM_GAS_MANAGER_ADDRESS, + ContractLanguage::Sol, + ), // For now, only zero address and the bootloader address have empty bytecode at the init // In the future, we might want to set all of the system contracts this way. ("", "EmptyContract", Address::zero(), ContractLanguage::Sol), @@ -170,6 +178,18 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 25] = [ ), ]; +static EVM_SIMULATOR_HASH: Lazy = Lazy::new(|| { + hash_bytecode(&read_sys_contract_bytecode( + "", + "EvmInterpreter", + ContractLanguage::Yul, + )) +}); + +pub fn get_evm_simulator_hash() -> H256 { + *EVM_SIMULATOR_HASH +} + static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { SYSTEM_CONTRACT_LIST .iter() diff --git a/core/lib/vm_executor/src/oneshot/mock.rs b/core/lib/vm_executor/src/oneshot/mock.rs index 8f3a12603c1a..8408206ede4c 100644 --- a/core/lib/vm_executor/src/oneshot/mock.rs +++ b/core/lib/vm_executor/src/oneshot/mock.rs @@ -68,6 +68,7 @@ impl MockOneshotExecutor { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), } }, ) diff --git a/core/lib/vm_executor/src/storage.rs b/core/lib/vm_executor/src/storage.rs index e39748786a30..e9b425c67cde 100644 --- a/core/lib/vm_executor/src/storage.rs +++ b/core/lib/vm_executor/src/storage.rs @@ -301,7 +301,11 @@ impl L1BatchParamsProvider { let contract_hashes = first_l2_block_in_batch.header.base_system_contracts_hashes; let base_system_contracts = storage .factory_deps_dal() - .get_base_system_contracts(contract_hashes.bootloader, contract_hashes.default_aa) + .get_base_system_contracts( + contract_hashes.bootloader, + contract_hashes.default_aa, + contract_hashes.evm_simulator, + ) .await .context("failed getting base system contracts")?; diff --git a/core/lib/vm_interface/Cargo.toml b/core/lib/vm_interface/Cargo.toml index 694576dca3b0..a605a8a055dc 100644 --- a/core/lib/vm_interface/Cargo.toml +++ b/core/lib/vm_interface/Cargo.toml @@ -14,6 +14,7 @@ categories.workspace = true zksync_contracts.workspace = true zksync_system_constants.workspace = true zksync_types.workspace = true +zksync_utils.workspace = true anyhow.workspace = true async-trait.workspace = true diff --git a/core/lib/vm_interface/src/storage/in_memory.rs b/core/lib/vm_interface/src/storage/in_memory.rs index 6a8b56433455..27dd9c239444 100644 --- a/core/lib/vm_interface/src/storage/in_memory.rs +++ b/core/lib/vm_interface/src/storage/in_memory.rs @@ -1,10 +1,12 @@ use std::collections::{hash_map::Entry, BTreeMap, HashMap}; use zksync_types::{ - block::DeployedContract, get_code_key, get_known_code_key, get_system_context_init_logs, - system_contracts::get_system_smart_contracts, L2ChainId, StorageKey, StorageLog, StorageValue, - H256, + block::DeployedContract, + get_code_key, get_deployer_key, get_known_code_key, get_system_context_init_logs, + system_contracts::{get_evm_simulator_hash, get_system_smart_contracts}, + L2ChainId, StorageKey, StorageLog, StorageValue, H256, }; +use zksync_utils::u256_to_h256; use super::ReadStorage; @@ -62,6 +64,10 @@ impl InMemoryStorage { ] }) .chain(system_context_init_log) + .chain(vec![StorageLog::new_write_log( + get_deployer_key(u256_to_h256(1.into())), + get_evm_simulator_hash(), + )]) .filter_map(|log| (log.is_write()).then_some((log.key, log.value))) .collect(); let state: HashMap<_, _> = state_without_indices diff --git a/core/lib/vm_interface/src/types/outputs/execution_result.rs b/core/lib/vm_interface/src/types/outputs/execution_result.rs index 6f9c02f0b587..3ca91c161525 100644 --- a/core/lib/vm_interface/src/types/outputs/execution_result.rs +++ b/core/lib/vm_interface/src/types/outputs/execution_result.rs @@ -118,6 +118,7 @@ pub struct VmExecutionResultAndLogs { pub logs: VmExecutionLogs, pub statistics: VmExecutionStatistics, pub refunds: Refunds, + pub new_known_factory_deps: Option)>>, } #[derive(Debug, Clone, PartialEq)] diff --git a/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs b/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs index 27241c2c0fae..a71c9f8f7a5e 100644 --- a/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs +++ b/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs @@ -26,6 +26,7 @@ impl FinishedL1Batch { logs: VmExecutionLogs::default(), statistics: VmExecutionStatistics::default(), refunds: Refunds::default(), + new_known_factory_deps: Default::default(), }, final_execution_state: CurrentExecutionState { events: vec![], diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index 26f4aa2b0b5f..c32ba3685f21 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -171,6 +171,12 @@ impl EnNamespace { genesis_commitment: Some(genesis_batch.metadata.commitment), bootloader_hash: Some(genesis_batch.header.base_system_contracts_hashes.bootloader), default_aa_hash: Some(genesis_batch.header.base_system_contracts_hashes.default_aa), + evm_simulator_hash: Some( + genesis_batch + .header + .base_system_contracts_hashes + .evm_simulator, + ), l1_chain_id: self.state.api_config.l1_chain_id, sl_chain_id: Some(self.state.api_config.l1_chain_id.into()), l2_chain_id: self.state.api_config.l2_chain_id, diff --git a/core/node/api_server/src/web3/tests/vm.rs b/core/node/api_server/src/web3/tests/vm.rs index d8d1a2c7768e..e6dee2c43104 100644 --- a/core/node/api_server/src/web3/tests/vm.rs +++ b/core/node/api_server/src/web3/tests/vm.rs @@ -337,6 +337,7 @@ impl HttpTest for SendTransactionWithDetailedOutputTest { logs: vm_execution_logs.clone(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), } }); tx_executor diff --git a/core/node/commitment_generator/src/lib.rs b/core/node/commitment_generator/src/lib.rs index 6cb14cfda531..f9235531b813 100644 --- a/core/node/commitment_generator/src/lib.rs +++ b/core/node/commitment_generator/src/lib.rs @@ -176,6 +176,7 @@ impl CommitmentGenerator { rollup_root_hash: tree_data.hash, bootloader_code_hash: header.base_system_contracts_hashes.bootloader, default_aa_code_hash: header.base_system_contracts_hashes.default_aa, + evm_simulator_code_hash: header.base_system_contracts_hashes.evm_simulator, protocol_version, }; let touched_slots = connection diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 6e9e71d74ea4..f07cecb0dfa4 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -183,6 +183,17 @@ impl EthTxAggregator { calldata: get_l2_default_aa_hash_input, }; + let get_l2_evm_simulator_hash_input = self + .functions + .get_evm_simulator_bytecode_hash + .encode_input(&[]) + .unwrap(); + let get_evm_simulator_hash_call = Multicall3Call { + target: self.state_transition_chain_contract, + allow_failure: ALLOW_FAILURE, + calldata: get_l2_evm_simulator_hash_input, + }; + // Third zksync contract call let get_verifier_params_input = self .functions @@ -219,6 +230,7 @@ impl EthTxAggregator { vec![ get_bootloader_hash_call.into_token(), get_default_aa_hash_call.into_token(), + get_evm_simulator_hash_call.into_token(), get_verifier_params_call.into_token(), get_verifier_call.into_token(), get_protocol_version_call.into_token(), @@ -239,7 +251,7 @@ impl EthTxAggregator { if let Token::Array(call_results) = token { // 5 calls are aggregated in multicall - if call_results.len() != 5 { + if call_results.len() != 6 { return parse_error(&call_results); } let mut call_results_iterator = call_results.into_iter(); @@ -268,9 +280,22 @@ impl EthTxAggregator { ))); } let default_aa = H256::from_slice(&multicall3_default_aa); + let multicall3_evm_simulator = + Multicall3Result::from_token(call_results_iterator.next().unwrap())?.return_data; + if multicall3_evm_simulator.len() != 32 { + return Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( + format!( + "multicall3 evm simulator hash data is not of the len of 32: {:?}", + multicall3_evm_simulator + ), + ))); + } + let evm_simulator = H256::from_slice(&multicall3_evm_simulator); + let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader, default_aa, + evm_simulator, }; call_results_iterator.next().unwrap(); diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index e03532458f18..4ddadf400e3e 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -41,8 +41,9 @@ pub(crate) fn mock_multicall_response() -> Token { Token::Array(vec![ Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![1u8; 32])]), Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![2u8; 32])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![3u8; 96])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![4u8; 32])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![3u8; 32])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![4u8; 96])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![5u8; 32])]), Token::Tuple(vec![ Token::Bool(true), Token::Bytes( @@ -74,6 +75,7 @@ pub(crate) fn default_l1_batch_metadata() -> L1BatchMetadata { zkporter_is_available: false, bootloader_code_hash: H256::default(), default_aa_code_hash: H256::default(), + evm_simulator_code_hash: H256::default(), protocol_version: Some(ProtocolVersionId::default()), }, aux_data_hash: H256::default(), diff --git a/core/node/eth_sender/src/zksync_functions.rs b/core/node/eth_sender/src/zksync_functions.rs index 8f13f0e63ae8..577c18277da0 100644 --- a/core/node/eth_sender/src/zksync_functions.rs +++ b/core/node/eth_sender/src/zksync_functions.rs @@ -12,6 +12,7 @@ pub(super) struct ZkSyncFunctions { pub(super) get_l2_bootloader_bytecode_hash: Function, pub(super) get_l2_default_account_bytecode_hash: Function, pub(super) get_verifier: Function, + pub(super) get_evm_simulator_bytecode_hash: Function, pub(super) get_verifier_params: Function, pub(super) get_protocol_version: Function, @@ -59,6 +60,8 @@ impl Default for ZkSyncFunctions { get_function(&zksync_contract, "getL2BootloaderBytecodeHash"); let get_l2_default_account_bytecode_hash = get_function(&zksync_contract, "getL2DefaultAccountBytecodeHash"); + let get_evm_simulator_bytecode_hash = + get_function(&zksync_contract, "getL2EvmSimulatorBytecodeHash"); let get_verifier = get_function(&zksync_contract, "getVerifier"); let get_verifier_params = get_function(&zksync_contract, "getVerifierParams"); let get_protocol_version = get_function(&zksync_contract, "getProtocolVersion"); @@ -74,6 +77,7 @@ impl Default for ZkSyncFunctions { post_shared_bridge_execute, get_l2_bootloader_bytecode_hash, get_l2_default_account_bytecode_hash, + get_evm_simulator_bytecode_hash, get_verifier, get_verifier_params, get_protocol_version, diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index e6e343f50bca..899690d6dabe 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -582,6 +582,7 @@ fn upgrade_into_diamond_cut(upgrade: ProtocolUpgrade) -> Token { factory_deps, bootloader_hash: upgrade.bootloader_code_hash.unwrap_or_default().into(), default_account_hash: upgrade.default_account_code_hash.unwrap_or_default().into(), + evm_simulator_hash: upgrade.evm_simulator_code_hash.unwrap_or_default().into(), verifier: upgrade.verifier_address.unwrap_or_default(), verifier_params: upgrade.verifier_params.unwrap_or_default().into(), l1_contracts_upgrade_calldata: vec![], diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 1f30d314bb06..65c795843bfb 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -104,6 +104,9 @@ impl GenesisParams { default_aa: config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, + evm_simulator: config + .evm_simulator_hash + .ok_or(GenesisError::MalformedConfig("evm_simulator_hash"))?, }; if base_system_contracts_hashes != base_system_contracts.hashes() { return Err(GenesisError::BaseSystemContractsHashes(Box::new( @@ -172,6 +175,7 @@ pub fn mock_genesis_config() -> GenesisConfig { genesis_commitment: Some(H256::default()), bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), + evm_simulator_hash: Some(base_system_contracts_hashes.evm_simulator), l1_chain_id: L1ChainId(9), sl_chain_id: None, l2_chain_id: L2ChainId::default(), @@ -235,6 +239,10 @@ pub async fn insert_genesis_batch( .config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, + evm_simulator: genesis_params + .config + .evm_simulator_hash + .ok_or(GenesisError::MalformedConfig("evm_simulator_hash"))?, }; let commitment_input = CommitmentInput::for_genesis_batch( genesis_root_hash, diff --git a/core/node/genesis/src/utils.rs b/core/node/genesis/src/utils.rs index a6c9513dbde8..d0e8aa020363 100644 --- a/core/node/genesis/src/utils.rs +++ b/core/node/genesis/src/utils.rs @@ -129,10 +129,14 @@ pub(super) async fn insert_base_system_contracts_to_factory_deps( storage: &mut Connection<'_, Core>, contracts: &BaseSystemContracts, ) -> Result<(), GenesisError> { - let factory_deps = [&contracts.bootloader, &contracts.default_aa] - .iter() - .map(|c| (c.hash, be_words_to_bytes(&c.code))) - .collect(); + let factory_deps = [ + &contracts.bootloader, + &contracts.default_aa, + &contracts.evm_simulator, + ] + .iter() + .map(|c| (c.hash, be_words_to_bytes(&c.code))) + .collect(); Ok(storage .factory_deps_dal() diff --git a/core/node/node_sync/src/external_io.rs b/core/node/node_sync/src/external_io.rs index b7b8930c4957..c9875744e240 100644 --- a/core/node/node_sync/src/external_io.rs +++ b/core/node/node_sync/src/external_io.rs @@ -345,6 +345,9 @@ impl StateKeeperIO for ExternalIO { let default_account_code_hash = protocol_version .default_account_code_hash() .context("Missing default account code hash")?; + let evm_simulator_code_hash = protocol_version + .evm_simulator_code_hash() + .context("Missing evm simulator code hash")?; let l2_system_upgrade_tx_hash = protocol_version.l2_system_upgrade_tx_hash(); self.pool .connection_tagged("sync_layer") @@ -362,6 +365,7 @@ impl StateKeeperIO for ExternalIO { BaseSystemContractsHashes { bootloader: bootloader_code_hash, default_aa: default_account_code_hash, + evm_simulator: evm_simulator_code_hash, }, l2_system_upgrade_tx_hash, ) @@ -375,9 +379,14 @@ impl StateKeeperIO for ExternalIO { .get_base_system_contract(default_account_code_hash, cursor.next_l2_block) .await .with_context(|| format!("cannot fetch default AA code for {protocol_version:?}"))?; + let evm_simulator = self + .get_base_system_contract(evm_simulator_code_hash, cursor.next_l2_block) + .await + .with_context(|| format!("cannot fetch EVM simulator code for {protocol_version:?}"))?; Ok(BaseSystemContracts { bootloader, default_aa, + evm_simulator, }) } diff --git a/core/node/node_sync/src/genesis.rs b/core/node/node_sync/src/genesis.rs index ccc26b417e98..645b96c16d05 100644 --- a/core/node/node_sync/src/genesis.rs +++ b/core/node/node_sync/src/genesis.rs @@ -38,6 +38,9 @@ async fn create_genesis_params( let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader: config.bootloader_hash.context("Genesis is not finished")?, default_aa: config.default_aa_hash.context("Genesis is not finished")?, + evm_simulator: config + .evm_simulator_hash + .context("Genesis is not finished")?, }; if zksync_chain_id != config.l2_chain_id { @@ -103,6 +106,10 @@ async fn fetch_base_system_contracts( .fetch_system_contract_by_hash(contract_hashes.default_aa) .await? .context("default AA bytecode is missing on main node")?; + let evm_simulator = client + .fetch_system_contract_by_hash(contract_hashes.evm_simulator) + .await? + .context("EVM Simulator bytecode is missing on main node")?; Ok(BaseSystemContracts { bootloader: SystemContractCode { code: zksync_utils::bytes_to_be_words(bootloader_bytecode), @@ -112,5 +119,9 @@ async fn fetch_base_system_contracts( code: zksync_utils::bytes_to_be_words(default_aa_bytecode), hash: contract_hashes.default_aa, }, + evm_simulator: SystemContractCode { + code: zksync_utils::bytes_to_be_words(evm_simulator), + hash: contract_hashes.evm_simulator, + }, }) } diff --git a/core/node/node_sync/src/tests.rs b/core/node/node_sync/src/tests.rs index d9a98c2bce36..a9eb2172e63e 100644 --- a/core/node/node_sync/src/tests.rs +++ b/core/node/node_sync/src/tests.rs @@ -304,6 +304,7 @@ async fn external_io_works_without_local_protocol_version(snapshot_recovery: boo timestamp: snapshot.l2_block_timestamp + 1, bootloader_code_hash: Some(H256::repeat_byte(1)), default_account_code_hash: Some(H256::repeat_byte(1)), + evm_simulator_code_hash: Some(H256::repeat_byte(1)), ..api::ProtocolVersion::default() }; client.insert_protocol_version(next_protocol_version.clone()); @@ -345,6 +346,13 @@ async fn external_io_works_without_local_protocol_version(snapshot_recovery: boo next_protocol_version.default_account_code_hash.unwrap() ); + assert_eq!( + persisted_protocol_version + .base_system_contracts_hashes + .evm_simulator, + next_protocol_version.evm_simulator_code_hash.unwrap() + ); + let l2_block = storage .blocks_dal() .get_l2_block_header(snapshot.l2_block_number + 1) diff --git a/core/node/proof_data_handler/src/tests.rs b/core/node/proof_data_handler/src/tests.rs index 6ab7e4dec436..19c1b92f86bc 100644 --- a/core/node/proof_data_handler/src/tests.rs +++ b/core/node/proof_data_handler/src/tests.rs @@ -62,6 +62,10 @@ async fn request_tee_proof_inputs() { code: vec![U256([1; 4])], hash: H256([1; 32]), }, + evm_simulator: SystemContractCode { + code: vec![U256([1; 4])], + hash: H256([1; 32]), + }, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/node/state_keeper/src/executor/mod.rs b/core/node/state_keeper/src/executor/mod.rs index 2fa5c3b9c128..903dae2f1cad 100644 --- a/core/node/state_keeper/src/executor/mod.rs +++ b/core/node/state_keeper/src/executor/mod.rs @@ -40,7 +40,7 @@ impl TxExecutionResult { _ => Self::Success { tx_metrics: Box::new(ExecutionMetricsForCriteria::new(Some(tx), &res.tx_result)), gas_remaining: res.tx_result.statistics.gas_remaining, - tx_result: res.tx_result, + tx_result: res.tx_result.clone(), compressed_bytecodes: res.compressed_bytecodes, call_tracer_result: res.call_traces, }, diff --git a/core/node/state_keeper/src/io/persistence.rs b/core/node/state_keeper/src/io/persistence.rs index 24b1ffca631c..d520fc8c88b6 100644 --- a/core/node/state_keeper/src/io/persistence.rs +++ b/core/node/state_keeper/src/io/persistence.rs @@ -462,6 +462,7 @@ mod tests { tx, tx_result, vec![], + vec![], BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index 7ea01e6af1e8..ef37f3cda75a 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -250,6 +250,7 @@ async fn processing_storage_logs_when_sealing_l2_block() { VmExecutionMetrics::default(), vec![], vec![], + vec![], ); let tx = create_transaction(10, 100); @@ -268,6 +269,7 @@ async fn processing_storage_logs_when_sealing_l2_block() { VmExecutionMetrics::default(), vec![], vec![], + vec![], ); let l1_batch_number = L1BatchNumber(2); @@ -357,6 +359,7 @@ async fn processing_events_when_sealing_l2_block() { VmExecutionMetrics::default(), vec![], vec![], + vec![], ); } @@ -457,6 +460,7 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom tx.into(), create_execution_result([]), vec![], + vec![], BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/keeper.rs b/core/node/state_keeper/src/keeper.rs index d36ceec7d70c..22f24573070b 100644 --- a/core/node/state_keeper/src/keeper.rs +++ b/core/node/state_keeper/src/keeper.rs @@ -498,8 +498,9 @@ impl ZkSyncStateKeeper { updates_manager.extend_from_executed_transaction( tx, - *tx_result, + *tx_result.clone(), compressed_bytecodes, + tx_result.new_known_factory_deps.unwrap_or_default(), tx_l1_gas_this_tx, tx_execution_metrics, call_tracer_result, @@ -624,8 +625,9 @@ impl ZkSyncStateKeeper { } = *tx_metrics; updates_manager.extend_from_executed_transaction( tx, - *tx_result, + *tx_result.clone(), compressed_bytecodes, + tx_result.new_known_factory_deps.unwrap_or_default(), tx_l1_gas_this_tx, tx_execution_metrics, call_tracer_result, @@ -704,8 +706,9 @@ impl ZkSyncStateKeeper { } = *tx_metrics; updates_manager.extend_from_executed_transaction( tx, - *tx_result, + *tx_result.clone(), compressed_bytecodes, + tx_result.new_known_factory_deps.unwrap_or_default(), tx_l1_gas_this_tx, tx_execution_metrics, vec![], diff --git a/core/node/state_keeper/src/seal_criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/mod.rs index e3fe849e8025..4919684a70d5 100644 --- a/core/node/state_keeper/src/seal_criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/mod.rs @@ -287,6 +287,7 @@ mod tests { tx, create_execution_result([]), vec![], + vec![], BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/testonly/mod.rs b/core/node/state_keeper/src/testonly/mod.rs index edcf3ccc4f5c..34a9a88bcb32 100644 --- a/core/node/state_keeper/src/testonly/mod.rs +++ b/core/node/state_keeper/src/testonly/mod.rs @@ -33,6 +33,7 @@ pub(crate) fn successful_exec() -> BatchTransactionExecutionResult { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }), compressed_bytecodes: vec![], call_traces: vec![], 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 ffca8dff8643..2a883bb011b3 100644 --- a/core/node/state_keeper/src/testonly/test_batch_executor.rs +++ b/core/node/state_keeper/src/testonly/test_batch_executor.rs @@ -264,6 +264,7 @@ pub(crate) fn successful_exec_with_log() -> BatchTransactionExecutionResult { }, statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }), compressed_bytecodes: vec![], call_traces: vec![], @@ -278,6 +279,7 @@ pub(crate) fn rejected_exec(reason: Halt) -> BatchTransactionExecutionResult { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), + new_known_factory_deps: Default::default(), }), compressed_bytecodes: vec![], call_traces: vec![], diff --git a/core/node/state_keeper/src/tests/mod.rs b/core/node/state_keeper/src/tests/mod.rs index 80de0f0beff9..10c42c7857bd 100644 --- a/core/node/state_keeper/src/tests/mod.rs +++ b/core/node/state_keeper/src/tests/mod.rs @@ -138,6 +138,7 @@ pub(super) fn create_execution_result( circuit_statistic: Default::default(), }, refunds: Refunds::default(), + new_known_factory_deps: Default::default(), } } diff --git a/core/node/state_keeper/src/updates/l1_batch_updates.rs b/core/node/state_keeper/src/updates/l1_batch_updates.rs index aa2e22cac483..8a714ed2e815 100644 --- a/core/node/state_keeper/src/updates/l1_batch_updates.rs +++ b/core/node/state_keeper/src/updates/l1_batch_updates.rs @@ -77,6 +77,7 @@ mod tests { VmExecutionMetrics::default(), vec![], vec![], + vec![], ); let mut l1_batch_accumulator = L1BatchUpdates::new(L1BatchNumber(1)); diff --git a/core/node/state_keeper/src/updates/l2_block_updates.rs b/core/node/state_keeper/src/updates/l2_block_updates.rs index d8673088dc32..3d0d35096c2f 100644 --- a/core/node/state_keeper/src/updates/l2_block_updates.rs +++ b/core/node/state_keeper/src/updates/l2_block_updates.rs @@ -1,17 +1,14 @@ use std::collections::HashMap; -use once_cell::sync::Lazy; use zksync_multivm::{ interface::{ Call, CompressedBytecodeInfo, ExecutionResult, L2BlockEnv, TransactionExecutionResult, TxExecutionStatus, VmEvent, VmExecutionMetrics, VmExecutionResultAndLogs, }, - vm_latest::TransactionVmExt, + vm_latest::{utils::extract_bytecodes_marked_as_known, TransactionVmExt}, }; -use zksync_system_constants::KNOWN_CODES_STORAGE_ADDRESS; use zksync_types::{ block::{BlockGasCount, L2BlockHasher}, - ethabi, l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, L2BlockNumber, ProtocolVersionId, StorageLogWithPreviousValue, Transaction, H256, }; @@ -19,27 +16,6 @@ use zksync_utils::bytecode::hash_bytecode; use crate::metrics::KEEPER_METRICS; -/// Extracts all bytecodes marked as known on the system contracts. -fn extract_bytecodes_marked_as_known(all_generated_events: &[VmEvent]) -> Vec { - static PUBLISHED_BYTECODE_SIGNATURE: Lazy = Lazy::new(|| { - ethabi::long_signature( - "MarkedAsKnown", - &[ethabi::ParamType::FixedBytes(32), ethabi::ParamType::Bool], - ) - }); - - all_generated_events - .iter() - .filter(|event| { - // Filter events from the deployer contract that match the expected signature. - event.address == KNOWN_CODES_STORAGE_ADDRESS - && event.indexed_topics.len() == 3 - && event.indexed_topics[0] == *PUBLISHED_BYTECODE_SIGNATURE - }) - .map(|event| event.indexed_topics[1]) - .collect() -} - #[derive(Debug, Clone, PartialEq)] pub struct L2BlockUpdates { pub executed_transactions: Vec, @@ -104,6 +80,7 @@ impl L2BlockUpdates { self.block_execution_metrics += execution_metrics; } + #[allow(clippy::too_many_arguments)] pub(crate) fn extend_from_executed_transaction( &mut self, tx: Transaction, @@ -111,10 +88,12 @@ impl L2BlockUpdates { tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, compressed_bytecodes: Vec, + new_known_factory_deps: Vec<(H256, Vec)>, call_traces: Vec, ) { let saved_factory_deps = extract_bytecodes_marked_as_known(&tx_execution_result.logs.events); + self.new_factory_deps.extend(new_known_factory_deps.clone()); self.events.extend(tx_execution_result.logs.events); self.user_l2_to_l1_logs .extend(tx_execution_result.logs.user_l2_to_l1_logs); @@ -145,11 +124,17 @@ impl L2BlockUpdates { // Get transaction factory deps let factory_deps = &tx.execute.factory_deps; - let tx_factory_deps: HashMap<_, _> = factory_deps + let mut tx_factory_deps: HashMap<_, _> = factory_deps .iter() - .map(|bytecode| (hash_bytecode(bytecode), bytecode)) + .map(|bytecode| (hash_bytecode(bytecode), bytecode.clone())) .collect(); + new_known_factory_deps + .into_iter() + .for_each(|(hash, bytecode)| { + tx_factory_deps.insert(hash, bytecode); + }); + // Save all bytecodes that were marked as known on the bootloader let known_bytecodes = saved_factory_deps.into_iter().map(|bytecode_hash| { let bytecode = tx_factory_deps.get(&bytecode_hash).unwrap_or_else(|| { @@ -231,6 +216,7 @@ mod tests { VmExecutionMetrics::default(), vec![], vec![], + vec![], ); assert_eq!(accumulator.executed_transactions.len(), 1); diff --git a/core/node/state_keeper/src/updates/mod.rs b/core/node/state_keeper/src/updates/mod.rs index 2fad56a99299..0761e36a97c9 100644 --- a/core/node/state_keeper/src/updates/mod.rs +++ b/core/node/state_keeper/src/updates/mod.rs @@ -8,7 +8,7 @@ use zksync_multivm::{ }; use zksync_types::{ block::BlockGasCount, fee_model::BatchFeeInput, Address, L1BatchNumber, L2BlockNumber, - ProtocolVersionId, Transaction, + ProtocolVersionId, Transaction, H256, }; pub(crate) use self::{l1_batch_updates::L1BatchUpdates, l2_block_updates::L2BlockUpdates}; @@ -104,11 +104,13 @@ impl UpdatesManager { self.protocol_version } + #[allow(clippy::too_many_arguments)] pub fn extend_from_executed_transaction( &mut self, tx: Transaction, tx_execution_result: VmExecutionResultAndLogs, compressed_bytecodes: Vec, + new_known_factory_deps: Vec<(H256, Vec)>, tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, call_traces: Vec, @@ -124,6 +126,7 @@ impl UpdatesManager { tx_l1_gas_this_tx, execution_metrics, compressed_bytecodes, + new_known_factory_deps, call_traces, ); latency.observe(); @@ -236,6 +239,7 @@ mod tests { new_block_gas_count(), VmExecutionMetrics::default(), vec![], + vec![], ); // Check that only pending state is updated. diff --git a/core/node/test_utils/src/lib.rs b/core/node/test_utils/src/lib.rs index b9984b782111..92b8b02462be 100644 --- a/core/node/test_utils/src/lib.rs +++ b/core/node/test_utils/src/lib.rs @@ -56,6 +56,7 @@ pub fn create_l1_batch(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), + evm_simulator: H256::repeat_byte(43), }, ProtocolVersionId::latest(), ); @@ -88,6 +89,7 @@ pub fn create_l1_batch_metadata(number: u32) -> L1BatchMetadata { zkporter_is_available: ZKPORTER_IS_AVAILABLE, bootloader_code_hash: BaseSystemContractsHashes::default().bootloader, default_aa_code_hash: BaseSystemContractsHashes::default().default_aa, + evm_simulator_code_hash: BaseSystemContractsHashes::default().evm_simulator, protocol_version: Some(ProtocolVersionId::latest()), }, aux_data_hash: H256::zero(), @@ -215,10 +217,14 @@ impl Snapshot { Snapshot { l1_batch, l2_block, - factory_deps: [&contracts.bootloader, &contracts.default_aa] - .into_iter() - .map(|c| (c.hash, zksync_utils::be_words_to_bytes(&c.code))) - .collect(), + factory_deps: [ + &contracts.bootloader, + &contracts.default_aa, + &contracts.evm_simulator, + ] + .into_iter() + .map(|c| (c.hash, zksync_utils::be_words_to_bytes(&c.code))) + .collect(), storage_logs, } } diff --git a/core/node/vm_runner/src/impls/bwip.rs b/core/node/vm_runner/src/impls/bwip.rs index f23f63533ff5..30473b6b3997 100644 --- a/core/node/vm_runner/src/impls/bwip.rs +++ b/core/node/vm_runner/src/impls/bwip.rs @@ -209,6 +209,10 @@ async fn get_updates_manager_witness_input_data( ) -> anyhow::Result { let initial_heap_content = output.batch.final_bootloader_memory.clone().unwrap(); // might be just empty let default_aa = system_env.base_system_smart_contracts.hashes().default_aa; + let evm_simulator = system_env + .base_system_smart_contracts + .hashes() + .evm_simulator; let bootloader = system_env.base_system_smart_contracts.hashes().bootloader; let bootloader_code_bytes = connection .factory_deps_dal() @@ -225,6 +229,14 @@ async fn get_updates_manager_witness_input_data( .ok_or_else(|| anyhow!("Default account bytecode should exist"))?; let account_bytecode = bytes_to_chunks(&account_bytecode_bytes); + let evm_simulator_code_hash = h256_to_u256(evm_simulator); + let simulator_bytecode_bytes = connection + .factory_deps_dal() + .get_sealed_factory_dep(evm_simulator) + .await? + .ok_or_else(|| anyhow!("EVM Simulator bytecode should exist"))?; + let evm_simulator_bytecode = bytes_to_chunks(&simulator_bytecode_bytes); + let used_contract_hashes = &output.batch.final_execution_state.used_contract_hashes; let hashes: HashSet = used_contract_hashes .iter() @@ -240,6 +252,10 @@ async fn get_updates_manager_witness_input_data( used_bytecodes.insert(account_code_hash, account_bytecode); } + if used_contract_hashes.contains(&evm_simulator_code_hash) { + used_bytecodes.insert(evm_simulator_code_hash, evm_simulator_bytecode); + } + let storage_refunds = output.batch.final_execution_state.storage_refunds.clone(); let pubdata_costs = output.batch.final_execution_state.pubdata_costs.clone(); let witness_block_state = WitnessStorageState { @@ -254,6 +270,7 @@ async fn get_updates_manager_witness_input_data( protocol_version: system_env.version, bootloader_code, default_account_code_hash: account_code_hash, + evm_simulator_code_hash, storage_refunds, pubdata_costs, witness_block_state, diff --git a/core/node/vm_runner/src/tests/mod.rs b/core/node/vm_runner/src/tests/mod.rs index 928da3b93157..ef1d37ef00e7 100644 --- a/core/node/vm_runner/src/tests/mod.rs +++ b/core/node/vm_runner/src/tests/mod.rs @@ -322,6 +322,10 @@ async fn store_l1_batches( .iter() .map(|contract| hash_bytecode(&contract.bytecode)) .chain([genesis_params.base_system_contracts().hashes().default_aa]) + .chain([genesis_params + .base_system_contracts() + .hashes() + .evm_simulator]) .map(h256_to_u256) .collect(); diff --git a/core/node/vm_runner/src/tests/output_handler.rs b/core/node/vm_runner/src/tests/output_handler.rs index 1bf30effdbe5..9376beab1aa7 100644 --- a/core/node/vm_runner/src/tests/output_handler.rs +++ b/core/node/vm_runner/src/tests/output_handler.rs @@ -66,6 +66,10 @@ impl OutputHandlerTester { code: vec![], hash: Default::default(), }, + evm_simulator: SystemContractCode { + code: vec![], + hash: Default::default(), + }, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/etc/env/base/chain.toml b/etc/env/base/chain.toml index 6cfacb3c72ce..b5a4e4b2e75c 100644 --- a/etc/env/base/chain.toml +++ b/etc/env/base/chain.toml @@ -90,8 +90,9 @@ fee_model_version = "V2" validation_computational_gas_limit = 300000 save_call_traces = true -bootloader_hash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e" -default_aa_hash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32" +bootloader_hash = "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1" +default_aa_hash = "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2" +evm_simulator_hash = "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee" protective_reads_persistence_enabled = false diff --git a/etc/env/base/contracts.toml b/etc/env/base/contracts.toml index daa317a8bc90..fab072c07cec 100644 --- a/etc/env/base/contracts.toml +++ b/etc/env/base/contracts.toml @@ -26,11 +26,11 @@ RECURSION_NODE_LEVEL_VK_HASH = "0x1186ec268d49f1905f8d9c1e9d39fc33e98c74f91d91a2 RECURSION_LEAF_LEVEL_VK_HASH = "0x101e08b00193e529145ee09823378ef51a3bc8966504064f1f6ba3f1ba863210" RECURSION_CIRCUITS_SET_VKS_HASH = "0x18c1639094f58177409186e8c48d9f577c9410901d2f1d486b3e7d6cf553ae4c" GENESIS_TX_HASH = "0xb99ebfea46cbe05a21cd80fe5597d97b204befc52a16303f579c607dc1ac2e2e" -GENESIS_ROOT = "0xabdb766b18a479a5c783a4b80e12686bc8ea3cc2d8a3050491b701d72370ebb5" -GENESIS_BATCH_COMMITMENT = "0x2d00e5f8d77afcebf58a6b82ae56ba967566fe7dfbcb6760319fb0d215d18ffd" +GENESIS_ROOT = "0xbfa72908d61bf6e208a1140eb8b66a8e9fc0cc3ecd76f73d994fa75c49778530" +GENESIS_BATCH_COMMITMENT = "0xeac224ce2445688015b7b88a168332657fb1de5ccb3c55407d6107fbd483459e" PRIORITY_TX_MAX_GAS_LIMIT = 72000000 DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = 10000000 -GENESIS_ROLLUP_LEAF_INDEX = "54" +GENESIS_ROLLUP_LEAF_INDEX = "56" GENESIS_PROTOCOL_VERSION = "24" GENESIS_PROTOCOL_SEMANTIC_VERSION = "0.24.2" L1_WETH_BRIDGE_IMPL_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 220a75944e02..7f0dca74ef79 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -4,8 +4,8 @@ genesis_batch_commitment: 0x2d00e5f8d77afcebf58a6b82ae56ba967566fe7dfbcb6760319f genesis_protocol_semantic_version: '0.24.2' # deprecated genesis_protocol_version: 24 -default_aa_hash: 0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32 -bootloader_hash: 0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e +default_aa_hash: 0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2 +bootloader_hash: 0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1 l1_chain_id: 9 l2_chain_id: 270 fee_account: '0x0000000000000000000000000000000000000001' @@ -13,3 +13,4 @@ prover: recursion_scheduler_level_vk_hash: 0x14f97b81e54b35fe673d8708cc1a19e1ea5b5e348e12d31e39824ed4f42bbca2 dummy_verifier: true l1_batch_commit_data_generator_mode: Rollup +evm_simulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 diff --git a/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts b/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts index e3b5f364efd9..98a4cf1fbd83 100644 --- a/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts +++ b/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts @@ -8,6 +8,7 @@ export async function callSystemContractDeployer( nonce: string, bootloader: boolean, defaultAA: boolean, + evmSimulator: boolean, systemContracts: boolean, file: string ) { @@ -20,6 +21,9 @@ export async function callSystemContractDeployer( if (defaultAA) { argsString += ' --default-aa'; } + if (evmSimulator) { + argsString += '--evm-simulator'; + } if (systemContracts) { argsString += ' --system-contracts'; } diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 21e2ea8b21de..a838c8cbc0ef 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -347,6 +347,18 @@ dependencies = [ "tower-service", ] +[[package]] +name = "backon" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" +dependencies = [ + "fastrand", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" version = "0.3.72" @@ -500,6 +512,27 @@ dependencies = [ "which", ] +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "prettyplease", + "proc-macro2 1.0.85", + "quote 1.0.36", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.66", +] + [[package]] name = "bindgen" version = "0.69.4" @@ -793,6 +826,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytecount" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" + [[package]] name = "byteorder" version = "1.5.0" @@ -805,6 +844,48 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.1.14" @@ -1500,6 +1581,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "debugid" version = "0.8.0" @@ -1866,6 +1960,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "etcetera" version = "0.8.0" @@ -3228,6 +3331,22 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "librocksdb-sys" +version = "0.11.0+8.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +dependencies = [ + "bindgen 0.65.1", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -3239,6 +3358,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -3305,6 +3435,16 @@ dependencies = [ "logos-codegen", ] +[[package]] +name = "lz4-sys" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -3402,6 +3542,21 @@ dependencies = [ "unicase", ] +[[package]] +name = "mini-moka" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" +dependencies = [ + "crossbeam-channel 0.5.13", + "crossbeam-utils 0.8.20", + "dashmap", + "skeptic", + "smallvec", + "tagptr", + "triomphe", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4474,6 +4629,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.6.0", + "memchr", + "unicase", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4882,6 +5048,16 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rocksdb" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +dependencies = [ + "libc", + "librocksdb-sys", +] + [[package]] name = "rsa" version = "0.9.6" @@ -5189,6 +5365,9 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "send_wrapper" @@ -5567,6 +5746,21 @@ dependencies = [ "time", ] +[[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + [[package]] name = "slab" version = "0.4.9" @@ -6046,6 +6240,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -6495,6 +6695,12 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "triomphe" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" + [[package]] name = "try-lock" version = "0.2.5" @@ -7657,6 +7863,8 @@ dependencies = [ "once_cell", "serde", "serde_json", + "zksync_config", + "zksync_env_config", "zksync_utils", ] @@ -7813,6 +8021,7 @@ dependencies = [ "circuit_sequencer_api 0.141.1", "circuit_sequencer_api 0.142.0", "circuit_sequencer_api 0.150.4", + "ethabi", "hex", "itertools 0.10.5", "once_cell", @@ -7827,6 +8036,7 @@ dependencies = [ "zk_evm 0.141.0", "zk_evm 0.150.4", "zksync_contracts", + "zksync_state", "zksync_system_constants", "zksync_types", "zksync_utils", @@ -8110,6 +8320,51 @@ dependencies = [ "zksync_utils", ] +[[package]] +name = "zksync_shared_metrics" +version = "0.1.0" +dependencies = [ + "rustc_version", + "tracing", + "vise", + "zksync_dal", + "zksync_types", +] + +[[package]] +name = "zksync_state" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "backon", + "chrono", + "itertools 0.10.5", + "mini-moka", + "once_cell", + "tokio", + "tracing", + "vise", + "zksync_dal", + "zksync_shared_metrics", + "zksync_storage", + "zksync_types", + "zksync_utils", + "zksync_vm_interface", +] + +[[package]] +name = "zksync_storage" +version = "0.1.0" +dependencies = [ + "num_cpus", + "once_cell", + "rocksdb", + "thread_local", + "tracing", + "vise", +] + [[package]] name = "zksync_system_constants" version = "0.1.0" @@ -8231,6 +8486,7 @@ dependencies = [ "zksync_contracts", "zksync_system_constants", "zksync_types", + "zksync_utils", ] [[package]] @@ -8317,3 +8573,13 @@ dependencies = [ "zksync_utils", "zksync_vlog", ] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/prover/crates/bin/witness_generator/src/basic_circuits.rs b/prover/crates/bin/witness_generator/src/basic_circuits.rs index 00a4d99ba9a9..a1adfed438a6 100644 --- a/prover/crates/bin/witness_generator/src/basic_circuits.rs +++ b/prover/crates/bin/witness_generator/src/basic_circuits.rs @@ -491,8 +491,7 @@ async fn generate_witness( bootloader_contents, false, input.vm_run_data.default_account_code_hash, - // NOTE: this will be evm_simulator_code_hash in future releases - input.vm_run_data.default_account_code_hash, + input.vm_run_data.evm_simulator_code_hash, input.vm_run_data.used_bytecodes, Vec::default(), MAX_CYCLES_FOR_TX as usize, diff --git a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs index 30ec0eeb9c48..a205f640331b 100644 --- a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs +++ b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs @@ -146,6 +146,7 @@ impl DeployL1Config { .diamond_init_minimal_l2_gas_price, bootloader_hash: genesis_config.bootloader_hash.unwrap(), default_aa_hash: genesis_config.default_aa_hash.unwrap(), + evm_simulator_hash: genesis_config.evm_simulator_hash.unwrap(), diamond_init_priority_tx_max_pubdata: initial_deployment_config .diamond_init_priority_tx_max_pubdata, diamond_init_pubdata_pricing_mode: initial_deployment_config @@ -194,6 +195,7 @@ pub struct ContractsDeployL1Config { pub diamond_init_minimal_l2_gas_price: u64, pub bootloader_hash: H256, pub default_aa_hash: H256, + pub evm_simulator_hash: H256, } #[derive(Debug, Deserialize, Serialize, Clone)] From 3a3a3003ac488295166a83af4e2def61ce44cc8e Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 16:50:39 -0300 Subject: [PATCH 04/72] Add ts tests and contracts for evm simulator --- .../contracts/create/TestEVMCreate.sol | 30 + .../ts-integration/contracts/token/ERC20.sol | 76 ++ .../contracts/uniswap-v2/UniswapV2Factory.sol | 683 +++++++++++++++ .../evm-contracts/ConstructorRevert.sol | 11 + .../evm-contracts/CounterFallback.sol | 14 + .../evm-contracts/CounterWithParam.sol | 39 + .../ts-integration/evm-contracts/Creator.sol | 19 + .../evm-contracts/CreatorFallback.sol | 20 + .../ts-integration/evm-contracts/ERC20.sol | 78 ++ .../evm-contracts/GasCaller.sol | 16 + .../evm-contracts/OpcodeTest.sol | 123 +++ .../evm-contracts/OpcodeTestFallback.sol | 139 +++ .../evm-contracts/ProxyCaller.sol | 25 + .../evm-contracts/SelfDestruct.sol | 13 + .../evm-contracts/UniswapFallback.sol | 125 +++ core/tests/ts-integration/package.json | 6 +- core/tests/ts-integration/src/helpers.ts | 47 + .../tests/evm-contracts.test.ts | 828 ++++++++++++++++++ 18 files changed, 2291 insertions(+), 1 deletion(-) create mode 100644 core/tests/ts-integration/contracts/create/TestEVMCreate.sol create mode 100644 core/tests/ts-integration/contracts/token/ERC20.sol create mode 100644 core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol create mode 100644 core/tests/ts-integration/evm-contracts/ConstructorRevert.sol create mode 100644 core/tests/ts-integration/evm-contracts/CounterFallback.sol create mode 100644 core/tests/ts-integration/evm-contracts/CounterWithParam.sol create mode 100644 core/tests/ts-integration/evm-contracts/Creator.sol create mode 100644 core/tests/ts-integration/evm-contracts/CreatorFallback.sol create mode 100644 core/tests/ts-integration/evm-contracts/ERC20.sol create mode 100644 core/tests/ts-integration/evm-contracts/GasCaller.sol create mode 100644 core/tests/ts-integration/evm-contracts/OpcodeTest.sol create mode 100644 core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol create mode 100644 core/tests/ts-integration/evm-contracts/ProxyCaller.sol create mode 100644 core/tests/ts-integration/evm-contracts/SelfDestruct.sol create mode 100644 core/tests/ts-integration/evm-contracts/UniswapFallback.sol create mode 100644 core/tests/ts-integration/tests/evm-contracts.test.ts diff --git a/core/tests/ts-integration/contracts/create/TestEVMCreate.sol b/core/tests/ts-integration/contracts/create/TestEVMCreate.sol new file mode 100644 index 000000000000..176790d14023 --- /dev/null +++ b/core/tests/ts-integration/contracts/create/TestEVMCreate.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +interface IContractDeployer { + function evmCodeHash(address key) external returns (bytes32); + + function createEVM( + bytes calldata _initCode + ) external payable returns (address newAddress); + + function create2EVM( + bytes32 _salt, + bytes calldata _initCode + ) external payable returns (address); +} + +/// @notice An example of a system contract that be used for local testing. +/// @dev It is not used anywhere except for testing +contract TestEVMCreate { + IContractDeployer deployer = IContractDeployer(address(0x8006)); + + function create(bytes calldata _code) external { + deployer.createEVM(_code); + } + + function create2(bytes32 _salt, bytes calldata _code) external payable { + deployer.create2EVM{value:msg.value}(_salt, _code); + } +} diff --git a/core/tests/ts-integration/contracts/token/ERC20.sol b/core/tests/ts-integration/contracts/token/ERC20.sol new file mode 100644 index 000000000000..514e2358624f --- /dev/null +++ b/core/tests/ts-integration/contracts/token/ERC20.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract ERC20{ + string public symbol; + string public name; + uint8 public decimals; + uint public totalSupply; + + mapping(address => uint) balances; + mapping(address => mapping(address => uint)) allowed; + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + + constructor() { + symbol = "TEST"; + name = "Test Coin"; + decimals = 18; + totalSupply = 1000000; + balances[msg.sender] = totalSupply; + emit Transfer(address(0), msg.sender, totalSupply); + } + + + function balanceOf(address tokenOwner) public view returns (uint balance) { + return balances[tokenOwner]; + } + + function transfer(address to, uint tokens) public returns (bool success) { + balances[msg.sender] = safeSub(balances[msg.sender], tokens); + balances[to] = safeAdd(balances[to], tokens); + emit Transfer(msg.sender, to, tokens); + return true; + } + + function approve(address spender, uint tokens) public returns (bool success) { + allowed[msg.sender][spender] = tokens; + emit Approval(msg.sender, spender, tokens); + return true; + } + + function transferFrom(address from, address to, uint tokens) public returns (bool success) { + balances[from] = safeSub(balances[from], tokens); + allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens); + balances[to] = safeAdd(balances[to], tokens); + emit Transfer(from, to, tokens); + return true; + } + + function allowance(address tokenOwner, address spender) public view returns (uint remaining) { + return allowed[tokenOwner][spender]; + } + + function safeAdd(uint a, uint b) internal pure returns (uint c) { + c = a + b; + require(c >= a); + } + + function safeSub(uint a, uint b) internal pure returns (uint c) { + require(b <= a); + c = a - b; + } + + function safeMul(uint a, uint b) internal pure returns (uint c) { + c = a * b; + require(a == 0 || c / a == b); + } + + function safeDiv(uint a, uint b) internal pure returns (uint c) { + require(b > 0); + c = a / b; + } + +} diff --git a/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol b/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol new file mode 100644 index 000000000000..91e74bb2b11a --- /dev/null +++ b/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol @@ -0,0 +1,683 @@ +// NOTE: Flattened to make easier to deploy to both native/evm + +// File contracts/uniswap-v2/interfaces/IUniswapV2Factory.sol + +pragma solidity ^0.8.0; + +interface IUniswapV2Factory { + function feeTo() external returns (address); + + function feeToSetter() external returns (address); + + function getPair( + address tokenA, + address tokenB + ) external returns (address pair); + + function allPairs(uint) external returns (address pair); + + function allPairsLength() external returns (uint); + + function createPair( + address tokenA, + address tokenB + ) external returns (address pair); + + function setFeeTo(address) external; + + function setFeeToSetter(address) external; +} + +// File contracts/uniswap-v2/libraries/SafeMath.sol + +pragma solidity ^0.8.0; + +// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) + +library SafeMath { + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, "ds-math-add-overflow"); + } + + function sub(uint x, uint y) internal pure returns (uint z) { + require((z = x - y) <= x, "ds-math-sub-underflow"); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); + } +} + +// File contracts/uniswap-v2/interfaces/IUniswapV2ERC20.sol + +pragma solidity ^0.8.0; + +interface IUniswapV2ERC20 { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external pure returns (string memory); + + function symbol() external pure returns (string memory); + + function decimals() external pure returns (uint8); + + function totalSupply() external returns (uint); + + function balanceOf(address owner) external returns (uint); + + function allowance(address owner, address spender) external returns (uint); + + function approve(address spender, uint value) external returns (bool); + + function transfer(address to, uint value) external returns (bool); + + function transferFrom( + address from, + address to, + uint value + ) external returns (bool); + + function DOMAIN_SEPARATOR() external returns (bytes32); + + function PERMIT_TYPEHASH() external pure returns (bytes32); + + function nonces(address owner) external returns (uint); + + function permit( + address owner, + address spender, + uint value, + uint deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} + +// File contracts/uniswap-v2/UniswapV2ERC20.sol + +pragma solidity ^0.8.0; + +contract UniswapV2ERC20 is IUniswapV2ERC20 { + using SafeMath for uint; + + string public override constant name = "Uniswap V2"; + string public override constant symbol = "UNI-V2"; + uint8 public override constant decimals = 18; + uint public override totalSupply; + mapping(address => uint) public override balanceOf; + mapping(address => mapping(address => uint)) public override allowance; + + bytes32 public override DOMAIN_SEPARATOR; + // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + bytes32 public override constant PERMIT_TYPEHASH = + 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + mapping(address => uint) public override nonces; + + constructor() { + uint chainId; + assembly { + chainId := chainid() + } + DOMAIN_SEPARATOR = keccak256( + abi.encode( + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), + keccak256(bytes(name)), + keccak256(bytes("1")), + chainId, + address(this) + ) + ); + } + + function _mint(address to, uint value) internal { + totalSupply = totalSupply.add(value); + balanceOf[to] = balanceOf[to].add(value); + emit Transfer(address(0), to, value); + } + + function _burn(address from, uint value) internal { + balanceOf[from] = balanceOf[from].sub(value); + totalSupply = totalSupply.sub(value); + emit Transfer(from, address(0), value); + } + + function _approve(address owner, address spender, uint value) private { + allowance[owner][spender] = value; + emit Approval(owner, spender, value); + } + + function _transfer(address from, address to, uint value) private { + balanceOf[from] = balanceOf[from].sub(value); + balanceOf[to] = balanceOf[to].add(value); + emit Transfer(from, to, value); + } + + function approve(address spender, uint value) external override returns (bool) { + _approve(msg.sender, spender, value); + return true; + } + + function transfer(address to, uint value) external override returns (bool) { + _transfer(msg.sender, to, value); + return true; + } + + function transferFrom( + address from, + address to, + uint value + ) external override returns (bool) { + if (allowance[from][msg.sender] != uint(int(-1))) { + allowance[from][msg.sender] = allowance[from][msg.sender].sub( + value + ); + } + _transfer(from, to, value); + return true; + } + + function permit( + address owner, + address spender, + uint value, + uint deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external override { + require(deadline >= block.timestamp, "UniswapV2: EXPIRED"); + bytes32 digest = keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR, + keccak256( + abi.encode( + PERMIT_TYPEHASH, + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ); + address recoveredAddress = ecrecover(digest, v, r, s); + require( + recoveredAddress != address(0) && recoveredAddress == owner, + "UniswapV2: INVALID_SIGNATURE" + ); + _approve(owner, spender, value); + } +} + +// File contracts/uniswap-v2/libraries/Math.sol + +pragma solidity ^0.8.0; + +// a library for performing various math operations + +library Math { + function min(uint x, uint y) internal pure returns (uint z) { + z = x < y ? x : y; + } + + // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) + function sqrt(uint y) internal pure returns (uint z) { + if (y > 3) { + z = y; + uint x = y / 2 + 1; + while (x < z) { + z = x; + x = (y / x + x) / 2; + } + } else if (y != 0) { + z = 1; + } + } +} + +// File contracts/uniswap-v2/interfaces/IERC20.sol + +pragma solidity ^0.8.0; + +interface IERC20 { + event Approval(address indexed owner, address indexed spender, uint value); + event Transfer(address indexed from, address indexed to, uint value); + + function name() external returns (string memory); + + function symbol() external returns (string memory); + + function decimals() external returns (uint8); + + function totalSupply() external returns (uint); + + function balanceOf(address owner) external returns (uint); + + function allowance(address owner, address spender) external returns (uint); + + function approve(address spender, uint value) external returns (bool); + + function transfer(address to, uint value) external returns (bool); + + function transferFrom( + address from, + address to, + uint value + ) external returns (bool); +} + +// File contracts/uniswap-v2/libraries/UQ112x112.sol + +pragma solidity ^0.8.0; + +// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) + +// range: [0, 2**112 - 1] +// resolution: 1 / 2**112 + +library UQ112x112 { + uint224 constant Q112 = 2 ** 112; + + // encode a uint112 as a UQ112x112 + function encode(uint112 y) internal pure returns (uint224 z) { + z = uint224(y) * Q112; // never overflows + } + + // divide a UQ112x112 by a uint112, returning a UQ112x112 + function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { + z = x / uint224(y); + } +} + +// File contracts/uniswap-v2/interfaces/IUniswapV2Pair.sol + +pragma solidity ^0.8.0; + +interface IUniswapV2Pair { + event Mint(address indexed sender, uint amount0, uint amount1); + event Burn( + address indexed sender, + uint amount0, + uint amount1, + address indexed to + ); + event Swap( + address indexed sender, + uint amount0In, + uint amount1In, + uint amount0Out, + uint amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + + function MINIMUM_LIQUIDITY() external pure returns (uint); + + function factory() external returns (address); + + function token0() external returns (address); + + function token1() external returns (address); + + function getReserves() + external + returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); + + function price0CumulativeLast() external returns (uint); + + function price1CumulativeLast() external returns (uint); + + function kLast() external returns (uint); + + function mint(address to) external returns (uint liquidity); + + function burn(address to) external returns (uint amount0, uint amount1); + + function swap( + uint amount0Out, + uint amount1Out, + address to, + bytes calldata data + ) external; + + function skim(address to) external; + + function sync() external; + + function initialize(address, address) external; +} + +// File contracts/uniswap-v2/interfaces/IUniswapV2Callee.sol + +pragma solidity ^0.8.0; + +interface IUniswapV2Callee { + function uniswapV2Call( + address sender, + uint amount0, + uint amount1, + bytes calldata data + ) external; +} + +// File contracts/uniswap-v2/UniswapV2Pair.sol + +pragma solidity ^0.8.0; + +contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { + using SafeMath for uint; + using UQ112x112 for uint224; + + uint public override constant MINIMUM_LIQUIDITY = 10 ** 3; + bytes4 private constant SELECTOR = + bytes4(keccak256(bytes("transfer(address,uint256)"))); + + address public override factory; + address public override token0; + address public override token1; + + uint112 private reserve0; // uses single storage slot, accessible via getReserves + uint112 private reserve1; // uses single storage slot, accessible via getReserves + uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves + + uint public override price0CumulativeLast; + uint public override price1CumulativeLast; + uint public override kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event + + uint private unlocked = 1; + modifier lock() { + require(unlocked == 1, "UniswapV2: LOCKED"); + unlocked = 0; + _; + unlocked = 1; + } + + function getReserves() + public + override + returns ( + uint112 _reserve0, + uint112 _reserve1, + uint32 _blockTimestampLast + ) + { + _reserve0 = reserve0; + _reserve1 = reserve1; + _blockTimestampLast = blockTimestampLast; + } + + function _safeTransfer(address token, address to, uint value) private { + IERC20(token).transfer(to, value); + } + + constructor() public { + factory = msg.sender; + } + + // called once by the factory at time of deployment + function initialize(address _token0, address _token1) external override { + require(msg.sender == factory, "UniswapV2: FORBIDDEN"); // sufficient check + token0 = _token0; + token1 = _token1; + } + + // update reserves and, on the first call per block, price accumulators + function _update( + uint balance0, + uint balance1, + uint112 _reserve0, + uint112 _reserve1 + ) private { + require( + balance0 <= uint112(int112(-1)) && balance1 <= uint112(int112(-1)), + "UniswapV2: OVERFLOW" + ); + uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32); + uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired + if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { + // * never overflows, and + overflow is desired + price0CumulativeLast += + uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * + timeElapsed; + price1CumulativeLast += + uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * + timeElapsed; + } + reserve0 = uint112(balance0); + reserve1 = uint112(balance1); + blockTimestampLast = blockTimestamp; + emit Sync(reserve0, reserve1); + } + + // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) + function _mintFee( + uint112 _reserve0, + uint112 _reserve1 + ) private returns (bool feeOn) { + address feeTo = IUniswapV2Factory(factory).feeTo(); + feeOn = feeTo != address(0); + uint _kLast = kLast; // gas savings + if (feeOn) { + if (_kLast != 0) { + uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); + uint rootKLast = Math.sqrt(_kLast); + if (rootK > rootKLast) { + uint numerator = totalSupply.mul(rootK.sub(rootKLast)); + uint denominator = rootK.mul(5).add(rootKLast); + uint liquidity = numerator / denominator; + if (liquidity > 0) _mint(feeTo, liquidity); + } + } + } else if (_kLast != 0) { + kLast = 0; + } + } + + // this low-level function should be called from a contract which performs important safety checks + function mint(address to) external override lock returns (uint liquidity) { + (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings + uint balance0 = IERC20(token0).balanceOf(address(this)); + uint balance1 = IERC20(token1).balanceOf(address(this)); + uint amount0 = balance0.sub(_reserve0); + uint amount1 = balance1.sub(_reserve1); + + bool feeOn = _mintFee(_reserve0, _reserve1); + uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + if (_totalSupply == 0) { + liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); + _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens + } else { + liquidity = Math.min( + amount0.mul(_totalSupply) / _reserve0, + amount1.mul(_totalSupply) / _reserve1 + ); + } + require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED"); + _mint(to, liquidity); + + _update(balance0, balance1, _reserve0, _reserve1); + if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date + emit Mint(msg.sender, amount0, amount1); + } + + // this low-level function should be called from a contract which performs important safety checks + function burn( + address to + ) external override lock returns (uint amount0, uint amount1) { + (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings + address _token0 = token0; // gas savings + address _token1 = token1; // gas savings + uint balance0 = IERC20(_token0).balanceOf(address(this)); + uint balance1 = IERC20(_token1).balanceOf(address(this)); + uint liquidity = balanceOf[address(this)]; + + bool feeOn = _mintFee(_reserve0, _reserve1); + uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee + amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution + amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution + require( + amount0 > 0 && amount1 > 0, + "UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED" + ); + _burn(address(this), liquidity); + _safeTransfer(_token0, to, amount0); + _safeTransfer(_token1, to, amount1); + balance0 = IERC20(_token0).balanceOf(address(this)); + balance1 = IERC20(_token1).balanceOf(address(this)); + + _update(balance0, balance1, _reserve0, _reserve1); + if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date + emit Burn(msg.sender, amount0, amount1, to); + } + + // this low-level function should be called from a contract which performs important safety checks + function swap( + uint amount0Out, + uint amount1Out, + address to, + bytes calldata data + ) external override lock { + // require( + // amount0Out > 0 || amount1Out > 0, + // "UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT" + // ); + // (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings + // require( + // amount0Out < _reserve0 && amount1Out < _reserve1, + // "UniswapV2: INSUFFICIENT_LIQUIDITY" + // ); + + // uint balance0; + // uint balance1; + // { + // // scope for _token{0,1}, avoids stack too deep errors + // address _token0 = token0; + // address _token1 = token1; + // require(to != _token0 && to != _token1, "UniswapV2: INVALID_TO"); + // if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens + // if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens + // if (data.length > 0) + // IUniswapV2Callee(to).uniswapV2Call( + // msg.sender, + // amount0Out, + // amount1Out, + // data + // ); + // balance0 = IERC20(_token0).balanceOf(address(this)); + // balance1 = IERC20(_token1).balanceOf(address(this)); + // } + // uint amount0In = balance0 > _reserve0 - amount0Out + // ? balance0 - (_reserve0 - amount0Out) + // : 0; + // uint amount1In = balance1 > _reserve1 - amount1Out + // ? balance1 - (_reserve1 - amount1Out) + // : 0; + // require( + // amount0In > 0 || amount1In > 0, + // "UniswapV2: INSUFFICIENT_INPUT_AMOUNT" + // ); + // { + // // scope for reserve{0,1}Adjusted, avoids stack too deep errors + // uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); + // uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); + // require( + // balance0Adjusted.mul(balance1Adjusted) >= + // uint(_reserve0).mul(_reserve1).mul(1000 ** 2), + // "UniswapV2: K" + // ); + // } + + // _update(balance0, balance1, _reserve0, _reserve1); + // emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); + } + + // force balances to match reserves + function skim(address to) external override lock { + address _token0 = token0; // gas savings + address _token1 = token1; // gas savings + _safeTransfer( + _token0, + to, + IERC20(_token0).balanceOf(address(this)).sub(reserve0) + ); + _safeTransfer( + _token1, + to, + IERC20(_token1).balanceOf(address(this)).sub(reserve1) + ); + } + + // force reserves to match balances + function sync() external override lock { + _update( + IERC20(token0).balanceOf(address(this)), + IERC20(token1).balanceOf(address(this)), + reserve0, + reserve1 + ); + } +} + +// File contracts/uniswap-v2/UniswapV2Factory.sol + +pragma solidity ^0.8.0; + +contract UniswapV2Factory is IUniswapV2Factory { + address public override feeTo; + address public override feeToSetter; + + mapping(address => mapping(address => address)) public override getPair; + address[] public override allPairs; + + event PairCreated( + address indexed token0, + address indexed token1, + address pair, + uint + ); + + constructor(address _feeToSetter) public { + feeToSetter = _feeToSetter; + } + + function allPairsLength() external override returns (uint) { + return allPairs.length; + } + + function createPair( + address tokenA, + address tokenB + ) external override returns (address pair) { + require(tokenA != tokenB, "UniswapV2: IDENTICAL_ADDRESSES"); + (address token0, address token1) = tokenA < tokenB + ? (tokenA, tokenB) + : (tokenB, tokenA); + require(token0 != address(0), "UniswapV2: ZERO_ADDRESS"); + require( + getPair[token0][token1] == address(0), + "UniswapV2: PAIR_EXISTS" + ); // single check is sufficient + pair = address(new UniswapV2Pair()); + IUniswapV2Pair(pair).initialize(token0, token1); + getPair[token0][token1] = pair; + getPair[token1][token0] = pair; // populate mapping in the reverse direction + allPairs.push(pair); + emit PairCreated(token0, token1, pair, allPairs.length); + } + + function setFeeTo(address _feeTo) external override { + require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); + feeTo = _feeTo; + } + + function setFeeToSetter(address _feeToSetter) external override { + require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); + feeToSetter = _feeToSetter; + } +} diff --git a/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol b/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol new file mode 100644 index 000000000000..868e57edca79 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract ConstructorRevert { + uint256 value; + + constructor() { + revert("Failure string"); + } +} diff --git a/core/tests/ts-integration/evm-contracts/CounterFallback.sol b/core/tests/ts-integration/evm-contracts/CounterFallback.sol new file mode 100644 index 000000000000..c67dfec9459e --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/CounterFallback.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract CounterFallback { + function performCall() external { + uint256 value = 0; + value += 1; + } + + fallback() external { + this.performCall(); + } +} diff --git a/core/tests/ts-integration/evm-contracts/CounterWithParam.sol b/core/tests/ts-integration/evm-contracts/CounterWithParam.sol new file mode 100644 index 000000000000..714b4d665ae3 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/CounterWithParam.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract CounterWithParam { + uint256 value; + + constructor(uint256 _startingValue) { + value = _startingValue; + } + + function increment(uint256 x) public { + value += x; + } + + function incrementWithRevertPayable(uint256 x, bool shouldRevert) public payable returns (uint256) { + return incrementWithRevert(x, shouldRevert); + } + + function incrementWithRevert(uint256 x, bool shouldRevert) public returns (uint256) { + value += x; + if (shouldRevert) { + revert("This method always reverts"); + } + return value; + } + + function set(uint256 x) public { + value = x; + } + + function get() public view returns (uint256) { + return value; + } + + function getBytes() public returns (bytes memory) { + return "Testing"; + } +} diff --git a/core/tests/ts-integration/evm-contracts/Creator.sol b/core/tests/ts-integration/evm-contracts/Creator.sol new file mode 100644 index 000000000000..63a6f7e3b1d7 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/Creator.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract Creation { + function blockNumber() external view returns (uint256) { + return block.number; + } +} + +contract Creator { + function create() external { + new Creation(); + } + + function getCreationRuntimeCode() external pure returns (bytes memory) { + return type(Creation).runtimeCode; + } +} diff --git a/core/tests/ts-integration/evm-contracts/CreatorFallback.sol b/core/tests/ts-integration/evm-contracts/CreatorFallback.sol new file mode 100644 index 000000000000..30ebabd7cc7a --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/CreatorFallback.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract Creation { + function blockNumber() external view returns (uint256) { + return block.number; + } +} + +contract CreatorFallback { + function performCall() external { + new Creation(); + type(Creation).runtimeCode; + } + + fallback() external { + this.performCall(); + } +} diff --git a/core/tests/ts-integration/evm-contracts/ERC20.sol b/core/tests/ts-integration/evm-contracts/ERC20.sol new file mode 100644 index 000000000000..1b65e6541804 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/ERC20.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract ERC20 { + string public symbol; + string public name; + uint8 public decimals; + uint256 public totalSupply; + + mapping(address => uint256) balances; + mapping(address => mapping(address => uint256)) allowed; + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + + constructor() { + symbol = "TEST"; + name = "Test Coin"; + decimals = 18; + totalSupply = 1000000; + balances[msg.sender] = totalSupply; + emit Transfer(address(0), msg.sender, totalSupply); + } + + function balanceOf(address tokenOwner) public view returns (uint256 balance) { + return balances[tokenOwner]; + } + + function transfer(address to, uint256 tokens) public returns (bool success) { + balances[msg.sender] = safeSub(balances[msg.sender], tokens); + balances[to] = safeAdd(balances[to], tokens); + emit Transfer(msg.sender, to, tokens); + return true; + } + + function approve(address spender, uint256 tokens) public returns (bool success) { + allowed[msg.sender][spender] = tokens; + emit Approval(msg.sender, spender, tokens); + return true; + } + + function transferFrom( + address from, + address to, + uint256 tokens + ) public returns (bool success) { + balances[from] = safeSub(balances[from], tokens); + allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens); + balances[to] = safeAdd(balances[to], tokens); + emit Transfer(from, to, tokens); + return true; + } + + function allowance(address tokenOwner, address spender) public view returns (uint256 remaining) { + return allowed[tokenOwner][spender]; + } + + function safeAdd(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a + b; + require(c >= a); + } + + function safeSub(uint256 a, uint256 b) internal pure returns (uint256 c) { + require(b <= a); + c = a - b; + } + + function safeMul(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a * b; + require(a == 0 || c / a == b); + } + + function safeDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { + require(b > 0); + c = a / b; + } +} diff --git a/core/tests/ts-integration/evm-contracts/GasCaller.sol b/core/tests/ts-integration/evm-contracts/GasCaller.sol new file mode 100644 index 000000000000..25b56aa744d6 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/GasCaller.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract GasCaller { + uint256 _resultGas; + + function callAndGetGas(address _to) external returns (uint256) { + uint256 startGas = gasleft(); + // Just doing a call to an address + (bool success, ) = _to.call(""); + require(success); + _resultGas = startGas - gasleft(); + return _resultGas; + } +} diff --git a/core/tests/ts-integration/evm-contracts/OpcodeTest.sol b/core/tests/ts-integration/evm-contracts/OpcodeTest.sol new file mode 100644 index 000000000000..721339bd7ae8 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/OpcodeTest.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract OpcodeTest { + function execute() external { + uint256 loaded = 1; + uint256 tmp; + uint256 prevBlock = block.number - 1; + assembly { + loaded := add(loaded, 1) + loaded := mul(loaded, 2) + loaded := sub(loaded, 1) + loaded := div(loaded, 2) + loaded := sdiv(loaded, 2) + loaded := mod(loaded, 2) + // ADDMOD + // MULMOD + loaded := exp(loaded, 2) + loaded := signextend(loaded, 2) + tmp := lt(loaded, 2) + tmp := gt(loaded, 2) + tmp := slt(loaded, 2) + tmp := sgt(loaded, 2) + tmp := eq(loaded, 2) + tmp := iszero(tmp) + tmp := and(1, 1) + tmp := or(1, 1) + tmp := xor(1, 1) + tmp := not(tmp) + tmp := byte(tmp, 1) + tmp := shl(tmp, 1) + tmp := shr(tmp, 1) + tmp := sar(tmp, 1) + tmp := keccak256(0, 0x40) + tmp := address() + tmp := balance(0x00) + tmp := origin() + tmp := caller() + tmp := callvalue() + // CALLDATALOAD + tmp := calldatasize() + // CALLDATACOPY + tmp := codesize() + // CODECOPY + tmp := gasprice() + // EXTCODESIZE + // EXTCODECOPY + tmp := returndatasize() + // RETURNDATACOPY + // EXTCODEHASH + tmp := blockhash(prevBlock) + tmp := coinbase() + tmp := timestamp() + tmp := number() + tmp := prevrandao() + tmp := gaslimit() + tmp := chainid() + tmp := selfbalance() + tmp := basefee() + // POP + tmp := mload(1) + mstore(1024, 1) + mstore8(10242, 1) + tmp := sload(0) + sstore(0, 1) + // JUMP + // JUMPI + // PC + tmp := msize() + tmp := gas() + // JUMPDEST + // PUSH0...PUSH32 + // DUP1...DUP16 + // SWAP1...SWAP16 + // LOG0...LOG4 + // CREATE + // CALL + // CALLCODE + // RETURN + // DELEGATECALL + // CREATE2 + // STATICCALL + // REVERT + // INVALID + // selfdestruct(sender) + } + + // tmp = 0; + // tmp = 0x11; + // tmp = 0x2211; + // tmp = 0x332211; + // tmp = 0x44332211; + // tmp = 0x5544332211; + // tmp = 0x665544332211; + // tmp = 0x77665544332211; + // tmp = 0x8877665544332211; + // tmp = 0x998877665544332211; + // tmp = 0xaa998877665544332211; + // tmp = 0xbbaa998877665544332211; + // tmp = 0xccbbaa998877665544332211; + // tmp = 0xddccbbaa998877665544332211; + // tmp = 0xeeddccbbaa998877665544332211; + // tmp = 0xffeeddccbbaa998877665544332211; + // tmp = 0x11ffeeddccbbaa998877665544332211; + // tmp = 0x2211ffeeddccbbaa998877665544332211; + // tmp = 0x332211ffeeddccbbaa998877665544332211; + // tmp = 0x44332211ffeeddccbbaa998877665544332211; + // tmp = uint256(uint160(0x5544332211FFeeDDCcbbAa998877665544332211)); + // tmp = 0x665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x77665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x8877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0xff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x11ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x2211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x44332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x5544332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x665544332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x77665544332211ff998877665544332211ffeeddccbbaa998877665544332211; + } +} diff --git a/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol b/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol new file mode 100644 index 000000000000..47f427a27333 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract OpcodeTestFallback { + function performCall() external { + uint256 loaded = 1; + uint256 tmp; + uint256 prevBlock = block.number - 1; + assembly { + loaded := add(loaded, 1) + loaded := mul(loaded, 2) + loaded := sub(loaded, 1) + loaded := div(loaded, 2) + loaded := sdiv(loaded, 2) + loaded := mod(loaded, 2) + // ADDMOD + // MULMOD + loaded := exp(loaded, 2) + loaded := signextend(loaded, 2) + tmp := lt(loaded, 2) + tmp := gt(loaded, 2) + tmp := slt(loaded, 2) + tmp := sgt(loaded, 2) + tmp := eq(loaded, 2) + tmp := iszero(tmp) + tmp := and(1, 1) + tmp := or(1, 1) + tmp := xor(1, 1) + tmp := not(tmp) + tmp := byte(tmp, 1) + tmp := shl(tmp, 1) + tmp := shr(tmp, 1) + tmp := sar(tmp, 1) + tmp := keccak256(0, 0x40) + tmp := address() + tmp := balance(0x00) + tmp := origin() + tmp := caller() + tmp := callvalue() + // CALLDATALOAD + tmp := calldatasize() + // CALLDATACOPY + tmp := codesize() + // CODECOPY + tmp := gasprice() + // EXTCODESIZE + // EXTCODECOPY + tmp := returndatasize() + // RETURNDATACOPY + // EXTCODEHASH + tmp := blockhash(prevBlock) + tmp := coinbase() + tmp := timestamp() + tmp := number() + tmp := prevrandao() + tmp := gaslimit() + tmp := chainid() + tmp := selfbalance() + tmp := basefee() + // POP + tmp := mload(1) + mstore(1024, 1) + mstore8(10242, 1) + tmp := sload(0) + sstore(0, 1) + // JUMP + // JUMPI + // PC + tmp := msize() + tmp := gas() + // JUMPDEST + // PUSH0...PUSH32 + // DUP1...DUP16 + // SWAP1...SWAP16 + // LOG0...LOG4 + // CREATE + // CALL + // CALLCODE + // RETURN + // DELEGATECALL + // CREATE2 + // STATICCALL + // REVERT + // INVALID + // selfdestruct(sender) + tmp := calldataload(0) + calldatacopy(10, 0, 1) + codecopy(10, 0, 1) + tmp := extcodesize(0) + extcodecopy(address(), 10, 0, 1) + returndatacopy(10, 0, 1) + pop(extcodehash(0)) + log0(0, 30) + log1(0, 30, 30) + log2(0, 30, 30, 30) + log3(0, 30, 30, 30, 30) + log4(0, 30, 30, 30, 30, 30) + } + + // tmp = 0; + // tmp = 0x11; + // tmp = 0x2211; + // tmp = 0x332211; + // tmp = 0x44332211; + // tmp = 0x5544332211; + // tmp = 0x665544332211; + // tmp = 0x77665544332211; + // tmp = 0x8877665544332211; + // tmp = 0x998877665544332211; + // tmp = 0xaa998877665544332211; + // tmp = 0xbbaa998877665544332211; + // tmp = 0xccbbaa998877665544332211; + // tmp = 0xddccbbaa998877665544332211; + // tmp = 0xeeddccbbaa998877665544332211; + // tmp = 0xffeeddccbbaa998877665544332211; + // tmp = 0x11ffeeddccbbaa998877665544332211; + // tmp = 0x2211ffeeddccbbaa998877665544332211; + // tmp = 0x332211ffeeddccbbaa998877665544332211; + // tmp = 0x44332211ffeeddccbbaa998877665544332211; + // tmp = uint256(uint160(0x5544332211FFeeDDCcbbAa998877665544332211)); + // tmp = 0x665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x77665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x8877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0xff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x11ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x2211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x44332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x5544332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x665544332211ff998877665544332211ffeeddccbbaa998877665544332211; + // tmp = 0x77665544332211ff998877665544332211ffeeddccbbaa998877665544332211; + } + + fallback() external { + this.performCall(); + } +} diff --git a/core/tests/ts-integration/evm-contracts/ProxyCaller.sol b/core/tests/ts-integration/evm-contracts/ProxyCaller.sol new file mode 100644 index 000000000000..379d7c7addcd --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/ProxyCaller.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +interface ICounterWithParam { + function increment(uint256 x) external; + + function get() external view returns (uint256); + + function getBytes() external returns (bytes memory); +} + +contract ProxyCaller { + function executeIncrememt(address dest, uint256 x) external { + ICounterWithParam(dest).increment(x); + } + + function proxyGet(address dest) external view returns (uint256) { + return ICounterWithParam(dest).get(); + } + + function proxyGetBytes(address dest) external returns (bytes memory returnData) { + return ICounterWithParam(dest).getBytes(); + } +} diff --git a/core/tests/ts-integration/evm-contracts/SelfDestruct.sol b/core/tests/ts-integration/evm-contracts/SelfDestruct.sol new file mode 100644 index 000000000000..12fec9555908 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/SelfDestruct.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.7.0; + +contract SelfDestruct { + constructor() payable {} + + function destroy(address recipient) external { + assembly { + selfdestruct(recipient) + } + } +} diff --git a/core/tests/ts-integration/evm-contracts/UniswapFallback.sol b/core/tests/ts-integration/evm-contracts/UniswapFallback.sol new file mode 100644 index 000000000000..0237b4be1ba5 --- /dev/null +++ b/core/tests/ts-integration/evm-contracts/UniswapFallback.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +interface IUniswapV2ERC20 { + event Approval(address indexed owner, address indexed spender, uint256 value); + event Transfer(address indexed from, address indexed to, uint256 value); + + function name() external pure returns (string memory); + + function symbol() external pure returns (string memory); + + function decimals() external pure returns (uint8); + + function totalSupply() external returns (uint256); + + function balanceOf(address owner) external returns (uint256); + + function allowance(address owner, address spender) external returns (uint256); + + function approve(address spender, uint256 value) external returns (bool); + + function transfer(address to, uint256 value) external returns (bool); + + function transferFrom( + address from, + address to, + uint256 value + ) external returns (bool); + + function DOMAIN_SEPARATOR() external returns (bytes32); + + function PERMIT_TYPEHASH() external pure returns (bytes32); + + function nonces(address owner) external returns (uint256); + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} + +interface IUniswapV2Pair { + event Mint(address indexed sender, uint256 amount0, uint256 amount1); + event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); + event Swap( + address indexed sender, + uint256 amount0In, + uint256 amount1In, + uint256 amount0Out, + uint256 amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + + function MINIMUM_LIQUIDITY() external pure returns (uint256); + + function factory() external returns (address); + + function token0() external returns (address); + + function token1() external returns (address); + + function getReserves() + external + returns ( + uint112 reserve0, + uint112 reserve1, + uint32 blockTimestampLast + ); + + function price0CumulativeLast() external returns (uint256); + + function price1CumulativeLast() external returns (uint256); + + function kLast() external returns (uint256); + + function mint(address to) external returns (uint256 liquidity); + + function burn(address to) external returns (uint256 amount0, uint256 amount1); + + function swap( + uint256 amount0Out, + uint256 amount1Out, + address to, + bytes calldata data + ) external; + + function skim(address to) external; + + function sync() external; + + function initialize(address, address) external; +} + +contract UniswapFallback { + IUniswapV2Pair public uniswapPair; + IUniswapV2ERC20 public uniswapPair2; + address public alice_address; + + function setUniswapAddress(address _uniswap_address) public { + uniswapPair = IUniswapV2Pair(_uniswap_address); + uniswapPair2 = IUniswapV2ERC20(_uniswap_address); + } + + function setAliceAddress(address _alice_address) public { + alice_address = _alice_address; + } + + // Fallback function + fallback() external { + // Implement any logic you want the contract to perform when it receives Ether + // This function will be called when the contract receives Ether and no other function matches the call data + uniswapPair.mint(alice_address); + uniswapPair.swap(0, 5000, alice_address, "0x"); + uint256 balance = uniswapPair2.balanceOf(alice_address); + //uniswapPair2.transfer(address(uniswapPair),balance); + //uniswapPair.burn(alice_address); + } +} diff --git a/core/tests/ts-integration/package.json b/core/tests/ts-integration/package.json index 0e9b863d8e16..b2494ed3878b 100644 --- a/core/tests/ts-integration/package.json +++ b/core/tests/ts-integration/package.json @@ -32,6 +32,10 @@ "typescript": "^4.3.5", "zksync-ethers": "^6.9.0", "elliptic": "^6.5.5", - "yaml": "^2.4.2" + "yaml": "^2.4.2", + "zksync-web3": "^0.15.5", + "csv-parser": "^3.0.0", + "csv-writer": "^1.6.0", + "solc": "0.8.20" } } diff --git a/core/tests/ts-integration/src/helpers.ts b/core/tests/ts-integration/src/helpers.ts index 8e31c1a691ff..327a4912a6c0 100644 --- a/core/tests/ts-integration/src/helpers.ts +++ b/core/tests/ts-integration/src/helpers.ts @@ -4,6 +4,8 @@ import * as ethers from 'ethers'; import * as hre from 'hardhat'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-solc/dist/src/types'; +const solc = require('solc'); + export const SYSTEM_CONTEXT_ADDRESS = '0x000000000000000000000000000000000000800b'; /** @@ -141,3 +143,48 @@ export function bigIntMax(...args: bigint[]) { return args.reduce((max, current) => (current > max ? current : max), args[0]); } + +/** Compiles and returns artifacts for a Solidity (EVM) contract + * + * @param contractPath The path of the contract relative to the contracts directory + * @param args Constructor arguments for the contract + * @returns The transaction data for the contract deployment + */ +export function getEVMArtifact(contractPath: string, contractName: string | undefined = undefined): any { + const compilerParams = { + language: 'Solidity', + sources: { + contract: { + content: getContractSource(contractPath) + } + }, + settings: { + outputSelection: { + '*': { + '*': ['*'] + } + } + } + } as any; + if (contractName === undefined) { + const splitPath = contractPath.split('/'); + contractName = splitPath[splitPath.length - 1]; + } + + const artifact = JSON.parse(solc.compile(JSON.stringify(compilerParams))).contracts['contract'][ + contractName.split('.')[0] + ]; + + return artifact; +} + +/** Gets the deployment transaction data for a given contract path and parameters + * + * @param initiator Wallet that should be used + * @param contractPath The path of the contract relative to the contracts directory + * @param args Constructor arguments for the contract + * @returns The transaction data for the contract deployment + */ +export function getEVMContractFactory(initiator: zksync.Wallet, artifact: any): ethers.ContractFactory { + return new ethers.ContractFactory(artifact.abi, '0x' + artifact.evm.bytecode.object, initiator); +} diff --git a/core/tests/ts-integration/tests/evm-contracts.test.ts b/core/tests/ts-integration/tests/evm-contracts.test.ts new file mode 100644 index 000000000000..90eb0975f021 --- /dev/null +++ b/core/tests/ts-integration/tests/evm-contracts.test.ts @@ -0,0 +1,828 @@ +/** + * Generic tests checking evm equivalence smart contract behavior. + * + * Note: if you are going to write multiple tests checking specific topic (e.g. `CREATE2` behavior or something like this), + * consider creating a separate suite. + * Let's try to keep only relatively simple and self-contained tests here. + */ + +import { TestMaster } from '../src'; +import { deployContract, getEVMArtifact, getEVMContractFactory, getTestContract } from '../src/helpers'; + +import * as ethers from 'ethers'; +import * as zksync from 'zksync-ethers'; + +const contracts = { + tester: getTestContract('TestEVMCreate'), + erc20: getTestContract('ERC20'), + uniswapV2Pair: getTestContract('UniswapV2Pair'), + uniswapV2Factory: getTestContract('UniswapV2Factory') +}; + +const artifacts = { + counter: getEVMArtifact('../evm-contracts/CounterWithParam.sol'), + proxyCaller: getEVMArtifact('../evm-contracts/ProxyCaller.sol'), + creator: getEVMArtifact('../evm-contracts/Creator.sol'), + erc20: getEVMArtifact('../evm-contracts/ERC20.sol'), + constructorRevert: getEVMArtifact('../evm-contracts/ConstructorRevert.sol'), + uniswapV2Pair: getEVMArtifact('../contracts/uniswap-v2/UniswapV2Factory.sol', 'UniswapV2Pair.sol'), + uniswapV2Factory: getEVMArtifact('../contracts/uniswap-v2/UniswapV2Factory.sol', 'UniswapV2Factory.sol'), + opcodeTest: getEVMArtifact('../evm-contracts/OpcodeTest.sol'), + selfDestruct: getEVMArtifact('../evm-contracts/SelfDestruct.sol'), + gasCaller: getEVMArtifact('../evm-contracts/GasCaller.sol'), + counterFallback: getEVMArtifact('../evm-contracts/CounterFallback.sol'), + uniswapFallback: getEVMArtifact('../evm-contracts/UniswapFallback.sol'), + creatorFallback: getEVMArtifact('../evm-contracts/CreatorFallback.sol'), + opcodeTestFallback: getEVMArtifact('../evm-contracts/OpcodeTestFallback.sol') +}; + +const initBytecode = '0x69602a60005260206000f3600052600a6016f3'; +const runtimeBytecode = '0x602a60005260206000f3'; + +let gasLimit = '0x01ffffff'; + +const logGasCosts = false; +describe('EVM equivalence contract', () => { + let testMaster: TestMaster; + let alice: zksync.Wallet; + + // Contracts shared in several tests. + let evmCreateTester: zksync.Contract; + let deployer: zksync.Contract; + + beforeAll(async () => { + testMaster = TestMaster.getInstance(__filename); + alice = testMaster.mainAccount(); + + evmCreateTester = await deployContract(alice, contracts.tester, []); + deployer = new zksync.Contract(zksync.utils.CONTRACT_DEPLOYER_ADDRESS, zksync.utils.CONTRACT_DEPLOYER, alice); + }); + + describe('Gas consumption', () => { + test("Should compare gas against counter fallback contract's call", async () => { + const gasCallerContract = await deploygasCallerContract(alice, artifacts.gasCaller); + + const counterContract = await deploygasCallerContract(alice, artifacts.counterFallback); + + let result = ( + await gasCallerContract.getFunction('callAndGetGas').staticCall(counterContract.getAddress()) + ).toString(); + + const expected_gas = '3617'; // Gas cost when run with solidity interpreter + expect(result).toEqual(expected_gas); + }); + + test("Should compare gas against creator fallback contract's call", async () => { + const gasCallerContract = await deploygasCallerContract(alice, artifacts.gasCaller); + + const creatorContract = await deploygasCallerContract(alice, artifacts.creatorFallback); + + let result = ( + await gasCallerContract.getFunction('callAndGetGas').staticCall(creatorContract.getAddress()) + ).toString(); + + const expected_gas = '70598'; // Gas cost when run with solidity interpreter - 3 (We have some changes that are needed) + expect(result).toEqual(expected_gas); + }); + }); + + describe('Contract creation', () => { + describe('Create from EOA', () => { + test('Should create evm contract from EOA and allow view and non-view calls', async () => { + const args = 1; + const factory = getEVMContractFactory(alice, artifacts.counter); + const contract = await factory.deploy(args); + await contract.deploymentTransaction()?.wait(); + await alice.provider.getTransactionReceipt( + contract.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })() + ); + + await assertCreatedCorrectly( + deployer, + await contract.getAddress(), + '0x' + artifacts.counter.evm.deployedBytecode.object + ); + + expect((await contract.getFunction('get').staticCall()).toString()).toEqual('1'); + await (await contract.getFunction('increment')(1)).wait(); + expect((await contract.getFunction('get').staticCall()).toString()).toEqual('2'); + }); + + test('Should create2 evm contract from ZKEVM contract', async () => { + const salt = ethers.randomBytes(32); + + const expectedAddress = ethers.getCreate2Address( + await evmCreateTester.getAddress(), + salt, + ethers.keccak256(initBytecode) + ); + + await (await evmCreateTester.create2(salt, initBytecode)).wait(); + + await assertCreatedCorrectly(deployer, expectedAddress, runtimeBytecode); + + try { + await (await evmCreateTester.create2(salt, initBytecode, { gasLimit })).wait(); + } catch (e) { + // Should fail + return; + } + throw 'Should fail to create2 the same contract with same salt twice'; + }); + + test('Should propegate revert in constructor', async () => { + const factory = getEVMContractFactory(alice, artifacts.constructorRevert); + const contract = await factory.deploy({ gasLimit }); + + let failReason; + + try { + await contract.deploymentTransaction()?.wait(); + } catch (e: any) { + failReason = e.reason; + } + + expect(failReason).toBe(null); + }); + + test('Should NOT create evm contract from EOA when `to` is address(0x0)', async () => { + const args = 1; + + const factory = getEVMContractFactory(alice, artifacts.counter); + const { data, ...rest } = await factory.getDeployTransaction(args); + const dep_transaction = { + ...rest, + to: '0x0000000000000000000000000000000000000000', + chainId: alice.provider._network.chainId, + data + }; + await (await alice.sendTransaction(dep_transaction)).wait(); + const expectedAddressCreate = ethers.getCreateAddress({ + from: alice.address, + nonce: await alice.getNonce() + }); + + await assertContractNotCreated(deployer, expectedAddressCreate); + }); + }); + }); + + describe('Inter-contract calls', () => { + test('Calls (read/write) between EVM contracts should work correctly', async () => { + const args = 1; + + const counterFactory = getEVMContractFactory(alice, artifacts.counter); + const counterContract = await counterFactory.deploy(args); + await counterContract.deploymentTransaction()?.wait(); + await alice.provider.getTransactionReceipt( + counterContract.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })() + ); + + const proxyCallerFactory = getEVMContractFactory(alice, artifacts.proxyCaller); + const proxyCallerContract = await proxyCallerFactory.deploy(); + await proxyCallerContract.deploymentTransaction()?.wait(); + await alice.provider.getTransactionReceipt( + proxyCallerContract.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })() + ); + + expect( + (await proxyCallerContract.getFunction('proxyGet')(await counterContract.getAddress())).toString() + ).toEqual('1'); + + await ( + await proxyCallerContract.getFunction('executeIncrememt')(await counterContract.getAddress(), 1) + ).wait(); + + expect( + (await proxyCallerContract.getFunction('proxyGet')(await counterContract.getAddress())).toString() + ).toEqual('2'); + + expect( + ( + await proxyCallerContract + .getFunction('proxyGetBytes') + .staticCall(await counterContract.getAddress()) + ).toString() + ).toEqual('0x54657374696e67'); + }); + + test('Create opcode works correctly', async () => { + const creatorFactory = getEVMContractFactory(alice, artifacts.creator); + const creatorContract = await creatorFactory.deploy(); + await creatorContract.deploymentTransaction()?.wait(); + + const nonce = 1; + + const runtimeBytecode = await creatorContract.getFunction('getCreationRuntimeCode')(); + + const expectedAddress = ethers.getCreateAddress({ + from: await creatorContract.getAddress(), + nonce + }); + + await (await creatorContract.getFunction('create')()).wait(); + + await assertCreatedCorrectly(deployer, expectedAddress, runtimeBytecode); + }); + + test('Should revert correctly', async () => { + const args = 1; + + const counterFactory = getEVMContractFactory(alice, artifacts.counter); + const counterContract = await counterFactory.deploy(args); + await counterContract.deploymentTransaction()?.wait(); + + let errorString; + + try { + await counterContract.getFunction('incrementWithRevert').staticCall(1, true); + } catch (e: any) { + errorString = e.reason; + } + + expect(errorString).toEqual('This method always reverts'); + }); + }); + + // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published + describe('ERC20', () => { + let evmToken: ethers.BaseContract; + let nativeToken: zksync.Contract; + let userAccount: zksync.Wallet; + let deployLogged: boolean = false; + + beforeEach(async () => { + const erc20Factory = getEVMContractFactory(alice, artifacts.erc20); + evmToken = await erc20Factory.deploy(); + await evmToken.deploymentTransaction()?.wait(); + nativeToken = await deployContract(alice, contracts.erc20, []); + + userAccount = testMaster.newEmptyAccount(); + // Only log the first deployment + if (logGasCosts && !deployLogged) { + let native_hash = + nativeToken.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let native_transanction_receipt = + (await alice.provider.getTransactionReceipt(native_hash)) ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let evm_hash = + evmToken.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let evm_transanction_receipt = + (await alice.provider.getTransactionReceipt(evm_hash)) ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + console.log('ERC20 native deploy gas: ' + native_transanction_receipt.gasUsed); + console.log('ERC20 evm deploy gas: ' + evm_transanction_receipt.gasUsed); + deployLogged = true; + } + await ( + await alice.sendTransaction({ + to: userAccount.address, + value: BigInt('0xffffffffffffff') + }) + ).wait(); + }); + + test('view functions should work', async () => { + const evmBalanceOfCost = await evmToken.getFunction('balanceOf').estimateGas(alice.address); + const nativeBalanceOfCost = await nativeToken.getFunction('balanceOf').estimateGas(alice.address); + if (logGasCosts) { + console.log('ERC20 native balanceOf gas: ' + nativeBalanceOfCost.toString()); + console.log('ERC20 evm balanceOf gas: ' + evmBalanceOfCost.toString()); + } + expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); + expect((await evmToken.getFunction('totalSupply')()).toString()).toEqual('1000000'); + expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('0'); + }); + + test('transfer should work', async () => { + expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); + const evmTransferTx = await (await evmToken.getFunction('transfer')(userAccount.address, 100000)).wait(); + const nativeTransferTx = await (await nativeToken.transfer(userAccount.address, 100000)).wait(); + if (logGasCosts) { + console.log('ERC20 native transfer gas: ' + nativeTransferTx.gasUsed.toString()); + console.log('ERC20 evm transfer gas: ' + evmTransferTx.gasUsed.toString()); + } + + expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('900000'); + expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('100000'); + }); + + test('approve & transferFrom should work', async () => { + expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); + const evmApproveTx = await ( + await evmToken.connect(alice).getFunction('approve')(userAccount.getAddress(), 100000) + ).wait(); + const nativeApproveTx = await ( + await nativeToken.connect(alice).getFunction('approve')(userAccount.address, 100000) + ).wait(); + if (logGasCosts) { + console.log('ERC20 native approve gas: ' + nativeApproveTx.gasUsed.toString()); + console.log('ERC20 evm approve gas: ' + evmApproveTx.gasUsed.toString()); + } + + const evmTransferFromTx = await ( + await evmToken.connect(userAccount).getFunction('transferFrom')( + alice.address, + userAccount.address, + 100000 + ) + ).wait(); + const nativeTransferFromTx = await ( + await nativeToken.connect(userAccount).getFunction('transferFrom')( + alice.address, + userAccount.address, + 100000 + ) + ).wait(); + if (logGasCosts) { + console.log('ERC20 native transferFrom gas: ' + nativeTransferFromTx.gasUsed.toString()); + console.log('ERC20 evm transferFrom gas: ' + evmTransferFromTx.gasUsed.toString()); + } + + expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('900000'); + expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('100000'); + }); + }); + + // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published + describe('Uniswap-v2', () => { + let evmToken1: ethers.BaseContract; + let evmToken2: ethers.BaseContract; + let evmUniswapFactory: ethers.BaseContract; + let nativeUniswapFactory: ethers.BaseContract; + let evmUniswapPair: ethers.BaseContract; + let nativeUniswapPair: ethers.BaseContract; + + let deployLogged: boolean = false; + const NEW_PAIR_TOPIC = '0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9'; + + beforeEach(async () => { + const erc20Factory = getEVMContractFactory(alice, artifacts.erc20); + evmToken1 = await erc20Factory.deploy({ gasLimit }); + await evmToken1.deploymentTransaction()?.wait(); + evmToken2 = await erc20Factory.deploy(); + await evmToken2.deploymentTransaction()?.wait(); + + const evmUniswapFactoryFactory = getEVMContractFactory(alice, artifacts.uniswapV2Factory); + evmUniswapFactory = await evmUniswapFactoryFactory.deploy('0x0000000000000000000000000000000000000000'); + await evmUniswapFactory.deploymentTransaction()?.wait(); + + nativeUniswapFactory = await deployContract( + alice, + contracts.uniswapV2Factory, + ['0x0000000000000000000000000000000000000000'], + undefined, + { + customData: { + factoryDeps: [contracts.uniswapV2Pair.bytecode] + } + } + ); + + const evmPairReceipt = await ( + await evmUniswapFactory.getFunction('createPair')(evmToken1.getAddress(), evmToken2.getAddress()) + ).wait(); + + const nativePairReceipt = await ( + await nativeUniswapFactory.getFunction('createPair')(evmToken1.getAddress(), evmToken2.getAddress()) + ).wait(); + + const evmUniswapPairFactory = getEVMContractFactory(alice, artifacts.uniswapV2Pair); + const nativeUniswapPairFactory = new zksync.ContractFactory( + contracts.uniswapV2Pair.abi, + contracts.uniswapV2Pair.bytecode, + alice + ); + evmUniswapPair = evmUniswapPairFactory.attach( + ethers.AbiCoder.defaultAbiCoder().decode( + ['address', 'uint256'], + evmPairReceipt.logs.find((log: any) => log.topics[0] === NEW_PAIR_TOPIC).data + )[0] + ); + nativeUniswapPair = nativeUniswapPairFactory.attach( + ethers.AbiCoder.defaultAbiCoder().decode( + ['address', 'uint256'], + nativePairReceipt.logs.find((log: any) => log.topics[0] === NEW_PAIR_TOPIC).data + )[0] + ); + const token1IsFirst = (await evmUniswapPair.getFunction('token0')()).toString() === evmToken1.getAddress(); + if (!token1IsFirst) { + [evmToken1, evmToken2] = [evmToken2, evmToken1]; + } + await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 100000)).wait(); + await (await evmToken1.getFunction('transfer')(nativeUniswapPair.getAddress(), 100000)).wait(); + await (await evmToken2.getFunction('transfer')(evmUniswapPair.getAddress(), 100000)).wait(); + await (await evmToken2.getFunction('transfer')(nativeUniswapPair.getAddress(), 100000)).wait(); + + // Only log the first deployment + if (logGasCosts && !deployLogged) { + let native_hash = + nativeUniswapFactory.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let native_transanction_receipt = + (await alice.provider.getTransactionReceipt(native_hash)) ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let evm_hash = + evmUniswapFactory.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + let evm_transanction_receipt = + (await alice.provider.getTransactionReceipt(evm_hash)) ?? + (() => { + throw new Error('Deployment transaction has failed'); + })(); + console.log('Uniswap Factory native deploy gas: ' + native_transanction_receipt.gasUsed); + console.log('Uniswap Factory evm deploy gas: ' + evm_transanction_receipt.gasUsed); + console.log('Uniswap Pair native create gas: ' + nativePairReceipt.gasUsed); + console.log('Uniswap Pair evm create gas: ' + evmPairReceipt.gasUsed); + deployLogged = true; + } + }); + + test('mint, swap, and burn should work', async () => { + const evmMintReceipt = await (await evmUniswapPair.getFunction('mint')(alice.address)).wait(); + const nativeMintReceipt = await (await nativeUniswapPair.getFunction('mint')(alice.address)).wait(); + + await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 10000)).wait(); + await (await evmToken1.getFunction('transfer')(nativeUniswapPair.getAddress(), 10000)).wait(); + const evmSwapReceipt = await ( + await evmUniswapPair.getFunction('swap')(0, 5000, alice.address, '0x') + ).wait(); + const nativeSwapReceipt = await ( + await nativeUniswapPair.getFunction('swap')(0, 5000, alice.address, '0x') + ).wait(); + + await ( + await evmUniswapPair.getFunction('transfer')( + evmUniswapPair.getAddress(), + (await evmUniswapPair.getFunction('balanceOf')(alice.address)).toString() + ) + ).wait(); + await ( + await nativeUniswapPair.getFunction('transfer')( + nativeUniswapPair.getAddress(), + (await nativeUniswapPair.getFunction('balanceOf')(alice.address)).toString() + ) + ).wait(); + const evmBurnReceipt = await (await evmUniswapPair.getFunction('burn')(alice.address)).wait(); + const nativeBurnReceipt = await (await nativeUniswapPair.getFunction('burn')(alice.address)).wait(); + expect(Number((await evmToken1.getFunction('balanceOf')(alice.address)).toString())).toBeGreaterThanOrEqual( + 990000 + ); + expect(Number((await evmToken2.getFunction('balanceOf')(alice.address)).toString())).toBeGreaterThanOrEqual( + 990000 + ); + + if (logGasCosts) { + console.log('UniswapV2Pair native mint gas: ' + nativeMintReceipt.gasUsed); + console.log('UniswapV2Pair evm mint gas: ' + evmMintReceipt.gasUsed); + console.log('UniswapV2Pair native swap gas: ' + nativeSwapReceipt.gasUsed); + console.log('UniswapV2Pair evm swap gas: ' + evmSwapReceipt.gasUsed); + console.log('UniswapV2Pair native burn gas: ' + nativeBurnReceipt.gasUsed); + console.log('UniswapV2Pair evm burn gas: ' + evmBurnReceipt.gasUsed); + } + }); + + test("Should compare gas against uniswap fallback contract's call", async () => { + const gasCallerFactory = getEVMContractFactory(alice, artifacts.gasCaller); + const gasCallerContract = await gasCallerFactory.deploy(); + await gasCallerContract.deploymentTransaction()?.wait(); + await alice.provider.getTransactionReceipt( + gasCallerContract.deploymentTransaction()?.hash ?? + (() => { + throw new Error('Deployment transaction has failed'); + })() + ); + + const uniswapContract = await deploygasCallerContract(alice, artifacts.uniswapFallback); + await (await uniswapContract.getFunction('setUniswapAddress')(evmUniswapPair.getAddress())).wait(); + await (await uniswapContract.getFunction('setAliceAddress')(alice.address)).wait(); + + await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 10000)).wait(); + await (await evmToken1.getFunction('transfer')(uniswapContract.getAddress(), 10000)).wait(); + + let result = ( + await gasCallerContract.getFunction('callAndGetGas').staticCall(uniswapContract.getAddress()) + ).toString(); + + const expected_gas = '165939'; // Gas cost when run with solidity interpreter + expect(result).toEqual(expected_gas); + }); + }); + + // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published + // describe('Bulk opcode tests', () => { + // let opcodeTest: ethers.Contract; + // beforeEach(async () => { + // const opcodeTestFactory = getEVMContractFactory(alice, artifacts.opcodeTest); + // console.log(opcodeTestFactory.bytecode) + // opcodeTest = await opcodeTestFactory.deploy() + // }); + + // test('should successfully execute bulk opcode test', async () => { + // console.log(await deployer.evmCode(opcodeTest.address)) + // // const receipt = await (await opcodeTest.execute()).wait() + // }); + // }); + + afterAll(async () => { + await testMaster.deinitialize(); + if (logGasCosts) { + printCostData(); + } + }); +}); + +async function deploygasCallerContract(alice: zksync.Wallet, contract: any, ...args: Array) { + const counterFactory = getEVMContractFactory(alice, contract); + const counterContract = await counterFactory.deploy(...args); + await counterContract.waitForDeployment(); + await counterContract.deploymentTransaction()?.wait(); + let hash = counterContract.deploymentTransaction()?.hash; + if (hash == undefined) { + throw new Error('Deployment transaction has failed'); + } + await alice.provider.getTransactionReceipt(hash); + + return counterContract; +} + +async function assertStoredBytecodeHash( + deployer: zksync.Contract, + deployedAddress: string, + expectedStoredHash: string +): Promise { + const ACCOUNT_CODE_STORAGE_ADDRESS = '0x0000000000000000000000000000000000008002'; + let runner = + deployer.runner ?? + (() => { + throw new Error('Runner get failed'); + })(); + let provider = + runner.provider ?? + (() => { + throw new Error('Provider get failed'); + })(); + const storedCodeHash = await provider.getStorage( + ACCOUNT_CODE_STORAGE_ADDRESS, + ethers.zeroPadValue(deployedAddress, 32) + ); + + expect(storedCodeHash).toEqual(expectedStoredHash); +} + +async function assertCreatedCorrectly( + deployer: zksync.Contract, + deployedAddress: string, + expectedEVMBytecode: string +): Promise { + const expectedStoredHash = getSha256BlobHash(expectedEVMBytecode); + await assertStoredBytecodeHash(deployer, deployedAddress, expectedStoredHash); +} + +function getPaddedBytecode(bytes: ethers.BytesLike) { + const length = ethers.getBytes(bytes).length; + + const encodedLength = ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [length]); + + let paddedBytecode = encodedLength + ethers.toBeHex(ethers.toBigInt(bytes)).slice(2); + + // The length needs to be 32 mod 64. We use 64 mod 128, since + // we are dealing with a hexlified string + while ((paddedBytecode.length - 2) % 128 != 64) { + paddedBytecode += '0'; + } + + return paddedBytecode; +} + +// Returns the canonical code hash of +function getSha256BlobHash(bytes: ethers.BytesLike): string { + const paddedBytes = getPaddedBytecode(bytes); + + const hash = ethers.getBytes(ethers.sha256(paddedBytes)); + hash[0] = 2; + hash[1] = 0; + + // Length of the bytecode + const lengthInBytes = ethers.getBytes(paddedBytes).length; + hash[2] = Math.floor(lengthInBytes / 256); + hash[3] = lengthInBytes % 256; + + return ethers.toBeHex(ethers.toBigInt(hash)); +} + +async function assertContractNotCreated(deployer: zksync.Contract, deployedAddress: string): Promise { + assertStoredBytecodeHash(deployer, deployedAddress, ethers.ZeroHash); +} + +function printCostData() { + let costsDataString = ''; + + const averageOverhead = + overheadDataDump.length === 0 + ? undefined + : Math.floor(overheadDataDump.reduce((a: number, c: number) => a + c) / overheadDataDump.length); + const minOverhead = overheadDataDump.length === 0 ? undefined : Math.min(...overheadDataDump); + const maxOverhead = overheadDataDump.length === 0 ? undefined : Math.max(...overheadDataDump); + + costsDataString += 'Overhead\t' + averageOverhead + '\t' + minOverhead + '\t' + maxOverhead + '\n'; + + Object.keys(opcodeDataDump).forEach((opcode) => { + const opcodeString = '0x' + Number(opcode).toString(16).padStart(2, '0'); + const values = opcodeDataDump[opcode.toString()]; + if (values.length === 0) { + costsDataString += opcodeString + '\n'; + return; + } + const average = Math.floor(values.reduce((a: number, c: number) => a + c) / values.length); + const min = Math.min(...values); + const max = Math.max(...values); + + costsDataString += + opcodeString + + '\t' + + average + + '\t' + + (min === average ? '' : min) + + '\t' + + (max === average ? '' : max) + + '\n'; + }); + console.log(costsDataString); +} + +const overheadDataDump: Array = []; +const opcodeDataDump: any = {}; +[ + '0x0', + '0x1', + '0x2', + '0x3', + '0x4', + '0x5', + '0x6', + '0x7', + '0x8', + '0x9', + '0x0A', + '0x0B', + '0x10', + '0x11', + '0x12', + '0x13', + '0x14', + '0x15', + '0x16', + '0x17', + '0x18', + '0x19', + '0x1A', + '0x1B', + '0x1C', + '0x1D', + '0x20', + '0x30', + '0x31', + '0x32', + '0x33', + '0x34', + '0x35', + '0x36', + '0x37', + '0x38', + '0x39', + '0x3A', + '0x3B', + '0x3C', + '0x3D', + '0x3E', + '0x3F', + '0x40', + '0x41', + '0x42', + '0x43', + '0x44', + '0x45', + '0x46', + '0x47', + '0x48', + '0x50', + '0x51', + '0x52', + '0x53', + '0x54', + '0x55', + '0x56', + '0x57', + '0x58', + '0x59', + '0x5A', + '0x5B', + '0x5F', + '0x60', + '0x61', + '0x62', + '0x63', + '0x64', + '0x65', + '0x66', + '0x67', + '0x68', + '0x69', + '0x6A', + '0x6B', + '0x6C', + '0x6D', + '0x6E', + '0x6F', + '0x70', + '0x71', + '0x72', + '0x73', + '0x74', + '0x75', + '0x76', + '0x77', + '0x78', + '0x79', + '0x7A', + '0x7B', + '0x7C', + '0x7D', + '0x7E', + '0x7F', + '0x80', + '0x81', + '0x82', + '0x83', + '0x84', + '0x85', + '0x86', + '0x87', + '0x88', + '0x89', + '0x8A', + '0x8B', + '0x8C', + '0x8D', + '0x8E', + '0x8F', + '0x90', + '0x91', + '0x92', + '0x93', + '0x94', + '0x95', + '0x96', + '0x97', + '0x98', + '0x99', + '0x9A', + '0x9B', + '0x9C', + '0x9D', + '0x9E', + '0x9F', + '0xA0', + '0xA1', + '0xA2', + '0xA3', + '0xA4', + '0xF0', + '0xF1', + '0xF2', + '0xF3', + '0xF4', + '0xF5', + '0xFA', + '0xFD', + '0xFE', + '0xFF' +].forEach((key) => { + opcodeDataDump[Number(key).toString()] = []; +}); From 81321326ad4865972ef211c87f3210e2de130edb Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 16:51:07 -0300 Subject: [PATCH 05/72] Update multivm bootloaders bin files for vm1_5_0 --- .../fee_estimate.yul/fee_estimate.yul.zbin | Bin 76320 -> 74912 bytes .../gas_test.yul/gas_test.yul.zbin | Bin 72416 -> 71008 bytes .../playground_batch.yul.zbin | Bin 76512 -> 75104 bytes .../proved_batch.yul/proved_batch.yul.zbin | Bin 72928 -> 71520 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/etc/multivm_bootloaders/vm_1_5_0_increased_memory/fee_estimate.yul/fee_estimate.yul.zbin b/etc/multivm_bootloaders/vm_1_5_0_increased_memory/fee_estimate.yul/fee_estimate.yul.zbin index 75ee6377bdb645532c55f06f0e883cc078b5bd2b..ad45ddb49571509167df6fd155d50130db9b6afb 100644 GIT binary patch literal 74912 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 literal 72416 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 PUBCIJ&;7~A_uTs5GOKah diff --git a/etc/multivm_bootloaders/vm_1_5_0_increased_memory/proved_batch.yul/proved_batch.yul.zbin b/etc/multivm_bootloaders/vm_1_5_0_increased_memory/proved_batch.yul/proved_batch.yul.zbin index 26bb767d1b306421afbad07509e3e3e0b1e68f8c..a7ba16384cc223b5a0018b18a61622aab864bfca 100644 GIT binary patch literal 71520 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 gzj^U9AG=}E?OV2O{*T}OlCEyaXQCedvZs=er6 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 Date: Wed, 11 Sep 2024 16:51:29 -0300 Subject: [PATCH 06/72] Update lock file --- Cargo.lock | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b98d343564b8..8634bff8a594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8478,6 +8478,8 @@ dependencies = [ "once_cell", "serde", "serde_json", + "zksync_config", + "zksync_env_config", "zksync_utils", ] @@ -8980,6 +8982,7 @@ dependencies = [ "zk_evm 0.150.4", "zksync_contracts", "zksync_eth_signer", + "zksync_state", "zksync_system_constants", "zksync_test_account", "zksync_types", @@ -9800,6 +9803,7 @@ dependencies = [ "zksync_contracts", "zksync_system_constants", "zksync_types", + "zksync_utils", ] [[package]] From dfef5ea76a97822394db196f98917580cb73874e Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 11 Sep 2024 17:23:23 -0300 Subject: [PATCH 07/72] Update contracts submodule --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index d3687694f71d..361d19af8346 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit d3687694f71d83fa286b9c186b4c3ea173028f83 +Subproject commit 361d19af8346efde0b53243e29612b15f232459e From ddc35ded3e7ec0f858b642b63aee323cc54b8464 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 12 Sep 2024 13:44:19 -0300 Subject: [PATCH 08/72] Improve get contract address for sql queries --- core/lib/dal/src/transactions_dal.rs | 76 ++++++++++------------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index bc44083ea319..a204a1a1979c 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -59,12 +59,9 @@ impl TransactionsDal<'_, '_> { l1_block_number: L1BlockNumber, ) -> DalResult<()> { let contract_address = tx.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: &[u8] = if contract_address.is_none() { - &[] - } else { - unwrapped_contract_address.as_bytes() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); let tx_hash = tx.hash(); let tx_hash_bytes = tx_hash.as_bytes(); let json_data = serde_json::to_value(&tx.execute) @@ -149,7 +146,7 @@ impl TransactionsDal<'_, '_> { serial_id, full_fee, layer_2_tip_fee, - contract_address_b, + contract_address_as_bytes, l1_block_number.0 as i32, value, empty_address.as_bytes(), @@ -168,12 +165,9 @@ impl TransactionsDal<'_, '_> { pub async fn insert_system_transaction(&mut self, tx: &ProtocolUpgradeTx) -> DalResult<()> { let contract_address = tx.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: &[u8] = if contract_address.is_none() { - &[] - } else { - unwrapped_contract_address.as_bytes() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); let tx_hash = tx.common_data.hash().0.to_vec(); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.common_data.hash())); @@ -250,7 +244,7 @@ impl TransactionsDal<'_, '_> { gas_per_pubdata_limit, json_data, upgrade_id, - contract_address_b, + contract_address_as_bytes, l1_block_number, value, &Address::default().0.to_vec(), @@ -298,11 +292,9 @@ impl TransactionsDal<'_, '_> { let initiator_address = tx.initiator_account(); let contract_address = tx.execute.contract_address; let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: &[u8] = if contract_address.is_none() { - &[] - } else { - unwrapped_contract_address.as_bytes() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())); let gas_limit = u256_to_big_decimal(tx.common_data.fee.gas_limit); @@ -431,7 +423,7 @@ impl TransactionsDal<'_, '_> { input_data, &json_data, tx_format, - contract_address_b, + contract_address_as_bytes, value, &paymaster, &paymaster_input, @@ -716,14 +708,11 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: Vec = if contract_address.is_none() { - Vec::new() - } else { - unwrapped_contract_address.as_bytes().to_vec() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); l2_values.push(u256_to_big_decimal(transaction.execute.value)); - l2_contract_addresses.push(contract_address_b); + l2_contract_addresses.push(contract_address_as_bytes); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); l2_paymaster.push(common_data.paymaster_params.paymaster.as_bytes()); l2_hashes.push(tx_res.hash.as_bytes()); @@ -927,14 +916,11 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: Vec = if contract_address.is_none() { - Vec::new() - } else { - unwrapped_contract_address.as_bytes().to_vec() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); l2_values.push(u256_to_big_decimal(transaction.execute.value)); - l2_contract_addresses.push(contract_address_b); + l2_contract_addresses.push(contract_address_as_bytes); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); l2_paymaster.push(common_data.paymaster_params.paymaster.as_bytes()); l2_hashes.push(tx_res.hash.as_bytes()); @@ -1116,12 +1102,9 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: Vec = if contract_address.is_none() { - Vec::new() - } else { - unwrapped_contract_address.as_bytes().to_vec() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); let tx = &tx_res.transaction; l1_hashes.push(tx_res.hash.as_bytes()); l1_initiator_address.push(common_data.sender.as_bytes()); @@ -1135,7 +1118,7 @@ impl TransactionsDal<'_, '_> { l1_priority_op_id.push(common_data.serial_id.0 as i64); l1_full_fee.push(u256_to_big_decimal(common_data.full_fee)); l1_layer_2_tip_fee.push(u256_to_big_decimal(common_data.layer_2_tip_fee)); - l1_contract_address.push(contract_address_b); + l1_contract_address.push(contract_address_as_bytes); l1_l1_block_number.push(common_data.eth_block as i32); l1_value.push(u256_to_big_decimal(tx.execute.value)); l1_tx_format.push(common_data.tx_format() as i32); @@ -1413,12 +1396,9 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); - let contract_address_b: Vec = if contract_address.is_none() { - Vec::new() - } else { - unwrapped_contract_address.as_bytes().to_vec() - }; + let contract_address_as_bytes = contract_address + .and_then(|addr| Some(addr.as_bytes().to_vec())) + .unwrap_or_default(); let tx = &tx_res.transaction; upgrade_hashes.push(tx_res.hash.as_bytes()); upgrade_initiator_address.push(common_data.sender.as_bytes()); @@ -1431,7 +1411,7 @@ impl TransactionsDal<'_, '_> { .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())), ); upgrade_upgrade_id.push(common_data.upgrade_id as i32); - upgrade_contract_address.push(contract_address_b); + upgrade_contract_address.push(contract_address_as_bytes); upgrade_l1_block_number.push(common_data.eth_block as i32); upgrade_value.push(u256_to_big_decimal(tx.execute.value)); upgrade_tx_format.push(common_data.tx_format() as i32); From a5c22ea2f21a34fb54f6dab1ee2132330c9ecc04 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 12 Sep 2024 15:11:40 -0300 Subject: [PATCH 09/72] Make recipient address optional for L2Tx --- core/lib/types/src/l2/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index abd60491af38..036d2a7a036d 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -232,8 +232,8 @@ impl L2Tx { } /// Returns recipient account of the transaction. - pub fn recipient_account(&self) -> Address { - self.execute.contract_address.unwrap_or_default() + pub fn recipient_account(&self) -> Option

{ + self.execute.contract_address } /// Returns the account nonce associated with transaction. @@ -324,7 +324,7 @@ impl From for TransactionRequest { let mut base_tx_req = TransactionRequest { nonce: U256::from(tx.common_data.nonce.0), from: Some(tx.common_data.initiator_address), - to: Some(tx.recipient_account()), + to: tx.recipient_account(), value: tx.execute.value, gas_price: tx.common_data.fee.max_fee_per_gas, max_priority_fee_per_gas: None, @@ -400,7 +400,7 @@ impl From for api::Transaction { chain_id: U256::from(tx.common_data.extract_chain_id().unwrap_or_default()), nonce: U256::from(tx.common_data.nonce.0), from: Some(tx.common_data.initiator_address), - to: Some(tx.recipient_account()), + to: tx.recipient_account(), value: tx.execute.value, gas_price: Some(tx.common_data.fee.max_fee_per_gas), max_priority_fee_per_gas: Some(tx.common_data.fee.max_priority_fee_per_gas), From c075fb4bd9f88fd25ce62cd2ef709f57b21b616c Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 12 Sep 2024 16:02:15 -0300 Subject: [PATCH 10/72] Fix error lints --- core/lib/dal/src/transactions_dal.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index a204a1a1979c..f9ff6b64957e 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -60,7 +60,7 @@ impl TransactionsDal<'_, '_> { ) -> DalResult<()> { let contract_address = tx.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); let tx_hash = tx.hash(); let tx_hash_bytes = tx_hash.as_bytes(); @@ -166,7 +166,7 @@ impl TransactionsDal<'_, '_> { pub async fn insert_system_transaction(&mut self, tx: &ProtocolUpgradeTx) -> DalResult<()> { let contract_address = tx.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); let tx_hash = tx.common_data.hash().0.to_vec(); let json_data = serde_json::to_value(&tx.execute) @@ -291,9 +291,8 @@ impl TransactionsDal<'_, '_> { let initiator_address = tx.initiator_account(); let contract_address = tx.execute.contract_address; - let unwrapped_contract_address = contract_address.unwrap_or_default(); let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())); @@ -709,7 +708,7 @@ impl TransactionsDal<'_, '_> { let contract_address = transaction.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); l2_values.push(u256_to_big_decimal(transaction.execute.value)); l2_contract_addresses.push(contract_address_as_bytes); @@ -917,7 +916,7 @@ impl TransactionsDal<'_, '_> { let contract_address = transaction.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); l2_values.push(u256_to_big_decimal(transaction.execute.value)); l2_contract_addresses.push(contract_address_as_bytes); @@ -1103,7 +1102,7 @@ impl TransactionsDal<'_, '_> { let contract_address = transaction.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); let tx = &tx_res.transaction; l1_hashes.push(tx_res.hash.as_bytes()); @@ -1397,7 +1396,7 @@ impl TransactionsDal<'_, '_> { let contract_address = transaction.execute.contract_address; let contract_address_as_bytes = contract_address - .and_then(|addr| Some(addr.as_bytes().to_vec())) + .map(|addr| addr.as_bytes().to_vec()) .unwrap_or_default(); let tx = &tx_res.transaction; upgrade_hashes.push(tx_res.hash.as_bytes()); From 6c94de922942c5c1dc258a0bb64bfd2c7b8d9b31 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 11:25:52 -0300 Subject: [PATCH 11/72] Insert null in sql for contract address instead of empty bytes --- core/lib/dal/src/transactions_dal.rs | 36 +++++++++------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/core/lib/dal/src/transactions_dal.rs b/core/lib/dal/src/transactions_dal.rs index f9ff6b64957e..0a72289b48a4 100644 --- a/core/lib/dal/src/transactions_dal.rs +++ b/core/lib/dal/src/transactions_dal.rs @@ -59,9 +59,7 @@ impl TransactionsDal<'_, '_> { l1_block_number: L1BlockNumber, ) -> DalResult<()> { let contract_address = tx.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); let tx_hash = tx.hash(); let tx_hash_bytes = tx_hash.as_bytes(); let json_data = serde_json::to_value(&tx.execute) @@ -165,9 +163,7 @@ impl TransactionsDal<'_, '_> { pub async fn insert_system_transaction(&mut self, tx: &ProtocolUpgradeTx) -> DalResult<()> { let contract_address = tx.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); let tx_hash = tx.common_data.hash().0.to_vec(); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.common_data.hash())); @@ -291,9 +287,7 @@ impl TransactionsDal<'_, '_> { let initiator_address = tx.initiator_account(); let contract_address = tx.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); let json_data = serde_json::to_value(&tx.execute) .unwrap_or_else(|_| panic!("cannot serialize tx {:?} to json", tx.hash())); let gas_limit = u256_to_big_decimal(tx.common_data.fee.gas_limit); @@ -707,9 +701,7 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); l2_values.push(u256_to_big_decimal(transaction.execute.value)); l2_contract_addresses.push(contract_address_as_bytes); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); @@ -831,7 +823,7 @@ impl TransactionsDal<'_, '_> { &l2_inputs as &[&[u8]], &l2_datas, &l2_tx_formats, - &l2_contract_addresses, + &l2_contract_addresses as &[Option>], &l2_values, &l2_paymaster as &[&[u8]], &l2_paymaster_input as &[&[u8]], @@ -915,9 +907,7 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); l2_values.push(u256_to_big_decimal(transaction.execute.value)); l2_contract_addresses.push(contract_address_as_bytes); l2_paymaster_input.push(&common_data.paymaster_params.paymaster_input[..]); @@ -1030,7 +1020,7 @@ impl TransactionsDal<'_, '_> { &l2_datas, &l2_refunded_gas, &l2_values, - &l2_contract_addresses, + &l2_contract_addresses as &[Option>], &l2_paymaster as &[&[u8]], &l2_paymaster_input as &[&[u8]], l2_block_number.0 as i32, @@ -1101,9 +1091,7 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); let tx = &tx_res.transaction; l1_hashes.push(tx_res.hash.as_bytes()); l1_initiator_address.push(common_data.sender.as_bytes()); @@ -1224,7 +1212,7 @@ impl TransactionsDal<'_, '_> { &l1_priority_op_id, &l1_full_fee, &l1_layer_2_tip_fee, - &l1_contract_address, + &l1_contract_address as &[Option>], &l1_l1_block_number, &l1_value, &l1_tx_format, @@ -1395,9 +1383,7 @@ impl TransactionsDal<'_, '_> { })?; let contract_address = transaction.execute.contract_address; - let contract_address_as_bytes = contract_address - .map(|addr| addr.as_bytes().to_vec()) - .unwrap_or_default(); + let contract_address_as_bytes = contract_address.map(|addr| addr.as_bytes().to_vec()); let tx = &tx_res.transaction; upgrade_hashes.push(tx_res.hash.as_bytes()); upgrade_initiator_address.push(common_data.sender.as_bytes()); @@ -1509,7 +1495,7 @@ impl TransactionsDal<'_, '_> { &upgrade_gas_per_pubdata_limit, &upgrade_data, &upgrade_upgrade_id, - &upgrade_contract_address, + &upgrade_contract_address as &[Option>], &upgrade_l1_block_number, &upgrade_value, &upgrade_tx_format, From b280eb3dff51cc9377438a4525f496b2460f0e29 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 12:19:07 -0300 Subject: [PATCH 12/72] Remove require and support None value for protobuff Transaction --- core/lib/dal/src/consensus/mod.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/core/lib/dal/src/consensus/mod.rs b/core/lib/dal/src/consensus/mod.rs index 88620575c88a..f54938e8ec1a 100644 --- a/core/lib/dal/src/consensus/mod.rs +++ b/core/lib/dal/src/consensus/mod.rs @@ -401,11 +401,10 @@ impl ProtoRepr for proto::Transaction { } }, execute: Execute { - contract_address: Some( - required(&execute.contract_address) - .and_then(|x| parse_h160(x)) - .context("execute.contract_address")?, - ), + contract_address: execute + .contract_address + .as_ref() + .and_then(|x| parse_h160(x).ok()), calldata: required(&execute.calldata).context("calldata")?.clone(), value: required(&execute.value) .and_then(|x| parse_h256(x)) @@ -489,13 +488,7 @@ impl ProtoRepr for proto::Transaction { } }; let execute = proto::Execute { - contract_address: Some( - this.execute - .contract_address - .unwrap_or_default() - .as_bytes() - .into(), - ), + contract_address: this.execute.contract_address.map(|x| x.as_bytes().into()), calldata: Some(this.execute.calldata.clone()), value: Some(u256_to_h256(this.execute.value).as_bytes().into()), factory_deps: this.execute.factory_deps.clone(), From d49f3f84814fdbe8dd35c84855cec29284adf024 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 12:22:23 -0300 Subject: [PATCH 13/72] Make address optional for Transaction recipient account --- core/lib/types/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 54e1b40b5b33..86b2e3f03d51 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -104,8 +104,8 @@ impl Eq for Transaction {} impl Transaction { /// Returns recipient account of the transaction. - pub fn recipient_account(&self) -> Address { - self.execute.contract_address.unwrap_or_default() + pub fn recipient_account(&self) -> Option
{ + self.execute.contract_address } pub fn nonce(&self) -> Option { From 5e9179d4558ec84e559dd58311e31561709a8864 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 16:24:30 -0300 Subject: [PATCH 14/72] Optionally add contract address to transaction signature --- core/lib/types/src/tx/execute.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/lib/types/src/tx/execute.rs b/core/lib/types/src/tx/execute.rs index c5d31c0f8a03..c133261bc232 100644 --- a/core/lib/types/src/tx/execute.rs +++ b/core/lib/types/src/tx/execute.rs @@ -72,10 +72,9 @@ impl EIP712TypedStructure for Execute { const TYPE_NAME: &'static str = "Transaction"; fn build_structure(&self, builder: &mut BUILDER) { - builder.add_member( - "to", - &U256::from(self.contract_address.unwrap_or_default().as_bytes()), - ); + if let Some(contract_address) = self.contract_address { + builder.add_member("to", &contract_address); + } builder.add_member("value", &self.value); builder.add_member("data", &self.calldata.as_slice()); // Factory deps are not included into the transaction signature, since they are parsed from the From 0034e3e86a9be2c5448dc78939384beec6e3c6bd Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 16:41:45 -0300 Subject: [PATCH 15/72] Check address is not null and reject transaction --- core/lib/types/src/transaction_request.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 057c905d1c66..5f26b1d6a6a5 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -817,6 +817,11 @@ impl L2Tx { let meta = value.eip712_meta.take().unwrap_or_default(); validate_factory_deps(&meta.factory_deps)?; + // TODO: Remove this check when evm equivalence gets enabled + if value.to.is_none() { + return Err(SerializationTransactionError::ToAddressIsNull); + } + let mut tx = L2Tx::new( value.to, value.input.0.clone(), From 9c3dad17cf08589cbe11c7f137af4c89dc4211b2 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 17:42:30 -0300 Subject: [PATCH 16/72] Make test only Execute to always have a valid address instead of null --- core/lib/dal/src/consensus/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/dal/src/consensus/tests.rs b/core/lib/dal/src/consensus/tests.rs index f21d09290a2f..7059f1a74ea0 100644 --- a/core/lib/dal/src/consensus/tests.rs +++ b/core/lib/dal/src/consensus/tests.rs @@ -17,7 +17,7 @@ use crate::tests::mock_protocol_upgrade_transaction; fn execute(rng: &mut impl Rng) -> Execute { Execute { - contract_address: rng.gen(), + contract_address: Some(rng.gen()), value: rng.gen::().into(), calldata: (0..10 * 32).map(|_| rng.gen()).collect(), // TODO: find a way to generate valid random bytecode. From 96523684d3bf6a599f12b7cc1839eced6738c5bd Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 17 Sep 2024 20:05:49 -0300 Subject: [PATCH 17/72] Update execute use for tests in multivm crate to have a valid contract address --- core/lib/multivm/src/versions/vm_1_4_1/tests/gas_limit.rs | 6 ++---- core/lib/multivm/src/versions/vm_1_4_2/tests/gas_limit.rs | 6 ++---- .../src/versions/vm_boojum_integration/tests/gas_limit.rs | 6 ++---- core/lib/multivm/src/versions/vm_fast/tests/gas_limit.rs | 5 ++++- core/lib/multivm/src/versions/vm_latest/tests/gas_limit.rs | 5 ++++- .../src/versions/vm_refunds_enhancement/tests/gas_limit.rs | 6 ++---- .../src/versions/vm_virtual_blocks/tests/gas_limit.rs | 6 ++---- 7 files changed, 18 insertions(+), 22 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_1_4_1/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_1_4_1/tests/gas_limit.rs index 0ec921450daf..9dfda9e1a68c 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/tests/gas_limit.rs @@ -21,10 +21,8 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: Default::default(), - calldata: vec![], - value: Default::default(), - factory_deps: None, + contract_address: Some(Default::default()), + ..Default::default() }, Some(Fee { gas_limit, diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_1_4_2/tests/gas_limit.rs index 6a57fd07ae71..b84e9d32126c 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tests/gas_limit.rs @@ -20,10 +20,8 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: Default::default(), - calldata: vec![], - value: Default::default(), - factory_deps: None, + contract_address: Some(Default::default()), + ..Default::default() }, Some(Fee { gas_limit, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_boojum_integration/tests/gas_limit.rs index 30a65097111d..637fd94c1c89 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/tests/gas_limit.rs @@ -21,10 +21,8 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: Default::default(), - calldata: vec![], - value: Default::default(), - factory_deps: None, + contract_address: Some(Default::default()), + ..Default::default() }, Some(Fee { gas_limit, diff --git a/core/lib/multivm/src/versions/vm_fast/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_fast/tests/gas_limit.rs index b7a2154bdc71..3f0a47b980e2 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/gas_limit.rs @@ -18,7 +18,10 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( - Execute::default(), + Execute { + contract_address: Some(Default::default()), + ..Default::default() + }, Some(Fee { gas_limit, ..Account::default_fee() diff --git a/core/lib/multivm/src/versions/vm_latest/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_latest/tests/gas_limit.rs index 34e1e2d25f31..cc9aac5bb91b 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/gas_limit.rs @@ -21,7 +21,10 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( - Execute::default(), + Execute { + contract_address: Some(Default::default()), + ..Default::default() + }, Some(Fee { gas_limit, ..Account::default_fee() diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/gas_limit.rs index 0ea1669cf217..1ff6ce12557f 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/gas_limit.rs @@ -21,10 +21,8 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: Default::default(), - calldata: vec![], - value: Default::default(), - factory_deps: None, + contract_address: Some(Default::default()), + ..Default::default() }, Some(Fee { gas_limit, diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/tests/gas_limit.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/tests/gas_limit.rs index 01ebe4c0d225..e51b8cab570e 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/tests/gas_limit.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/tests/gas_limit.rs @@ -21,10 +21,8 @@ fn test_tx_gas_limit_offset() { let gas_limit = 9999.into(); let tx = vm.rich_accounts[0].get_l2_tx_for_execute( Execute { - contract_address: Default::default(), - calldata: vec![], - value: Default::default(), - factory_deps: None, + contract_address: Some(Default::default()), + ..Default::default() }, Some(Fee { gas_limit, From 189e591222736930a6e18eb6665f23844f34043e Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 18 Sep 2024 10:52:43 -0300 Subject: [PATCH 18/72] Update comment for optional field in execute proto message --- core/lib/dal/src/consensus/proto/mod.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/dal/src/consensus/proto/mod.proto b/core/lib/dal/src/consensus/proto/mod.proto index da9151f10f4d..3ea49e9c0cd6 100644 --- a/core/lib/dal/src/consensus/proto/mod.proto +++ b/core/lib/dal/src/consensus/proto/mod.proto @@ -102,7 +102,7 @@ message ProtocolUpgradeTxCommonData { } message Execute { - optional bytes contract_address = 1; // required; H160 + optional bytes contract_address = 1; // optional; H160 optional bytes calldata = 2; // required optional bytes value = 3; // required; U256 repeated bytes factory_deps = 4; From 2ac399e174d4f53c3c94f02e5c128fbb7e6bcea6 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 18 Sep 2024 11:55:47 -0300 Subject: [PATCH 19/72] Unwrap contract address for l1 tx since it should always be present --- core/lib/types/src/l1/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/lib/types/src/l1/mod.rs b/core/lib/types/src/l1/mod.rs index 215836cb52f5..e8144c75db2e 100644 --- a/core/lib/types/src/l1/mod.rs +++ b/core/lib/types/src/l1/mod.rs @@ -274,7 +274,9 @@ impl From for abi::NewPriorityRequest { transaction: abi::L2CanonicalTransaction { tx_type: PRIORITY_OPERATION_L2_TX_TYPE.into(), from: address_to_u256(&t.common_data.sender), - to: address_to_u256(&t.execute.contract_address.unwrap_or_default()), + // Unwrap used here because the contract address should always be present for L1 transactions. + // TODO: Consider restricting the contract address to not be optional in L1Tx. + to: address_to_u256(&t.execute.contract_address.unwrap()), gas_limit: t.common_data.gas_limit, gas_per_pubdata_byte_limit: t.common_data.gas_per_pubdata_limit, max_fee_per_gas: t.common_data.max_fee_per_gas, From be7793810acb7e5a517389d44ae08815fb400607 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 19 Sep 2024 12:59:02 -0300 Subject: [PATCH 20/72] Remove tests for the evm simulator --- .../evm-contracts/ConstructorRevert.sol | 11 - .../evm-contracts/CounterFallback.sol | 14 - .../evm-contracts/CounterWithParam.sol | 39 - .../ts-integration/evm-contracts/Creator.sol | 19 - .../evm-contracts/CreatorFallback.sol | 20 - .../ts-integration/evm-contracts/ERC20.sol | 78 -- .../evm-contracts/GasCaller.sol | 16 - .../evm-contracts/OpcodeTest.sol | 123 --- .../evm-contracts/OpcodeTestFallback.sol | 139 --- .../evm-contracts/ProxyCaller.sol | 25 - .../evm-contracts/SelfDestruct.sol | 13 - .../evm-contracts/UniswapFallback.sol | 125 --- .../tests/evm-contracts.test.ts | 828 ------------------ 13 files changed, 1450 deletions(-) delete mode 100644 core/tests/ts-integration/evm-contracts/ConstructorRevert.sol delete mode 100644 core/tests/ts-integration/evm-contracts/CounterFallback.sol delete mode 100644 core/tests/ts-integration/evm-contracts/CounterWithParam.sol delete mode 100644 core/tests/ts-integration/evm-contracts/Creator.sol delete mode 100644 core/tests/ts-integration/evm-contracts/CreatorFallback.sol delete mode 100644 core/tests/ts-integration/evm-contracts/ERC20.sol delete mode 100644 core/tests/ts-integration/evm-contracts/GasCaller.sol delete mode 100644 core/tests/ts-integration/evm-contracts/OpcodeTest.sol delete mode 100644 core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol delete mode 100644 core/tests/ts-integration/evm-contracts/ProxyCaller.sol delete mode 100644 core/tests/ts-integration/evm-contracts/SelfDestruct.sol delete mode 100644 core/tests/ts-integration/evm-contracts/UniswapFallback.sol delete mode 100644 core/tests/ts-integration/tests/evm-contracts.test.ts diff --git a/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol b/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol deleted file mode 100644 index 868e57edca79..000000000000 --- a/core/tests/ts-integration/evm-contracts/ConstructorRevert.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract ConstructorRevert { - uint256 value; - - constructor() { - revert("Failure string"); - } -} diff --git a/core/tests/ts-integration/evm-contracts/CounterFallback.sol b/core/tests/ts-integration/evm-contracts/CounterFallback.sol deleted file mode 100644 index c67dfec9459e..000000000000 --- a/core/tests/ts-integration/evm-contracts/CounterFallback.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -contract CounterFallback { - function performCall() external { - uint256 value = 0; - value += 1; - } - - fallback() external { - this.performCall(); - } -} diff --git a/core/tests/ts-integration/evm-contracts/CounterWithParam.sol b/core/tests/ts-integration/evm-contracts/CounterWithParam.sol deleted file mode 100644 index 714b4d665ae3..000000000000 --- a/core/tests/ts-integration/evm-contracts/CounterWithParam.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract CounterWithParam { - uint256 value; - - constructor(uint256 _startingValue) { - value = _startingValue; - } - - function increment(uint256 x) public { - value += x; - } - - function incrementWithRevertPayable(uint256 x, bool shouldRevert) public payable returns (uint256) { - return incrementWithRevert(x, shouldRevert); - } - - function incrementWithRevert(uint256 x, bool shouldRevert) public returns (uint256) { - value += x; - if (shouldRevert) { - revert("This method always reverts"); - } - return value; - } - - function set(uint256 x) public { - value = x; - } - - function get() public view returns (uint256) { - return value; - } - - function getBytes() public returns (bytes memory) { - return "Testing"; - } -} diff --git a/core/tests/ts-integration/evm-contracts/Creator.sol b/core/tests/ts-integration/evm-contracts/Creator.sol deleted file mode 100644 index 63a6f7e3b1d7..000000000000 --- a/core/tests/ts-integration/evm-contracts/Creator.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract Creation { - function blockNumber() external view returns (uint256) { - return block.number; - } -} - -contract Creator { - function create() external { - new Creation(); - } - - function getCreationRuntimeCode() external pure returns (bytes memory) { - return type(Creation).runtimeCode; - } -} diff --git a/core/tests/ts-integration/evm-contracts/CreatorFallback.sol b/core/tests/ts-integration/evm-contracts/CreatorFallback.sol deleted file mode 100644 index 30ebabd7cc7a..000000000000 --- a/core/tests/ts-integration/evm-contracts/CreatorFallback.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract Creation { - function blockNumber() external view returns (uint256) { - return block.number; - } -} - -contract CreatorFallback { - function performCall() external { - new Creation(); - type(Creation).runtimeCode; - } - - fallback() external { - this.performCall(); - } -} diff --git a/core/tests/ts-integration/evm-contracts/ERC20.sol b/core/tests/ts-integration/evm-contracts/ERC20.sol deleted file mode 100644 index 1b65e6541804..000000000000 --- a/core/tests/ts-integration/evm-contracts/ERC20.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract ERC20 { - string public symbol; - string public name; - uint8 public decimals; - uint256 public totalSupply; - - mapping(address => uint256) balances; - mapping(address => mapping(address => uint256)) allowed; - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); - - constructor() { - symbol = "TEST"; - name = "Test Coin"; - decimals = 18; - totalSupply = 1000000; - balances[msg.sender] = totalSupply; - emit Transfer(address(0), msg.sender, totalSupply); - } - - function balanceOf(address tokenOwner) public view returns (uint256 balance) { - return balances[tokenOwner]; - } - - function transfer(address to, uint256 tokens) public returns (bool success) { - balances[msg.sender] = safeSub(balances[msg.sender], tokens); - balances[to] = safeAdd(balances[to], tokens); - emit Transfer(msg.sender, to, tokens); - return true; - } - - function approve(address spender, uint256 tokens) public returns (bool success) { - allowed[msg.sender][spender] = tokens; - emit Approval(msg.sender, spender, tokens); - return true; - } - - function transferFrom( - address from, - address to, - uint256 tokens - ) public returns (bool success) { - balances[from] = safeSub(balances[from], tokens); - allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens); - balances[to] = safeAdd(balances[to], tokens); - emit Transfer(from, to, tokens); - return true; - } - - function allowance(address tokenOwner, address spender) public view returns (uint256 remaining) { - return allowed[tokenOwner][spender]; - } - - function safeAdd(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a + b; - require(c >= a); - } - - function safeSub(uint256 a, uint256 b) internal pure returns (uint256 c) { - require(b <= a); - c = a - b; - } - - function safeMul(uint256 a, uint256 b) internal pure returns (uint256 c) { - c = a * b; - require(a == 0 || c / a == b); - } - - function safeDiv(uint256 a, uint256 b) internal pure returns (uint256 c) { - require(b > 0); - c = a / b; - } -} diff --git a/core/tests/ts-integration/evm-contracts/GasCaller.sol b/core/tests/ts-integration/evm-contracts/GasCaller.sol deleted file mode 100644 index 25b56aa744d6..000000000000 --- a/core/tests/ts-integration/evm-contracts/GasCaller.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -contract GasCaller { - uint256 _resultGas; - - function callAndGetGas(address _to) external returns (uint256) { - uint256 startGas = gasleft(); - // Just doing a call to an address - (bool success, ) = _to.call(""); - require(success); - _resultGas = startGas - gasleft(); - return _resultGas; - } -} diff --git a/core/tests/ts-integration/evm-contracts/OpcodeTest.sol b/core/tests/ts-integration/evm-contracts/OpcodeTest.sol deleted file mode 100644 index 721339bd7ae8..000000000000 --- a/core/tests/ts-integration/evm-contracts/OpcodeTest.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -contract OpcodeTest { - function execute() external { - uint256 loaded = 1; - uint256 tmp; - uint256 prevBlock = block.number - 1; - assembly { - loaded := add(loaded, 1) - loaded := mul(loaded, 2) - loaded := sub(loaded, 1) - loaded := div(loaded, 2) - loaded := sdiv(loaded, 2) - loaded := mod(loaded, 2) - // ADDMOD - // MULMOD - loaded := exp(loaded, 2) - loaded := signextend(loaded, 2) - tmp := lt(loaded, 2) - tmp := gt(loaded, 2) - tmp := slt(loaded, 2) - tmp := sgt(loaded, 2) - tmp := eq(loaded, 2) - tmp := iszero(tmp) - tmp := and(1, 1) - tmp := or(1, 1) - tmp := xor(1, 1) - tmp := not(tmp) - tmp := byte(tmp, 1) - tmp := shl(tmp, 1) - tmp := shr(tmp, 1) - tmp := sar(tmp, 1) - tmp := keccak256(0, 0x40) - tmp := address() - tmp := balance(0x00) - tmp := origin() - tmp := caller() - tmp := callvalue() - // CALLDATALOAD - tmp := calldatasize() - // CALLDATACOPY - tmp := codesize() - // CODECOPY - tmp := gasprice() - // EXTCODESIZE - // EXTCODECOPY - tmp := returndatasize() - // RETURNDATACOPY - // EXTCODEHASH - tmp := blockhash(prevBlock) - tmp := coinbase() - tmp := timestamp() - tmp := number() - tmp := prevrandao() - tmp := gaslimit() - tmp := chainid() - tmp := selfbalance() - tmp := basefee() - // POP - tmp := mload(1) - mstore(1024, 1) - mstore8(10242, 1) - tmp := sload(0) - sstore(0, 1) - // JUMP - // JUMPI - // PC - tmp := msize() - tmp := gas() - // JUMPDEST - // PUSH0...PUSH32 - // DUP1...DUP16 - // SWAP1...SWAP16 - // LOG0...LOG4 - // CREATE - // CALL - // CALLCODE - // RETURN - // DELEGATECALL - // CREATE2 - // STATICCALL - // REVERT - // INVALID - // selfdestruct(sender) - } - - // tmp = 0; - // tmp = 0x11; - // tmp = 0x2211; - // tmp = 0x332211; - // tmp = 0x44332211; - // tmp = 0x5544332211; - // tmp = 0x665544332211; - // tmp = 0x77665544332211; - // tmp = 0x8877665544332211; - // tmp = 0x998877665544332211; - // tmp = 0xaa998877665544332211; - // tmp = 0xbbaa998877665544332211; - // tmp = 0xccbbaa998877665544332211; - // tmp = 0xddccbbaa998877665544332211; - // tmp = 0xeeddccbbaa998877665544332211; - // tmp = 0xffeeddccbbaa998877665544332211; - // tmp = 0x11ffeeddccbbaa998877665544332211; - // tmp = 0x2211ffeeddccbbaa998877665544332211; - // tmp = 0x332211ffeeddccbbaa998877665544332211; - // tmp = 0x44332211ffeeddccbbaa998877665544332211; - // tmp = uint256(uint160(0x5544332211FFeeDDCcbbAa998877665544332211)); - // tmp = 0x665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x77665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x8877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0xff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x11ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x2211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x44332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x5544332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x665544332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x77665544332211ff998877665544332211ffeeddccbbaa998877665544332211; - } -} diff --git a/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol b/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol deleted file mode 100644 index 47f427a27333..000000000000 --- a/core/tests/ts-integration/evm-contracts/OpcodeTestFallback.sol +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -contract OpcodeTestFallback { - function performCall() external { - uint256 loaded = 1; - uint256 tmp; - uint256 prevBlock = block.number - 1; - assembly { - loaded := add(loaded, 1) - loaded := mul(loaded, 2) - loaded := sub(loaded, 1) - loaded := div(loaded, 2) - loaded := sdiv(loaded, 2) - loaded := mod(loaded, 2) - // ADDMOD - // MULMOD - loaded := exp(loaded, 2) - loaded := signextend(loaded, 2) - tmp := lt(loaded, 2) - tmp := gt(loaded, 2) - tmp := slt(loaded, 2) - tmp := sgt(loaded, 2) - tmp := eq(loaded, 2) - tmp := iszero(tmp) - tmp := and(1, 1) - tmp := or(1, 1) - tmp := xor(1, 1) - tmp := not(tmp) - tmp := byte(tmp, 1) - tmp := shl(tmp, 1) - tmp := shr(tmp, 1) - tmp := sar(tmp, 1) - tmp := keccak256(0, 0x40) - tmp := address() - tmp := balance(0x00) - tmp := origin() - tmp := caller() - tmp := callvalue() - // CALLDATALOAD - tmp := calldatasize() - // CALLDATACOPY - tmp := codesize() - // CODECOPY - tmp := gasprice() - // EXTCODESIZE - // EXTCODECOPY - tmp := returndatasize() - // RETURNDATACOPY - // EXTCODEHASH - tmp := blockhash(prevBlock) - tmp := coinbase() - tmp := timestamp() - tmp := number() - tmp := prevrandao() - tmp := gaslimit() - tmp := chainid() - tmp := selfbalance() - tmp := basefee() - // POP - tmp := mload(1) - mstore(1024, 1) - mstore8(10242, 1) - tmp := sload(0) - sstore(0, 1) - // JUMP - // JUMPI - // PC - tmp := msize() - tmp := gas() - // JUMPDEST - // PUSH0...PUSH32 - // DUP1...DUP16 - // SWAP1...SWAP16 - // LOG0...LOG4 - // CREATE - // CALL - // CALLCODE - // RETURN - // DELEGATECALL - // CREATE2 - // STATICCALL - // REVERT - // INVALID - // selfdestruct(sender) - tmp := calldataload(0) - calldatacopy(10, 0, 1) - codecopy(10, 0, 1) - tmp := extcodesize(0) - extcodecopy(address(), 10, 0, 1) - returndatacopy(10, 0, 1) - pop(extcodehash(0)) - log0(0, 30) - log1(0, 30, 30) - log2(0, 30, 30, 30) - log3(0, 30, 30, 30, 30) - log4(0, 30, 30, 30, 30, 30) - } - - // tmp = 0; - // tmp = 0x11; - // tmp = 0x2211; - // tmp = 0x332211; - // tmp = 0x44332211; - // tmp = 0x5544332211; - // tmp = 0x665544332211; - // tmp = 0x77665544332211; - // tmp = 0x8877665544332211; - // tmp = 0x998877665544332211; - // tmp = 0xaa998877665544332211; - // tmp = 0xbbaa998877665544332211; - // tmp = 0xccbbaa998877665544332211; - // tmp = 0xddccbbaa998877665544332211; - // tmp = 0xeeddccbbaa998877665544332211; - // tmp = 0xffeeddccbbaa998877665544332211; - // tmp = 0x11ffeeddccbbaa998877665544332211; - // tmp = 0x2211ffeeddccbbaa998877665544332211; - // tmp = 0x332211ffeeddccbbaa998877665544332211; - // tmp = 0x44332211ffeeddccbbaa998877665544332211; - // tmp = uint256(uint160(0x5544332211FFeeDDCcbbAa998877665544332211)); - // tmp = 0x665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x77665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x8877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0xff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x11ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x2211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x44332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x5544332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x665544332211ff998877665544332211ffeeddccbbaa998877665544332211; - // tmp = 0x77665544332211ff998877665544332211ffeeddccbbaa998877665544332211; - } - - fallback() external { - this.performCall(); - } -} diff --git a/core/tests/ts-integration/evm-contracts/ProxyCaller.sol b/core/tests/ts-integration/evm-contracts/ProxyCaller.sol deleted file mode 100644 index 379d7c7addcd..000000000000 --- a/core/tests/ts-integration/evm-contracts/ProxyCaller.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -interface ICounterWithParam { - function increment(uint256 x) external; - - function get() external view returns (uint256); - - function getBytes() external returns (bytes memory); -} - -contract ProxyCaller { - function executeIncrememt(address dest, uint256 x) external { - ICounterWithParam(dest).increment(x); - } - - function proxyGet(address dest) external view returns (uint256) { - return ICounterWithParam(dest).get(); - } - - function proxyGetBytes(address dest) external returns (bytes memory returnData) { - return ICounterWithParam(dest).getBytes(); - } -} diff --git a/core/tests/ts-integration/evm-contracts/SelfDestruct.sol b/core/tests/ts-integration/evm-contracts/SelfDestruct.sol deleted file mode 100644 index 12fec9555908..000000000000 --- a/core/tests/ts-integration/evm-contracts/SelfDestruct.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity >=0.7.0; - -contract SelfDestruct { - constructor() payable {} - - function destroy(address recipient) external { - assembly { - selfdestruct(recipient) - } - } -} diff --git a/core/tests/ts-integration/evm-contracts/UniswapFallback.sol b/core/tests/ts-integration/evm-contracts/UniswapFallback.sol deleted file mode 100644 index 0237b4be1ba5..000000000000 --- a/core/tests/ts-integration/evm-contracts/UniswapFallback.sol +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -interface IUniswapV2ERC20 { - event Approval(address indexed owner, address indexed spender, uint256 value); - event Transfer(address indexed from, address indexed to, uint256 value); - - function name() external pure returns (string memory); - - function symbol() external pure returns (string memory); - - function decimals() external pure returns (uint8); - - function totalSupply() external returns (uint256); - - function balanceOf(address owner) external returns (uint256); - - function allowance(address owner, address spender) external returns (uint256); - - function approve(address spender, uint256 value) external returns (bool); - - function transfer(address to, uint256 value) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool); - - function DOMAIN_SEPARATOR() external returns (bytes32); - - function PERMIT_TYPEHASH() external pure returns (bytes32); - - function nonces(address owner) external returns (uint256); - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; -} - -interface IUniswapV2Pair { - event Mint(address indexed sender, uint256 amount0, uint256 amount1); - event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); - event Swap( - address indexed sender, - uint256 amount0In, - uint256 amount1In, - uint256 amount0Out, - uint256 amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - function MINIMUM_LIQUIDITY() external pure returns (uint256); - - function factory() external returns (address); - - function token0() external returns (address); - - function token1() external returns (address); - - function getReserves() - external - returns ( - uint112 reserve0, - uint112 reserve1, - uint32 blockTimestampLast - ); - - function price0CumulativeLast() external returns (uint256); - - function price1CumulativeLast() external returns (uint256); - - function kLast() external returns (uint256); - - function mint(address to) external returns (uint256 liquidity); - - function burn(address to) external returns (uint256 amount0, uint256 amount1); - - function swap( - uint256 amount0Out, - uint256 amount1Out, - address to, - bytes calldata data - ) external; - - function skim(address to) external; - - function sync() external; - - function initialize(address, address) external; -} - -contract UniswapFallback { - IUniswapV2Pair public uniswapPair; - IUniswapV2ERC20 public uniswapPair2; - address public alice_address; - - function setUniswapAddress(address _uniswap_address) public { - uniswapPair = IUniswapV2Pair(_uniswap_address); - uniswapPair2 = IUniswapV2ERC20(_uniswap_address); - } - - function setAliceAddress(address _alice_address) public { - alice_address = _alice_address; - } - - // Fallback function - fallback() external { - // Implement any logic you want the contract to perform when it receives Ether - // This function will be called when the contract receives Ether and no other function matches the call data - uniswapPair.mint(alice_address); - uniswapPair.swap(0, 5000, alice_address, "0x"); - uint256 balance = uniswapPair2.balanceOf(alice_address); - //uniswapPair2.transfer(address(uniswapPair),balance); - //uniswapPair.burn(alice_address); - } -} diff --git a/core/tests/ts-integration/tests/evm-contracts.test.ts b/core/tests/ts-integration/tests/evm-contracts.test.ts deleted file mode 100644 index 90eb0975f021..000000000000 --- a/core/tests/ts-integration/tests/evm-contracts.test.ts +++ /dev/null @@ -1,828 +0,0 @@ -/** - * Generic tests checking evm equivalence smart contract behavior. - * - * Note: if you are going to write multiple tests checking specific topic (e.g. `CREATE2` behavior or something like this), - * consider creating a separate suite. - * Let's try to keep only relatively simple and self-contained tests here. - */ - -import { TestMaster } from '../src'; -import { deployContract, getEVMArtifact, getEVMContractFactory, getTestContract } from '../src/helpers'; - -import * as ethers from 'ethers'; -import * as zksync from 'zksync-ethers'; - -const contracts = { - tester: getTestContract('TestEVMCreate'), - erc20: getTestContract('ERC20'), - uniswapV2Pair: getTestContract('UniswapV2Pair'), - uniswapV2Factory: getTestContract('UniswapV2Factory') -}; - -const artifacts = { - counter: getEVMArtifact('../evm-contracts/CounterWithParam.sol'), - proxyCaller: getEVMArtifact('../evm-contracts/ProxyCaller.sol'), - creator: getEVMArtifact('../evm-contracts/Creator.sol'), - erc20: getEVMArtifact('../evm-contracts/ERC20.sol'), - constructorRevert: getEVMArtifact('../evm-contracts/ConstructorRevert.sol'), - uniswapV2Pair: getEVMArtifact('../contracts/uniswap-v2/UniswapV2Factory.sol', 'UniswapV2Pair.sol'), - uniswapV2Factory: getEVMArtifact('../contracts/uniswap-v2/UniswapV2Factory.sol', 'UniswapV2Factory.sol'), - opcodeTest: getEVMArtifact('../evm-contracts/OpcodeTest.sol'), - selfDestruct: getEVMArtifact('../evm-contracts/SelfDestruct.sol'), - gasCaller: getEVMArtifact('../evm-contracts/GasCaller.sol'), - counterFallback: getEVMArtifact('../evm-contracts/CounterFallback.sol'), - uniswapFallback: getEVMArtifact('../evm-contracts/UniswapFallback.sol'), - creatorFallback: getEVMArtifact('../evm-contracts/CreatorFallback.sol'), - opcodeTestFallback: getEVMArtifact('../evm-contracts/OpcodeTestFallback.sol') -}; - -const initBytecode = '0x69602a60005260206000f3600052600a6016f3'; -const runtimeBytecode = '0x602a60005260206000f3'; - -let gasLimit = '0x01ffffff'; - -const logGasCosts = false; -describe('EVM equivalence contract', () => { - let testMaster: TestMaster; - let alice: zksync.Wallet; - - // Contracts shared in several tests. - let evmCreateTester: zksync.Contract; - let deployer: zksync.Contract; - - beforeAll(async () => { - testMaster = TestMaster.getInstance(__filename); - alice = testMaster.mainAccount(); - - evmCreateTester = await deployContract(alice, contracts.tester, []); - deployer = new zksync.Contract(zksync.utils.CONTRACT_DEPLOYER_ADDRESS, zksync.utils.CONTRACT_DEPLOYER, alice); - }); - - describe('Gas consumption', () => { - test("Should compare gas against counter fallback contract's call", async () => { - const gasCallerContract = await deploygasCallerContract(alice, artifacts.gasCaller); - - const counterContract = await deploygasCallerContract(alice, artifacts.counterFallback); - - let result = ( - await gasCallerContract.getFunction('callAndGetGas').staticCall(counterContract.getAddress()) - ).toString(); - - const expected_gas = '3617'; // Gas cost when run with solidity interpreter - expect(result).toEqual(expected_gas); - }); - - test("Should compare gas against creator fallback contract's call", async () => { - const gasCallerContract = await deploygasCallerContract(alice, artifacts.gasCaller); - - const creatorContract = await deploygasCallerContract(alice, artifacts.creatorFallback); - - let result = ( - await gasCallerContract.getFunction('callAndGetGas').staticCall(creatorContract.getAddress()) - ).toString(); - - const expected_gas = '70598'; // Gas cost when run with solidity interpreter - 3 (We have some changes that are needed) - expect(result).toEqual(expected_gas); - }); - }); - - describe('Contract creation', () => { - describe('Create from EOA', () => { - test('Should create evm contract from EOA and allow view and non-view calls', async () => { - const args = 1; - const factory = getEVMContractFactory(alice, artifacts.counter); - const contract = await factory.deploy(args); - await contract.deploymentTransaction()?.wait(); - await alice.provider.getTransactionReceipt( - contract.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })() - ); - - await assertCreatedCorrectly( - deployer, - await contract.getAddress(), - '0x' + artifacts.counter.evm.deployedBytecode.object - ); - - expect((await contract.getFunction('get').staticCall()).toString()).toEqual('1'); - await (await contract.getFunction('increment')(1)).wait(); - expect((await contract.getFunction('get').staticCall()).toString()).toEqual('2'); - }); - - test('Should create2 evm contract from ZKEVM contract', async () => { - const salt = ethers.randomBytes(32); - - const expectedAddress = ethers.getCreate2Address( - await evmCreateTester.getAddress(), - salt, - ethers.keccak256(initBytecode) - ); - - await (await evmCreateTester.create2(salt, initBytecode)).wait(); - - await assertCreatedCorrectly(deployer, expectedAddress, runtimeBytecode); - - try { - await (await evmCreateTester.create2(salt, initBytecode, { gasLimit })).wait(); - } catch (e) { - // Should fail - return; - } - throw 'Should fail to create2 the same contract with same salt twice'; - }); - - test('Should propegate revert in constructor', async () => { - const factory = getEVMContractFactory(alice, artifacts.constructorRevert); - const contract = await factory.deploy({ gasLimit }); - - let failReason; - - try { - await contract.deploymentTransaction()?.wait(); - } catch (e: any) { - failReason = e.reason; - } - - expect(failReason).toBe(null); - }); - - test('Should NOT create evm contract from EOA when `to` is address(0x0)', async () => { - const args = 1; - - const factory = getEVMContractFactory(alice, artifacts.counter); - const { data, ...rest } = await factory.getDeployTransaction(args); - const dep_transaction = { - ...rest, - to: '0x0000000000000000000000000000000000000000', - chainId: alice.provider._network.chainId, - data - }; - await (await alice.sendTransaction(dep_transaction)).wait(); - const expectedAddressCreate = ethers.getCreateAddress({ - from: alice.address, - nonce: await alice.getNonce() - }); - - await assertContractNotCreated(deployer, expectedAddressCreate); - }); - }); - }); - - describe('Inter-contract calls', () => { - test('Calls (read/write) between EVM contracts should work correctly', async () => { - const args = 1; - - const counterFactory = getEVMContractFactory(alice, artifacts.counter); - const counterContract = await counterFactory.deploy(args); - await counterContract.deploymentTransaction()?.wait(); - await alice.provider.getTransactionReceipt( - counterContract.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })() - ); - - const proxyCallerFactory = getEVMContractFactory(alice, artifacts.proxyCaller); - const proxyCallerContract = await proxyCallerFactory.deploy(); - await proxyCallerContract.deploymentTransaction()?.wait(); - await alice.provider.getTransactionReceipt( - proxyCallerContract.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })() - ); - - expect( - (await proxyCallerContract.getFunction('proxyGet')(await counterContract.getAddress())).toString() - ).toEqual('1'); - - await ( - await proxyCallerContract.getFunction('executeIncrememt')(await counterContract.getAddress(), 1) - ).wait(); - - expect( - (await proxyCallerContract.getFunction('proxyGet')(await counterContract.getAddress())).toString() - ).toEqual('2'); - - expect( - ( - await proxyCallerContract - .getFunction('proxyGetBytes') - .staticCall(await counterContract.getAddress()) - ).toString() - ).toEqual('0x54657374696e67'); - }); - - test('Create opcode works correctly', async () => { - const creatorFactory = getEVMContractFactory(alice, artifacts.creator); - const creatorContract = await creatorFactory.deploy(); - await creatorContract.deploymentTransaction()?.wait(); - - const nonce = 1; - - const runtimeBytecode = await creatorContract.getFunction('getCreationRuntimeCode')(); - - const expectedAddress = ethers.getCreateAddress({ - from: await creatorContract.getAddress(), - nonce - }); - - await (await creatorContract.getFunction('create')()).wait(); - - await assertCreatedCorrectly(deployer, expectedAddress, runtimeBytecode); - }); - - test('Should revert correctly', async () => { - const args = 1; - - const counterFactory = getEVMContractFactory(alice, artifacts.counter); - const counterContract = await counterFactory.deploy(args); - await counterContract.deploymentTransaction()?.wait(); - - let errorString; - - try { - await counterContract.getFunction('incrementWithRevert').staticCall(1, true); - } catch (e: any) { - errorString = e.reason; - } - - expect(errorString).toEqual('This method always reverts'); - }); - }); - - // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published - describe('ERC20', () => { - let evmToken: ethers.BaseContract; - let nativeToken: zksync.Contract; - let userAccount: zksync.Wallet; - let deployLogged: boolean = false; - - beforeEach(async () => { - const erc20Factory = getEVMContractFactory(alice, artifacts.erc20); - evmToken = await erc20Factory.deploy(); - await evmToken.deploymentTransaction()?.wait(); - nativeToken = await deployContract(alice, contracts.erc20, []); - - userAccount = testMaster.newEmptyAccount(); - // Only log the first deployment - if (logGasCosts && !deployLogged) { - let native_hash = - nativeToken.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let native_transanction_receipt = - (await alice.provider.getTransactionReceipt(native_hash)) ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let evm_hash = - evmToken.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let evm_transanction_receipt = - (await alice.provider.getTransactionReceipt(evm_hash)) ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - console.log('ERC20 native deploy gas: ' + native_transanction_receipt.gasUsed); - console.log('ERC20 evm deploy gas: ' + evm_transanction_receipt.gasUsed); - deployLogged = true; - } - await ( - await alice.sendTransaction({ - to: userAccount.address, - value: BigInt('0xffffffffffffff') - }) - ).wait(); - }); - - test('view functions should work', async () => { - const evmBalanceOfCost = await evmToken.getFunction('balanceOf').estimateGas(alice.address); - const nativeBalanceOfCost = await nativeToken.getFunction('balanceOf').estimateGas(alice.address); - if (logGasCosts) { - console.log('ERC20 native balanceOf gas: ' + nativeBalanceOfCost.toString()); - console.log('ERC20 evm balanceOf gas: ' + evmBalanceOfCost.toString()); - } - expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); - expect((await evmToken.getFunction('totalSupply')()).toString()).toEqual('1000000'); - expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('0'); - }); - - test('transfer should work', async () => { - expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); - const evmTransferTx = await (await evmToken.getFunction('transfer')(userAccount.address, 100000)).wait(); - const nativeTransferTx = await (await nativeToken.transfer(userAccount.address, 100000)).wait(); - if (logGasCosts) { - console.log('ERC20 native transfer gas: ' + nativeTransferTx.gasUsed.toString()); - console.log('ERC20 evm transfer gas: ' + evmTransferTx.gasUsed.toString()); - } - - expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('900000'); - expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('100000'); - }); - - test('approve & transferFrom should work', async () => { - expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('1000000'); - const evmApproveTx = await ( - await evmToken.connect(alice).getFunction('approve')(userAccount.getAddress(), 100000) - ).wait(); - const nativeApproveTx = await ( - await nativeToken.connect(alice).getFunction('approve')(userAccount.address, 100000) - ).wait(); - if (logGasCosts) { - console.log('ERC20 native approve gas: ' + nativeApproveTx.gasUsed.toString()); - console.log('ERC20 evm approve gas: ' + evmApproveTx.gasUsed.toString()); - } - - const evmTransferFromTx = await ( - await evmToken.connect(userAccount).getFunction('transferFrom')( - alice.address, - userAccount.address, - 100000 - ) - ).wait(); - const nativeTransferFromTx = await ( - await nativeToken.connect(userAccount).getFunction('transferFrom')( - alice.address, - userAccount.address, - 100000 - ) - ).wait(); - if (logGasCosts) { - console.log('ERC20 native transferFrom gas: ' + nativeTransferFromTx.gasUsed.toString()); - console.log('ERC20 evm transferFrom gas: ' + evmTransferFromTx.gasUsed.toString()); - } - - expect((await evmToken.getFunction('balanceOf')(alice.address)).toString()).toEqual('900000'); - expect((await evmToken.getFunction('balanceOf')(userAccount.address)).toString()).toEqual('100000'); - }); - }); - - // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published - describe('Uniswap-v2', () => { - let evmToken1: ethers.BaseContract; - let evmToken2: ethers.BaseContract; - let evmUniswapFactory: ethers.BaseContract; - let nativeUniswapFactory: ethers.BaseContract; - let evmUniswapPair: ethers.BaseContract; - let nativeUniswapPair: ethers.BaseContract; - - let deployLogged: boolean = false; - const NEW_PAIR_TOPIC = '0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9'; - - beforeEach(async () => { - const erc20Factory = getEVMContractFactory(alice, artifacts.erc20); - evmToken1 = await erc20Factory.deploy({ gasLimit }); - await evmToken1.deploymentTransaction()?.wait(); - evmToken2 = await erc20Factory.deploy(); - await evmToken2.deploymentTransaction()?.wait(); - - const evmUniswapFactoryFactory = getEVMContractFactory(alice, artifacts.uniswapV2Factory); - evmUniswapFactory = await evmUniswapFactoryFactory.deploy('0x0000000000000000000000000000000000000000'); - await evmUniswapFactory.deploymentTransaction()?.wait(); - - nativeUniswapFactory = await deployContract( - alice, - contracts.uniswapV2Factory, - ['0x0000000000000000000000000000000000000000'], - undefined, - { - customData: { - factoryDeps: [contracts.uniswapV2Pair.bytecode] - } - } - ); - - const evmPairReceipt = await ( - await evmUniswapFactory.getFunction('createPair')(evmToken1.getAddress(), evmToken2.getAddress()) - ).wait(); - - const nativePairReceipt = await ( - await nativeUniswapFactory.getFunction('createPair')(evmToken1.getAddress(), evmToken2.getAddress()) - ).wait(); - - const evmUniswapPairFactory = getEVMContractFactory(alice, artifacts.uniswapV2Pair); - const nativeUniswapPairFactory = new zksync.ContractFactory( - contracts.uniswapV2Pair.abi, - contracts.uniswapV2Pair.bytecode, - alice - ); - evmUniswapPair = evmUniswapPairFactory.attach( - ethers.AbiCoder.defaultAbiCoder().decode( - ['address', 'uint256'], - evmPairReceipt.logs.find((log: any) => log.topics[0] === NEW_PAIR_TOPIC).data - )[0] - ); - nativeUniswapPair = nativeUniswapPairFactory.attach( - ethers.AbiCoder.defaultAbiCoder().decode( - ['address', 'uint256'], - nativePairReceipt.logs.find((log: any) => log.topics[0] === NEW_PAIR_TOPIC).data - )[0] - ); - const token1IsFirst = (await evmUniswapPair.getFunction('token0')()).toString() === evmToken1.getAddress(); - if (!token1IsFirst) { - [evmToken1, evmToken2] = [evmToken2, evmToken1]; - } - await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 100000)).wait(); - await (await evmToken1.getFunction('transfer')(nativeUniswapPair.getAddress(), 100000)).wait(); - await (await evmToken2.getFunction('transfer')(evmUniswapPair.getAddress(), 100000)).wait(); - await (await evmToken2.getFunction('transfer')(nativeUniswapPair.getAddress(), 100000)).wait(); - - // Only log the first deployment - if (logGasCosts && !deployLogged) { - let native_hash = - nativeUniswapFactory.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let native_transanction_receipt = - (await alice.provider.getTransactionReceipt(native_hash)) ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let evm_hash = - evmUniswapFactory.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - let evm_transanction_receipt = - (await alice.provider.getTransactionReceipt(evm_hash)) ?? - (() => { - throw new Error('Deployment transaction has failed'); - })(); - console.log('Uniswap Factory native deploy gas: ' + native_transanction_receipt.gasUsed); - console.log('Uniswap Factory evm deploy gas: ' + evm_transanction_receipt.gasUsed); - console.log('Uniswap Pair native create gas: ' + nativePairReceipt.gasUsed); - console.log('Uniswap Pair evm create gas: ' + evmPairReceipt.gasUsed); - deployLogged = true; - } - }); - - test('mint, swap, and burn should work', async () => { - const evmMintReceipt = await (await evmUniswapPair.getFunction('mint')(alice.address)).wait(); - const nativeMintReceipt = await (await nativeUniswapPair.getFunction('mint')(alice.address)).wait(); - - await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 10000)).wait(); - await (await evmToken1.getFunction('transfer')(nativeUniswapPair.getAddress(), 10000)).wait(); - const evmSwapReceipt = await ( - await evmUniswapPair.getFunction('swap')(0, 5000, alice.address, '0x') - ).wait(); - const nativeSwapReceipt = await ( - await nativeUniswapPair.getFunction('swap')(0, 5000, alice.address, '0x') - ).wait(); - - await ( - await evmUniswapPair.getFunction('transfer')( - evmUniswapPair.getAddress(), - (await evmUniswapPair.getFunction('balanceOf')(alice.address)).toString() - ) - ).wait(); - await ( - await nativeUniswapPair.getFunction('transfer')( - nativeUniswapPair.getAddress(), - (await nativeUniswapPair.getFunction('balanceOf')(alice.address)).toString() - ) - ).wait(); - const evmBurnReceipt = await (await evmUniswapPair.getFunction('burn')(alice.address)).wait(); - const nativeBurnReceipt = await (await nativeUniswapPair.getFunction('burn')(alice.address)).wait(); - expect(Number((await evmToken1.getFunction('balanceOf')(alice.address)).toString())).toBeGreaterThanOrEqual( - 990000 - ); - expect(Number((await evmToken2.getFunction('balanceOf')(alice.address)).toString())).toBeGreaterThanOrEqual( - 990000 - ); - - if (logGasCosts) { - console.log('UniswapV2Pair native mint gas: ' + nativeMintReceipt.gasUsed); - console.log('UniswapV2Pair evm mint gas: ' + evmMintReceipt.gasUsed); - console.log('UniswapV2Pair native swap gas: ' + nativeSwapReceipt.gasUsed); - console.log('UniswapV2Pair evm swap gas: ' + evmSwapReceipt.gasUsed); - console.log('UniswapV2Pair native burn gas: ' + nativeBurnReceipt.gasUsed); - console.log('UniswapV2Pair evm burn gas: ' + evmBurnReceipt.gasUsed); - } - }); - - test("Should compare gas against uniswap fallback contract's call", async () => { - const gasCallerFactory = getEVMContractFactory(alice, artifacts.gasCaller); - const gasCallerContract = await gasCallerFactory.deploy(); - await gasCallerContract.deploymentTransaction()?.wait(); - await alice.provider.getTransactionReceipt( - gasCallerContract.deploymentTransaction()?.hash ?? - (() => { - throw new Error('Deployment transaction has failed'); - })() - ); - - const uniswapContract = await deploygasCallerContract(alice, artifacts.uniswapFallback); - await (await uniswapContract.getFunction('setUniswapAddress')(evmUniswapPair.getAddress())).wait(); - await (await uniswapContract.getFunction('setAliceAddress')(alice.address)).wait(); - - await (await evmToken1.getFunction('transfer')(evmUniswapPair.getAddress(), 10000)).wait(); - await (await evmToken1.getFunction('transfer')(uniswapContract.getAddress(), 10000)).wait(); - - let result = ( - await gasCallerContract.getFunction('callAndGetGas').staticCall(uniswapContract.getAddress()) - ).toString(); - - const expected_gas = '165939'; // Gas cost when run with solidity interpreter - expect(result).toEqual(expected_gas); - }); - }); - - // NOTE: Gas cost comparisons should be done on a *fresh* chain that doesn't have e.g. bytecodes already published - // describe('Bulk opcode tests', () => { - // let opcodeTest: ethers.Contract; - // beforeEach(async () => { - // const opcodeTestFactory = getEVMContractFactory(alice, artifacts.opcodeTest); - // console.log(opcodeTestFactory.bytecode) - // opcodeTest = await opcodeTestFactory.deploy() - // }); - - // test('should successfully execute bulk opcode test', async () => { - // console.log(await deployer.evmCode(opcodeTest.address)) - // // const receipt = await (await opcodeTest.execute()).wait() - // }); - // }); - - afterAll(async () => { - await testMaster.deinitialize(); - if (logGasCosts) { - printCostData(); - } - }); -}); - -async function deploygasCallerContract(alice: zksync.Wallet, contract: any, ...args: Array) { - const counterFactory = getEVMContractFactory(alice, contract); - const counterContract = await counterFactory.deploy(...args); - await counterContract.waitForDeployment(); - await counterContract.deploymentTransaction()?.wait(); - let hash = counterContract.deploymentTransaction()?.hash; - if (hash == undefined) { - throw new Error('Deployment transaction has failed'); - } - await alice.provider.getTransactionReceipt(hash); - - return counterContract; -} - -async function assertStoredBytecodeHash( - deployer: zksync.Contract, - deployedAddress: string, - expectedStoredHash: string -): Promise { - const ACCOUNT_CODE_STORAGE_ADDRESS = '0x0000000000000000000000000000000000008002'; - let runner = - deployer.runner ?? - (() => { - throw new Error('Runner get failed'); - })(); - let provider = - runner.provider ?? - (() => { - throw new Error('Provider get failed'); - })(); - const storedCodeHash = await provider.getStorage( - ACCOUNT_CODE_STORAGE_ADDRESS, - ethers.zeroPadValue(deployedAddress, 32) - ); - - expect(storedCodeHash).toEqual(expectedStoredHash); -} - -async function assertCreatedCorrectly( - deployer: zksync.Contract, - deployedAddress: string, - expectedEVMBytecode: string -): Promise { - const expectedStoredHash = getSha256BlobHash(expectedEVMBytecode); - await assertStoredBytecodeHash(deployer, deployedAddress, expectedStoredHash); -} - -function getPaddedBytecode(bytes: ethers.BytesLike) { - const length = ethers.getBytes(bytes).length; - - const encodedLength = ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [length]); - - let paddedBytecode = encodedLength + ethers.toBeHex(ethers.toBigInt(bytes)).slice(2); - - // The length needs to be 32 mod 64. We use 64 mod 128, since - // we are dealing with a hexlified string - while ((paddedBytecode.length - 2) % 128 != 64) { - paddedBytecode += '0'; - } - - return paddedBytecode; -} - -// Returns the canonical code hash of -function getSha256BlobHash(bytes: ethers.BytesLike): string { - const paddedBytes = getPaddedBytecode(bytes); - - const hash = ethers.getBytes(ethers.sha256(paddedBytes)); - hash[0] = 2; - hash[1] = 0; - - // Length of the bytecode - const lengthInBytes = ethers.getBytes(paddedBytes).length; - hash[2] = Math.floor(lengthInBytes / 256); - hash[3] = lengthInBytes % 256; - - return ethers.toBeHex(ethers.toBigInt(hash)); -} - -async function assertContractNotCreated(deployer: zksync.Contract, deployedAddress: string): Promise { - assertStoredBytecodeHash(deployer, deployedAddress, ethers.ZeroHash); -} - -function printCostData() { - let costsDataString = ''; - - const averageOverhead = - overheadDataDump.length === 0 - ? undefined - : Math.floor(overheadDataDump.reduce((a: number, c: number) => a + c) / overheadDataDump.length); - const minOverhead = overheadDataDump.length === 0 ? undefined : Math.min(...overheadDataDump); - const maxOverhead = overheadDataDump.length === 0 ? undefined : Math.max(...overheadDataDump); - - costsDataString += 'Overhead\t' + averageOverhead + '\t' + minOverhead + '\t' + maxOverhead + '\n'; - - Object.keys(opcodeDataDump).forEach((opcode) => { - const opcodeString = '0x' + Number(opcode).toString(16).padStart(2, '0'); - const values = opcodeDataDump[opcode.toString()]; - if (values.length === 0) { - costsDataString += opcodeString + '\n'; - return; - } - const average = Math.floor(values.reduce((a: number, c: number) => a + c) / values.length); - const min = Math.min(...values); - const max = Math.max(...values); - - costsDataString += - opcodeString + - '\t' + - average + - '\t' + - (min === average ? '' : min) + - '\t' + - (max === average ? '' : max) + - '\n'; - }); - console.log(costsDataString); -} - -const overheadDataDump: Array = []; -const opcodeDataDump: any = {}; -[ - '0x0', - '0x1', - '0x2', - '0x3', - '0x4', - '0x5', - '0x6', - '0x7', - '0x8', - '0x9', - '0x0A', - '0x0B', - '0x10', - '0x11', - '0x12', - '0x13', - '0x14', - '0x15', - '0x16', - '0x17', - '0x18', - '0x19', - '0x1A', - '0x1B', - '0x1C', - '0x1D', - '0x20', - '0x30', - '0x31', - '0x32', - '0x33', - '0x34', - '0x35', - '0x36', - '0x37', - '0x38', - '0x39', - '0x3A', - '0x3B', - '0x3C', - '0x3D', - '0x3E', - '0x3F', - '0x40', - '0x41', - '0x42', - '0x43', - '0x44', - '0x45', - '0x46', - '0x47', - '0x48', - '0x50', - '0x51', - '0x52', - '0x53', - '0x54', - '0x55', - '0x56', - '0x57', - '0x58', - '0x59', - '0x5A', - '0x5B', - '0x5F', - '0x60', - '0x61', - '0x62', - '0x63', - '0x64', - '0x65', - '0x66', - '0x67', - '0x68', - '0x69', - '0x6A', - '0x6B', - '0x6C', - '0x6D', - '0x6E', - '0x6F', - '0x70', - '0x71', - '0x72', - '0x73', - '0x74', - '0x75', - '0x76', - '0x77', - '0x78', - '0x79', - '0x7A', - '0x7B', - '0x7C', - '0x7D', - '0x7E', - '0x7F', - '0x80', - '0x81', - '0x82', - '0x83', - '0x84', - '0x85', - '0x86', - '0x87', - '0x88', - '0x89', - '0x8A', - '0x8B', - '0x8C', - '0x8D', - '0x8E', - '0x8F', - '0x90', - '0x91', - '0x92', - '0x93', - '0x94', - '0x95', - '0x96', - '0x97', - '0x98', - '0x99', - '0x9A', - '0x9B', - '0x9C', - '0x9D', - '0x9E', - '0x9F', - '0xA0', - '0xA1', - '0xA2', - '0xA3', - '0xA4', - '0xF0', - '0xF1', - '0xF2', - '0xF3', - '0xF4', - '0xF5', - '0xFA', - '0xFD', - '0xFE', - '0xFF' -].forEach((key) => { - opcodeDataDump[Number(key).toString()] = []; -}); From 7608ace8f1eb2c7d4d377e990c831eb4a728b312 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 19 Sep 2024 13:23:28 -0300 Subject: [PATCH 21/72] Delete contracts and aux functions used for evm tests --- .../contracts/create/TestEVMCreate.sol | 30 - .../ts-integration/contracts/token/ERC20.sol | 76 -- .../contracts/uniswap-v2/UniswapV2Factory.sol | 683 ------------------ core/tests/ts-integration/package.json | 6 +- core/tests/ts-integration/src/helpers.ts | 47 -- 5 files changed, 1 insertion(+), 841 deletions(-) delete mode 100644 core/tests/ts-integration/contracts/create/TestEVMCreate.sol delete mode 100644 core/tests/ts-integration/contracts/token/ERC20.sol delete mode 100644 core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol diff --git a/core/tests/ts-integration/contracts/create/TestEVMCreate.sol b/core/tests/ts-integration/contracts/create/TestEVMCreate.sol deleted file mode 100644 index 176790d14023..000000000000 --- a/core/tests/ts-integration/contracts/create/TestEVMCreate.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -interface IContractDeployer { - function evmCodeHash(address key) external returns (bytes32); - - function createEVM( - bytes calldata _initCode - ) external payable returns (address newAddress); - - function create2EVM( - bytes32 _salt, - bytes calldata _initCode - ) external payable returns (address); -} - -/// @notice An example of a system contract that be used for local testing. -/// @dev It is not used anywhere except for testing -contract TestEVMCreate { - IContractDeployer deployer = IContractDeployer(address(0x8006)); - - function create(bytes calldata _code) external { - deployer.createEVM(_code); - } - - function create2(bytes32 _salt, bytes calldata _code) external payable { - deployer.create2EVM{value:msg.value}(_salt, _code); - } -} diff --git a/core/tests/ts-integration/contracts/token/ERC20.sol b/core/tests/ts-integration/contracts/token/ERC20.sol deleted file mode 100644 index 514e2358624f..000000000000 --- a/core/tests/ts-integration/contracts/token/ERC20.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.0; - -contract ERC20{ - string public symbol; - string public name; - uint8 public decimals; - uint public totalSupply; - - mapping(address => uint) balances; - mapping(address => mapping(address => uint)) allowed; - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); - - constructor() { - symbol = "TEST"; - name = "Test Coin"; - decimals = 18; - totalSupply = 1000000; - balances[msg.sender] = totalSupply; - emit Transfer(address(0), msg.sender, totalSupply); - } - - - function balanceOf(address tokenOwner) public view returns (uint balance) { - return balances[tokenOwner]; - } - - function transfer(address to, uint tokens) public returns (bool success) { - balances[msg.sender] = safeSub(balances[msg.sender], tokens); - balances[to] = safeAdd(balances[to], tokens); - emit Transfer(msg.sender, to, tokens); - return true; - } - - function approve(address spender, uint tokens) public returns (bool success) { - allowed[msg.sender][spender] = tokens; - emit Approval(msg.sender, spender, tokens); - return true; - } - - function transferFrom(address from, address to, uint tokens) public returns (bool success) { - balances[from] = safeSub(balances[from], tokens); - allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens); - balances[to] = safeAdd(balances[to], tokens); - emit Transfer(from, to, tokens); - return true; - } - - function allowance(address tokenOwner, address spender) public view returns (uint remaining) { - return allowed[tokenOwner][spender]; - } - - function safeAdd(uint a, uint b) internal pure returns (uint c) { - c = a + b; - require(c >= a); - } - - function safeSub(uint a, uint b) internal pure returns (uint c) { - require(b <= a); - c = a - b; - } - - function safeMul(uint a, uint b) internal pure returns (uint c) { - c = a * b; - require(a == 0 || c / a == b); - } - - function safeDiv(uint a, uint b) internal pure returns (uint c) { - require(b > 0); - c = a / b; - } - -} diff --git a/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol b/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol deleted file mode 100644 index 91e74bb2b11a..000000000000 --- a/core/tests/ts-integration/contracts/uniswap-v2/UniswapV2Factory.sol +++ /dev/null @@ -1,683 +0,0 @@ -// NOTE: Flattened to make easier to deploy to both native/evm - -// File contracts/uniswap-v2/interfaces/IUniswapV2Factory.sol - -pragma solidity ^0.8.0; - -interface IUniswapV2Factory { - function feeTo() external returns (address); - - function feeToSetter() external returns (address); - - function getPair( - address tokenA, - address tokenB - ) external returns (address pair); - - function allPairs(uint) external returns (address pair); - - function allPairsLength() external returns (uint); - - function createPair( - address tokenA, - address tokenB - ) external returns (address pair); - - function setFeeTo(address) external; - - function setFeeToSetter(address) external; -} - -// File contracts/uniswap-v2/libraries/SafeMath.sol - -pragma solidity ^0.8.0; - -// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) - -library SafeMath { - function add(uint x, uint y) internal pure returns (uint z) { - require((z = x + y) >= x, "ds-math-add-overflow"); - } - - function sub(uint x, uint y) internal pure returns (uint z) { - require((z = x - y) <= x, "ds-math-sub-underflow"); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); - } -} - -// File contracts/uniswap-v2/interfaces/IUniswapV2ERC20.sol - -pragma solidity ^0.8.0; - -interface IUniswapV2ERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external pure returns (string memory); - - function symbol() external pure returns (string memory); - - function decimals() external pure returns (uint8); - - function totalSupply() external returns (uint); - - function balanceOf(address owner) external returns (uint); - - function allowance(address owner, address spender) external returns (uint); - - function approve(address spender, uint value) external returns (bool); - - function transfer(address to, uint value) external returns (bool); - - function transferFrom( - address from, - address to, - uint value - ) external returns (bool); - - function DOMAIN_SEPARATOR() external returns (bytes32); - - function PERMIT_TYPEHASH() external pure returns (bytes32); - - function nonces(address owner) external returns (uint); - - function permit( - address owner, - address spender, - uint value, - uint deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; -} - -// File contracts/uniswap-v2/UniswapV2ERC20.sol - -pragma solidity ^0.8.0; - -contract UniswapV2ERC20 is IUniswapV2ERC20 { - using SafeMath for uint; - - string public override constant name = "Uniswap V2"; - string public override constant symbol = "UNI-V2"; - uint8 public override constant decimals = 18; - uint public override totalSupply; - mapping(address => uint) public override balanceOf; - mapping(address => mapping(address => uint)) public override allowance; - - bytes32 public override DOMAIN_SEPARATOR; - // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 public override constant PERMIT_TYPEHASH = - 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - mapping(address => uint) public override nonces; - - constructor() { - uint chainId; - assembly { - chainId := chainid() - } - DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes(name)), - keccak256(bytes("1")), - chainId, - address(this) - ) - ); - } - - function _mint(address to, uint value) internal { - totalSupply = totalSupply.add(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(address(0), to, value); - } - - function _burn(address from, uint value) internal { - balanceOf[from] = balanceOf[from].sub(value); - totalSupply = totalSupply.sub(value); - emit Transfer(from, address(0), value); - } - - function _approve(address owner, address spender, uint value) private { - allowance[owner][spender] = value; - emit Approval(owner, spender, value); - } - - function _transfer(address from, address to, uint value) private { - balanceOf[from] = balanceOf[from].sub(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(from, to, value); - } - - function approve(address spender, uint value) external override returns (bool) { - _approve(msg.sender, spender, value); - return true; - } - - function transfer(address to, uint value) external override returns (bool) { - _transfer(msg.sender, to, value); - return true; - } - - function transferFrom( - address from, - address to, - uint value - ) external override returns (bool) { - if (allowance[from][msg.sender] != uint(int(-1))) { - allowance[from][msg.sender] = allowance[from][msg.sender].sub( - value - ); - } - _transfer(from, to, value); - return true; - } - - function permit( - address owner, - address spender, - uint value, - uint deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external override { - require(deadline >= block.timestamp, "UniswapV2: EXPIRED"); - bytes32 digest = keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256( - abi.encode( - PERMIT_TYPEHASH, - owner, - spender, - value, - nonces[owner]++, - deadline - ) - ) - ) - ); - address recoveredAddress = ecrecover(digest, v, r, s); - require( - recoveredAddress != address(0) && recoveredAddress == owner, - "UniswapV2: INVALID_SIGNATURE" - ); - _approve(owner, spender, value); - } -} - -// File contracts/uniswap-v2/libraries/Math.sol - -pragma solidity ^0.8.0; - -// a library for performing various math operations - -library Math { - function min(uint x, uint y) internal pure returns (uint z) { - z = x < y ? x : y; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrt(uint y) internal pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - } -} - -// File contracts/uniswap-v2/interfaces/IERC20.sol - -pragma solidity ^0.8.0; - -interface IERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external returns (string memory); - - function symbol() external returns (string memory); - - function decimals() external returns (uint8); - - function totalSupply() external returns (uint); - - function balanceOf(address owner) external returns (uint); - - function allowance(address owner, address spender) external returns (uint); - - function approve(address spender, uint value) external returns (bool); - - function transfer(address to, uint value) external returns (bool); - - function transferFrom( - address from, - address to, - uint value - ) external returns (bool); -} - -// File contracts/uniswap-v2/libraries/UQ112x112.sol - -pragma solidity ^0.8.0; - -// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) - -// range: [0, 2**112 - 1] -// resolution: 1 / 2**112 - -library UQ112x112 { - uint224 constant Q112 = 2 ** 112; - - // encode a uint112 as a UQ112x112 - function encode(uint112 y) internal pure returns (uint224 z) { - z = uint224(y) * Q112; // never overflows - } - - // divide a UQ112x112 by a uint112, returning a UQ112x112 - function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { - z = x / uint224(y); - } -} - -// File contracts/uniswap-v2/interfaces/IUniswapV2Pair.sol - -pragma solidity ^0.8.0; - -interface IUniswapV2Pair { - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn( - address indexed sender, - uint amount0, - uint amount1, - address indexed to - ); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - function MINIMUM_LIQUIDITY() external pure returns (uint); - - function factory() external returns (address); - - function token0() external returns (address); - - function token1() external returns (address); - - function getReserves() - external - returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); - - function price0CumulativeLast() external returns (uint); - - function price1CumulativeLast() external returns (uint); - - function kLast() external returns (uint); - - function mint(address to) external returns (uint liquidity); - - function burn(address to) external returns (uint amount0, uint amount1); - - function swap( - uint amount0Out, - uint amount1Out, - address to, - bytes calldata data - ) external; - - function skim(address to) external; - - function sync() external; - - function initialize(address, address) external; -} - -// File contracts/uniswap-v2/interfaces/IUniswapV2Callee.sol - -pragma solidity ^0.8.0; - -interface IUniswapV2Callee { - function uniswapV2Call( - address sender, - uint amount0, - uint amount1, - bytes calldata data - ) external; -} - -// File contracts/uniswap-v2/UniswapV2Pair.sol - -pragma solidity ^0.8.0; - -contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { - using SafeMath for uint; - using UQ112x112 for uint224; - - uint public override constant MINIMUM_LIQUIDITY = 10 ** 3; - bytes4 private constant SELECTOR = - bytes4(keccak256(bytes("transfer(address,uint256)"))); - - address public override factory; - address public override token0; - address public override token1; - - uint112 private reserve0; // uses single storage slot, accessible via getReserves - uint112 private reserve1; // uses single storage slot, accessible via getReserves - uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves - - uint public override price0CumulativeLast; - uint public override price1CumulativeLast; - uint public override kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event - - uint private unlocked = 1; - modifier lock() { - require(unlocked == 1, "UniswapV2: LOCKED"); - unlocked = 0; - _; - unlocked = 1; - } - - function getReserves() - public - override - returns ( - uint112 _reserve0, - uint112 _reserve1, - uint32 _blockTimestampLast - ) - { - _reserve0 = reserve0; - _reserve1 = reserve1; - _blockTimestampLast = blockTimestampLast; - } - - function _safeTransfer(address token, address to, uint value) private { - IERC20(token).transfer(to, value); - } - - constructor() public { - factory = msg.sender; - } - - // called once by the factory at time of deployment - function initialize(address _token0, address _token1) external override { - require(msg.sender == factory, "UniswapV2: FORBIDDEN"); // sufficient check - token0 = _token0; - token1 = _token1; - } - - // update reserves and, on the first call per block, price accumulators - function _update( - uint balance0, - uint balance1, - uint112 _reserve0, - uint112 _reserve1 - ) private { - require( - balance0 <= uint112(int112(-1)) && balance1 <= uint112(int112(-1)), - "UniswapV2: OVERFLOW" - ); - uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32); - uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired - if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { - // * never overflows, and + overflow is desired - price0CumulativeLast += - uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * - timeElapsed; - price1CumulativeLast += - uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * - timeElapsed; - } - reserve0 = uint112(balance0); - reserve1 = uint112(balance1); - blockTimestampLast = blockTimestamp; - emit Sync(reserve0, reserve1); - } - - // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) - function _mintFee( - uint112 _reserve0, - uint112 _reserve1 - ) private returns (bool feeOn) { - address feeTo = IUniswapV2Factory(factory).feeTo(); - feeOn = feeTo != address(0); - uint _kLast = kLast; // gas savings - if (feeOn) { - if (_kLast != 0) { - uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); - uint rootKLast = Math.sqrt(_kLast); - if (rootK > rootKLast) { - uint numerator = totalSupply.mul(rootK.sub(rootKLast)); - uint denominator = rootK.mul(5).add(rootKLast); - uint liquidity = numerator / denominator; - if (liquidity > 0) _mint(feeTo, liquidity); - } - } - } else if (_kLast != 0) { - kLast = 0; - } - } - - // this low-level function should be called from a contract which performs important safety checks - function mint(address to) external override lock returns (uint liquidity) { - (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - uint balance0 = IERC20(token0).balanceOf(address(this)); - uint balance1 = IERC20(token1).balanceOf(address(this)); - uint amount0 = balance0.sub(_reserve0); - uint amount1 = balance1.sub(_reserve1); - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - if (_totalSupply == 0) { - liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); - _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens - } else { - liquidity = Math.min( - amount0.mul(_totalSupply) / _reserve0, - amount1.mul(_totalSupply) / _reserve1 - ); - } - require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED"); - _mint(to, liquidity); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Mint(msg.sender, amount0, amount1); - } - - // this low-level function should be called from a contract which performs important safety checks - function burn( - address to - ) external override lock returns (uint amount0, uint amount1) { - (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - uint balance0 = IERC20(_token0).balanceOf(address(this)); - uint balance1 = IERC20(_token1).balanceOf(address(this)); - uint liquidity = balanceOf[address(this)]; - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution - amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution - require( - amount0 > 0 && amount1 > 0, - "UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED" - ); - _burn(address(this), liquidity); - _safeTransfer(_token0, to, amount0); - _safeTransfer(_token1, to, amount1); - balance0 = IERC20(_token0).balanceOf(address(this)); - balance1 = IERC20(_token1).balanceOf(address(this)); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Burn(msg.sender, amount0, amount1, to); - } - - // this low-level function should be called from a contract which performs important safety checks - function swap( - uint amount0Out, - uint amount1Out, - address to, - bytes calldata data - ) external override lock { - // require( - // amount0Out > 0 || amount1Out > 0, - // "UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT" - // ); - // (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings - // require( - // amount0Out < _reserve0 && amount1Out < _reserve1, - // "UniswapV2: INSUFFICIENT_LIQUIDITY" - // ); - - // uint balance0; - // uint balance1; - // { - // // scope for _token{0,1}, avoids stack too deep errors - // address _token0 = token0; - // address _token1 = token1; - // require(to != _token0 && to != _token1, "UniswapV2: INVALID_TO"); - // if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens - // if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens - // if (data.length > 0) - // IUniswapV2Callee(to).uniswapV2Call( - // msg.sender, - // amount0Out, - // amount1Out, - // data - // ); - // balance0 = IERC20(_token0).balanceOf(address(this)); - // balance1 = IERC20(_token1).balanceOf(address(this)); - // } - // uint amount0In = balance0 > _reserve0 - amount0Out - // ? balance0 - (_reserve0 - amount0Out) - // : 0; - // uint amount1In = balance1 > _reserve1 - amount1Out - // ? balance1 - (_reserve1 - amount1Out) - // : 0; - // require( - // amount0In > 0 || amount1In > 0, - // "UniswapV2: INSUFFICIENT_INPUT_AMOUNT" - // ); - // { - // // scope for reserve{0,1}Adjusted, avoids stack too deep errors - // uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); - // uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); - // require( - // balance0Adjusted.mul(balance1Adjusted) >= - // uint(_reserve0).mul(_reserve1).mul(1000 ** 2), - // "UniswapV2: K" - // ); - // } - - // _update(balance0, balance1, _reserve0, _reserve1); - // emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); - } - - // force balances to match reserves - function skim(address to) external override lock { - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - _safeTransfer( - _token0, - to, - IERC20(_token0).balanceOf(address(this)).sub(reserve0) - ); - _safeTransfer( - _token1, - to, - IERC20(_token1).balanceOf(address(this)).sub(reserve1) - ); - } - - // force reserves to match balances - function sync() external override lock { - _update( - IERC20(token0).balanceOf(address(this)), - IERC20(token1).balanceOf(address(this)), - reserve0, - reserve1 - ); - } -} - -// File contracts/uniswap-v2/UniswapV2Factory.sol - -pragma solidity ^0.8.0; - -contract UniswapV2Factory is IUniswapV2Factory { - address public override feeTo; - address public override feeToSetter; - - mapping(address => mapping(address => address)) public override getPair; - address[] public override allPairs; - - event PairCreated( - address indexed token0, - address indexed token1, - address pair, - uint - ); - - constructor(address _feeToSetter) public { - feeToSetter = _feeToSetter; - } - - function allPairsLength() external override returns (uint) { - return allPairs.length; - } - - function createPair( - address tokenA, - address tokenB - ) external override returns (address pair) { - require(tokenA != tokenB, "UniswapV2: IDENTICAL_ADDRESSES"); - (address token0, address token1) = tokenA < tokenB - ? (tokenA, tokenB) - : (tokenB, tokenA); - require(token0 != address(0), "UniswapV2: ZERO_ADDRESS"); - require( - getPair[token0][token1] == address(0), - "UniswapV2: PAIR_EXISTS" - ); // single check is sufficient - pair = address(new UniswapV2Pair()); - IUniswapV2Pair(pair).initialize(token0, token1); - getPair[token0][token1] = pair; - getPair[token1][token0] = pair; // populate mapping in the reverse direction - allPairs.push(pair); - emit PairCreated(token0, token1, pair, allPairs.length); - } - - function setFeeTo(address _feeTo) external override { - require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); - feeTo = _feeTo; - } - - function setFeeToSetter(address _feeToSetter) external override { - require(msg.sender == feeToSetter, "UniswapV2: FORBIDDEN"); - feeToSetter = _feeToSetter; - } -} diff --git a/core/tests/ts-integration/package.json b/core/tests/ts-integration/package.json index 6196355e95a0..8e5c0cf7470e 100644 --- a/core/tests/ts-integration/package.json +++ b/core/tests/ts-integration/package.json @@ -33,10 +33,6 @@ "typescript": "^4.3.5", "zksync-ethers": "^6.9.0", "elliptic": "^6.5.5", - "yaml": "^2.4.2", - "zksync-web3": "^0.15.5", - "csv-parser": "^3.0.0", - "csv-writer": "^1.6.0", - "solc": "0.8.20" + "yaml": "^2.4.2" } } diff --git a/core/tests/ts-integration/src/helpers.ts b/core/tests/ts-integration/src/helpers.ts index 327a4912a6c0..8e31c1a691ff 100644 --- a/core/tests/ts-integration/src/helpers.ts +++ b/core/tests/ts-integration/src/helpers.ts @@ -4,8 +4,6 @@ import * as ethers from 'ethers'; import * as hre from 'hardhat'; import { ZkSyncArtifact } from '@matterlabs/hardhat-zksync-solc/dist/src/types'; -const solc = require('solc'); - export const SYSTEM_CONTEXT_ADDRESS = '0x000000000000000000000000000000000000800b'; /** @@ -143,48 +141,3 @@ export function bigIntMax(...args: bigint[]) { return args.reduce((max, current) => (current > max ? current : max), args[0]); } - -/** Compiles and returns artifacts for a Solidity (EVM) contract - * - * @param contractPath The path of the contract relative to the contracts directory - * @param args Constructor arguments for the contract - * @returns The transaction data for the contract deployment - */ -export function getEVMArtifact(contractPath: string, contractName: string | undefined = undefined): any { - const compilerParams = { - language: 'Solidity', - sources: { - contract: { - content: getContractSource(contractPath) - } - }, - settings: { - outputSelection: { - '*': { - '*': ['*'] - } - } - } - } as any; - if (contractName === undefined) { - const splitPath = contractPath.split('/'); - contractName = splitPath[splitPath.length - 1]; - } - - const artifact = JSON.parse(solc.compile(JSON.stringify(compilerParams))).contracts['contract'][ - contractName.split('.')[0] - ]; - - return artifact; -} - -/** Gets the deployment transaction data for a given contract path and parameters - * - * @param initiator Wallet that should be used - * @param contractPath The path of the contract relative to the contracts directory - * @param args Constructor arguments for the contract - * @returns The transaction data for the contract deployment - */ -export function getEVMContractFactory(initiator: zksync.Wallet, artifact: any): ethers.ContractFactory { - return new ethers.ContractFactory(artifact.abi, '0x' + artifact.evm.bytecode.object, initiator); -} From ed97d2415558c1f27c07d5ab494cfafa2cf8427f Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 19 Sep 2024 13:24:38 -0300 Subject: [PATCH 22/72] Fix fmt --- docs/guides/external-node/00_quick_start.md | 4 ++-- prover/crates/lib/prover_dal/src/fri_prover_dal.rs | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/guides/external-node/00_quick_start.md b/docs/guides/external-node/00_quick_start.md index 776e8a56e497..5eb601e3d590 100644 --- a/docs/guides/external-node/00_quick_start.md +++ b/docs/guides/external-node/00_quick_start.md @@ -65,8 +65,8 @@ The HTTP JSON-RPC API can be accessed on port `3060` and WebSocket API can be ac > [!NOTE] > -> To stop historical DB growth, you can enable DB pruning by uncommenting `EN_PRUNING_ENABLED: true` in docker compose file, -> you can read more about pruning in +> To stop historical DB growth, you can enable DB pruning by uncommenting `EN_PRUNING_ENABLED: true` in docker compose +> file, you can read more about pruning in > [08_pruning.md](https://github.com/matter-labs/zksync-era/blob/main/docs/guides/external-node/08_pruning.md) - 32 GB of RAM and a relatively modern CPU diff --git a/prover/crates/lib/prover_dal/src/fri_prover_dal.rs b/prover/crates/lib/prover_dal/src/fri_prover_dal.rs index 1b6c43f4c177..0c6ced8d169a 100644 --- a/prover/crates/lib/prover_dal/src/fri_prover_dal.rs +++ b/prover/crates/lib/prover_dal/src/fri_prover_dal.rs @@ -456,8 +456,14 @@ impl FriProverDal<'_, '_> { SELECT protocol_version AS "protocol_version!", protocol_version_patch AS "protocol_version_patch!", - COUNT(*) FILTER (WHERE status = 'queued') as queued, - COUNT(*) FILTER (WHERE status = 'in_progress') as in_progress + COUNT(*) FILTER ( + WHERE + status = 'queued' + ) AS queued, + COUNT(*) FILTER ( + WHERE + status = 'in_progress' + ) AS in_progress FROM prover_jobs_fri WHERE From f92206890e760f8841de2431feb8e036959988d5 Mon Sep 17 00:00:00 2001 From: Nacho Avecilla Date: Thu, 19 Sep 2024 13:29:24 -0300 Subject: [PATCH 23/72] feat: EVM simulator as optional for the server (#276) * Add evm simulator as optional for the server * Changes to make it work against era-contracts `main` * fmt * Calculate bytecode of evm gas manager only if evm simulator flag is on * Add multicall for get evm simulator bytecode hash * Use bytecode of default account for the evm simulator if not present * Remove unnecessary comments * Use bytecode of default account for evm simulator in gas test sc * Remove tests for the evm simulator --------- Co-authored-by: Javier Chatruc --- Cargo.lock | 6 + contracts | 2 +- .../bin/system-constants-generator/Cargo.toml | 2 + .../system-constants-generator/src/utils.rs | 27 +- core/lib/config/src/configs/mod.rs | 1 + .../config/src/configs/use_evm_simulator.rs | 7 + core/lib/contracts/src/lib.rs | 22 +- core/lib/env_config/src/lib.rs | 1 + core/lib/env_config/src/use_evm_simulator.rs | 9 + core/lib/multivm/Cargo.toml | 2 + .../vm_latest/tracers/default_tracers.rs | 26 +- core/lib/types/Cargo.toml | 1 + core/lib/types/src/system_contracts.rs | 54 +++- core/node/eth_sender/Cargo.toml | 1 + core/node/eth_sender/src/eth_tx_aggregator.rs | 72 +++-- core/node/eth_sender/src/zksync_functions.rs | 4 +- etc/env/base/chain.toml | 6 +- etc/env/base/contracts.toml | 6 +- etc/env/base/use_evm_simulator.toml | 2 + prover/Cargo.lock | 269 ++++++++++++++++++ 20 files changed, 460 insertions(+), 60 deletions(-) create mode 100644 core/lib/config/src/configs/use_evm_simulator.rs create mode 100644 core/lib/env_config/src/use_evm_simulator.rs create mode 100644 etc/env/base/use_evm_simulator.toml diff --git a/Cargo.lock b/Cargo.lock index 68e8b2770607..a6c3689c8a4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7494,7 +7494,9 @@ dependencies = [ "once_cell", "serde", "serde_json", + "zksync_config", "zksync_contracts", + "zksync_env_config", "zksync_multivm", "zksync_types", "zksync_utils", @@ -9813,6 +9815,7 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_dal", + "zksync_env_config", "zksync_eth_client", "zksync_l1_contract_interface", "zksync_node_fee_model", @@ -10159,7 +10162,9 @@ dependencies = [ "zk_evm 0.140.0", "zk_evm 0.141.0", "zk_evm 0.150.5", + "zksync_config", "zksync_contracts", + "zksync_env_config", "zksync_eth_signer", "zksync_state", "zksync_system_constants", @@ -10910,6 +10915,7 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_crypto_primitives", + "zksync_env_config", "zksync_mini_merkle_tree", "zksync_protobuf", "zksync_protobuf_build", diff --git a/contracts b/contracts index 2edbd6912c6a..bce4b2d0f34b 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 2edbd6912c6a73b120377f5e53fe1cc5343407fc +Subproject commit bce4b2d0f34bd87f1aaadd291772935afb1c3bd6 diff --git a/core/bin/system-constants-generator/Cargo.toml b/core/bin/system-constants-generator/Cargo.toml index 7177d29ca743..39f4b458817d 100644 --- a/core/bin/system-constants-generator/Cargo.toml +++ b/core/bin/system-constants-generator/Cargo.toml @@ -15,6 +15,8 @@ zksync_types.workspace = true zksync_utils.workspace = true zksync_contracts.workspace = true zksync_multivm.workspace = true +zksync_config.workspace = true +zksync_env_config.workspace = true codegen.workspace = true serde.workspace = true diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 32b4d04506d1..ac4d66185e33 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -1,10 +1,12 @@ -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, rc::Rc, str::FromStr}; use once_cell::sync::Lazy; +use zksync_config::configs::use_evm_simulator; use zksync_contracts::{ load_sys_contract, read_bootloader_code, read_bytecode_from_path, read_sys_contract_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, }; +use zksync_env_config::FromEnv; use zksync_multivm::{ interface::{ storage::{InMemoryStorage, StorageView, WriteStorage}, @@ -24,8 +26,9 @@ use zksync_types::{ block::L2BlockHasher, ethabi::Token, fee::Fee, fee_model::BatchFeeInput, l1::L1Tx, l2::L2Tx, utils::storage_key_for_eth_balance, AccountTreeId, Address, Execute, K256PrivateKey, L1BatchNumber, L1TxCommonData, L2BlockNumber, L2ChainId, Nonce, ProtocolVersionId, StorageKey, - Transaction, BOOTLOADER_ADDRESS, SYSTEM_CONTEXT_ADDRESS, SYSTEM_CONTEXT_GAS_PRICE_POSITION, - SYSTEM_CONTEXT_TX_ORIGIN_POSITION, U256, ZKPORTER_IS_AVAILABLE, + Transaction, BOOTLOADER_ADDRESS, H256, SYSTEM_CONTEXT_ADDRESS, + SYSTEM_CONTEXT_GAS_PRICE_POSITION, SYSTEM_CONTEXT_TX_ORIGIN_POSITION, U256, + ZKPORTER_IS_AVAILABLE, }; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, u256_to_h256}; @@ -71,9 +74,21 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + + let mut evm_simulator_bytecode = bytecode.clone(); + let mut evm_simulator_hash = + H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") + .unwrap(); + + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode.clone()); + } + BaseSystemContracts { default_aa: SystemContractCode { code: bytes_to_be_words(bytecode), diff --git a/core/lib/config/src/configs/mod.rs b/core/lib/config/src/configs/mod.rs index 1ad503e0687f..456749e05a5e 100644 --- a/core/lib/config/src/configs/mod.rs +++ b/core/lib/config/src/configs/mod.rs @@ -65,6 +65,7 @@ pub mod pruning; pub mod secrets; pub mod snapshot_recovery; pub mod snapshots_creator; +pub mod use_evm_simulator; pub mod utils; pub mod vm_runner; pub mod wallets; diff --git a/core/lib/config/src/configs/use_evm_simulator.rs b/core/lib/config/src/configs/use_evm_simulator.rs new file mode 100644 index 000000000000..76113613a17d --- /dev/null +++ b/core/lib/config/src/configs/use_evm_simulator.rs @@ -0,0 +1,7 @@ +use serde::Deserialize; + +/// Configuration for the use evm simulator +#[derive(Debug, Deserialize, Clone, PartialEq)] +pub struct UseEvmSimulator { + pub use_evm_simulator: bool, +} diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 0d3a2a853f0d..5f86f546c767 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -8,6 +8,7 @@ use std::{ fs::{self, File}, io::BufReader, path::{Path, PathBuf}, + str::FromStr, }; use ethabi::{ @@ -16,6 +17,8 @@ use ethabi::{ }; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use zksync_config::configs::use_evm_simulator::{self}; +use zksync_env_config::FromEnv; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, env::Workspace}; pub mod test_contracts; @@ -338,13 +341,24 @@ impl BaseSystemContracts { let hash = hash_bytecode(&bytecode); let default_aa = SystemContractCode { - code: bytes_to_be_words(bytecode), + code: bytes_to_be_words(bytecode.clone()), hash, }; - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + // If evm simulator is not enabled, use the default account bytecode and hash. + let mut evm_simulator_bytecode = bytecode; + let mut evm_simulator_hash = + H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") + .unwrap(); + + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + } let evm_simulator = SystemContractCode { code: bytes_to_be_words(evm_simulator_bytecode), diff --git a/core/lib/env_config/src/lib.rs b/core/lib/env_config/src/lib.rs index b72c2c5d5b94..701817522d37 100644 --- a/core/lib/env_config/src/lib.rs +++ b/core/lib/env_config/src/lib.rs @@ -29,6 +29,7 @@ mod genesis; mod prover_job_monitor; #[cfg(test)] mod test_utils; +mod use_evm_simulator; mod vm_runner; mod wallets; diff --git a/core/lib/env_config/src/use_evm_simulator.rs b/core/lib/env_config/src/use_evm_simulator.rs new file mode 100644 index 000000000000..c2a58387e62f --- /dev/null +++ b/core/lib/env_config/src/use_evm_simulator.rs @@ -0,0 +1,9 @@ +use zksync_config::configs::use_evm_simulator::UseEvmSimulator; + +use crate::{envy_load, FromEnv}; + +impl FromEnv for UseEvmSimulator { + fn from_env() -> anyhow::Result { + envy_load("use_evm_simulator", "USE_EVM_SIMULATOR_") + } +} diff --git a/core/lib/multivm/Cargo.toml b/core/lib/multivm/Cargo.toml index 6156c1138890..86e19637b2b6 100644 --- a/core/lib/multivm/Cargo.toml +++ b/core/lib/multivm/Cargo.toml @@ -25,6 +25,8 @@ circuit_sequencer_api_1_4_2.workspace = true circuit_sequencer_api_1_5_0.workspace = true zksync_types.workspace = true +zksync_config.workspace = true +zksync_env_config.workspace = true zksync_contracts.workspace = true zksync_utils.workspace = true zksync_system_constants.workspace = true diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index f7def2a66106..5b61b5174e19 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -12,6 +12,8 @@ use zk_evm_1_5_0::{ witness_trace::DummyTracer, zkevm_opcode_defs::{decoding::EncodingModeProduction, Opcode, RetOpcode}, }; +use zksync_config::configs::use_evm_simulator::{self}; +use zksync_env_config::FromEnv; use super::{EvmDeployTracer, PubdataTracer}; use crate::{ @@ -64,7 +66,7 @@ pub struct DefaultExecutionTracer { // take into account e.g circuits produced by the initial bootloader memory commitment. pub(crate) circuits_tracer: CircuitsTracer, // This tracer is responsible for handling EVM deployments and providing the data to the code decommitter. - pub(crate) evm_deploy_tracer: EvmDeployTracer, + pub(crate) evm_deploy_tracer: Option>, subversion: MultiVMSubversion, storage: StoragePtr, _phantom: PhantomData, @@ -80,6 +82,9 @@ impl DefaultExecutionTracer { pubdata_tracer: Option>, subversion: MultiVMSubversion, ) -> Self { + let active_evm = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; Self { tx_has_been_processed: false, execution_mode, @@ -94,7 +99,11 @@ impl DefaultExecutionTracer { pubdata_tracer, ret_from_the_bootloader: None, circuits_tracer: CircuitsTracer::new(), - evm_deploy_tracer: EvmDeployTracer::new(), + evm_deploy_tracer: if active_evm { + Some(EvmDeployTracer::new()) + } else { + None + }, storage, _phantom: PhantomData, } @@ -175,7 +184,9 @@ macro_rules! dispatch_tracers { tracer.$function($( $params ),*); } $self.circuits_tracer.$function($( $params ),*); - $self.evm_deploy_tracer.$function($( $params ),*); + if let Some(tracer) = &mut $self.evm_deploy_tracer { + tracer.$function($( $params ),*); + } }; } @@ -293,10 +304,11 @@ impl DefaultExecutionTracer { .finish_cycle(state, bootloader_state) .stricter(&result); - result = self - .evm_deploy_tracer - .finish_cycle(state, bootloader_state) - .stricter(&result); + if let Some(evm_deploy_tracer) = &mut self.evm_deploy_tracer { + result = evm_deploy_tracer + .finish_cycle(state, bootloader_state) + .stricter(&result); + } result.stricter(&self.should_stop_execution()) } diff --git a/core/lib/types/Cargo.toml b/core/lib/types/Cargo.toml index 54c38384a7ad..f976c26b71c1 100644 --- a/core/lib/types/Cargo.toml +++ b/core/lib/types/Cargo.toml @@ -17,6 +17,7 @@ zksync_basic_types.workspace = true zksync_contracts.workspace = true zksync_mini_merkle_tree.workspace = true zksync_config.workspace = true +zksync_env_config.workspace = true zksync_protobuf.workspace = true zksync_crypto_primitives.workspace = true diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 57ca0150f7f4..f88e24e21ca7 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -1,8 +1,10 @@ -use std::path::PathBuf; +use std::{path::PathBuf, str::FromStr}; use once_cell::sync::Lazy; use zksync_basic_types::{AccountTreeId, Address, H256, U256}; +use zksync_config::configs::use_evm_simulator; use zksync_contracts::{read_sys_contract_bytecode, ContractLanguage, SystemContractsRepo}; +use zksync_env_config::FromEnv; use zksync_system_constants::{ BOOTLOADER_UTILITIES_ADDRESS, CODE_ORACLE_ADDRESS, COMPRESSOR_ADDRESS, CREATE2_FACTORY_ADDRESS, EVENT_WRITER_ADDRESS, EVM_GAS_MANAGER_ADDRESS, P256VERIFY_PRECOMPILE_ADDRESS, @@ -179,11 +181,19 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 26] = [ ]; static EVM_SIMULATOR_HASH: Lazy = Lazy::new(|| { - hash_bytecode(&read_sys_contract_bytecode( - "", - "EvmInterpreter", - ContractLanguage::Yul, - )) + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + hash_bytecode(&read_sys_contract_bytecode( + "", + "EvmInterpreter", + ContractLanguage::Yul, + )) + } else { + H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") + .unwrap() + } }); pub fn get_evm_simulator_hash() -> H256 { @@ -191,11 +201,21 @@ pub fn get_evm_simulator_hash() -> H256 { } static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { + let evm_simulator_is_used = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; SYSTEM_CONTRACT_LIST .iter() - .map(|(path, name, address, contract_lang)| DeployedContract { - account_id: AccountTreeId::new(*address), - bytecode: read_sys_contract_bytecode(path, name, contract_lang.clone()), + .filter_map(|(path, name, address, contract_lang)| { + let result = if *name == "EvmGasManager" && !evm_simulator_is_used { + None + } else { + Some(DeployedContract { + account_id: AccountTreeId::new(*address), + bytecode: read_sys_contract_bytecode(path, name, contract_lang.clone()), + }) + }; + result }) .collect::>() }); @@ -207,12 +227,22 @@ pub fn get_system_smart_contracts() -> Vec { /// Loads system contracts from a given directory. pub fn get_system_smart_contracts_from_dir(path: PathBuf) -> Vec { + let evm_simulator_is_used = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; let repo = SystemContractsRepo { root: path }; SYSTEM_CONTRACT_LIST .iter() - .map(|(path, name, address, contract_lang)| DeployedContract { - account_id: AccountTreeId::new(*address), - bytecode: repo.read_sys_contract_bytecode(path, name, contract_lang.clone()), + .filter_map(|(path, name, address, contract_lang)| { + let result = if *name == "EvmGasManager" && !evm_simulator_is_used { + None + } else { + Some(DeployedContract { + account_id: AccountTreeId::new(*address), + bytecode: repo.read_sys_contract_bytecode(path, name, contract_lang.clone()), + }) + }; + result }) .collect::>() } diff --git a/core/node/eth_sender/Cargo.toml b/core/node/eth_sender/Cargo.toml index a7aa88c3550e..d58c7488262d 100644 --- a/core/node/eth_sender/Cargo.toml +++ b/core/node/eth_sender/Cargo.toml @@ -15,6 +15,7 @@ vise.workspace = true zksync_types.workspace = true zksync_dal.workspace = true zksync_config.workspace = true +zksync_env_config.workspace = true zksync_contracts.workspace = true zksync_eth_client.workspace = true zksync_utils.workspace = true diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index f07cecb0dfa4..49a108231b2a 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -1,7 +1,13 @@ +use std::str::FromStr; + use tokio::sync::watch; -use zksync_config::configs::eth_sender::SenderConfig; +use zksync_config::configs::{ + eth_sender::SenderConfig, + use_evm_simulator::{self}, +}; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; +use zksync_env_config::FromEnv; use zksync_eth_client::{BoundEthInterface, CallFunctionArgs}; use zksync_l1_contract_interface::{ i_executor::{ @@ -186,12 +192,17 @@ impl EthTxAggregator { let get_l2_evm_simulator_hash_input = self .functions .get_evm_simulator_bytecode_hash - .encode_input(&[]) - .unwrap(); - let get_evm_simulator_hash_call = Multicall3Call { - target: self.state_transition_chain_contract, - allow_failure: ALLOW_FAILURE, - calldata: get_l2_evm_simulator_hash_input, + .as_ref() + .and_then(|f| f.encode_input(&[]).ok()); + + let get_evm_simulator_hash_call = if let Some(input) = get_l2_evm_simulator_hash_input { + Some(Multicall3Call { + target: self.state_transition_chain_contract, + allow_failure: ALLOW_FAILURE, + calldata: input, + }) + } else { + None }; // Third zksync contract call @@ -226,15 +237,19 @@ impl EthTxAggregator { calldata: get_protocol_version_input, }; - // Convert structs into tokens and return vector with them - vec![ + let mut token_vec = vec![ get_bootloader_hash_call.into_token(), get_default_aa_hash_call.into_token(), - get_evm_simulator_hash_call.into_token(), get_verifier_params_call.into_token(), get_verifier_call.into_token(), get_protocol_version_call.into_token(), - ] + ]; + + if let Some(call) = get_evm_simulator_hash_call { + token_vec.push(call.into_token()); + } + + token_vec } // The role of the method below is to de-tokenize multicall call's result, which is actually a token. @@ -250,8 +265,12 @@ impl EthTxAggregator { }; if let Token::Array(call_results) = token { + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; + let number_of_calls = if use_evm_simulator { 6 } else { 5 }; // 5 calls are aggregated in multicall - if call_results.len() != 6 { + if call_results.len() != number_of_calls { return parse_error(&call_results); } let mut call_results_iterator = call_results.into_iter(); @@ -280,17 +299,26 @@ impl EthTxAggregator { ))); } let default_aa = H256::from_slice(&multicall3_default_aa); - let multicall3_evm_simulator = - Multicall3Result::from_token(call_results_iterator.next().unwrap())?.return_data; - if multicall3_evm_simulator.len() != 32 { - return Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( - format!( - "multicall3 evm simulator hash data is not of the len of 32: {:?}", - multicall3_evm_simulator - ), - ))); + + let mut evm_simulator = H256::from_str( + "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32", + ) + .unwrap(); + + if use_evm_simulator { + let multicall3_evm_simulator = + Multicall3Result::from_token(call_results_iterator.next().unwrap())? + .return_data; + if multicall3_evm_simulator.len() != 32 { + return Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( + format!( + "multicall3 evm simulator hash data is not of the len of 32: {:?}", + multicall3_evm_simulator + ), + ))); + } + evm_simulator = H256::from_slice(&multicall3_evm_simulator); } - let evm_simulator = H256::from_slice(&multicall3_evm_simulator); let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader, diff --git a/core/node/eth_sender/src/zksync_functions.rs b/core/node/eth_sender/src/zksync_functions.rs index 577c18277da0..6779ac24836c 100644 --- a/core/node/eth_sender/src/zksync_functions.rs +++ b/core/node/eth_sender/src/zksync_functions.rs @@ -12,7 +12,7 @@ pub(super) struct ZkSyncFunctions { pub(super) get_l2_bootloader_bytecode_hash: Function, pub(super) get_l2_default_account_bytecode_hash: Function, pub(super) get_verifier: Function, - pub(super) get_evm_simulator_bytecode_hash: Function, + pub(super) get_evm_simulator_bytecode_hash: Option, pub(super) get_verifier_params: Function, pub(super) get_protocol_version: Function, @@ -61,7 +61,7 @@ impl Default for ZkSyncFunctions { let get_l2_default_account_bytecode_hash = get_function(&zksync_contract, "getL2DefaultAccountBytecodeHash"); let get_evm_simulator_bytecode_hash = - get_function(&zksync_contract, "getL2EvmSimulatorBytecodeHash"); + get_optional_function(&zksync_contract, "getL2EvmSimulatorBytecodeHash"); let get_verifier = get_function(&zksync_contract, "getVerifier"); let get_verifier_params = get_function(&zksync_contract, "getVerifierParams"); let get_protocol_version = get_function(&zksync_contract, "getProtocolVersion"); diff --git a/etc/env/base/chain.toml b/etc/env/base/chain.toml index 5bdb08e3f952..15b14c9f2cc1 100644 --- a/etc/env/base/chain.toml +++ b/etc/env/base/chain.toml @@ -90,9 +90,9 @@ fee_model_version = "V2" validation_computational_gas_limit = 300000 save_call_traces = true -bootloader_hash = "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1" -default_aa_hash = "0x0100058de8a8fda78449f14bece247271bdbba5dc73fc96135c35a17ee4dd090" -evm_simulator_hash = "0x01000cdf5bb7dd8a97faf231a5e1e20f2fe308d6f200c3295c6e3629547cc4a4" +bootloader_hash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e" +default_aa_hash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32" +evm_simulator_hash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32" protective_reads_persistence_enabled = false diff --git a/etc/env/base/contracts.toml b/etc/env/base/contracts.toml index 69bcbf6dabec..daa317a8bc90 100644 --- a/etc/env/base/contracts.toml +++ b/etc/env/base/contracts.toml @@ -26,11 +26,11 @@ RECURSION_NODE_LEVEL_VK_HASH = "0x1186ec268d49f1905f8d9c1e9d39fc33e98c74f91d91a2 RECURSION_LEAF_LEVEL_VK_HASH = "0x101e08b00193e529145ee09823378ef51a3bc8966504064f1f6ba3f1ba863210" RECURSION_CIRCUITS_SET_VKS_HASH = "0x18c1639094f58177409186e8c48d9f577c9410901d2f1d486b3e7d6cf553ae4c" GENESIS_TX_HASH = "0xb99ebfea46cbe05a21cd80fe5597d97b204befc52a16303f579c607dc1ac2e2e" -GENESIS_ROOT = "0x79679719d4932b95d89e1ad1faeccb4982bed5ca79f738d3d72d3cfcea6f3722" -GENESIS_BATCH_COMMITMENT = "0xb793269d781342f2980720a9da3009d91cfebb5187977b69807fea8444c5cb2f" +GENESIS_ROOT = "0xabdb766b18a479a5c783a4b80e12686bc8ea3cc2d8a3050491b701d72370ebb5" +GENESIS_BATCH_COMMITMENT = "0x2d00e5f8d77afcebf58a6b82ae56ba967566fe7dfbcb6760319fb0d215d18ffd" PRIORITY_TX_MAX_GAS_LIMIT = 72000000 DEPLOY_L2_BRIDGE_COUNTERPART_GAS_LIMIT = 10000000 -GENESIS_ROLLUP_LEAF_INDEX = "56" +GENESIS_ROLLUP_LEAF_INDEX = "54" GENESIS_PROTOCOL_VERSION = "24" GENESIS_PROTOCOL_SEMANTIC_VERSION = "0.24.2" L1_WETH_BRIDGE_IMPL_ADDR = "0x5E6D086F5eC079ADFF4FB3774CDf3e8D6a34F7E9" diff --git a/etc/env/base/use_evm_simulator.toml b/etc/env/base/use_evm_simulator.toml new file mode 100644 index 000000000000..0db670361f16 --- /dev/null +++ b/etc/env/base/use_evm_simulator.toml @@ -0,0 +1,2 @@ +[use_evm_simulator] +use_evm_simulator = false diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 5624403d7853..57d160560b0d 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -355,6 +355,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "backon" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" +dependencies = [ + "fastrand", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" version = "0.3.72" @@ -460,6 +472,27 @@ dependencies = [ "which", ] +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "prettyplease", + "proc-macro2 1.0.85", + "quote 1.0.36", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.66", +] + [[package]] name = "bindgen" version = "0.69.4" @@ -731,6 +764,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytecount" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" + [[package]] name = "byteorder" version = "1.5.0" @@ -743,6 +782,48 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.1.14" @@ -1360,6 +1441,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "debugid" version = "0.8.0" @@ -1718,6 +1812,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "etcetera" version = "0.8.0" @@ -3064,6 +3167,22 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "librocksdb-sys" +version = "0.11.0+8.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +dependencies = [ + "bindgen 0.65.1", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -3075,6 +3194,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -3141,6 +3271,16 @@ dependencies = [ "logos-codegen", ] +[[package]] +name = "lz4-sys" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb44a01837a858d47e5a630d2ccf304c8efcc4b83b8f9f75b7a9ee4fcc6e57d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -3223,6 +3363,21 @@ dependencies = [ "unicase", ] +[[package]] +name = "mini-moka" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" +dependencies = [ + "crossbeam-channel", + "crossbeam-utils", + "dashmap", + "skeptic", + "smallvec", + "tagptr", + "triomphe", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4282,6 +4437,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.6.0", + "memchr", + "unicase", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4690,6 +4856,16 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rocksdb" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +dependencies = [ + "libc", + "librocksdb-sys", +] + [[package]] name = "rsa" version = "0.9.6" @@ -4997,6 +5173,9 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "send_wrapper" @@ -5385,6 +5564,21 @@ dependencies = [ "time", ] +[[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + [[package]] name = "slab" version = "0.4.9" @@ -5864,6 +6058,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -6313,6 +6513,12 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "triomphe" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" + [[package]] name = "try-lock" version = "0.2.5" @@ -7485,6 +7691,8 @@ dependencies = [ "once_cell", "serde", "serde_json", + "zksync_config", + "zksync_env_config", "zksync_utils", ] @@ -7681,6 +7889,7 @@ dependencies = [ "circuit_sequencer_api 0.141.2", "circuit_sequencer_api 0.142.2", "circuit_sequencer_api 0.150.5", + "ethabi", "hex", "itertools 0.10.5", "once_cell", @@ -7693,7 +7902,10 @@ dependencies = [ "zk_evm 0.140.0", "zk_evm 0.141.0", "zk_evm 0.150.5", + "zksync_config", "zksync_contracts", + "zksync_env_config", + "zksync_state", "zksync_system_constants", "zksync_types", "zksync_utils", @@ -7995,6 +8207,51 @@ dependencies = [ "zksync_utils", ] +[[package]] +name = "zksync_shared_metrics" +version = "0.1.0" +dependencies = [ + "rustc_version", + "tracing", + "vise", + "zksync_dal", + "zksync_types", +] + +[[package]] +name = "zksync_state" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "backon", + "chrono", + "itertools 0.10.5", + "mini-moka", + "once_cell", + "tokio", + "tracing", + "vise", + "zksync_dal", + "zksync_shared_metrics", + "zksync_storage", + "zksync_types", + "zksync_utils", + "zksync_vm_interface", +] + +[[package]] +name = "zksync_storage" +version = "0.1.0" +dependencies = [ + "num_cpus", + "once_cell", + "rocksdb", + "thread_local", + "tracing", + "vise", +] + [[package]] name = "zksync_system_constants" version = "0.1.0" @@ -8031,6 +8288,7 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_crypto_primitives", + "zksync_env_config", "zksync_mini_merkle_tree", "zksync_protobuf", "zksync_protobuf_build", @@ -8137,6 +8395,7 @@ dependencies = [ "zksync_contracts", "zksync_system_constants", "zksync_types", + "zksync_utils", ] [[package]] @@ -8223,3 +8482,13 @@ dependencies = [ "zksync_utils", "zksync_vlog", ] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] From 2388ae823225f524051d10eacd0dab6e716de1b6 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Thu, 19 Sep 2024 13:31:26 -0300 Subject: [PATCH 24/72] Revert multivm bootloader change --- .../fee_estimate.yul/fee_estimate.yul.zbin | Bin 74912 -> 76320 bytes .../gas_test.yul/gas_test.yul.zbin | Bin 71008 -> 72416 bytes .../playground_batch.yul.zbin | Bin 75104 -> 76512 bytes .../proved_batch.yul/proved_batch.yul.zbin | Bin 71520 -> 72928 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/etc/multivm_bootloaders/vm_1_5_0_increased_memory/fee_estimate.yul/fee_estimate.yul.zbin b/etc/multivm_bootloaders/vm_1_5_0_increased_memory/fee_estimate.yul/fee_estimate.yul.zbin index ad45ddb49571509167df6fd155d50130db9b6afb..75ee6377bdb645532c55f06f0e883cc078b5bd2b 100644 GIT binary patch literal 76320 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 diff --git a/etc/multivm_bootloaders/vm_1_5_0_increased_memory/playground_batch.yul/playground_batch.yul.zbin b/etc/multivm_bootloaders/vm_1_5_0_increased_memory/playground_batch.yul/playground_batch.yul.zbin index aa92225a4782a7a937208a46dbee5dbac7da7dcb..b1a5e063d84b66ebea9a6e021ef42d29b1346760 100644 GIT binary patch literal 76512 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 PUBCIJ&;7~A_uTs5GOKah literal 75104 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 gzj^U9AG=}E?OV2O{*T Date: Thu, 19 Sep 2024 14:52:55 -0300 Subject: [PATCH 25/72] Check for evm simulator to avoid failing for transactions with null contract address --- core/lib/types/src/transaction_request.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 5f26b1d6a6a5..e99e228086fb 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -4,6 +4,8 @@ use rlp::{DecoderError, Rlp, RlpStream}; use serde::{Deserialize, Serialize}; use thiserror::Error; use zksync_basic_types::H256; +use zksync_config::configs::use_evm_simulator; +use zksync_env_config::FromEnv; use zksync_system_constants::{DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE, MAX_ENCODED_TX_SIZE}; use zksync_utils::{ bytecode::{hash_bytecode, validate_bytecode, InvalidBytecodeError}, @@ -817,8 +819,11 @@ impl L2Tx { let meta = value.eip712_meta.take().unwrap_or_default(); validate_factory_deps(&meta.factory_deps)?; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; // TODO: Remove this check when evm equivalence gets enabled - if value.to.is_none() { + if value.to.is_none() && !use_evm_simulator { return Err(SerializationTransactionError::ToAddressIsNull); } From c14b5aa95f8354265d8886f48fa0b2675fbe12f7 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 19 Sep 2024 14:53:34 -0300 Subject: [PATCH 26/72] Fix multicall with evm simulator on --- core/node/eth_sender/src/eth_tx_aggregator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 49a108231b2a..2ce923fa1213 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -246,7 +246,7 @@ impl EthTxAggregator { ]; if let Some(call) = get_evm_simulator_hash_call { - token_vec.push(call.into_token()); + token_vec.insert(2, call.into_token()); } token_vec From c8d189603a8d162ceb65167ae2e800cfe09b73df Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 19 Sep 2024 15:47:31 -0300 Subject: [PATCH 27/72] Fix multicall when evm simulator is absent --- core/node/eth_sender/src/eth_tx_aggregator.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 2ce923fa1213..0b3656024927 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -189,20 +189,23 @@ impl EthTxAggregator { calldata: get_l2_default_aa_hash_input, }; - let get_l2_evm_simulator_hash_input = self + let mut get_l2_evm_simulator_hash_input = self .functions .get_evm_simulator_bytecode_hash .as_ref() .and_then(|f| f.encode_input(&[]).ok()); - let get_evm_simulator_hash_call = if let Some(input) = get_l2_evm_simulator_hash_input { - Some(Multicall3Call { + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; + + let get_evm_simulator_hash_call = match get_l2_evm_simulator_hash_input { + Some(input) if use_evm_simulator => Some(Multicall3Call { target: self.state_transition_chain_contract, allow_failure: ALLOW_FAILURE, calldata: input, - }) - } else { - None + }), + _ => None, }; // Third zksync contract call From 072222df4ebcafaccded990d3ea0b892bb19c7a1 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 20 Sep 2024 13:16:30 -0300 Subject: [PATCH 28/72] Remove hardcoded hash for evm simulator when its not enabled --- .../system-constants-generator/src/utils.rs | 19 ++++++------------- core/lib/contracts/src/lib.rs | 19 ++++++------------- core/lib/types/src/system_contracts.rs | 8 ++++++-- core/lib/types/src/transaction_request.rs | 1 + core/node/eth_sender/src/eth_tx_aggregator.rs | 13 +++++-------- 5 files changed, 24 insertions(+), 36 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index ac4d66185e33..b5f5717b5c23 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -75,19 +75,12 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); - let mut evm_simulator_bytecode = bytecode.clone(); - let mut evm_simulator_hash = - H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") - .unwrap(); - - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode.clone()); - } + let (evm_simulator_bytecode, evm_simulator_hash) = if use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator { + let evm_simulator_bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + (evm_simulator_bytecode.clone(), hash_bytecode(&evm_simulator_bytecode)) + } else { + (bytecode.clone(), hash) + }; BaseSystemContracts { default_aa: SystemContractCode { diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 5f86f546c767..2f29098f73dc 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -346,19 +346,12 @@ impl BaseSystemContracts { }; // If evm simulator is not enabled, use the default account bytecode and hash. - let mut evm_simulator_bytecode = bytecode; - let mut evm_simulator_hash = - H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") - .unwrap(); - - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); - } + let (evm_simulator_bytecode, evm_simulator_hash) = if use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator { + let evm_simulator_bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + (evm_simulator_bytecode.clone(), hash_bytecode(&evm_simulator_bytecode)) + } else { + (bytecode.clone(), hash) + }; let evm_simulator = SystemContractCode { code: bytes_to_be_words(evm_simulator_bytecode), diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index f88e24e21ca7..628da94af573 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -191,8 +191,12 @@ static EVM_SIMULATOR_HASH: Lazy = Lazy::new(|| { ContractLanguage::Yul, )) } else { - H256::from_str("0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32") - .unwrap() + let default_account_code = read_sys_contract_bytecode( + "", + "DefaultAccount", + ContractLanguage::Sol, + ); + hash_bytecode(&default_account_code) } }); diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index e99e228086fb..5de1ef003442 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -822,6 +822,7 @@ impl L2Tx { let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() .unwrap() .use_evm_simulator; + // TODO: Remove this check when evm equivalence gets enabled if value.to.is_none() && !use_evm_simulator { return Err(SerializationTransactionError::ToAddressIsNull); diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 0b3656024927..54c6c698e270 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -303,12 +303,7 @@ impl EthTxAggregator { } let default_aa = H256::from_slice(&multicall3_default_aa); - let mut evm_simulator = H256::from_str( - "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32", - ) - .unwrap(); - - if use_evm_simulator { + let evm_simulator = if use_evm_simulator { let multicall3_evm_simulator = Multicall3Result::from_token(call_results_iterator.next().unwrap())? .return_data; @@ -320,8 +315,10 @@ impl EthTxAggregator { ), ))); } - evm_simulator = H256::from_slice(&multicall3_evm_simulator); - } + H256::from_slice(&multicall3_evm_simulator) + } else { + default_aa + }; let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader, From a08ea6c2e3e5205915e7139195c173e74f11b4bf Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 20 Sep 2024 13:36:29 -0300 Subject: [PATCH 29/72] Fix format --- .../system-constants-generator/src/utils.rs | 20 +++++++++++++------ core/lib/contracts/src/lib.rs | 20 +++++++++++++------ core/lib/types/src/system_contracts.rs | 7 ++----- core/lib/types/src/transaction_request.rs | 2 +- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index b5f5717b5c23..1ad9d28ab1ac 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -75,12 +75,20 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); - let (evm_simulator_bytecode, evm_simulator_hash) = if use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator { - let evm_simulator_bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - (evm_simulator_bytecode.clone(), hash_bytecode(&evm_simulator_bytecode)) - } else { - (bytecode.clone(), hash) - }; + let (evm_simulator_bytecode, evm_simulator_hash) = + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + ( + evm_simulator_bytecode.clone(), + hash_bytecode(&evm_simulator_bytecode), + ) + } else { + (bytecode.clone(), hash) + }; BaseSystemContracts { default_aa: SystemContractCode { diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 2f29098f73dc..2fd8bf44c24c 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -346,12 +346,20 @@ impl BaseSystemContracts { }; // If evm simulator is not enabled, use the default account bytecode and hash. - let (evm_simulator_bytecode, evm_simulator_hash) = if use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator { - let evm_simulator_bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - (evm_simulator_bytecode.clone(), hash_bytecode(&evm_simulator_bytecode)) - } else { - (bytecode.clone(), hash) - }; + let (evm_simulator_bytecode, evm_simulator_hash) = + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + ( + evm_simulator_bytecode.clone(), + hash_bytecode(&evm_simulator_bytecode), + ) + } else { + (bytecode.clone(), hash) + }; let evm_simulator = SystemContractCode { code: bytes_to_be_words(evm_simulator_bytecode), diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 628da94af573..f92ff7c0c518 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -191,11 +191,8 @@ static EVM_SIMULATOR_HASH: Lazy = Lazy::new(|| { ContractLanguage::Yul, )) } else { - let default_account_code = read_sys_contract_bytecode( - "", - "DefaultAccount", - ContractLanguage::Sol, - ); + let default_account_code = + read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); hash_bytecode(&default_account_code) } }); diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 5de1ef003442..cfcc659008b9 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -822,7 +822,7 @@ impl L2Tx { let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() .unwrap() .use_evm_simulator; - + // TODO: Remove this check when evm equivalence gets enabled if value.to.is_none() && !use_evm_simulator { return Err(SerializationTransactionError::ToAddressIsNull); From 5bdabe3c8e48987a2d4114b19b3a79fdab47ca31 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 20 Sep 2024 16:28:19 -0300 Subject: [PATCH 30/72] Check for evm simulator in execute_internal_transfer_test function --- .../system-constants-generator/src/utils.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 1ad9d28ab1ac..220962475fd8 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -237,13 +237,24 @@ pub(super) fn execute_internal_transfer_test() -> u32 { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); let default_aa = SystemContractCode { - code: bytes_to_be_words(bytecode), + code: bytes_to_be_words(bytecode.clone()), hash, }; - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - let evm_simulator_hash = hash_bytecode(&evm_simulator_bytecode); + let (evm_simulator_bytecode, evm_simulator_hash) = + if use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator + { + let evm_simulator_bytecode = + read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + ( + evm_simulator_bytecode.clone(), + hash_bytecode(&evm_simulator_bytecode), + ) + } else { + (bytecode.clone(), hash) + }; let evm_simulator = SystemContractCode { code: bytes_to_be_words(evm_simulator_bytecode), hash: evm_simulator_hash, From 9010c5692c6f361fe1219855fb9de656c2cb31ae Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 24 Sep 2024 13:59:16 -0300 Subject: [PATCH 31/72] Fix doc comment for UseEvmSimulator config --- core/lib/config/src/configs/use_evm_simulator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/config/src/configs/use_evm_simulator.rs b/core/lib/config/src/configs/use_evm_simulator.rs index 76113613a17d..7309c92a3445 100644 --- a/core/lib/config/src/configs/use_evm_simulator.rs +++ b/core/lib/config/src/configs/use_evm_simulator.rs @@ -1,6 +1,6 @@ use serde::Deserialize; -/// Configuration for the use evm simulator +/// Configure whether to enable the EVM simulator on the stack. #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct UseEvmSimulator { pub use_evm_simulator: bool, From 774b8481048644bc38c3fd0f900f3c9e43ca0292 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 24 Sep 2024 14:18:21 -0300 Subject: [PATCH 32/72] Remove evm simulator code hash from miniblocks table --- ...1089c4f64c785f758b3684771073f9967923.json} | 4 +- ...00ff851252dd9da2df5ab7da51324f9258400.json | 31 -------- ...ba3af74e8e7b5944cb2943b5badb906167046.json | 30 +++++++ ...2ffa59f55223e99383ada49b633428a72718.json} | 4 +- ...bb57ffb1411826a6406d9d86958650183bbb.json} | 4 +- ...ce25e8b15a8f8c15a3523ef2a04528be2741.json} | 4 +- .../20240911161714_evm-simulator.up.sql | 1 - core/lib/dal/src/blocks_dal.rs | 78 +++++++++---------- core/lib/dal/src/blocks_web3_dal.rs | 2 +- core/lib/dal/src/sync_dal.rs | 3 +- ...0cd5c6b1122c35d7ffdbbba30327ca3fb5a8.json} | 4 +- 11 files changed, 80 insertions(+), 85 deletions(-) rename core/lib/dal/.sqlx/{query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json => query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json} (90%) delete mode 100644 core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json create mode 100644 core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json rename core/lib/dal/.sqlx/{query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json => query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json} (66%) rename core/lib/dal/.sqlx/{query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json => query-e4d2e039442c204cdcb6ee24fde9bb57ffb1411826a6406d9d86958650183bbb.json} (96%) rename core/lib/dal/.sqlx/{query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json => query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json} (65%) rename prover/crates/lib/prover_dal/.sqlx/{query-97adb49780c9edde6a3cfda09dadbd694e1781e013247d090a280a1f894de464.json => query-29f7a564a8373f7e44840e8e9e7d0cd5c6b1122c35d7ffdbbba30327ca3fb5a8.json} (53%) diff --git a/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json b/core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json similarity index 90% rename from core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json rename to core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json index 7b4fa2793dba..b624e45f2bb1 100644 --- a/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json +++ b/core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n INNER JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", "describe": { "columns": [ { @@ -97,5 +97,5 @@ false ] }, - "hash": "2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb" + "hash": "0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923" } diff --git a/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json b/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json deleted file mode 100644 index 52ef95716470..000000000000 --- a/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Bytea", - "Int4", - "Int4", - "Bytea", - "Numeric", - "Int8", - "Int8", - "Int8", - "Bytea", - "Bytea", - "Bytea", - "Int4", - "Int8", - "Int8", - "Int8", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400" -} diff --git a/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json b/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json new file mode 100644 index 000000000000..9ae9d2e50cde --- /dev/null +++ b/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json @@ -0,0 +1,30 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 NOW(),\n NOW()\n )\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Bytea", + "Int4", + "Int4", + "Bytea", + "Numeric", + "Int8", + "Int8", + "Int8", + "Bytea", + "Bytea", + "Int4", + "Int8", + "Int8", + "Int8", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046" +} diff --git a/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json b/core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json similarity index 66% rename from core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json rename to core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json index 287c69687e53..c1205a219525 100644 --- a/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json +++ b/core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", + "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n WHERE\n miniblocks.number = $1\n ", "describe": { "columns": [ { @@ -120,5 +120,5 @@ true ] }, - "hash": "922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e" + "hash": "c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718" } diff --git a/core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json b/core/lib/dal/.sqlx/query-e4d2e039442c204cdcb6ee24fde9bb57ffb1411826a6406d9d86958650183bbb.json similarity index 96% rename from core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json rename to core/lib/dal/.sqlx/query-e4d2e039442c204cdcb6ee24fde9bb57ffb1411826a6406d9d86958650183bbb.json index 12ddbfbc4211..444870f46031 100644 --- a/core/lib/dal/.sqlx/query-1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a.json +++ b/core/lib/dal/.sqlx/query-e4d2e039442c204cdcb6ee24fde9bb57ffb1411826a6406d9d86958650183bbb.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", "describe": { "columns": [ { @@ -132,5 +132,5 @@ false ] }, - "hash": "1ab1ee0657abc6586204dae61cb54a0fe2f0c3bf5f11aec8400c0b6e5b58c62a" + "hash": "e4d2e039442c204cdcb6ee24fde9bb57ffb1411826a6406d9d86958650183bbb" } diff --git a/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json b/core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json similarity index 65% rename from core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json rename to core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json index 16f258cf3047..8b323291548b 100644 --- a/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json +++ b/core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -118,5 +118,5 @@ true ] }, - "hash": "3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709" + "hash": "f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741" } diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql index ea8e0a83d20c..4bc764b77d7c 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql @@ -1,3 +1,2 @@ ALTER TABLE protocol_versions ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; ALTER TABLE l1_batches ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; -ALTER TABLE miniblocks ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 5d82dc18d48c..2ede5005b9f6 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -708,7 +708,6 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -736,7 +735,6 @@ impl BlocksDal<'_, '_> { $15, $16, $17, - $18, NOW(), NOW() ) @@ -759,10 +757,6 @@ impl BlocksDal<'_, '_> { .base_system_contracts_hashes .default_aa .as_bytes(), - l2_block_header - .base_system_contracts_hashes - .evm_simulator - .as_bytes(), l2_block_header.protocol_version.map(|v| v as i32), i64::from(l2_block_header.virtual_blocks), l2_block_header.batch_fee_input.fair_pubdata_price() as i64, @@ -779,26 +773,27 @@ impl BlocksDal<'_, '_> { StorageL2BlockHeader, r#" SELECT - number, - timestamp, - hash, - l1_tx_count, - l2_tx_count, + miniblocks.number, + miniblocks.timestamp, + miniblocks.hash, + miniblocks.l1_tx_count, + miniblocks.l2_tx_count, fee_account_address AS "fee_account_address!", - base_fee_per_gas, - l1_gas_price, - l2_fair_gas_price, - gas_per_pubdata_limit, - bootloader_code_hash, - default_aa_code_hash, - evm_simulator_code_hash, - protocol_version, - virtual_blocks, - fair_pubdata_price, - gas_limit, - logs_bloom + miniblocks.base_fee_per_gas, + miniblocks.l1_gas_price, + miniblocks.l2_fair_gas_price, + miniblocks.gas_per_pubdata_limit, + miniblocks.bootloader_code_hash, + miniblocks.default_aa_code_hash, + l1_batches.evm_simulator_code_hash, + miniblocks.protocol_version, + miniblocks.virtual_blocks, + miniblocks.fair_pubdata_price, + miniblocks.gas_limit, + miniblocks.logs_bloom FROM miniblocks + INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number ORDER BY number DESC LIMIT @@ -820,28 +815,29 @@ impl BlocksDal<'_, '_> { StorageL2BlockHeader, r#" SELECT - number, - timestamp, - hash, - l1_tx_count, - l2_tx_count, + miniblocks.number, + miniblocks.timestamp, + miniblocks.hash, + miniblocks.l1_tx_count, + miniblocks.l2_tx_count, fee_account_address AS "fee_account_address!", - base_fee_per_gas, - l1_gas_price, - l2_fair_gas_price, - gas_per_pubdata_limit, - bootloader_code_hash, - default_aa_code_hash, - evm_simulator_code_hash, - protocol_version, - virtual_blocks, - fair_pubdata_price, - gas_limit, - logs_bloom + miniblocks.base_fee_per_gas, + miniblocks.l1_gas_price, + miniblocks.l2_fair_gas_price, + miniblocks.gas_per_pubdata_limit, + miniblocks.bootloader_code_hash, + miniblocks.default_aa_code_hash, + l1_batches.evm_simulator_code_hash, + miniblocks.protocol_version, + miniblocks.virtual_blocks, + miniblocks.fair_pubdata_price, + miniblocks.gas_limit, + miniblocks.logs_bloom FROM miniblocks + INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number WHERE - number = $1 + miniblocks.number = $1 "#, i64::from(l2_block_number.0), ) diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 78c01dc1f6b0..332d4cd6c113 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -663,7 +663,7 @@ impl BlocksWeb3Dal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, - miniblocks.evm_simulator_code_hash, + l1_batches.evm_simulator_code_hash, miniblocks.protocol_version, miniblocks.fee_account_address FROM diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index 22c72fc4d152..c3120d240c49 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -50,13 +50,14 @@ impl SyncDal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, - miniblocks.evm_simulator_code_hash, + l1_batches.evm_simulator_code_hash, miniblocks.virtual_blocks, miniblocks.hash, miniblocks.protocol_version AS "protocol_version!", miniblocks.fee_account_address AS "fee_account_address!" FROM miniblocks + INNER JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number WHERE miniblocks.number BETWEEN $1 AND $2 "#, diff --git a/prover/crates/lib/prover_dal/.sqlx/query-97adb49780c9edde6a3cfda09dadbd694e1781e013247d090a280a1f894de464.json b/prover/crates/lib/prover_dal/.sqlx/query-29f7a564a8373f7e44840e8e9e7d0cd5c6b1122c35d7ffdbbba30327ca3fb5a8.json similarity index 53% rename from prover/crates/lib/prover_dal/.sqlx/query-97adb49780c9edde6a3cfda09dadbd694e1781e013247d090a280a1f894de464.json rename to prover/crates/lib/prover_dal/.sqlx/query-29f7a564a8373f7e44840e8e9e7d0cd5c6b1122c35d7ffdbbba30327ca3fb5a8.json index ce9e492a7d4a..05163dcfa2e6 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-97adb49780c9edde6a3cfda09dadbd694e1781e013247d090a280a1f894de464.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-29f7a564a8373f7e44840e8e9e7d0cd5c6b1122c35d7ffdbbba30327ca3fb5a8.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n protocol_version AS \"protocol_version!\",\n protocol_version_patch AS \"protocol_version_patch!\",\n COUNT(*) FILTER (WHERE status = 'queued') as queued,\n COUNT(*) FILTER (WHERE status = 'in_progress') as in_progress\n FROM\n prover_jobs_fri\n WHERE\n status IN ('queued', 'in_progress')\n AND protocol_version IS NOT NULL\n GROUP BY\n protocol_version,\n protocol_version_patch\n ", + "query": "\n SELECT\n protocol_version AS \"protocol_version!\",\n protocol_version_patch AS \"protocol_version_patch!\",\n COUNT(*) FILTER (\n WHERE\n status = 'queued'\n ) AS queued,\n COUNT(*) FILTER (\n WHERE\n status = 'in_progress'\n ) AS in_progress\n FROM\n prover_jobs_fri\n WHERE\n status IN ('queued', 'in_progress')\n AND protocol_version IS NOT NULL\n GROUP BY\n protocol_version,\n protocol_version_patch\n ", "describe": { "columns": [ { @@ -34,5 +34,5 @@ null ] }, - "hash": "97adb49780c9edde6a3cfda09dadbd694e1781e013247d090a280a1f894de464" + "hash": "29f7a564a8373f7e44840e8e9e7d0cd5c6b1122c35d7ffdbbba30327ca3fb5a8" } From e85228b2e49b266945f10a550d80db67e0c2fc40 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 24 Sep 2024 18:03:39 -0300 Subject: [PATCH 33/72] Fix review comments --- core/lib/dal/src/models/storage_transaction.rs | 3 ++- .../lib/multivm/src/glue/types/vm/vm_block_result.rs | 12 ++++++------ .../src/glue/types/vm/vm_partial_execution_result.rs | 6 +++--- .../src/glue/types/vm/vm_tx_execution_result.rs | 10 +++++----- .../versions/vm_1_4_1/implementation/execution.rs | 2 +- .../versions/vm_1_4_2/implementation/execution.rs | 2 +- .../implementation/execution.rs | 2 +- core/lib/multivm/src/versions/vm_fast/vm.rs | 2 +- .../implementation/execution.rs | 2 +- .../vm_virtual_blocks/implementation/execution.rs | 2 +- core/lib/types/src/l2/mod.rs | 5 ++++- core/lib/types/src/lib.rs | 5 ++++- core/lib/types/src/transaction_request.rs | 8 +++----- core/lib/vm_executor/src/oneshot/mock.rs | 2 +- .../src/types/outputs/finished_l1batch.rs | 2 +- core/node/api_server/src/web3/tests/vm.rs | 2 +- core/node/state_keeper/src/testonly/mod.rs | 2 +- .../state_keeper/src/testonly/test_batch_executor.rs | 4 ++-- core/node/state_keeper/src/tests/mod.rs | 2 +- .../state_keeper/src/updates/l2_block_updates.rs | 7 +------ 20 files changed, 41 insertions(+), 41 deletions(-) diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 746026af73e5..6dc9c5c7a924 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -367,7 +367,8 @@ impl From for TransactionReceipt { .and_then(|addr| { serde_json::from_value::>(addr) .expect("invalid address value in the database") - }), + // For better compatibility with various clients, we never return null. + }).or_else(|| Some(Address::zero())), cumulative_gas_used: Default::default(), // TODO: Should be actually calculated (SMA-1183). gas_used: { let refunded_gas: U256 = storage_receipt.refunded_gas.into(); diff --git a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs index 6ef9b2947746..50bb19938fe7 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs @@ -47,7 +47,7 @@ impl GlueFrom for crate::interface::Fi circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -104,7 +104,7 @@ impl GlueFrom for crate::interface::Fi circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -160,7 +160,7 @@ impl GlueFrom for crate::interface: circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, final_execution_state: CurrentExecutionState { events: value.full_result.events, @@ -230,7 +230,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } @@ -263,7 +263,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } @@ -312,7 +312,7 @@ impl GlueFrom circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } diff --git a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs index 1891330b6d29..4c4cffcc6876 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs @@ -22,7 +22,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } @@ -49,7 +49,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } @@ -76,7 +76,7 @@ impl GlueFrom gas_refunded: 0, operator_suggested_refund: 0, }, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } } diff --git a/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs index 2ea1e3984c47..8978d4348edd 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_tx_execution_result.rs @@ -66,14 +66,14 @@ impl GlueFrom VmExecutionResultAndLogs { result: ExecutionResult::Halt { reason: halt }, logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, } } @@ -102,14 +102,14 @@ impl logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, TxRevertReason::Halt(halt) => VmExecutionResultAndLogs { result: ExecutionResult::Halt { reason: halt }, logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, } } @@ -133,7 +133,7 @@ impl GlueFrom { unreachable!("Halt is the only revert reason for VM 5") diff --git a/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs b/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs index 4767b5dcfa92..cc199fef9416 100644 --- a/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_1_4_1/implementation/execution.rs @@ -99,7 +99,7 @@ impl Vm { logs, statistics, refunds, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs b/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs index f49eb10e26bc..f6e49cd8b149 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/implementation/execution.rs @@ -96,7 +96,7 @@ impl Vm { logs, statistics, refunds, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs index d21db3992040..b8b939f86731 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs @@ -93,7 +93,7 @@ impl Vm { logs, statistics, refunds, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_fast/vm.rs b/core/lib/multivm/src/versions/vm_fast/vm.rs index a94c51de6a7f..1757d952bfe8 100644 --- a/core/lib/multivm/src/versions/vm_fast/vm.rs +++ b/core/lib/multivm/src/versions/vm_fast/vm.rs @@ -601,7 +601,7 @@ impl VmInterface for Vm { circuit_statistic: full_tracer.1.circuit_statistic(), }, refunds, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs index 696f2993f511..9462a89be2ab 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs @@ -90,7 +90,7 @@ impl Vm { logs, statistics, refunds, - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }; (stop_reason, result) diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs index 33946f20ecbd..b1ad4d257b77 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs @@ -88,7 +88,7 @@ impl Vm { .refund_tracer .map(|r| r.get_refunds()) .unwrap_or_default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }; tx_tracer.dispatcher.save_results(&mut result); diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index 036d2a7a036d..110a90c44242 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -4,7 +4,9 @@ use anyhow::Context as _; use num_enum::TryFromPrimitive; use rlp::Rlp; use serde::{Deserialize, Serialize}; +use zksync_config::configs::use_evm_simulator; use zksync_crypto_primitives::K256PrivateKey; +use zksync_env_config::FromEnv; use self::error::SignError; use crate::{ @@ -216,7 +218,8 @@ impl L2Tx { let raw = req.get_signed_bytes(&sig).context("get_signed_bytes")?; let (req, hash) = TransactionRequest::from_bytes_unverified(&raw).context("from_bytes_unverified()")?; - let mut tx = L2Tx::from_request_unverified(req).context("from_request_unverified()")?; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; + let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator).context("from_request_unverified()")?; tx.set_input(raw, hash); Ok(tx) } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 86b2e3f03d51..1e38b63dcdda 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -16,7 +16,9 @@ use serde::{Deserialize, Serialize}; pub use storage::*; pub use tx::Execute; pub use zksync_basic_types::{protocol_version::ProtocolVersionId, vm, *}; +use zksync_config::configs::use_evm_simulator; pub use zksync_crypto_primitives::*; +use zksync_env_config::FromEnv; use zksync_utils::{ address_to_u256, bytecode::hash_bytecode, h256_to_u256, u256_to_account_address, }; @@ -389,7 +391,8 @@ impl TryFrom for Transaction { abi::Transaction::L2(raw) => { let (req, hash) = transaction_request::TransactionRequest::from_bytes_unverified(&raw)?; - let mut tx = L2Tx::from_request_unverified(req)?; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; + let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator)?; tx.set_input(raw, hash); tx.into() } diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index cfcc659008b9..d51378452dda 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -811,6 +811,7 @@ impl TransactionRequest { impl L2Tx { pub(crate) fn from_request_unverified( mut value: TransactionRequest, + use_evm_simulator: bool, ) -> Result { let fee = value.get_fee_data_checked()?; let nonce = value.get_nonce_checked()?; @@ -819,10 +820,6 @@ impl L2Tx { let meta = value.eip712_meta.take().unwrap_or_default(); validate_factory_deps(&meta.factory_deps)?; - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; - // TODO: Remove this check when evm equivalence gets enabled if value.to.is_none() && !use_evm_simulator { return Err(SerializationTransactionError::ToAddressIsNull); @@ -858,7 +855,8 @@ impl L2Tx { value: TransactionRequest, max_tx_size: usize, ) -> Result { - let tx = Self::from_request_unverified(value)?; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; + let tx = Self::from_request_unverified(value, use_evm_simulator)?; tx.check_encoded_size(max_tx_size)?; Ok(tx) } diff --git a/core/lib/vm_executor/src/oneshot/mock.rs b/core/lib/vm_executor/src/oneshot/mock.rs index 8408206ede4c..a7363c633c6c 100644 --- a/core/lib/vm_executor/src/oneshot/mock.rs +++ b/core/lib/vm_executor/src/oneshot/mock.rs @@ -68,7 +68,7 @@ impl MockOneshotExecutor { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } }, ) diff --git a/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs b/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs index a71c9f8f7a5e..8f7c1d4fb0d6 100644 --- a/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs +++ b/core/lib/vm_interface/src/types/outputs/finished_l1batch.rs @@ -26,7 +26,7 @@ impl FinishedL1Batch { logs: VmExecutionLogs::default(), statistics: VmExecutionStatistics::default(), refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }, final_execution_state: CurrentExecutionState { events: vec![], diff --git a/core/node/api_server/src/web3/tests/vm.rs b/core/node/api_server/src/web3/tests/vm.rs index 0093712767dc..b6ec32b1afc6 100644 --- a/core/node/api_server/src/web3/tests/vm.rs +++ b/core/node/api_server/src/web3/tests/vm.rs @@ -393,7 +393,7 @@ impl HttpTest for SendTransactionWithDetailedOutputTest { logs: vm_execution_logs.clone(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } }); tx_executor diff --git a/core/node/state_keeper/src/testonly/mod.rs b/core/node/state_keeper/src/testonly/mod.rs index 34a9a88bcb32..d1e82c44bd6f 100644 --- a/core/node/state_keeper/src/testonly/mod.rs +++ b/core/node/state_keeper/src/testonly/mod.rs @@ -33,7 +33,7 @@ pub(crate) fn successful_exec() -> BatchTransactionExecutionResult { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }), compressed_bytecodes: vec![], call_traces: vec![], 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 2a883bb011b3..cb282f3b7d6d 100644 --- a/core/node/state_keeper/src/testonly/test_batch_executor.rs +++ b/core/node/state_keeper/src/testonly/test_batch_executor.rs @@ -264,7 +264,7 @@ pub(crate) fn successful_exec_with_log() -> BatchTransactionExecutionResult { }, statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }), compressed_bytecodes: vec![], call_traces: vec![], @@ -279,7 +279,7 @@ pub(crate) fn rejected_exec(reason: Halt) -> BatchTransactionExecutionResult { logs: Default::default(), statistics: Default::default(), refunds: Default::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, }), compressed_bytecodes: vec![], call_traces: vec![], diff --git a/core/node/state_keeper/src/tests/mod.rs b/core/node/state_keeper/src/tests/mod.rs index 10c42c7857bd..9e971541b204 100644 --- a/core/node/state_keeper/src/tests/mod.rs +++ b/core/node/state_keeper/src/tests/mod.rs @@ -138,7 +138,7 @@ pub(super) fn create_execution_result( circuit_statistic: Default::default(), }, refunds: Refunds::default(), - new_known_factory_deps: Default::default(), + new_known_factory_deps: None, } } diff --git a/core/node/state_keeper/src/updates/l2_block_updates.rs b/core/node/state_keeper/src/updates/l2_block_updates.rs index 3d0d35096c2f..2301016c314a 100644 --- a/core/node/state_keeper/src/updates/l2_block_updates.rs +++ b/core/node/state_keeper/src/updates/l2_block_updates.rs @@ -129,12 +129,7 @@ impl L2BlockUpdates { .map(|bytecode| (hash_bytecode(bytecode), bytecode.clone())) .collect(); - new_known_factory_deps - .into_iter() - .for_each(|(hash, bytecode)| { - tx_factory_deps.insert(hash, bytecode); - }); - + tx_factory_deps.extend(new_known_factory_deps.clone()); // Save all bytecodes that were marked as known on the bootloader let known_bytecodes = saved_factory_deps.into_iter().map(|bytecode_hash| { let bytecode = tx_factory_deps.get(&bytecode_hash).unwrap_or_else(|| { From 0f7c5da093d4791e809ac3fa67b6f80531cbee9a Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 25 Sep 2024 11:43:06 -0300 Subject: [PATCH 34/72] Update sqlx cached queries --- ...f1cdac8b194f09926c133985479c533a651f2.json | 18 ++++++++++++++++++ ...0d001cdf5bc7ba988b742571ec90a938434e3.json | 17 ----------------- ...cf8c93630d529ec96e67aac078f18196f61a5.json | 19 +++++++++++++++++++ ...adefab0bf3abf6853a6d36123c8adcaf813b.json} | 4 ++-- ...d48c95ca5b4520dde415a2b5ff32ece47c86.json} | 4 ++-- ...8d4cc59246dda91b19526e73f27a17c8e3da.json} | 4 ++-- ...a468057599be1e6c6c96a947c33df53a68224.json | 15 --------------- ...2e61157bf58aec70903623afc9da24d46a336.json | 16 ---------------- ...1b931c0d8dbc6835dfac20107ea7412ce9fbb.json | 15 --------------- ...9a67936d572f8046d3a1c7a4f100ff209d81d.json | 18 ------------------ ...41976a264759c4060c1a38e466ee2052fc17d.json | 15 +++++++++++++++ ...2a4a98ec63eb942c73ce4448d0957346047cd.json | 17 +++++++++++++++++ ...08a01b63ae4aa03c983c3a52c802d585e5a80.json | 15 +++++++++++++++ ...700302981be0afef31a8864613484f8521f9e.json | 19 ------------------- ...b5a4672ad50a9de92c84d939ac4c69842e355.json | 16 ++++++++++++++++ ...d005d8760c4809b7aef902155196873da66e.json} | 4 ++-- ...8e1010d7389457b3c97e9b238a3a0291a54e.json} | 4 ++-- 17 files changed, 110 insertions(+), 110 deletions(-) create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-1297f0977132185d6bd4501f490f1cdac8b194f09926c133985479c533a651f2.json delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-1926cf432237684de2383179a6d0d001cdf5bc7ba988b742571ec90a938434e3.json create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-2d1461e068e43fd16714610b383cf8c93630d529ec96e67aac078f18196f61a5.json rename prover/crates/lib/prover_dal/.sqlx/{query-75c1affbca0901edd5d0e2f12ef4d935674a5aff2f34421d753b4d1a9dea5b12.json => query-35a76415cb746d03da31481edc65adefab0bf3abf6853a6d36123c8adcaf813b.json} (70%) rename prover/crates/lib/prover_dal/.sqlx/{query-548414f8148740c991c345e5fd46ea738d209eb07e7a6bcbdb33e25b3347a08c.json => query-3727d5614d2fe2a4d96f880eb72cd48c95ca5b4520dde415a2b5ff32ece47c86.json} (70%) rename prover/crates/lib/prover_dal/.sqlx/{query-c19fc4c8e4b3a3ef4f9c0f4c22ed68c598eada8e60938a8e4b5cd32b53f5a574.json => query-37ad15f54f4a6f4f79c71a857f3a8d4cc59246dda91b19526e73f27a17c8e3da.json} (69%) delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-39f60c638d445c5dbf23e01fd89a468057599be1e6c6c96a947c33df53a68224.json delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-3a9ffd4d88f2cfac22835aac2512e61157bf58aec70903623afc9da24d46a336.json delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-3bb8fbd9e83703887e0a3c196031b931c0d8dbc6835dfac20107ea7412ce9fbb.json delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-434f7cb51a7d22948cd26e962679a67936d572f8046d3a1c7a4f100ff209d81d.json create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-73266a8526c6adc315900e2e95441976a264759c4060c1a38e466ee2052fc17d.json create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-9730c8225ff2cf3111185e81f602a4a98ec63eb942c73ce4448d0957346047cd.json create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-a817f0fec85388b3e2510ce259208a01b63ae4aa03c983c3a52c802d585e5a80.json delete mode 100644 prover/crates/lib/prover_dal/.sqlx/query-aabcfa9005b8e1d84cfa083a47a700302981be0afef31a8864613484f8521f9e.json create mode 100644 prover/crates/lib/prover_dal/.sqlx/query-c8daa62b3835c15fafb3f83deabb5a4672ad50a9de92c84d939ac4c69842e355.json rename prover/crates/lib/prover_dal/.sqlx/{query-63cf7038e6c48af8ed9afc7d6ea07edd87cb16a79c13e7d4291d99736e51d3b9.json => query-e875dcbbdaed6998dbea45d4eab5d005d8760c4809b7aef902155196873da66e.json} (82%) rename prover/crates/lib/prover_dal/.sqlx/{query-0eac6f7b2d799059328584029b437891598dc79b5ed11258b2c90c3f282929ad.json => query-eec29cbff034818f4fb5ec1e6ad38e1010d7389457b3c97e9b238a3a0291a54e.json} (78%) diff --git a/prover/crates/lib/prover_dal/.sqlx/query-1297f0977132185d6bd4501f490f1cdac8b194f09926c133985479c533a651f2.json b/prover/crates/lib/prover_dal/.sqlx/query-1297f0977132185d6bd4501f490f1cdac8b194f09926c133985479c533a651f2.json new file mode 100644 index 000000000000..c99572bcc8e5 --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-1297f0977132185d6bd4501f490f1cdac8b194f09926c133985479c533a651f2.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE prover_jobs_fri\n SET\n status = $1\n WHERE\n l1_batch_number = $2\n AND sequence_number = $3\n AND aggregation_round = $4\n AND circuit_id = $5\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int8", + "Int4", + "Int2", + "Int2" + ] + }, + "nullable": [] + }, + "hash": "1297f0977132185d6bd4501f490f1cdac8b194f09926c133985479c533a651f2" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-1926cf432237684de2383179a6d0d001cdf5bc7ba988b742571ec90a938434e3.json b/prover/crates/lib/prover_dal/.sqlx/query-1926cf432237684de2383179a6d0d001cdf5bc7ba988b742571ec90a938434e3.json deleted file mode 100644 index 4015a22ff3fd..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-1926cf432237684de2383179a6d0d001cdf5bc7ba988b742571ec90a938434e3.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE leaf_aggregation_witness_jobs_fri \n SET status = $1, attempts = $2\n WHERE l1_batch_number = $3\n AND circuit_id = $4", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Int2", - "Int8", - "Int2" - ] - }, - "nullable": [] - }, - "hash": "1926cf432237684de2383179a6d0d001cdf5bc7ba988b742571ec90a938434e3" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-2d1461e068e43fd16714610b383cf8c93630d529ec96e67aac078f18196f61a5.json b/prover/crates/lib/prover_dal/.sqlx/query-2d1461e068e43fd16714610b383cf8c93630d529ec96e67aac078f18196f61a5.json new file mode 100644 index 000000000000..50d121213fb9 --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-2d1461e068e43fd16714610b383cf8c93630d529ec96e67aac078f18196f61a5.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE prover_jobs_fri\n SET\n status = $1,\n attempts = $2\n WHERE\n l1_batch_number = $3\n AND sequence_number = $4\n AND aggregation_round = $5\n AND circuit_id = $6\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int2", + "Int8", + "Int4", + "Int2", + "Int2" + ] + }, + "nullable": [] + }, + "hash": "2d1461e068e43fd16714610b383cf8c93630d529ec96e67aac078f18196f61a5" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-75c1affbca0901edd5d0e2f12ef4d935674a5aff2f34421d753b4d1a9dea5b12.json b/prover/crates/lib/prover_dal/.sqlx/query-35a76415cb746d03da31481edc65adefab0bf3abf6853a6d36123c8adcaf813b.json similarity index 70% rename from prover/crates/lib/prover_dal/.sqlx/query-75c1affbca0901edd5d0e2f12ef4d935674a5aff2f34421d753b4d1a9dea5b12.json rename to prover/crates/lib/prover_dal/.sqlx/query-35a76415cb746d03da31481edc65adefab0bf3abf6853a6d36123c8adcaf813b.json index 14463ecbe426..bf8db798e7d4 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-75c1affbca0901edd5d0e2f12ef4d935674a5aff2f34421d753b4d1a9dea5b12.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-35a76415cb746d03da31481edc65adefab0bf3abf6853a6d36123c8adcaf813b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE scheduler_witness_jobs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (status = 'in_progress' OR status = 'failed')\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", + "query": "\n UPDATE scheduler_witness_jobs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (\n status = 'in_progress'\n OR status = 'failed'\n )\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", "describe": { "columns": [ { @@ -43,5 +43,5 @@ true ] }, - "hash": "75c1affbca0901edd5d0e2f12ef4d935674a5aff2f34421d753b4d1a9dea5b12" + "hash": "35a76415cb746d03da31481edc65adefab0bf3abf6853a6d36123c8adcaf813b" } diff --git a/prover/crates/lib/prover_dal/.sqlx/query-548414f8148740c991c345e5fd46ea738d209eb07e7a6bcbdb33e25b3347a08c.json b/prover/crates/lib/prover_dal/.sqlx/query-3727d5614d2fe2a4d96f880eb72cd48c95ca5b4520dde415a2b5ff32ece47c86.json similarity index 70% rename from prover/crates/lib/prover_dal/.sqlx/query-548414f8148740c991c345e5fd46ea738d209eb07e7a6bcbdb33e25b3347a08c.json rename to prover/crates/lib/prover_dal/.sqlx/query-3727d5614d2fe2a4d96f880eb72cd48c95ca5b4520dde415a2b5ff32ece47c86.json index 8f5b046b974f..d7eb6a32b421 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-548414f8148740c991c345e5fd46ea738d209eb07e7a6bcbdb33e25b3347a08c.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-3727d5614d2fe2a4d96f880eb72cd48c95ca5b4520dde415a2b5ff32ece47c86.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE witness_inputs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (status = 'in_progress' OR status = 'failed')\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", + "query": "\n UPDATE witness_inputs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (\n status = 'in_progress'\n OR status = 'failed'\n )\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", "describe": { "columns": [ { @@ -43,5 +43,5 @@ true ] }, - "hash": "548414f8148740c991c345e5fd46ea738d209eb07e7a6bcbdb33e25b3347a08c" + "hash": "3727d5614d2fe2a4d96f880eb72cd48c95ca5b4520dde415a2b5ff32ece47c86" } diff --git a/prover/crates/lib/prover_dal/.sqlx/query-c19fc4c8e4b3a3ef4f9c0f4c22ed68c598eada8e60938a8e4b5cd32b53f5a574.json b/prover/crates/lib/prover_dal/.sqlx/query-37ad15f54f4a6f4f79c71a857f3a8d4cc59246dda91b19526e73f27a17c8e3da.json similarity index 69% rename from prover/crates/lib/prover_dal/.sqlx/query-c19fc4c8e4b3a3ef4f9c0f4c22ed68c598eada8e60938a8e4b5cd32b53f5a574.json rename to prover/crates/lib/prover_dal/.sqlx/query-37ad15f54f4a6f4f79c71a857f3a8d4cc59246dda91b19526e73f27a17c8e3da.json index 3c4c8d7a29f3..c97fe7f4042b 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-c19fc4c8e4b3a3ef4f9c0f4c22ed68c598eada8e60938a8e4b5cd32b53f5a574.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-37ad15f54f4a6f4f79c71a857f3a8d4cc59246dda91b19526e73f27a17c8e3da.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE recursion_tip_witness_jobs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (status = 'in_progress' OR status = 'failed')\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", + "query": "\n UPDATE recursion_tip_witness_jobs_fri\n SET\n status = 'queued',\n updated_at = NOW(),\n processing_started_at = NOW()\n WHERE\n l1_batch_number = $1\n AND attempts >= $2\n AND (\n status = 'in_progress'\n OR status = 'failed'\n )\n RETURNING\n l1_batch_number,\n status,\n attempts,\n error,\n picked_by\n ", "describe": { "columns": [ { @@ -43,5 +43,5 @@ true ] }, - "hash": "c19fc4c8e4b3a3ef4f9c0f4c22ed68c598eada8e60938a8e4b5cd32b53f5a574" + "hash": "37ad15f54f4a6f4f79c71a857f3a8d4cc59246dda91b19526e73f27a17c8e3da" } diff --git a/prover/crates/lib/prover_dal/.sqlx/query-39f60c638d445c5dbf23e01fd89a468057599be1e6c6c96a947c33df53a68224.json b/prover/crates/lib/prover_dal/.sqlx/query-39f60c638d445c5dbf23e01fd89a468057599be1e6c6c96a947c33df53a68224.json deleted file mode 100644 index 5cec4d7d7d03..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-39f60c638d445c5dbf23e01fd89a468057599be1e6c6c96a947c33df53a68224.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n recursion_tip_witness_jobs_fri (\n l1_batch_number,\n status,\n number_of_final_node_jobs,\n created_at,\n updated_at\n )\n VALUES\n ($1, 'waiting_for_proofs',1, NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET status = $2\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Text" - ] - }, - "nullable": [] - }, - "hash": "39f60c638d445c5dbf23e01fd89a468057599be1e6c6c96a947c33df53a68224" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-3a9ffd4d88f2cfac22835aac2512e61157bf58aec70903623afc9da24d46a336.json b/prover/crates/lib/prover_dal/.sqlx/query-3a9ffd4d88f2cfac22835aac2512e61157bf58aec70903623afc9da24d46a336.json deleted file mode 100644 index 063ae8fc90a3..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-3a9ffd4d88f2cfac22835aac2512e61157bf58aec70903623afc9da24d46a336.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n node_aggregation_witness_jobs_fri (\n l1_batch_number,\n circuit_id,\n status,\n created_at,\n updated_at\n )\n VALUES\n ($1, $2, 'waiting_for_proofs', NOW(), NOW())\n ON CONFLICT (l1_batch_number, circuit_id, depth) DO\n UPDATE\n SET status = $3\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int2", - "Text" - ] - }, - "nullable": [] - }, - "hash": "3a9ffd4d88f2cfac22835aac2512e61157bf58aec70903623afc9da24d46a336" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-3bb8fbd9e83703887e0a3c196031b931c0d8dbc6835dfac20107ea7412ce9fbb.json b/prover/crates/lib/prover_dal/.sqlx/query-3bb8fbd9e83703887e0a3c196031b931c0d8dbc6835dfac20107ea7412ce9fbb.json deleted file mode 100644 index 693905084151..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-3bb8fbd9e83703887e0a3c196031b931c0d8dbc6835dfac20107ea7412ce9fbb.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n proof_compression_jobs_fri (\n l1_batch_number,\n status,\n created_at,\n updated_at\n )\n VALUES\n ($1, $2, NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET status = $2\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Text" - ] - }, - "nullable": [] - }, - "hash": "3bb8fbd9e83703887e0a3c196031b931c0d8dbc6835dfac20107ea7412ce9fbb" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-434f7cb51a7d22948cd26e962679a67936d572f8046d3a1c7a4f100ff209d81d.json b/prover/crates/lib/prover_dal/.sqlx/query-434f7cb51a7d22948cd26e962679a67936d572f8046d3a1c7a4f100ff209d81d.json deleted file mode 100644 index 7615523f92f1..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-434f7cb51a7d22948cd26e962679a67936d572f8046d3a1c7a4f100ff209d81d.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE prover_jobs_fri SET status = $1\n WHERE l1_batch_number = $2\n AND sequence_number = $3\n AND aggregation_round = $4\n AND circuit_id = $5", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Int8", - "Int4", - "Int2", - "Int2" - ] - }, - "nullable": [] - }, - "hash": "434f7cb51a7d22948cd26e962679a67936d572f8046d3a1c7a4f100ff209d81d" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-73266a8526c6adc315900e2e95441976a264759c4060c1a38e466ee2052fc17d.json b/prover/crates/lib/prover_dal/.sqlx/query-73266a8526c6adc315900e2e95441976a264759c4060c1a38e466ee2052fc17d.json new file mode 100644 index 000000000000..f8b141a8dac9 --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-73266a8526c6adc315900e2e95441976a264759c4060c1a38e466ee2052fc17d.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n recursion_tip_witness_jobs_fri (l1_batch_number, status, number_of_final_node_jobs, created_at, updated_at)\n VALUES\n ($1, 'waiting_for_proofs', 1, NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET\n status = $2\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Text" + ] + }, + "nullable": [] + }, + "hash": "73266a8526c6adc315900e2e95441976a264759c4060c1a38e466ee2052fc17d" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-9730c8225ff2cf3111185e81f602a4a98ec63eb942c73ce4448d0957346047cd.json b/prover/crates/lib/prover_dal/.sqlx/query-9730c8225ff2cf3111185e81f602a4a98ec63eb942c73ce4448d0957346047cd.json new file mode 100644 index 000000000000..d23ed8d9fc8a --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-9730c8225ff2cf3111185e81f602a4a98ec63eb942c73ce4448d0957346047cd.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE leaf_aggregation_witness_jobs_fri\n SET\n status = $1,\n attempts = $2\n WHERE\n l1_batch_number = $3\n AND circuit_id = $4\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int2", + "Int8", + "Int2" + ] + }, + "nullable": [] + }, + "hash": "9730c8225ff2cf3111185e81f602a4a98ec63eb942c73ce4448d0957346047cd" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-a817f0fec85388b3e2510ce259208a01b63ae4aa03c983c3a52c802d585e5a80.json b/prover/crates/lib/prover_dal/.sqlx/query-a817f0fec85388b3e2510ce259208a01b63ae4aa03c983c3a52c802d585e5a80.json new file mode 100644 index 000000000000..93532150f7f8 --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-a817f0fec85388b3e2510ce259208a01b63ae4aa03c983c3a52c802d585e5a80.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n proof_compression_jobs_fri (l1_batch_number, status, created_at, updated_at)\n VALUES\n ($1, $2, NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET\n status = $2\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Text" + ] + }, + "nullable": [] + }, + "hash": "a817f0fec85388b3e2510ce259208a01b63ae4aa03c983c3a52c802d585e5a80" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-aabcfa9005b8e1d84cfa083a47a700302981be0afef31a8864613484f8521f9e.json b/prover/crates/lib/prover_dal/.sqlx/query-aabcfa9005b8e1d84cfa083a47a700302981be0afef31a8864613484f8521f9e.json deleted file mode 100644 index 3d60050c92ed..000000000000 --- a/prover/crates/lib/prover_dal/.sqlx/query-aabcfa9005b8e1d84cfa083a47a700302981be0afef31a8864613484f8521f9e.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE prover_jobs_fri \n SET status = $1, attempts = $2\n WHERE l1_batch_number = $3\n AND sequence_number =$4\n AND aggregation_round = $5\n AND circuit_id = $6", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Int2", - "Int8", - "Int4", - "Int2", - "Int2" - ] - }, - "nullable": [] - }, - "hash": "aabcfa9005b8e1d84cfa083a47a700302981be0afef31a8864613484f8521f9e" -} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-c8daa62b3835c15fafb3f83deabb5a4672ad50a9de92c84d939ac4c69842e355.json b/prover/crates/lib/prover_dal/.sqlx/query-c8daa62b3835c15fafb3f83deabb5a4672ad50a9de92c84d939ac4c69842e355.json new file mode 100644 index 000000000000..cadc931fa1ca --- /dev/null +++ b/prover/crates/lib/prover_dal/.sqlx/query-c8daa62b3835c15fafb3f83deabb5a4672ad50a9de92c84d939ac4c69842e355.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n node_aggregation_witness_jobs_fri (l1_batch_number, circuit_id, status, created_at, updated_at)\n VALUES\n ($1, $2, 'waiting_for_proofs', NOW(), NOW())\n ON CONFLICT (l1_batch_number, circuit_id, depth) DO\n UPDATE\n SET\n status = $3\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int2", + "Text" + ] + }, + "nullable": [] + }, + "hash": "c8daa62b3835c15fafb3f83deabb5a4672ad50a9de92c84d939ac4c69842e355" +} diff --git a/prover/crates/lib/prover_dal/.sqlx/query-63cf7038e6c48af8ed9afc7d6ea07edd87cb16a79c13e7d4291d99736e51d3b9.json b/prover/crates/lib/prover_dal/.sqlx/query-e875dcbbdaed6998dbea45d4eab5d005d8760c4809b7aef902155196873da66e.json similarity index 82% rename from prover/crates/lib/prover_dal/.sqlx/query-63cf7038e6c48af8ed9afc7d6ea07edd87cb16a79c13e7d4291d99736e51d3b9.json rename to prover/crates/lib/prover_dal/.sqlx/query-e875dcbbdaed6998dbea45d4eab5d005d8760c4809b7aef902155196873da66e.json index 208b23d939f8..4ee9278fe42a 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-63cf7038e6c48af8ed9afc7d6ea07edd87cb16a79c13e7d4291d99736e51d3b9.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-e875dcbbdaed6998dbea45d4eab5d005d8760c4809b7aef902155196873da66e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n scheduler_witness_jobs_fri (\n l1_batch_number,\n scheduler_partial_input_blob_url,\n status,\n created_at,\n updated_at\n )\n VALUES\n ($1, '', 'waiting_for_proofs', NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET status = $2\n ", + "query": "\n INSERT INTO\n scheduler_witness_jobs_fri (\n l1_batch_number,\n scheduler_partial_input_blob_url,\n status,\n created_at,\n updated_at\n )\n VALUES\n ($1, '', 'waiting_for_proofs', NOW(), NOW())\n ON CONFLICT (l1_batch_number) DO\n UPDATE\n SET\n status = $2\n ", "describe": { "columns": [], "parameters": { @@ -11,5 +11,5 @@ }, "nullable": [] }, - "hash": "63cf7038e6c48af8ed9afc7d6ea07edd87cb16a79c13e7d4291d99736e51d3b9" + "hash": "e875dcbbdaed6998dbea45d4eab5d005d8760c4809b7aef902155196873da66e" } diff --git a/prover/crates/lib/prover_dal/.sqlx/query-0eac6f7b2d799059328584029b437891598dc79b5ed11258b2c90c3f282929ad.json b/prover/crates/lib/prover_dal/.sqlx/query-eec29cbff034818f4fb5ec1e6ad38e1010d7389457b3c97e9b238a3a0291a54e.json similarity index 78% rename from prover/crates/lib/prover_dal/.sqlx/query-0eac6f7b2d799059328584029b437891598dc79b5ed11258b2c90c3f282929ad.json rename to prover/crates/lib/prover_dal/.sqlx/query-eec29cbff034818f4fb5ec1e6ad38e1010d7389457b3c97e9b238a3a0291a54e.json index 61518273b4d3..f8e92b1ad666 100644 --- a/prover/crates/lib/prover_dal/.sqlx/query-0eac6f7b2d799059328584029b437891598dc79b5ed11258b2c90c3f282929ad.json +++ b/prover/crates/lib/prover_dal/.sqlx/query-eec29cbff034818f4fb5ec1e6ad38e1010d7389457b3c97e9b238a3a0291a54e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n leaf_aggregation_witness_jobs_fri (\n l1_batch_number,\n circuit_id,\n status,\n number_of_basic_circuits,\n created_at,\n updated_at\n )\n VALUES\n ($1, $2, 'waiting_for_proofs', 2, NOW(), NOW())\n ON CONFLICT (l1_batch_number, circuit_id) DO\n UPDATE\n SET status = $3\n ", + "query": "\n INSERT INTO\n leaf_aggregation_witness_jobs_fri (\n l1_batch_number,\n circuit_id,\n status,\n number_of_basic_circuits,\n created_at,\n updated_at\n )\n VALUES\n ($1, $2, 'waiting_for_proofs', 2, NOW(), NOW())\n ON CONFLICT (l1_batch_number, circuit_id) DO\n UPDATE\n SET\n status = $3\n ", "describe": { "columns": [], "parameters": { @@ -12,5 +12,5 @@ }, "nullable": [] }, - "hash": "0eac6f7b2d799059328584029b437891598dc79b5ed11258b2c90c3f282929ad" + "hash": "eec29cbff034818f4fb5ec1e6ad38e1010d7389457b3c97e9b238a3a0291a54e" } From b5c7544c3e48370b0fca6bc6ade93c44a798f766 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 25 Sep 2024 11:43:22 -0300 Subject: [PATCH 35/72] Fix lints and format --- .../system-constants-generator/src/utils.rs | 7 +- core/lib/contracts/src/lib.rs | 1 - .../lib/dal/src/models/storage_transaction.rs | 5 +- .../src/versions/vm_fast/tests/rollbacks.rs | 3 +- .../tests/tester/transaction_test_info.rs | 2 +- core/lib/multivm/src/versions/vm_latest/vm.rs | 3 +- core/lib/types/src/l2/mod.rs | 7 +- core/lib/types/src/lib.rs | 4 +- core/lib/types/src/system_contracts.rs | 12 +-- core/lib/types/src/transaction_request.rs | 4 +- core/node/eth_sender/src/eth_tx_aggregator.rs | 4 +- core/node/state_keeper/src/updates/mod.rs | 2 +- docs/guides/external-node/00_quick_start.md | 3 +- .../crates/lib/prover_dal/src/cli_test_dal.rs | 99 ++++++++++--------- .../src/fri_witness_generator_dal.rs | 15 ++- 15 files changed, 92 insertions(+), 79 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index a11590729aec..002836b5d962 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, rc::Rc, str::FromStr}; +use std::{cell::RefCell, rc::Rc}; use once_cell::sync::Lazy; use zksync_config::configs::use_evm_simulator; @@ -26,9 +26,8 @@ use zksync_types::{ block::L2BlockHasher, ethabi::Token, fee::Fee, fee_model::BatchFeeInput, l1::L1Tx, l2::L2Tx, utils::storage_key_for_eth_balance, AccountTreeId, Address, Execute, K256PrivateKey, L1BatchNumber, L1TxCommonData, L2BlockNumber, L2ChainId, Nonce, ProtocolVersionId, StorageKey, - Transaction, BOOTLOADER_ADDRESS, H256, SYSTEM_CONTEXT_ADDRESS, - SYSTEM_CONTEXT_GAS_PRICE_POSITION, SYSTEM_CONTEXT_TX_ORIGIN_POSITION, U256, - ZKPORTER_IS_AVAILABLE, + Transaction, BOOTLOADER_ADDRESS, SYSTEM_CONTEXT_ADDRESS, SYSTEM_CONTEXT_GAS_PRICE_POSITION, + SYSTEM_CONTEXT_TX_ORIGIN_POSITION, U256, ZKPORTER_IS_AVAILABLE, }; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, u256_to_h256}; diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 2fd8bf44c24c..33c811277dfd 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -8,7 +8,6 @@ use std::{ fs::{self, File}, io::BufReader, path::{Path, PathBuf}, - str::FromStr, }; use ethabi::{ diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 6dc9c5c7a924..7106b0dadf21 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -367,8 +367,9 @@ impl From for TransactionReceipt { .and_then(|addr| { serde_json::from_value::>(addr) .expect("invalid address value in the database") - // For better compatibility with various clients, we never return null. - }).or_else(|| Some(Address::zero())), + // For better compatibility with various clients, we never return null. + }) + .or_else(|| Some(Address::zero())), cumulative_gas_used: Default::default(), // TODO: Should be actually calculated (SMA-1183). gas_used: { let refunded_gas: U256 = storage_receipt.refunded_gas.into(); diff --git a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs index 81d7303b74dc..548bf8daadfc 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs @@ -152,7 +152,8 @@ fn test_vm_loadnext_rollbacks() { TxModifier::NonceReused( loadnext_deploy_tx.initiator_account(), loadnext_deploy_tx.nonce().unwrap(), - ), + ) + .into(), ), TransactionTestInfo::new_processed(loadnext_tx_1, false), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), diff --git a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs index 5cc9ead8b548..46def9e52499 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs @@ -1,6 +1,6 @@ use std::fmt; -use zksync_types::{ExecuteTransactionCommon, Transaction, H160, U256}; +use zksync_types::{ExecuteTransactionCommon, Nonce, Transaction, H160, U256}; use zksync_vm2::interface::{Event, StateInterface}; use super::VmTester; diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index 48020a329ef5..e66ff00e885f 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -4,8 +4,7 @@ use zksync_types::{ vm::VmVersion, Transaction, H256, }; -use zksync_utils::{be_words_to_bytes, h256_to_u256}; -use zksync_utils::u256_to_h256; +use zksync_utils::{be_words_to_bytes, h256_to_u256, u256_to_h256}; use crate::{ glue::GlueInto, diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index 110a90c44242..106a0afd2c40 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -218,8 +218,11 @@ impl L2Tx { let raw = req.get_signed_bytes(&sig).context("get_signed_bytes")?; let (req, hash) = TransactionRequest::from_bytes_unverified(&raw).context("from_bytes_unverified()")?; - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; - let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator).context("from_request_unverified()")?; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; + let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator) + .context("from_request_unverified()")?; tx.set_input(raw, hash); Ok(tx) } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 1e38b63dcdda..6b7d3b2e2ab0 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -391,7 +391,9 @@ impl TryFrom for Transaction { abi::Transaction::L2(raw) => { let (req, hash) = transaction_request::TransactionRequest::from_bytes_unverified(&raw)?; - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator)?; tx.set_input(raw, hash); tx.into() diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index f92ff7c0c518..dd0355cd8435 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, str::FromStr}; +use std::path::PathBuf; use once_cell::sync::Lazy; use zksync_basic_types::{AccountTreeId, Address, H256, U256}; @@ -208,15 +208,14 @@ static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { SYSTEM_CONTRACT_LIST .iter() .filter_map(|(path, name, address, contract_lang)| { - let result = if *name == "EvmGasManager" && !evm_simulator_is_used { + if *name == "EvmGasManager" && !evm_simulator_is_used { None } else { Some(DeployedContract { account_id: AccountTreeId::new(*address), bytecode: read_sys_contract_bytecode(path, name, contract_lang.clone()), }) - }; - result + } }) .collect::>() }); @@ -235,15 +234,14 @@ pub fn get_system_smart_contracts_from_dir(path: PathBuf) -> Vec>() } diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index d51378452dda..0ec77d5016d9 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -855,7 +855,9 @@ impl L2Tx { value: TransactionRequest, max_tx_size: usize, ) -> Result { - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env().unwrap().use_evm_simulator; + let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() + .unwrap() + .use_evm_simulator; let tx = Self::from_request_unverified(value, use_evm_simulator)?; tx.check_encoded_size(max_tx_size)?; Ok(tx) diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 54c6c698e270..be73188f8e89 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use tokio::sync::watch; use zksync_config::configs::{ eth_sender::SenderConfig, @@ -189,7 +187,7 @@ impl EthTxAggregator { calldata: get_l2_default_aa_hash_input, }; - let mut get_l2_evm_simulator_hash_input = self + let get_l2_evm_simulator_hash_input = self .functions .get_evm_simulator_bytecode_hash .as_ref() diff --git a/core/node/state_keeper/src/updates/mod.rs b/core/node/state_keeper/src/updates/mod.rs index 0761e36a97c9..59267b976dbe 100644 --- a/core/node/state_keeper/src/updates/mod.rs +++ b/core/node/state_keeper/src/updates/mod.rs @@ -236,10 +236,10 @@ mod tests { tx, create_execution_result([]), vec![], + vec![], new_block_gas_count(), VmExecutionMetrics::default(), vec![], - vec![], ); // Check that only pending state is updated. diff --git a/docs/guides/external-node/00_quick_start.md b/docs/guides/external-node/00_quick_start.md index 75d8ba891512..287a4d2d47c0 100644 --- a/docs/guides/external-node/00_quick_start.md +++ b/docs/guides/external-node/00_quick_start.md @@ -34,8 +34,7 @@ cd docker-compose-examples docker compose --file testnet-external-node-docker-compose.yml down --volumes ``` -You can see the status of the node (after recovery) in -[local grafana dashboard](http://localhost:3000/dashboards). +You can see the status of the node (after recovery) in [local grafana dashboard](http://localhost:3000/dashboards). Those commands start ZKsync node locally inside docker. diff --git a/prover/crates/lib/prover_dal/src/cli_test_dal.rs b/prover/crates/lib/prover_dal/src/cli_test_dal.rs index 19fe0e4f57b0..d08418203378 100644 --- a/prover/crates/lib/prover_dal/src/cli_test_dal.rs +++ b/prover/crates/lib/prover_dal/src/cli_test_dal.rs @@ -21,11 +21,16 @@ impl CliTestDal<'_, '_> { sequence_number: usize, ) { sqlx::query!( - "UPDATE prover_jobs_fri SET status = $1 - WHERE l1_batch_number = $2 + r#" + UPDATE prover_jobs_fri + SET + status = $1 + WHERE + l1_batch_number = $2 AND sequence_number = $3 AND aggregation_round = $4 - AND circuit_id = $5", + AND circuit_id = $5 + "#, status.to_string(), batch_number.0 as i64, sequence_number as i64, @@ -44,7 +49,7 @@ impl CliTestDal<'_, '_> { circuit_id: u8, ) { sqlx::query!( - " + r#" INSERT INTO leaf_aggregation_witness_jobs_fri ( l1_batch_number, @@ -58,8 +63,9 @@ impl CliTestDal<'_, '_> { ($1, $2, 'waiting_for_proofs', 2, NOW(), NOW()) ON CONFLICT (l1_batch_number, circuit_id) DO UPDATE - SET status = $3 - ", + SET + status = $3 + "#, batch_number.0 as i64, circuit_id as i16, status.to_string() @@ -76,21 +82,16 @@ impl CliTestDal<'_, '_> { circuit_id: u8, ) { sqlx::query!( - " + r#" INSERT INTO - node_aggregation_witness_jobs_fri ( - l1_batch_number, - circuit_id, - status, - created_at, - updated_at - ) + node_aggregation_witness_jobs_fri (l1_batch_number, circuit_id, status, created_at, updated_at) VALUES ($1, $2, 'waiting_for_proofs', NOW(), NOW()) ON CONFLICT (l1_batch_number, circuit_id, depth) DO UPDATE - SET status = $3 - ", + SET + status = $3 + "#, batch_number.0 as i64, circuit_id as i16, status.to_string(), @@ -102,21 +103,16 @@ impl CliTestDal<'_, '_> { pub async fn insert_rt_job(&mut self, status: WitnessJobStatus, batch_number: L1BatchNumber) { sqlx::query!( - " + r#" INSERT INTO - recursion_tip_witness_jobs_fri ( - l1_batch_number, - status, - number_of_final_node_jobs, - created_at, - updated_at - ) + recursion_tip_witness_jobs_fri (l1_batch_number, status, number_of_final_node_jobs, created_at, updated_at) VALUES - ($1, 'waiting_for_proofs',1, NOW(), NOW()) + ($1, 'waiting_for_proofs', 1, NOW(), NOW()) ON CONFLICT (l1_batch_number) DO UPDATE - SET status = $2 - ", + SET + status = $2 + "#, batch_number.0 as i64, status.to_string(), ) @@ -131,7 +127,7 @@ impl CliTestDal<'_, '_> { batch_number: L1BatchNumber, ) { sqlx::query!( - " + r#" INSERT INTO scheduler_witness_jobs_fri ( l1_batch_number, @@ -144,8 +140,9 @@ impl CliTestDal<'_, '_> { ($1, '', 'waiting_for_proofs', NOW(), NOW()) ON CONFLICT (l1_batch_number) DO UPDATE - SET status = $2 - ", + SET + status = $2 + "#, batch_number.0 as i64, status.to_string(), ) @@ -160,20 +157,16 @@ impl CliTestDal<'_, '_> { batch_number: L1BatchNumber, ) { sqlx::query!( - " + r#" INSERT INTO - proof_compression_jobs_fri ( - l1_batch_number, - status, - created_at, - updated_at - ) + proof_compression_jobs_fri (l1_batch_number, status, created_at, updated_at) VALUES ($1, $2, NOW(), NOW()) ON CONFLICT (l1_batch_number) DO UPDATE - SET status = $2 - ", + SET + status = $2 + "#, batch_number.0 as i64, status.to_string(), ) @@ -192,12 +185,17 @@ impl CliTestDal<'_, '_> { sequence_number: usize, ) { sqlx::query!( - "UPDATE prover_jobs_fri - SET status = $1, attempts = $2 - WHERE l1_batch_number = $3 - AND sequence_number =$4 + r#" + UPDATE prover_jobs_fri + SET + status = $1, + attempts = $2 + WHERE + l1_batch_number = $3 + AND sequence_number = $4 AND aggregation_round = $5 - AND circuit_id = $6", + AND circuit_id = $6 + "#, status.to_string(), attempts as i64, batch_number.0 as i64, @@ -218,10 +216,15 @@ impl CliTestDal<'_, '_> { batch_number: L1BatchNumber, ) { sqlx::query!( - "UPDATE leaf_aggregation_witness_jobs_fri - SET status = $1, attempts = $2 - WHERE l1_batch_number = $3 - AND circuit_id = $4", + r#" + UPDATE leaf_aggregation_witness_jobs_fri + SET + status = $1, + attempts = $2 + WHERE + l1_batch_number = $3 + AND circuit_id = $4 + "#, status.to_string(), attempts as i64, batch_number.0 as i64, diff --git a/prover/crates/lib/prover_dal/src/fri_witness_generator_dal.rs b/prover/crates/lib/prover_dal/src/fri_witness_generator_dal.rs index 66e34f7f8e75..c7ba0f60ef3f 100644 --- a/prover/crates/lib/prover_dal/src/fri_witness_generator_dal.rs +++ b/prover/crates/lib/prover_dal/src/fri_witness_generator_dal.rs @@ -1719,7 +1719,10 @@ impl FriWitnessGeneratorDal<'_, '_> { WHERE l1_batch_number = $1 AND attempts >= $2 - AND (status = 'in_progress' OR status = 'failed') + AND ( + status = 'in_progress' + OR status = 'failed' + ) RETURNING l1_batch_number, status, @@ -1786,7 +1789,10 @@ impl FriWitnessGeneratorDal<'_, '_> { WHERE l1_batch_number = $1 AND attempts >= $2 - AND (status = 'in_progress' OR status = 'failed') + AND ( + status = 'in_progress' + OR status = 'failed' + ) RETURNING l1_batch_number, status, @@ -1827,7 +1833,10 @@ impl FriWitnessGeneratorDal<'_, '_> { WHERE l1_batch_number = $1 AND attempts >= $2 - AND (status = 'in_progress' OR status = 'failed') + AND ( + status = 'in_progress' + OR status = 'failed' + ) RETURNING l1_batch_number, status, From 653b5433c797d6b910d7ded42165f84ce6476ee1 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 25 Sep 2024 12:08:15 -0300 Subject: [PATCH 36/72] Add evm simulator config to load config function --- core/bin/zksync_server/src/main.rs | 2 ++ core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index 84898d6da067..748a9437ed27 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -11,6 +11,7 @@ use zksync_config::{ }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, + use_evm_simulator::UseEvmSimulator, BasicWitnessInputProducerConfig, ContractsConfig, DatabaseSecrets, ExperimentalVmConfig, ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig, FriProverGatewayConfig, FriWitnessGeneratorConfig, FriWitnessVectorGeneratorConfig, @@ -205,6 +206,7 @@ fn load_env_config() -> anyhow::Result { basic_witness_input_producer_config: BasicWitnessInputProducerConfig::from_env().ok(), core_object_store: ObjectStoreConfig::from_env().ok(), base_token_adjuster_config: BaseTokenAdjusterConfig::from_env().ok(), + use_evm_simulator: UseEvmSimulator::from_env().ok(), commitment_generator: None, pruning: None, snapshot_recovery: None, 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 2d6af705f482..90c3750e3261 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 @@ -10,6 +10,7 @@ use zksync_config::{ }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, + use_evm_simulator::UseEvmSimulator, vm_runner::BasicWitnessInputProducerConfig, wallets::{AddressWallet, EthSender, StateKeeper, TokenMultiplierSetter, Wallet, Wallets}, CommitmentGeneratorConfig, DatabaseSecrets, ExperimentalVmConfig, @@ -75,6 +76,7 @@ pub struct TempConfigStore { pub core_object_store: Option, pub base_token_adjuster_config: Option, pub commitment_generator: Option, + pub use_evm_simulator: Option, pub pruning: Option, pub snapshot_recovery: Option, pub external_price_api_client_config: Option, @@ -196,6 +198,7 @@ fn load_env_config() -> anyhow::Result { basic_witness_input_producer_config: BasicWitnessInputProducerConfig::from_env().ok(), core_object_store: ObjectStoreConfig::from_env().ok(), base_token_adjuster_config: BaseTokenAdjusterConfig::from_env().ok(), + use_evm_simulator: UseEvmSimulator::from_env().ok(), commitment_generator: None, pruning: None, snapshot_recovery: None, From d2d61a4108f812d254702f130be61728a21be337 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 25 Sep 2024 13:07:57 -0300 Subject: [PATCH 37/72] Add evm simulator to general test config and protobuf message --- core/lib/config/src/configs/general.rs | 2 ++ core/lib/config/src/testonly.rs | 9 +++++++++ core/lib/protobuf_config/src/general.rs | 2 ++ core/lib/protobuf_config/src/lib.rs | 1 + .../src/proto/config/general.proto | 2 ++ .../src/proto/config/use_evm_simulator.proto | 7 +++++++ .../protobuf_config/src/use_evm_simulator.rs | 20 +++++++++++++++++++ .../src/temp_config_store/mod.rs | 1 + 8 files changed, 44 insertions(+) create mode 100644 core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto create mode 100644 core/lib/protobuf_config/src/use_evm_simulator.rs diff --git a/core/lib/config/src/configs/general.rs b/core/lib/config/src/configs/general.rs index bb733510f77d..b7c78cbdb700 100644 --- a/core/lib/config/src/configs/general.rs +++ b/core/lib/config/src/configs/general.rs @@ -10,6 +10,7 @@ use crate::{ prover_job_monitor::ProverJobMonitorConfig, pruning::PruningConfig, snapshot_recovery::SnapshotRecoveryConfig, + use_evm_simulator::UseEvmSimulator, vm_runner::{BasicWitnessInputProducerConfig, ProtectiveReadsWriterConfig}, CommitmentGeneratorConfig, ExperimentalVmConfig, ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig, FriProverGatewayConfig, @@ -51,6 +52,7 @@ pub struct GeneralConfig { pub pruning: Option, pub core_object_store: Option, pub base_token_adjuster: Option, + pub use_evm_simulator: Option, pub external_price_api_client_config: Option, pub consensus_config: Option, pub external_proof_integration_api_config: Option, diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 1884b30b5f9a..e05459aa7858 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -40,6 +40,14 @@ impl Sample for Network { } } +impl Distribution for EncodeDist { + fn sample(&self, rng: &mut R) -> configs::use_evm_simulator::UseEvmSimulator { + configs::use_evm_simulator::UseEvmSimulator { + use_evm_simulator: rng.gen(), + } + } +} + impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> configs::chain::FeeModelVersion { type T = configs::chain::FeeModelVersion; @@ -1154,6 +1162,7 @@ impl Distribution for EncodeDist { protective_reads_writer_config: self.sample(rng), basic_witness_input_producer_config: self.sample(rng), commitment_generator: self.sample(rng), + use_evm_simulator: self.sample(rng), snapshot_recovery: self.sample(rng), pruning: self.sample(rng), core_object_store: self.sample(rng), diff --git a/core/lib/protobuf_config/src/general.rs b/core/lib/protobuf_config/src/general.rs index b73539a0897f..736420e34268 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), + use_evm_simulator: read_optional_repr(&self.use_evm_simulator), }) } @@ -102,6 +103,7 @@ impl ProtoRepr for proto::GeneralConfig { .as_ref() .map(ProtoRepr::build), experimental_vm: this.experimental_vm_config.as_ref().map(ProtoRepr::build), + use_evm_simulator: this.use_evm_simulator.as_ref().map(ProtoRepr::build), prover_job_monitor: this .prover_job_monitor_config .as_ref() diff --git a/core/lib/protobuf_config/src/lib.rs b/core/lib/protobuf_config/src/lib.rs index a4822edbe8e4..c1a65ee55b6d 100644 --- a/core/lib/protobuf_config/src/lib.rs +++ b/core/lib/protobuf_config/src/lib.rs @@ -28,6 +28,7 @@ mod prover; mod pruning; mod secrets; mod snapshots_creator; +mod use_evm_simulator; mod da_client; mod external_price_api_client; diff --git a/core/lib/protobuf_config/src/proto/config/general.proto b/core/lib/protobuf_config/src/proto/config/general.proto index ee70b61b18b3..c3f7c88cf850 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/use_evm_simulator.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 use_evm_simulator.UseEvmSimulator use_evm_simulator = 47; } diff --git a/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto b/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto new file mode 100644 index 000000000000..f0ca7329f903 --- /dev/null +++ b/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package zksync.config.use_evm_simulator; + +message UseEvmSimulator { + optional bool use_evm_simulator = 1; +} diff --git a/core/lib/protobuf_config/src/use_evm_simulator.rs b/core/lib/protobuf_config/src/use_evm_simulator.rs new file mode 100644 index 000000000000..703b8f8cc3ce --- /dev/null +++ b/core/lib/protobuf_config/src/use_evm_simulator.rs @@ -0,0 +1,20 @@ +use zksync_config::configs::{self}; +use zksync_protobuf::ProtoRepr; + +use crate::proto::use_evm_simulator as proto; + +impl ProtoRepr for proto::UseEvmSimulator { + type Type = configs::use_evm_simulator::UseEvmSimulator; + + fn read(&self) -> anyhow::Result { + Ok(configs::use_evm_simulator::UseEvmSimulator { + use_evm_simulator: self.use_evm_simulator.unwrap_or_default(), + }) + } + + fn build(this: &Self::Type) -> Self { + Self { + use_evm_simulator: Some(this.use_evm_simulator), + } + } +} 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 90c3750e3261..47f6e6a2241c 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 @@ -119,6 +119,7 @@ impl TempConfigStore { pruning: self.pruning.clone(), external_price_api_client_config: self.external_price_api_client_config.clone(), consensus_config: None, + use_evm_simulator: self.use_evm_simulator.clone(), external_proof_integration_api_config: self .external_proof_integration_api_config .clone(), From 44e714b9b27a58939c54e7377f330e4afd05acc7 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 25 Sep 2024 13:25:54 -0300 Subject: [PATCH 38/72] Add use evm simulator config to general config file --- etc/env/file_based/general.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index cdf02175458b..23455ecc972d 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -305,6 +305,9 @@ external_price_api_client: house_keeper: l1_batch_metrics_reporting_interval_ms: 10000 +use_evm_simulator: + use_evm_simulator: false + prometheus: listener_port: 3314 pushgateway_url: http://127.0.0.1:9091 From e4aee9bd5703004c481af438eb9cf48b43125a74 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 26 Sep 2024 11:18:28 +0300 Subject: [PATCH 39/72] Make EVM simulator optional --- Cargo.lock | 4 - core/bin/genesis_generator/src/main.rs | 2 +- .../bin/system-constants-generator/Cargo.toml | 2 - .../system-constants-generator/src/utils.rs | 43 +-- core/lib/contracts/src/lib.rs | 34 +-- core/lib/dal/src/blocks_dal.rs | 6 +- core/lib/dal/src/factory_deps_dal.rs | 24 +- core/lib/dal/src/models/storage_block.rs | 13 +- .../src/models/storage_protocol_version.rs | 18 +- core/lib/dal/src/models/storage_sync.rs | 6 +- core/lib/dal/src/protocol_versions_dal.rs | 10 +- core/lib/dal/src/tests/mod.rs | 2 +- core/lib/multivm/Cargo.toml | 4 +- .../vm_fast/tests/get_used_contracts.rs | 7 +- .../vm_latest/tests/get_used_contracts.rs | 8 +- .../vm_latest/tracers/evm_deploy_tracer.rs | 3 +- .../vm_latest/types/internals/vm_state.rs | 28 +- core/lib/prover_interface/src/inputs.rs | 3 +- core/lib/tee_verifier/src/lib.rs | 4 +- core/lib/types/src/api/mod.rs | 6 +- core/lib/types/src/commitment/mod.rs | 14 +- core/lib/types/src/protocol_upgrade.rs | 2 +- .../node/api_server/src/web3/namespaces/en.rs | 10 +- core/node/eth_sender/Cargo.toml | 1 - core/node/eth_sender/src/eth_tx_aggregator.rs | 26 +- core/node/eth_sender/src/tests.rs | 6 +- core/node/genesis/src/lib.rs | 11 +- core/node/genesis/src/utils.rs | 13 +- core/node/node_sync/src/external_io.rs | 20 +- core/node/node_sync/src/genesis.rs | 25 +- core/node/node_sync/src/tests.rs | 2 +- core/node/proof_data_handler/src/tests.rs | 4 +- core/node/test_utils/src/lib.rs | 15 +- core/node/vm_runner/src/impls/bwip.rs | 26 +- core/node/vm_runner/src/tests/mod.rs | 10 +- .../vm_runner/src/tests/output_handler.rs | 4 +- prover/Cargo.lock | 262 ------------------ 37 files changed, 180 insertions(+), 498 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 871af4bc8765..2f80479a9ce2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7494,9 +7494,7 @@ dependencies = [ "once_cell", "serde", "serde_json", - "zksync_config", "zksync_contracts", - "zksync_env_config", "zksync_multivm", "zksync_types", "zksync_utils", @@ -9815,7 +9813,6 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_dal", - "zksync_env_config", "zksync_eth_client", "zksync_l1_contract_interface", "zksync_node_fee_model", @@ -10166,7 +10163,6 @@ dependencies = [ "zksync_contracts", "zksync_env_config", "zksync_eth_signer", - "zksync_state", "zksync_system_constants", "zksync_test_account", "zksync_types", diff --git a/core/bin/genesis_generator/src/main.rs b/core/bin/genesis_generator/src/main.rs index c90daac46b1c..405fcf64234b 100644 --- a/core/bin/genesis_generator/src/main.rs +++ b/core/bin/genesis_generator/src/main.rs @@ -91,7 +91,7 @@ async fn generate_new_config( genesis_commitment: None, bootloader_hash: Some(base_system_contracts.bootloader), default_aa_hash: Some(base_system_contracts.default_aa), - evm_simulator_hash: Some(base_system_contracts.evm_simulator), + evm_simulator_hash: base_system_contracts.evm_simulator, ..genesis_config }; diff --git a/core/bin/system-constants-generator/Cargo.toml b/core/bin/system-constants-generator/Cargo.toml index 39f4b458817d..7177d29ca743 100644 --- a/core/bin/system-constants-generator/Cargo.toml +++ b/core/bin/system-constants-generator/Cargo.toml @@ -15,8 +15,6 @@ zksync_types.workspace = true zksync_utils.workspace = true zksync_contracts.workspace = true zksync_multivm.workspace = true -zksync_config.workspace = true -zksync_env_config.workspace = true codegen.workspace = true serde.workspace = true diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 002836b5d962..87fcb7171c5b 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -1,12 +1,10 @@ use std::{cell::RefCell, rc::Rc}; use once_cell::sync::Lazy; -use zksync_config::configs::use_evm_simulator; use zksync_contracts::{ load_sys_contract, read_bootloader_code, read_bytecode_from_path, read_sys_contract_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, }; -use zksync_env_config::FromEnv; use zksync_multivm::{ interface::{ storage::{InMemoryStorage, StorageView, WriteStorage}, @@ -74,31 +72,13 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); - let (evm_simulator_bytecode, evm_simulator_hash) = - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - ( - evm_simulator_bytecode.clone(), - hash_bytecode(&evm_simulator_bytecode), - ) - } else { - (bytecode.clone(), hash) - }; - BaseSystemContracts { default_aa: SystemContractCode { code: bytes_to_be_words(bytecode), hash, }, bootloader, - evm_simulator: SystemContractCode { - code: bytes_to_be_words(evm_simulator_bytecode), - hash: evm_simulator_hash, - }, + evm_simulator: None, } }); @@ -240,29 +220,10 @@ pub(super) fn execute_internal_transfer_test() -> u32 { hash, }; - let (evm_simulator_bytecode, evm_simulator_hash) = - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - ( - evm_simulator_bytecode.clone(), - hash_bytecode(&evm_simulator_bytecode), - ) - } else { - (bytecode.clone(), hash) - }; - let evm_simulator = SystemContractCode { - code: bytes_to_be_words(evm_simulator_bytecode), - hash: evm_simulator_hash, - }; - let base_system_smart_contracts = BaseSystemContracts { bootloader, default_aa, - evm_simulator, + evm_simulator: None, }; let system_env = SystemEnv { diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 33c811277dfd..8166b29e884c 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -16,8 +16,6 @@ use ethabi::{ }; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use zksync_config::configs::use_evm_simulator::{self}; -use zksync_env_config::FromEnv; use zksync_utils::{bytecode::hash_bytecode, bytes_to_be_words, env::Workspace}; pub mod test_contracts; @@ -309,21 +307,22 @@ pub struct SystemContractCode { pub struct BaseSystemContracts { pub bootloader: SystemContractCode, pub default_aa: SystemContractCode, - pub evm_simulator: SystemContractCode, + pub evm_simulator: Option, } #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)] pub struct BaseSystemContractsHashes { pub bootloader: H256, pub default_aa: H256, - pub evm_simulator: H256, + pub evm_simulator: Option, } impl PartialEq for BaseSystemContracts { fn eq(&self, other: &Self) -> bool { self.bootloader.hash == other.bootloader.hash && self.default_aa.hash == other.default_aa.hash - && self.evm_simulator.hash == other.evm_simulator.hash + && self.evm_simulator.as_ref().map(|contract| contract.hash) + == other.evm_simulator.as_ref().map(|contract| contract.hash) } } @@ -344,31 +343,10 @@ impl BaseSystemContracts { hash, }; - // If evm simulator is not enabled, use the default account bytecode and hash. - let (evm_simulator_bytecode, evm_simulator_hash) = - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - let evm_simulator_bytecode = - read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); - ( - evm_simulator_bytecode.clone(), - hash_bytecode(&evm_simulator_bytecode), - ) - } else { - (bytecode.clone(), hash) - }; - - let evm_simulator = SystemContractCode { - code: bytes_to_be_words(evm_simulator_bytecode), - hash: evm_simulator_hash, - }; - BaseSystemContracts { bootloader, default_aa, - evm_simulator, + evm_simulator: None, } } // BaseSystemContracts with proved bootloader - for handling transactions. @@ -505,7 +483,7 @@ impl BaseSystemContracts { BaseSystemContractsHashes { bootloader: self.bootloader.hash, default_aa: self.default_aa.hash, - evm_simulator: self.evm_simulator.hash, + evm_simulator: self.evm_simulator.as_ref().map(|contract| contract.hash), } } } diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 2ede5005b9f6..3296b4ee8e00 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -663,7 +663,11 @@ impl BlocksDal<'_, '_> { used_contract_hashes, header.base_system_contracts_hashes.bootloader.as_bytes(), header.base_system_contracts_hashes.default_aa.as_bytes(), - header.base_system_contracts_hashes.evm_simulator.as_bytes(), + header + .base_system_contracts_hashes + .evm_simulator + .as_ref() + .map(H256::as_bytes), header.protocol_version.map(|v| v as i32), &system_logs, &storage_refunds, diff --git a/core/lib/dal/src/factory_deps_dal.rs b/core/lib/dal/src/factory_deps_dal.rs index 6731b05166dc..dd082edcf8d7 100644 --- a/core/lib/dal/src/factory_deps_dal.rs +++ b/core/lib/dal/src/factory_deps_dal.rs @@ -94,7 +94,7 @@ impl FactoryDepsDal<'_, '_> { &mut self, bootloader_hash: H256, default_aa_hash: H256, - evm_simulator_hash: H256, + evm_simulator_hash: Option, ) -> anyhow::Result { let bootloader_bytecode = self .get_sealed_factory_dep(bootloader_hash) @@ -117,15 +117,19 @@ impl FactoryDepsDal<'_, '_> { hash: default_aa_hash, }; - let evm_simulator_bytecode = self - .get_sealed_factory_dep(evm_simulator_hash) - .await - .context("failed loading evm simulator code")? - .with_context(|| format!("evm simulator code with hash {default_aa_hash:?} should be present in the database"))?; - - let evm_simulator_code = SystemContractCode { - code: bytes_to_be_words(evm_simulator_bytecode), - hash: evm_simulator_hash, + let evm_simulator_code = if let Some(evm_simulator_hash) = evm_simulator_hash { + let evm_simulator_bytecode = self + .get_sealed_factory_dep(evm_simulator_hash) + .await + .context("failed loading evm simulator code")? + .with_context(|| format!("evm simulator code with hash {default_aa_hash:?} should be present in the database"))?; + + Some(SystemContractCode { + code: bytes_to_be_words(evm_simulator_bytecode), + hash: evm_simulator_hash, + }) + } else { + None }; Ok(BaseSystemContracts { diff --git a/core/lib/dal/src/models/storage_block.rs b/core/lib/dal/src/models/storage_block.rs index a98049e8ac6d..71296c87e4ff 100644 --- a/core/lib/dal/src/models/storage_block.rs +++ b/core/lib/dal/src/models/storage_block.rs @@ -114,9 +114,7 @@ fn convert_base_system_contracts_hashes( default_aa: default_aa_code_hash .map(|hash| H256::from_slice(&hash)) .expect("should not be none"), - evm_simulator: evm_simulator_code_hash - .map(|hash| H256::from_slice(&hash)) - .expect("should not be none"), + evm_simulator: evm_simulator_code_hash.map(|hash| H256::from_slice(&hash)), } } @@ -248,11 +246,10 @@ impl TryFrom for L1BatchMetadata { .default_aa_code_hash .ok_or(L1BatchMetadataError::Incomplete("default_aa_code_hash"))?, ), - evm_simulator_code_hash: H256::from_slice( - &batch - .evm_simulator_code_hash - .ok_or(L1BatchMetadataError::Incomplete("evm_simulator_code_hash"))?, - ), + evm_simulator_code_hash: batch + .evm_simulator_code_hash + .as_deref() + .map(H256::from_slice), protocol_version: batch .protocol_version .map(|v| (v as u16).try_into().unwrap()), diff --git a/core/lib/dal/src/models/storage_protocol_version.rs b/core/lib/dal/src/models/storage_protocol_version.rs index a1a61bd0670f..3dcb64f1b147 100644 --- a/core/lib/dal/src/models/storage_protocol_version.rs +++ b/core/lib/dal/src/models/storage_protocol_version.rs @@ -35,11 +35,10 @@ pub(crate) fn protocol_version_from_storage( base_system_contracts_hashes: BaseSystemContractsHashes { bootloader: H256::from_slice(&storage_version.bootloader_code_hash), default_aa: H256::from_slice(&storage_version.default_account_code_hash), - evm_simulator: H256::from_slice( - &storage_version - .evm_simulator_code_hash - .unwrap_or(H256::zero().as_bytes().to_vec()), - ), + evm_simulator: storage_version + .evm_simulator_code_hash + .as_deref() + .map(H256::from_slice), }, tx, } @@ -67,11 +66,10 @@ impl From for api::ProtocolVersion { storage_protocol_version.timestamp as u64, H256::from_slice(&storage_protocol_version.bootloader_code_hash), H256::from_slice(&storage_protocol_version.default_account_code_hash), - H256::from_slice( - &storage_protocol_version - .evm_simulator_code_hash - .unwrap_or(H256::zero().as_bytes().to_vec()), - ), + storage_protocol_version + .evm_simulator_code_hash + .as_deref() + .map(H256::from_slice), l2_system_upgrade_tx_hash, ) } diff --git a/core/lib/dal/src/models/storage_sync.rs b/core/lib/dal/src/models/storage_sync.rs index 0fb7527aa42a..a3f2ee9a4f0a 100644 --- a/core/lib/dal/src/models/storage_sync.rs +++ b/core/lib/dal/src/models/storage_sync.rs @@ -76,7 +76,11 @@ impl TryFrom for SyncBlock { .decode_column("bootloader_code_hash")?, default_aa: parse_h256_opt(block.default_aa_code_hash.as_deref()) .decode_column("default_aa_code_hash")?, - evm_simulator: parse_h256_opt(block.evm_simulator_code_hash.as_deref()) + evm_simulator: block + .evm_simulator_code_hash + .as_deref() + .map(parse_h256) + .transpose() .decode_column("evm_simulator_code_hash")?, }, fee_account_address: parse_h160(&block.fee_account_address) diff --git a/core/lib/dal/src/protocol_versions_dal.rs b/core/lib/dal/src/protocol_versions_dal.rs index d01ae3a52ac8..792f68eae571 100644 --- a/core/lib/dal/src/protocol_versions_dal.rs +++ b/core/lib/dal/src/protocol_versions_dal.rs @@ -57,7 +57,10 @@ impl ProtocolVersionsDal<'_, '_> { timestamp as i64, base_system_contracts_hashes.bootloader.as_bytes(), base_system_contracts_hashes.default_aa.as_bytes(), - base_system_contracts_hashes.evm_simulator.as_bytes(), + base_system_contracts_hashes + .evm_simulator + .as_ref() + .map(H256::as_bytes), tx_hash.as_ref().map(H256::as_bytes), ) .instrument("save_protocol_version#minor") @@ -215,10 +218,7 @@ impl ProtocolVersionsDal<'_, '_> { .get_base_system_contracts( H256::from_slice(&row.bootloader_code_hash), H256::from_slice(&row.default_account_code_hash), - H256::from_slice( - &row.evm_simulator_code_hash - .unwrap_or(H256::zero().as_bytes().to_vec()), - ), + row.evm_simulator_code_hash.as_deref().map(H256::from_slice), ) .await?; Some(contracts) diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index dd725aeda3ee..0b22c6283070 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -61,7 +61,7 @@ pub(crate) fn create_l1_batch_header(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), - evm_simulator: H256::repeat_byte(43), + evm_simulator: Some(H256::repeat_byte(43)), }, ProtocolVersionId::latest(), ) diff --git a/core/lib/multivm/Cargo.toml b/core/lib/multivm/Cargo.toml index 25649da6b4a9..aa4776a650c0 100644 --- a/core/lib/multivm/Cargo.toml +++ b/core/lib/multivm/Cargo.toml @@ -25,13 +25,12 @@ circuit_sequencer_api_1_4_2.workspace = true circuit_sequencer_api_1_5_0.workspace = true zksync_types.workspace = true -zksync_config.workspace = true +zksync_config.workspace = true # FIXME: remove zksync_env_config.workspace = true zksync_contracts.workspace = true zksync_utils.workspace = true zksync_system_constants.workspace = true zksync_vm_interface.workspace = true -zksync_state.workspace = true anyhow.workspace = true hex.workspace = true @@ -47,5 +46,4 @@ assert_matches.workspace = true pretty_assertions.workspace = true tokio = { workspace = true, features = ["time"] } zksync_test_account.workspace = true -ethabi.workspace = true zksync_eth_signer.workspace = true diff --git a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs index 00c2917c10c8..aa88d7fb0165 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/get_used_contracts.rs @@ -97,8 +97,11 @@ fn known_bytecodes_without_base_system_contracts(vm: &Vm) -> .collect::>(); known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)); - known_bytecodes_without_base_system_contracts - .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.evm_simulator.hash)); + if let Some(evm_simulator) = &BASE_SYSTEM_CONTRACTS.evm_simulator { + let was_removed = + known_bytecodes_without_base_system_contracts.remove(&h256_to_u256(evm_simulator.hash)); + assert!(was_removed); + } known_bytecodes_without_base_system_contracts } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs index 10f4bff22635..5d1ccc52a5a4 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs @@ -159,9 +159,11 @@ fn known_bytecodes_without_base_system_contracts( Timestamp(0), ); - decommittment_processor.populate( - vec![( - h256_to_u256(system_env.base_system_smart_contracts.evm_simulator.hash), - system_env - .base_system_smart_contracts - .evm_simulator - .code - .clone(), - )], - Timestamp(0), - ); + if let Some(evm_simulator) = &system_env.base_system_smart_contracts.evm_simulator { + decommittment_processor.populate( + vec![(h256_to_u256(evm_simulator.hash), evm_simulator.code.clone())], + Timestamp(0), + ); + } memory.populate( vec![( @@ -129,6 +124,13 @@ pub(crate) fn new_vm_state( Timestamp(0), ); + // By convention, default AA is used as a fallback if the EVM simulator is not available. + let evm_simulator_code_hash = system_env + .base_system_smart_contracts + .evm_simulator + .as_ref() + .unwrap_or(&system_env.base_system_smart_contracts.default_aa) + .hash; let mut vm = VmState::empty_state( storage_oracle, memory, @@ -140,9 +142,7 @@ pub(crate) fn new_vm_state( default_aa_code_hash: h256_to_u256( system_env.base_system_smart_contracts.default_aa.hash, ), - evm_simulator_code_hash: h256_to_u256( - system_env.base_system_smart_contracts.evm_simulator.hash, - ), + evm_simulator_code_hash: h256_to_u256(evm_simulator_code_hash), zkporter_is_available: system_env.zk_porter_available, }, ); diff --git a/core/lib/prover_interface/src/inputs.rs b/core/lib/prover_interface/src/inputs.rs index 776ca516aa3b..c9fae5a41ade 100644 --- a/core/lib/prover_interface/src/inputs.rs +++ b/core/lib/prover_interface/src/inputs.rs @@ -144,7 +144,8 @@ pub struct VMRunWitnessInputData { pub protocol_version: ProtocolVersionId, pub bootloader_code: Vec<[u8; 32]>, pub default_account_code_hash: U256, - pub evm_simulator_code_hash: U256, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub evm_simulator_code_hash: Option, pub storage_refunds: Vec, pub pubdata_costs: Vec, pub witness_block_state: WitnessStorageState, diff --git a/core/lib/tee_verifier/src/lib.rs b/core/lib/tee_verifier/src/lib.rs index 348eded90e41..4301508873f6 100644 --- a/core/lib/tee_verifier/src/lib.rs +++ b/core/lib/tee_verifier/src/lib.rs @@ -306,10 +306,10 @@ mod tests { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: SystemContractCode { + evm_simulator: Some(SystemContractCode { code: vec![U256([1; 4])], hash: H256([1; 32]), - }, + }), }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index d0d066999b44..278406fd7269 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -670,7 +670,7 @@ impl ProtocolVersion { timestamp: u64, bootloader_code_hash: H256, default_account_code_hash: H256, - evm_simulator_code_hash: H256, + evm_simulator_code_hash: Option, l2_system_upgrade_tx_hash: Option, ) -> Self { Self { @@ -685,7 +685,7 @@ impl ProtocolVersion { }), bootloader_code_hash: Some(bootloader_code_hash), default_account_code_hash: Some(default_account_code_hash), - evm_simulator_code_hash: Some(evm_simulator_code_hash), + evm_simulator_code_hash, l2_system_upgrade_tx_hash, l2_system_upgrade_tx_hash_new: l2_system_upgrade_tx_hash, } @@ -704,7 +704,7 @@ impl ProtocolVersion { pub fn evm_simulator_code_hash(&self) -> Option { self.evm_simulator_code_hash.or_else(|| { self.base_system_contracts - .map(|hashes| hashes.evm_simulator) + .and_then(|hashes| hashes.evm_simulator) }) } diff --git a/core/lib/types/src/commitment/mod.rs b/core/lib/types/src/commitment/mod.rs index 944c0705f4f8..1c823d7fee1b 100644 --- a/core/lib/types/src/commitment/mod.rs +++ b/core/lib/types/src/commitment/mod.rs @@ -467,7 +467,7 @@ pub struct L1BatchMetaParameters { pub zkporter_is_available: bool, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, - pub evm_simulator_code_hash: H256, + pub evm_simulator_code_hash: Option, pub protocol_version: Option, } @@ -479,7 +479,15 @@ impl L1BatchMetaParameters { result.extend(self.bootloader_code_hash.as_bytes()); result.extend(self.default_aa_code_hash.as_bytes()); - result.extend(self.evm_simulator_code_hash.as_bytes()); + if self + .protocol_version + .map_or(false, |ver| ver.is_post_1_5_0()) + { + let evm_simulator_code_hash = self + .evm_simulator_code_hash + .unwrap_or(self.default_aa_code_hash); + result.extend(evm_simulator_code_hash.as_bytes()); + } result } @@ -648,7 +656,7 @@ pub struct CommitmentCommonInput { pub rollup_root_hash: H256, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, - pub evm_simulator_code_hash: H256, + pub evm_simulator_code_hash: Option, pub protocol_version: ProtocolVersionId, } diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 3766bda51ef3..3de65605ed59 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -305,7 +305,7 @@ impl ProtocolVersion { .unwrap_or(self.base_system_contracts_hashes.default_aa), evm_simulator: upgrade .evm_simulator_code_hash - .unwrap_or(self.base_system_contracts_hashes.evm_simulator), + .or(self.base_system_contracts_hashes.evm_simulator), }, tx: upgrade.tx, } diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index c32ba3685f21..5b39e1ab31c1 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -171,12 +171,10 @@ impl EnNamespace { genesis_commitment: Some(genesis_batch.metadata.commitment), bootloader_hash: Some(genesis_batch.header.base_system_contracts_hashes.bootloader), default_aa_hash: Some(genesis_batch.header.base_system_contracts_hashes.default_aa), - evm_simulator_hash: Some( - genesis_batch - .header - .base_system_contracts_hashes - .evm_simulator, - ), + evm_simulator_hash: genesis_batch + .header + .base_system_contracts_hashes + .evm_simulator, l1_chain_id: self.state.api_config.l1_chain_id, sl_chain_id: Some(self.state.api_config.l1_chain_id.into()), l2_chain_id: self.state.api_config.l2_chain_id, diff --git a/core/node/eth_sender/Cargo.toml b/core/node/eth_sender/Cargo.toml index d58c7488262d..a7aa88c3550e 100644 --- a/core/node/eth_sender/Cargo.toml +++ b/core/node/eth_sender/Cargo.toml @@ -15,7 +15,6 @@ vise.workspace = true zksync_types.workspace = true zksync_dal.workspace = true zksync_config.workspace = true -zksync_env_config.workspace = true zksync_contracts.workspace = true zksync_eth_client.workspace = true zksync_utils.workspace = true diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index be73188f8e89..18d706759398 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -1,11 +1,7 @@ use tokio::sync::watch; -use zksync_config::configs::{ - eth_sender::SenderConfig, - use_evm_simulator::{self}, -}; +use zksync_config::configs::eth_sender::SenderConfig; use zksync_contracts::BaseSystemContractsHashes; use zksync_dal::{Connection, ConnectionPool, Core, CoreDal}; -use zksync_env_config::FromEnv; use zksync_eth_client::{BoundEthInterface, CallFunctionArgs}; use zksync_l1_contract_interface::{ i_executor::{ @@ -148,19 +144,21 @@ impl EthTxAggregator { } pub(super) async fn get_multicall_data(&mut self) -> Result { - let calldata = self.generate_calldata_for_multicall(); + const USE_EVM_SIMULATOR: bool = false; // FIXME: define in an adequate way + + let calldata = self.generate_calldata_for_multicall(USE_EVM_SIMULATOR); let args = CallFunctionArgs::new(&self.functions.aggregate3.name, calldata).for_contract( self.l1_multicall3_address, &self.functions.multicall_contract, ); let aggregate3_result: Token = args.call((*self.eth_client).as_ref()).await?; - self.parse_multicall_data(aggregate3_result) + self.parse_multicall_data(aggregate3_result, USE_EVM_SIMULATOR) } // Multicall's aggregate function accepts 1 argument - arrays of different contract calls. // The role of the method below is to tokenize input for multicall, which is actually a vector of tokens. // Each token describes a specific contract call. - pub(super) fn generate_calldata_for_multicall(&self) -> Vec { + pub(super) fn generate_calldata_for_multicall(&self, use_evm_simulator: bool) -> Vec { const ALLOW_FAILURE: bool = false; // First zksync contract call @@ -193,10 +191,6 @@ impl EthTxAggregator { .as_ref() .and_then(|f| f.encode_input(&[]).ok()); - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; - let get_evm_simulator_hash_call = match get_l2_evm_simulator_hash_input { Some(input) if use_evm_simulator => Some(Multicall3Call { target: self.state_transition_chain_contract, @@ -258,6 +252,7 @@ impl EthTxAggregator { pub(super) fn parse_multicall_data( &self, token: Token, + use_evm_simulator: bool, ) -> Result { let parse_error = |tokens: &[Token]| { Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( @@ -266,9 +261,6 @@ impl EthTxAggregator { }; if let Token::Array(call_results) = token { - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; let number_of_calls = if use_evm_simulator { 6 } else { 5 }; // 5 calls are aggregated in multicall if call_results.len() != number_of_calls { @@ -313,9 +305,9 @@ impl EthTxAggregator { ), ))); } - H256::from_slice(&multicall3_evm_simulator) + Some(H256::from_slice(&multicall3_evm_simulator)) } else { - default_aa + None }; let base_system_contracts_hashes = BaseSystemContractsHashes { diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index 4ddadf400e3e..e051a80252ab 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -75,7 +75,7 @@ pub(crate) fn default_l1_batch_metadata() -> L1BatchMetadata { zkporter_is_available: false, bootloader_code_hash: H256::default(), default_aa_code_hash: H256::default(), - evm_simulator_code_hash: H256::default(), + evm_simulator_code_hash: None, protocol_version: Some(ProtocolVersionId::default()), }, aux_data_hash: H256::default(), @@ -672,7 +672,7 @@ async fn test_parse_multicall_data(commitment_mode: L1BatchCommitmentMode) { assert!(tester .aggregator - .parse_multicall_data(mock_multicall_response()) + .parse_multicall_data(mock_multicall_response(), true) .is_ok()); let original_wrong_form_data = vec![ @@ -724,7 +724,7 @@ async fn test_parse_multicall_data(commitment_mode: L1BatchCommitmentMode) { assert_matches!( tester .aggregator - .parse_multicall_data(wrong_data_instance.clone()), + .parse_multicall_data(wrong_data_instance.clone(), true), Err(EthSenderError::Parse(Error::InvalidOutputType(_))) ); } diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 65c795843bfb..a5c985540e60 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -104,9 +104,7 @@ impl GenesisParams { default_aa: config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, - evm_simulator: config - .evm_simulator_hash - .ok_or(GenesisError::MalformedConfig("evm_simulator_hash"))?, + evm_simulator: config.evm_simulator_hash, }; if base_system_contracts_hashes != base_system_contracts.hashes() { return Err(GenesisError::BaseSystemContractsHashes(Box::new( @@ -175,7 +173,7 @@ pub fn mock_genesis_config() -> GenesisConfig { genesis_commitment: Some(H256::default()), bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), - evm_simulator_hash: Some(base_system_contracts_hashes.evm_simulator), + evm_simulator_hash: base_system_contracts_hashes.evm_simulator, l1_chain_id: L1ChainId(9), sl_chain_id: None, l2_chain_id: L2ChainId::default(), @@ -239,10 +237,7 @@ pub async fn insert_genesis_batch( .config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, - evm_simulator: genesis_params - .config - .evm_simulator_hash - .ok_or(GenesisError::MalformedConfig("evm_simulator_hash"))?, + evm_simulator: genesis_params.config.evm_simulator_hash, }; let commitment_input = CommitmentInput::for_genesis_batch( genesis_root_hash, diff --git a/core/node/genesis/src/utils.rs b/core/node/genesis/src/utils.rs index d0e8aa020363..c1c43f654081 100644 --- a/core/node/genesis/src/utils.rs +++ b/core/node/genesis/src/utils.rs @@ -129,14 +129,11 @@ pub(super) async fn insert_base_system_contracts_to_factory_deps( storage: &mut Connection<'_, Core>, contracts: &BaseSystemContracts, ) -> Result<(), GenesisError> { - let factory_deps = [ - &contracts.bootloader, - &contracts.default_aa, - &contracts.evm_simulator, - ] - .iter() - .map(|c| (c.hash, be_words_to_bytes(&c.code))) - .collect(); + let factory_deps = [&contracts.bootloader, &contracts.default_aa] + .into_iter() + .chain(contracts.evm_simulator.as_ref()) + .map(|c| (c.hash, be_words_to_bytes(&c.code))) + .collect(); Ok(storage .factory_deps_dal() diff --git a/core/node/node_sync/src/external_io.rs b/core/node/node_sync/src/external_io.rs index 581920041178..1972496b048a 100644 --- a/core/node/node_sync/src/external_io.rs +++ b/core/node/node_sync/src/external_io.rs @@ -345,9 +345,7 @@ impl StateKeeperIO for ExternalIO { let default_account_code_hash = protocol_version .default_account_code_hash() .context("Missing default account code hash")?; - let evm_simulator_code_hash = protocol_version - .evm_simulator_code_hash() - .context("Missing evm simulator code hash")?; + let evm_simulator_code_hash = protocol_version.evm_simulator_code_hash(); let l2_system_upgrade_tx_hash = protocol_version.l2_system_upgrade_tx_hash(); self.pool .connection_tagged("sync_layer") @@ -379,10 +377,18 @@ impl StateKeeperIO for ExternalIO { .get_base_system_contract(default_account_code_hash, cursor.next_l2_block) .await .with_context(|| format!("cannot fetch default AA code for {protocol_version:?}"))?; - let evm_simulator = self - .get_base_system_contract(evm_simulator_code_hash, cursor.next_l2_block) - .await - .with_context(|| format!("cannot fetch EVM simulator code for {protocol_version:?}"))?; + let evm_simulator = if let Some(hash) = evm_simulator_code_hash { + Some( + self.get_base_system_contract(hash, cursor.next_l2_block) + .await + .with_context(|| { + format!("cannot fetch EVM simulator code for {protocol_version:?}") + })?, + ) + } else { + None + }; + Ok(BaseSystemContracts { bootloader, default_aa, diff --git a/core/node/node_sync/src/genesis.rs b/core/node/node_sync/src/genesis.rs index 645b96c16d05..e98d2d557706 100644 --- a/core/node/node_sync/src/genesis.rs +++ b/core/node/node_sync/src/genesis.rs @@ -38,9 +38,7 @@ async fn create_genesis_params( let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader: config.bootloader_hash.context("Genesis is not finished")?, default_aa: config.default_aa_hash.context("Genesis is not finished")?, - evm_simulator: config - .evm_simulator_hash - .context("Genesis is not finished")?, + evm_simulator: config.evm_simulator_hash, }; if zksync_chain_id != config.l2_chain_id { @@ -106,10 +104,18 @@ async fn fetch_base_system_contracts( .fetch_system_contract_by_hash(contract_hashes.default_aa) .await? .context("default AA bytecode is missing on main node")?; - let evm_simulator = client - .fetch_system_contract_by_hash(contract_hashes.evm_simulator) - .await? - .context("EVM Simulator bytecode is missing on main node")?; + let evm_simulator = if let Some(hash) = contract_hashes.evm_simulator { + let bytes = client + .fetch_system_contract_by_hash(hash) + .await? + .context("EVM Simulator bytecode is missing on main node")?; + Some(SystemContractCode { + code: zksync_utils::bytes_to_be_words(bytes), + hash, + }) + } else { + None + }; Ok(BaseSystemContracts { bootloader: SystemContractCode { code: zksync_utils::bytes_to_be_words(bootloader_bytecode), @@ -119,9 +125,6 @@ async fn fetch_base_system_contracts( code: zksync_utils::bytes_to_be_words(default_aa_bytecode), hash: contract_hashes.default_aa, }, - evm_simulator: SystemContractCode { - code: zksync_utils::bytes_to_be_words(evm_simulator), - hash: contract_hashes.evm_simulator, - }, + evm_simulator, }) } diff --git a/core/node/node_sync/src/tests.rs b/core/node/node_sync/src/tests.rs index a9eb2172e63e..620b0331bd8f 100644 --- a/core/node/node_sync/src/tests.rs +++ b/core/node/node_sync/src/tests.rs @@ -350,7 +350,7 @@ async fn external_io_works_without_local_protocol_version(snapshot_recovery: boo persisted_protocol_version .base_system_contracts_hashes .evm_simulator, - next_protocol_version.evm_simulator_code_hash.unwrap() + next_protocol_version.evm_simulator_code_hash ); let l2_block = storage diff --git a/core/node/proof_data_handler/src/tests.rs b/core/node/proof_data_handler/src/tests.rs index f92f0fa67b4a..a13b3c8063d7 100644 --- a/core/node/proof_data_handler/src/tests.rs +++ b/core/node/proof_data_handler/src/tests.rs @@ -62,10 +62,10 @@ async fn request_tee_proof_inputs() { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: SystemContractCode { + evm_simulator: Some(SystemContractCode { code: vec![U256([1; 4])], hash: H256([1; 32]), - }, + }), }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/node/test_utils/src/lib.rs b/core/node/test_utils/src/lib.rs index 92b8b02462be..3706231cab0d 100644 --- a/core/node/test_utils/src/lib.rs +++ b/core/node/test_utils/src/lib.rs @@ -56,7 +56,7 @@ pub fn create_l1_batch(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), - evm_simulator: H256::repeat_byte(43), + evm_simulator: Some(H256::repeat_byte(43)), }, ProtocolVersionId::latest(), ); @@ -217,14 +217,11 @@ impl Snapshot { Snapshot { l1_batch, l2_block, - factory_deps: [ - &contracts.bootloader, - &contracts.default_aa, - &contracts.evm_simulator, - ] - .into_iter() - .map(|c| (c.hash, zksync_utils::be_words_to_bytes(&c.code))) - .collect(), + factory_deps: [&contracts.bootloader, &contracts.default_aa] + .into_iter() + .chain(contracts.evm_simulator.as_ref()) + .map(|c| (c.hash, zksync_utils::be_words_to_bytes(&c.code))) + .collect(), storage_logs, } } diff --git a/core/node/vm_runner/src/impls/bwip.rs b/core/node/vm_runner/src/impls/bwip.rs index 5364f93a9736..f6ffd8520268 100644 --- a/core/node/vm_runner/src/impls/bwip.rs +++ b/core/node/vm_runner/src/impls/bwip.rs @@ -229,14 +229,6 @@ async fn get_updates_manager_witness_input_data( .ok_or_else(|| anyhow!("Default account bytecode should exist"))?; let account_bytecode = bytes_to_chunks(&account_bytecode_bytes); - let evm_simulator_code_hash = h256_to_u256(evm_simulator); - let simulator_bytecode_bytes = connection - .factory_deps_dal() - .get_sealed_factory_dep(evm_simulator) - .await? - .ok_or_else(|| anyhow!("EVM Simulator bytecode should exist"))?; - let evm_simulator_bytecode = bytes_to_chunks(&simulator_bytecode_bytes); - let used_contract_hashes = &output.batch.final_execution_state.used_contract_hashes; let hashes: HashSet = used_contract_hashes .iter() @@ -252,9 +244,21 @@ async fn get_updates_manager_witness_input_data( used_bytecodes.insert(account_code_hash, account_bytecode); } - if used_contract_hashes.contains(&evm_simulator_code_hash) { - used_bytecodes.insert(evm_simulator_code_hash, evm_simulator_bytecode); - } + let evm_simulator_code_hash = if let Some(evm_simulator) = evm_simulator { + let evm_simulator_code_hash = h256_to_u256(evm_simulator); + if used_contract_hashes.contains(&evm_simulator_code_hash) { + let simulator_bytecode_bytes = connection + .factory_deps_dal() + .get_sealed_factory_dep(evm_simulator) + .await? + .ok_or_else(|| anyhow!("EVM Simulator bytecode should exist"))?; + let evm_simulator_bytecode = bytes_to_chunks(&simulator_bytecode_bytes); + used_bytecodes.insert(evm_simulator_code_hash, evm_simulator_bytecode); + } + Some(evm_simulator_code_hash) + } else { + None + }; let storage_refunds = output.batch.final_execution_state.storage_refunds.clone(); let pubdata_costs = output.batch.final_execution_state.pubdata_costs.clone(); diff --git a/core/node/vm_runner/src/tests/mod.rs b/core/node/vm_runner/src/tests/mod.rs index 15fc30259337..7202f83d5949 100644 --- a/core/node/vm_runner/src/tests/mod.rs +++ b/core/node/vm_runner/src/tests/mod.rs @@ -322,10 +322,12 @@ async fn store_l1_batches( .iter() .map(|contract| hash_bytecode(&contract.bytecode)) .chain([genesis_params.base_system_contracts().hashes().default_aa]) - .chain([genesis_params - .base_system_contracts() - .hashes() - .evm_simulator]) + .chain( + genesis_params + .base_system_contracts() + .hashes() + .evm_simulator, + ) .map(h256_to_u256) .collect(); diff --git a/core/node/vm_runner/src/tests/output_handler.rs b/core/node/vm_runner/src/tests/output_handler.rs index 9376beab1aa7..2bc881a5f22f 100644 --- a/core/node/vm_runner/src/tests/output_handler.rs +++ b/core/node/vm_runner/src/tests/output_handler.rs @@ -66,10 +66,10 @@ impl OutputHandlerTester { code: vec![], hash: Default::default(), }, - evm_simulator: SystemContractCode { + evm_simulator: Some(SystemContractCode { code: vec![], hash: Default::default(), - }, + }), }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 413fc265be65..3c15948dd9a5 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -355,18 +355,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "backon" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" -dependencies = [ - "fastrand", - "futures-core", - "pin-project", - "tokio", -] - [[package]] name = "backtrace" version = "0.3.72" @@ -472,27 +460,6 @@ dependencies = [ "which", ] -[[package]] -name = "bindgen" -version = "0.65.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "prettyplease", - "proc-macro2 1.0.85", - "quote 1.0.36", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.66", -] - [[package]] name = "bindgen" version = "0.69.4" @@ -764,12 +731,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "bytecount" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" - [[package]] name = "byteorder" version = "1.5.0" @@ -782,48 +743,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - [[package]] name = "cc" version = "1.1.14" @@ -1441,19 +1360,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "debugid" version = "0.8.0" @@ -1812,15 +1718,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check", -] - [[package]] name = "etcetera" version = "0.8.0" @@ -3167,22 +3064,6 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "librocksdb-sys" -version = "0.11.0+8.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" -dependencies = [ - "bindgen 0.65.1", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", - "zstd-sys", -] - [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -3194,17 +3075,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-sys" -version = "1.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -3271,16 +3141,6 @@ dependencies = [ "logos-codegen", ] -[[package]] -name = "lz4-sys" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb44a01837a858d47e5a630d2ccf304c8efcc4b83b8f9f75b7a9ee4fcc6e57d" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "match_cfg" version = "0.1.0" @@ -3363,21 +3223,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "mini-moka" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" -dependencies = [ - "crossbeam-channel", - "crossbeam-utils", - "dashmap", - "skeptic", - "smallvec", - "tagptr", - "triomphe", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4437,17 +4282,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags 2.6.0", - "memchr", - "unicase", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -4856,16 +4690,6 @@ dependencies = [ "rustc-hex", ] -[[package]] -name = "rocksdb" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" -dependencies = [ - "libc", - "librocksdb-sys", -] - [[package]] name = "rsa" version = "0.9.6" @@ -5173,9 +4997,6 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -dependencies = [ - "serde", -] [[package]] name = "send_wrapper" @@ -5564,21 +5385,6 @@ dependencies = [ "time", ] -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - [[package]] name = "slab" version = "0.4.9" @@ -6058,12 +5864,6 @@ dependencies = [ "libc", ] -[[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - [[package]] name = "tap" version = "1.0.1" @@ -6513,12 +6313,6 @@ dependencies = [ "tracing-serde", ] -[[package]] -name = "triomphe" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" - [[package]] name = "try-lock" version = "0.2.5" @@ -7932,7 +7726,6 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_env_config", - "zksync_state", "zksync_system_constants", "zksync_types", "zksync_utils", @@ -8236,51 +8029,6 @@ dependencies = [ "zksync_utils", ] -[[package]] -name = "zksync_shared_metrics" -version = "0.1.0" -dependencies = [ - "rustc_version", - "tracing", - "vise", - "zksync_dal", - "zksync_types", -] - -[[package]] -name = "zksync_state" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "backon", - "chrono", - "itertools 0.10.5", - "mini-moka", - "once_cell", - "tokio", - "tracing", - "vise", - "zksync_dal", - "zksync_shared_metrics", - "zksync_storage", - "zksync_types", - "zksync_utils", - "zksync_vm_interface", -] - -[[package]] -name = "zksync_storage" -version = "0.1.0" -dependencies = [ - "num_cpus", - "once_cell", - "rocksdb", - "thread_local", - "tracing", - "vise", -] - [[package]] name = "zksync_system_constants" version = "0.1.0" @@ -8512,13 +8260,3 @@ dependencies = [ "zksync_utils", "zksync_vlog", ] - -[[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" -dependencies = [ - "cc", - "pkg-config", -] From a7d45b04fb90732ad6aec014a2830273d809bf48 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 26 Sep 2024 11:21:27 +0300 Subject: [PATCH 40/72] Remove garbage deps from `multivm` --- Cargo.lock | 2 -- core/lib/multivm/Cargo.toml | 2 -- .../src/versions/vm_latest/implementation/execution.rs | 4 ++++ .../src/versions/vm_latest/tracers/default_tracers.rs | 9 +++------ prover/Cargo.lock | 2 -- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f80479a9ce2..a35a4f936df4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10159,9 +10159,7 @@ dependencies = [ "zk_evm 0.140.0", "zk_evm 0.141.0", "zk_evm 0.150.5", - "zksync_config", "zksync_contracts", - "zksync_env_config", "zksync_eth_signer", "zksync_system_constants", "zksync_test_account", diff --git a/core/lib/multivm/Cargo.toml b/core/lib/multivm/Cargo.toml index aa4776a650c0..9d302811f25b 100644 --- a/core/lib/multivm/Cargo.toml +++ b/core/lib/multivm/Cargo.toml @@ -25,8 +25,6 @@ circuit_sequencer_api_1_4_2.workspace = true circuit_sequencer_api_1_5_0.workspace = true zksync_types.workspace = true -zksync_config.workspace = true # FIXME: remove -zksync_env_config.workspace = true zksync_contracts.workspace = true zksync_utils.workspace = true zksync_system_constants.workspace = true diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index 94cce9e2c21b..def149770d1e 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -56,6 +56,10 @@ impl Vm { .then_some(RefundsTracer::new(self.batch_env.clone(), self.subversion)); let mut tx_tracer: DefaultExecutionTracer = DefaultExecutionTracer::new( self.system_env.default_validation_computational_gas_limit, + self.system_env + .base_system_smart_contracts + .evm_simulator + .is_some(), execution_mode, mem::take(dispatcher), self.storage.clone(), diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index 5b61b5174e19..2d8e6da4b1a1 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -12,8 +12,6 @@ use zk_evm_1_5_0::{ witness_trace::DummyTracer, zkevm_opcode_defs::{decoding::EncodingModeProduction, Opcode, RetOpcode}, }; -use zksync_config::configs::use_evm_simulator::{self}; -use zksync_env_config::FromEnv; use super::{EvmDeployTracer, PubdataTracer}; use crate::{ @@ -73,8 +71,10 @@ pub struct DefaultExecutionTracer { } impl DefaultExecutionTracer { + #[allow(clippy::too_many_arguments)] pub(crate) fn new( computational_gas_limit: u32, + use_evm_simulator: bool, execution_mode: VmExecutionMode, dispatcher: TracerDispatcher, storage: StoragePtr, @@ -82,9 +82,6 @@ impl DefaultExecutionTracer { pubdata_tracer: Option>, subversion: MultiVMSubversion, ) -> Self { - let active_evm = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; Self { tx_has_been_processed: false, execution_mode, @@ -99,7 +96,7 @@ impl DefaultExecutionTracer { pubdata_tracer, ret_from_the_bootloader: None, circuits_tracer: CircuitsTracer::new(), - evm_deploy_tracer: if active_evm { + evm_deploy_tracer: if use_evm_simulator { Some(EvmDeployTracer::new()) } else { None diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 3c15948dd9a5..368f398ef346 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7723,9 +7723,7 @@ dependencies = [ "zk_evm 0.140.0", "zk_evm 0.141.0", "zk_evm 0.150.5", - "zksync_config", "zksync_contracts", - "zksync_env_config", "zksync_system_constants", "zksync_types", "zksync_utils", From 9b04a757ef4d73951bfdd704b9a697182af79bd3 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 26 Sep 2024 12:33:41 +0300 Subject: [PATCH 41/72] Remove garbage deps from `types` --- Cargo.lock | 1 - core/lib/dal/src/consensus/mod.rs | 2 +- .../versions/vm_fast/tests/require_eip712.rs | 4 +- .../vm_latest/tests/require_eip712.rs | 4 +- core/lib/protobuf_config/src/genesis.rs | 11 ++-- core/lib/types/src/l2/mod.rs | 10 ++-- core/lib/types/src/lib.rs | 10 +--- core/lib/types/src/protocol_upgrade.rs | 26 ++++++---- core/lib/types/src/system_contracts.rs | 52 ++++--------------- core/lib/types/src/transaction_request.rs | 41 ++++++++------- core/lib/vm_interface/Cargo.toml | 1 - .../lib/vm_interface/src/storage/in_memory.rs | 15 ++---- .../api_server/src/web3/namespaces/debug.rs | 3 +- .../api_server/src/web3/namespaces/eth.rs | 4 +- .../api_server/src/web3/namespaces/zks.rs | 7 +-- core/node/api_server/src/web3/state.rs | 4 +- core/node/consensus/src/batch.rs | 2 +- core/node/consensus/src/storage/testonly.rs | 2 +- core/node/eth_watch/src/tests.rs | 18 ++++--- core/node/genesis/src/lib.rs | 4 +- core/node/node_sync/src/genesis.rs | 9 ++-- .../state_keeper/src/executor/tests/tester.rs | 2 +- core/node/state_keeper/src/io/tests/tester.rs | 2 +- core/tests/test_account/src/lib.rs | 7 ++- prover/Cargo.lock | 1 - 25 files changed, 106 insertions(+), 136 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a35a4f936df4..76f451f6790b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11020,7 +11020,6 @@ dependencies = [ "zksync_contracts", "zksync_system_constants", "zksync_types", - "zksync_utils", ] [[package]] diff --git a/core/lib/dal/src/consensus/mod.rs b/core/lib/dal/src/consensus/mod.rs index f01655d56a95..876dfe14beda 100644 --- a/core/lib/dal/src/consensus/mod.rs +++ b/core/lib/dal/src/consensus/mod.rs @@ -244,7 +244,7 @@ impl ProtoRepr for proto::TransactionV25 { }, T::L2(l2) => abi::Transaction::L2(required(&l2.rlp).context("rlp")?.clone()), }; - tx.try_into() + Transaction::from_abi(tx, true) } fn build(tx: &Self::Type) -> Self { diff --git a/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs b/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs index e119cea01143..43f2ed020c31 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/require_eip712.rs @@ -107,7 +107,7 @@ async fn test_require_eip712() { let aa_tx = private_account.sign_legacy_tx(aa_raw_tx).await; let (tx_request, hash) = TransactionRequest::from_bytes(&aa_tx, L2ChainId::from(270)).unwrap(); - let mut l2_tx: L2Tx = L2Tx::from_request(tx_request, 10000).unwrap(); + let mut l2_tx: L2Tx = L2Tx::from_request(tx_request, 10000, false).unwrap(); l2_tx.set_input(aa_tx, hash); // Pretend that operator is malicious and sets the initiator to the AA account. l2_tx.common_data.initiator_address = account_abstraction.address; @@ -158,7 +158,7 @@ async fn test_require_eip712() { let (aa_txn_request, aa_hash) = TransactionRequest::from_bytes(&encoded_tx, L2ChainId::from(chain_id)).unwrap(); - let mut l2_tx = L2Tx::from_request(aa_txn_request, 100000).unwrap(); + let mut l2_tx = L2Tx::from_request(aa_txn_request, 100000, false).unwrap(); l2_tx.set_input(encoded_tx, aa_hash); let transaction: Transaction = l2_tx.into(); diff --git a/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs b/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs index cdd71354c8de..8e2a0b8b1a63 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/require_eip712.rs @@ -98,7 +98,7 @@ async fn test_require_eip712() { let aa_tx = private_account.sign_legacy_tx(aa_raw_tx).await; let (tx_request, hash) = TransactionRequest::from_bytes(&aa_tx, L2ChainId::from(270)).unwrap(); - let mut l2_tx: L2Tx = L2Tx::from_request(tx_request, 10000).unwrap(); + let mut l2_tx: L2Tx = L2Tx::from_request(tx_request, 10000, false).unwrap(); l2_tx.set_input(aa_tx, hash); // Pretend that operator is malicious and sets the initiator to the AA account. l2_tx.common_data.initiator_address = account_abstraction.address; @@ -149,7 +149,7 @@ async fn test_require_eip712() { let (aa_txn_request, aa_hash) = TransactionRequest::from_bytes(&encoded_tx, L2ChainId::from(chain_id)).unwrap(); - let mut l2_tx = L2Tx::from_request(aa_txn_request, 100000).unwrap(); + let mut l2_tx = L2Tx::from_request(aa_txn_request, 100000, false).unwrap(); l2_tx.set_input(encoded_tx, aa_hash); let transaction: Transaction = l2_tx.into(); diff --git a/core/lib/protobuf_config/src/genesis.rs b/core/lib/protobuf_config/src/genesis.rs index 42215cda9533..e1698ef3aa01 100644 --- a/core/lib/protobuf_config/src/genesis.rs +++ b/core/lib/protobuf_config/src/genesis.rs @@ -75,11 +75,12 @@ impl ProtoRepr for proto::Genesis { .and_then(|x| parse_h256(x)) .context("default_aa_hash")?, ), - evm_simulator_hash: Some( - required(&self.evm_simulator_hash) - .and_then(|x| parse_h256(x)) - .context("evm_simulator_hash")?, - ), + evm_simulator_hash: self + .evm_simulator_hash + .as_deref() + .map(parse_h256) + .transpose() + .context("evm_simulator_hash")?, l1_chain_id: required(&self.l1_chain_id) .map(|x| L1ChainId(*x)) .context("l1_chain_id")?, diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index 106a0afd2c40..f08fd72f66a8 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -4,9 +4,7 @@ use anyhow::Context as _; use num_enum::TryFromPrimitive; use rlp::Rlp; use serde::{Deserialize, Serialize}; -use zksync_config::configs::use_evm_simulator; use zksync_crypto_primitives::K256PrivateKey; -use zksync_env_config::FromEnv; use self::error::SignError; use crate::{ @@ -218,11 +216,9 @@ impl L2Tx { let raw = req.get_signed_bytes(&sig).context("get_signed_bytes")?; let (req, hash) = TransactionRequest::from_bytes_unverified(&raw).context("from_bytes_unverified()")?; - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; - let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator) - .context("from_request_unverified()")?; + // Since we allow users to specify `None` recipient, EVM simulation is implicitly enabled. + let mut tx = + L2Tx::from_request_unverified(req, true).context("from_request_unverified()")?; tx.set_input(raw, hash); Ok(tx) } diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 6b7d3b2e2ab0..1d065de4ea93 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -16,9 +16,7 @@ use serde::{Deserialize, Serialize}; pub use storage::*; pub use tx::Execute; pub use zksync_basic_types::{protocol_version::ProtocolVersionId, vm, *}; -use zksync_config::configs::use_evm_simulator; pub use zksync_crypto_primitives::*; -use zksync_env_config::FromEnv; use zksync_utils::{ address_to_u256, bytecode::hash_bytecode, h256_to_u256, u256_to_account_address, }; @@ -317,9 +315,8 @@ impl TryFrom for abi::Transaction { } } -impl TryFrom for Transaction { - type Error = anyhow::Error; - fn try_from(tx: abi::Transaction) -> anyhow::Result { +impl Transaction { + pub fn from_abi(tx: abi::Transaction, use_evm_simulator: bool) -> anyhow::Result { Ok(match tx { abi::Transaction::L1 { tx, @@ -391,9 +388,6 @@ impl TryFrom for Transaction { abi::Transaction::L2(raw) => { let (req, hash) = transaction_request::TransactionRequest::from_bytes_unverified(&raw)?; - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator)?; tx.set_input(raw, hash); tx.into() diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 3de65605ed59..3eac7bfd0b47 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -129,11 +129,14 @@ impl ProtocolUpgrade { timestamp: upgrade.upgrade_timestamp.try_into().unwrap(), tx: (upgrade.l2_protocol_upgrade_tx.tx_type != U256::zero()) .then(|| { - Transaction::try_from(abi::Transaction::L1 { - tx: upgrade.l2_protocol_upgrade_tx, - factory_deps: upgrade.factory_deps, - eth_block: 0, - }) + Transaction::from_abi( + abi::Transaction::L1 { + tx: upgrade.l2_protocol_upgrade_tx, + factory_deps: upgrade.factory_deps, + eth_block: 0, + }, + true, + ) .context("Transaction::try_from()")? .try_into() .map_err(|err| anyhow::format_err!("try_into::(): {err}")) @@ -154,11 +157,14 @@ pub fn decode_set_chain_id_event( .unwrap_or_else(|_| panic!("Version is not supported, packed version: {full_version_id}")); Ok(( protocol_version, - Transaction::try_from(abi::Transaction::L1 { - tx: tx.into(), - eth_block: 0, - factory_deps: vec![], - }) + Transaction::from_abi( + abi::Transaction::L1 { + tx: tx.into(), + eth_block: 0, + factory_deps: vec![], + }, + true, + ) .unwrap() .try_into() .unwrap(), diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index dd0355cd8435..88743fdc9b1a 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -1,16 +1,12 @@ use std::path::PathBuf; -use once_cell::sync::Lazy; -use zksync_basic_types::{AccountTreeId, Address, H256, U256}; -use zksync_config::configs::use_evm_simulator; +use zksync_basic_types::{AccountTreeId, Address, U256}; use zksync_contracts::{read_sys_contract_bytecode, ContractLanguage, SystemContractsRepo}; -use zksync_env_config::FromEnv; use zksync_system_constants::{ BOOTLOADER_UTILITIES_ADDRESS, CODE_ORACLE_ADDRESS, COMPRESSOR_ADDRESS, CREATE2_FACTORY_ADDRESS, EVENT_WRITER_ADDRESS, EVM_GAS_MANAGER_ADDRESS, P256VERIFY_PRECOMPILE_ADDRESS, PUBDATA_CHUNK_PUBLISHER_ADDRESS, }; -use zksync_utils::bytecode::hash_bytecode; use crate::{ block::DeployedContract, ACCOUNT_CODE_STORAGE_ADDRESS, BOOTLOADER_ADDRESS, @@ -180,35 +176,12 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 26] = [ ), ]; -static EVM_SIMULATOR_HASH: Lazy = Lazy::new(|| { - if use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator - { - hash_bytecode(&read_sys_contract_bytecode( - "", - "EvmInterpreter", - ContractLanguage::Yul, - )) - } else { - let default_account_code = - read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); - hash_bytecode(&default_account_code) - } -}); - -pub fn get_evm_simulator_hash() -> H256 { - *EVM_SIMULATOR_HASH -} - -static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { - let evm_simulator_is_used = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; +/// Gets default set of system contracts, based on Cargo workspace location. +pub fn get_system_smart_contracts(use_evm_simulator: bool) -> Vec { SYSTEM_CONTRACT_LIST .iter() .filter_map(|(path, name, address, contract_lang)| { - if *name == "EvmGasManager" && !evm_simulator_is_used { + if *name == "EvmGasManager" && !use_evm_simulator { None } else { Some(DeployedContract { @@ -217,24 +190,19 @@ static SYSTEM_CONTRACTS: Lazy> = Lazy::new(|| { }) } }) - .collect::>() -}); - -/// Gets default set of system contracts, based on Cargo workspace location. -pub fn get_system_smart_contracts() -> Vec { - SYSTEM_CONTRACTS.clone() + .collect() } /// Loads system contracts from a given directory. -pub fn get_system_smart_contracts_from_dir(path: PathBuf) -> Vec { - let evm_simulator_is_used = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; +pub fn get_system_smart_contracts_from_dir( + path: PathBuf, + use_evm_simulator: bool, +) -> Vec { let repo = SystemContractsRepo { root: path }; SYSTEM_CONTRACT_LIST .iter() .filter_map(|(path, name, address, contract_lang)| { - if *name == "EvmGasManager" && !evm_simulator_is_used { + if *name == "EvmGasManager" && !use_evm_simulator { None } else { Some(DeployedContract { diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 0ec77d5016d9..1c0434a66bbe 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -4,8 +4,6 @@ use rlp::{DecoderError, Rlp, RlpStream}; use serde::{Deserialize, Serialize}; use thiserror::Error; use zksync_basic_types::H256; -use zksync_config::configs::use_evm_simulator; -use zksync_env_config::FromEnv; use zksync_system_constants::{DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE, MAX_ENCODED_TX_SIZE}; use zksync_utils::{ bytecode::{hash_bytecode, validate_bytecode, InvalidBytecodeError}, @@ -854,10 +852,8 @@ impl L2Tx { pub fn from_request( value: TransactionRequest, max_tx_size: usize, + use_evm_simulator: bool, ) -> Result { - let use_evm_simulator = use_evm_simulator::UseEvmSimulator::from_env() - .unwrap() - .use_evm_simulator; let tx = Self::from_request_unverified(value, use_evm_simulator)?; tx.check_encoded_size(max_tx_size)?; Ok(tx) @@ -922,11 +918,13 @@ impl From for TransactionRequest { } } -impl TryFrom for L1Tx { - type Error = SerializationTransactionError; - fn try_from(tx: CallRequest) -> Result { +impl L1Tx { + pub fn from_request( + tx: CallRequest, + use_evm_simulator: bool, + ) -> Result { // L1 transactions have no limitations on the transaction size. - let tx: L2Tx = L2Tx::from_request(tx.into(), MAX_ENCODED_TX_SIZE)?; + let tx: L2Tx = L2Tx::from_request(tx.into(), MAX_ENCODED_TX_SIZE, use_evm_simulator)?; // Note, that while the user has theoretically provided the fee for ETH on L1, // the payment to the operator as well as refunds happen on L2 and so all the ETH @@ -1322,7 +1320,7 @@ mod tests { ..Default::default() }; let execute_tx1: Result = - L2Tx::from_request(tx1, usize::MAX); + L2Tx::from_request(tx1, usize::MAX, true); assert!(execute_tx1.is_ok()); let tx2 = TransactionRequest { @@ -1333,7 +1331,7 @@ mod tests { ..Default::default() }; let execute_tx2: Result = - L2Tx::from_request(tx2, usize::MAX); + L2Tx::from_request(tx2, usize::MAX, true); assert_eq!( execute_tx2.unwrap_err(), SerializationTransactionError::TooBigNonce @@ -1350,7 +1348,7 @@ mod tests { ..Default::default() }; let execute_tx1: Result = - L2Tx::from_request(tx1, usize::MAX); + L2Tx::from_request(tx1, usize::MAX, true); assert_eq!( execute_tx1.unwrap_err(), SerializationTransactionError::MaxFeePerGasNotU64 @@ -1364,7 +1362,7 @@ mod tests { ..Default::default() }; let execute_tx2: Result = - L2Tx::from_request(tx2, usize::MAX); + L2Tx::from_request(tx2, usize::MAX, true); assert_eq!( execute_tx2.unwrap_err(), SerializationTransactionError::MaxPriorityFeePerGasNotU64 @@ -1382,7 +1380,7 @@ mod tests { }; let execute_tx3: Result = - L2Tx::from_request(tx3, usize::MAX); + L2Tx::from_request(tx3, usize::MAX, true); assert_eq!( execute_tx3.unwrap_err(), SerializationTransactionError::MaxFeePerPubdataByteNotU64 @@ -1438,7 +1436,7 @@ mod tests { let request = TransactionRequest::from_bytes(data.as_slice(), L2ChainId::from(270)).unwrap(); assert_matches!( - L2Tx::from_request(request.0, random_tx_max_size), + L2Tx::from_request(request.0, random_tx_max_size, true), Err(SerializationTransactionError::OversizedData(_, _)) ) } @@ -1464,7 +1462,7 @@ mod tests { }; let try_to_l2_tx: Result = - L2Tx::from_request(call_request.into(), random_tx_max_size); + L2Tx::from_request(call_request.into(), random_tx_max_size, true); assert_matches!( try_to_l2_tx, @@ -1489,15 +1487,20 @@ mod tests { access_list: None, eip712_meta: None, }; - let l2_tx = L2Tx::from_request(call_request_with_nonce.clone().into(), MAX_ENCODED_TX_SIZE) - .unwrap(); + let l2_tx = L2Tx::from_request( + call_request_with_nonce.clone().into(), + MAX_ENCODED_TX_SIZE, + true, + ) + .unwrap(); assert_eq!(l2_tx.nonce(), Nonce(123u32)); let mut call_request_without_nonce = call_request_with_nonce; call_request_without_nonce.nonce = None; let l2_tx = - L2Tx::from_request(call_request_without_nonce.into(), MAX_ENCODED_TX_SIZE).unwrap(); + L2Tx::from_request(call_request_without_nonce.into(), MAX_ENCODED_TX_SIZE, true) + .unwrap(); assert_eq!(l2_tx.nonce(), Nonce(0u32)); } diff --git a/core/lib/vm_interface/Cargo.toml b/core/lib/vm_interface/Cargo.toml index 2ed458d6e71f..8bff19ddc475 100644 --- a/core/lib/vm_interface/Cargo.toml +++ b/core/lib/vm_interface/Cargo.toml @@ -14,7 +14,6 @@ categories.workspace = true zksync_contracts.workspace = true zksync_system_constants.workspace = true zksync_types.workspace = true -zksync_utils.workspace = true anyhow.workspace = true async-trait.workspace = true diff --git a/core/lib/vm_interface/src/storage/in_memory.rs b/core/lib/vm_interface/src/storage/in_memory.rs index 27dd9c239444..9efda7e00225 100644 --- a/core/lib/vm_interface/src/storage/in_memory.rs +++ b/core/lib/vm_interface/src/storage/in_memory.rs @@ -1,12 +1,10 @@ use std::collections::{hash_map::Entry, BTreeMap, HashMap}; use zksync_types::{ - block::DeployedContract, - get_code_key, get_deployer_key, get_known_code_key, get_system_context_init_logs, - system_contracts::{get_evm_simulator_hash, get_system_smart_contracts}, - L2ChainId, StorageKey, StorageLog, StorageValue, H256, + block::DeployedContract, get_code_key, get_known_code_key, get_system_context_init_logs, + system_contracts::get_system_smart_contracts, L2ChainId, StorageKey, StorageLog, StorageValue, + H256, }; -use zksync_utils::u256_to_h256; use super::ReadStorage; @@ -38,10 +36,11 @@ impl InMemoryStorage { Self::with_custom_system_contracts_and_chain_id( chain_id, bytecode_hasher, - get_system_smart_contracts(), + get_system_smart_contracts(false), ) } + // TODO: add `(get_deployer_key(1), evm_simulator_hash)` if EVM simulator is enabled (as a separate method?) /// Constructs a storage that contains custom system contracts (provided in a vector). pub fn with_custom_system_contracts_and_chain_id( chain_id: L2ChainId, @@ -64,10 +63,6 @@ impl InMemoryStorage { ] }) .chain(system_context_init_log) - .chain(vec![StorageLog::new_write_log( - get_deployer_key(u256_to_h256(1.into())), - get_evm_simulator_hash(), - )]) .filter_map(|log| (log.is_write()).then_some((log.key, log.value))) .collect(); let state: HashMap<_, _> = state_without_indices diff --git a/core/node/api_server/src/web3/namespaces/debug.rs b/core/node/api_server/src/web3/namespaces/debug.rs index 68c7951cee45..1182c1826783 100644 --- a/core/node/api_server/src/web3/namespaces/debug.rs +++ b/core/node/api_server/src/web3/namespaces/debug.rs @@ -265,7 +265,8 @@ impl DebugNamespace { drop(connection); let call_overrides = request.get_call_overrides()?; - let call = L2Tx::from_request(request.into(), MAX_ENCODED_TX_SIZE)?; + // FIXME: configure + let call = L2Tx::from_request(request.into(), MAX_ENCODED_TX_SIZE, false)?; let vm_permit = self .state diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index 0bc0bce30d73..f153b2197b66 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -76,7 +76,8 @@ impl EthNamespace { drop(connection); let call_overrides = request.get_call_overrides()?; - let tx = L2Tx::from_request(request.into(), self.state.api_config.max_tx_size)?; + // FIXME: configure + let tx = L2Tx::from_request(request.into(), self.state.api_config.max_tx_size, false)?; // It is assumed that the previous checks has already enforced that the `max_fee_per_gas` is at most u64. let call_result: Vec = self @@ -111,6 +112,7 @@ impl EthNamespace { let mut tx: L2Tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, + false, // FIXME: configure )?; // The user may not include the proper transaction type during the estimation of diff --git a/core/node/api_server/src/web3/namespaces/zks.rs b/core/node/api_server/src/web3/namespaces/zks.rs index 4f88eb17e231..dfc1299b0d0a 100644 --- a/core/node/api_server/src/web3/namespaces/zks.rs +++ b/core/node/api_server/src/web3/namespaces/zks.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, convert::TryInto}; +use std::collections::HashMap; use anyhow::Context as _; use zksync_dal::{Connection, Core, CoreDal, DalError}; @@ -65,6 +65,7 @@ impl ZksNamespace { let mut tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, + false, // FIXME: configure )?; // When we're estimating fee, we are trying to deduce values related to fee, so we should @@ -88,8 +89,8 @@ impl ZksNamespace { } } - let tx: L1Tx = request_with_gas_per_pubdata_overridden - .try_into() + // FIXME: configure + let tx = L1Tx::from_request(request_with_gas_per_pubdata_overridden, false) .map_err(Web3Error::SerializationError)?; let fee = self.estimate_fee(tx.into(), state_override).await?; diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 5c8b47dabeb0..0fe324edd420 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -262,9 +262,9 @@ impl RpcState { pub fn parse_transaction_bytes(&self, bytes: &[u8]) -> Result<(L2Tx, H256), Web3Error> { let chain_id = self.api_config.l2_chain_id; let (tx_request, hash) = api::TransactionRequest::from_bytes(bytes, chain_id)?; - + // FIXME: configure Ok(( - L2Tx::from_request(tx_request, self.api_config.max_tx_size)?, + L2Tx::from_request(tx_request, self.api_config.max_tx_size, false)?, hash, )) } diff --git a/core/node/consensus/src/batch.rs b/core/node/consensus/src/batch.rs index 08246c4e5c04..af38f446c1b3 100644 --- a/core/node/consensus/src/batch.rs +++ b/core/node/consensus/src/batch.rs @@ -261,7 +261,7 @@ impl L1BatchWithWitness { // TODO: make consensus payload contain `abi::Transaction` instead. // TODO: currently the payload doesn't contain the block number, which is // annoying. Consider adding it to payload. - let t2: Transaction = abi::Transaction::try_from(t.clone())?.try_into()?; + let t2 = Transaction::from_abi(abi::Transaction::try_from(t.clone())?, true)?; anyhow::ensure!(t == &t2); hasher.push_tx_hash(t.hash()); } diff --git a/core/node/consensus/src/storage/testonly.rs b/core/node/consensus/src/storage/testonly.rs index 65c464d98b93..5817e766c6b4 100644 --- a/core/node/consensus/src/storage/testonly.rs +++ b/core/node/consensus/src/storage/testonly.rs @@ -57,7 +57,7 @@ pub(crate) fn mock_genesis_params(protocol_version: ProtocolVersionId) -> Genesi GenesisParams::from_genesis_config( cfg, BaseSystemContracts::load_from_disk(), - get_system_smart_contracts(), + get_system_smart_contracts(false), ) .unwrap() } diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index 899690d6dabe..df575dcaddf1 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -170,8 +170,11 @@ fn build_l1_tx(serial_id: u64, eth_block: u64) -> L1Tx { received_timestamp_ms: 0, }; // Convert to abi::Transaction and back, so that canonical_tx_hash is computed. - let tx = - Transaction::try_from(abi::Transaction::try_from(Transaction::from(tx)).unwrap()).unwrap(); + let tx = Transaction::from_abi( + abi::Transaction::try_from(Transaction::from(tx)).unwrap(), + false, + ) + .unwrap(); tx.try_into().unwrap() } @@ -197,10 +200,13 @@ fn build_upgrade_tx(id: ProtocolVersionId, eth_block: u64) -> ProtocolUpgradeTx received_timestamp_ms: 0, }; // Convert to abi::Transaction and back, so that canonical_tx_hash is computed. - Transaction::try_from(abi::Transaction::try_from(Transaction::from(tx)).unwrap()) - .unwrap() - .try_into() - .unwrap() + Transaction::from_abi( + abi::Transaction::try_from(Transaction::from(tx)).unwrap(), + false, + ) + .unwrap() + .try_into() + .unwrap() } async fn create_test_watcher(connection_pool: ConnectionPool) -> (EthWatch, MockEthClient) { diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index a5c985540e60..c33a5e326ee9 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -126,14 +126,14 @@ impl GenesisParams { pub fn load_genesis_params(config: GenesisConfig) -> Result { let base_system_contracts = BaseSystemContracts::load_from_disk(); - let system_contracts = get_system_smart_contracts(); + let system_contracts = get_system_smart_contracts(config.evm_simulator_hash.is_some()); Self::from_genesis_config(config, base_system_contracts, system_contracts) } pub fn mock() -> Self { Self { base_system_contracts: BaseSystemContracts::load_from_disk(), - system_contracts: get_system_smart_contracts(), + system_contracts: get_system_smart_contracts(false), config: mock_genesis_config(), } } diff --git a/core/node/node_sync/src/genesis.rs b/core/node/node_sync/src/genesis.rs index e98d2d557706..07fb7b423eb0 100644 --- a/core/node/node_sync/src/genesis.rs +++ b/core/node/node_sync/src/genesis.rs @@ -48,10 +48,11 @@ async fn create_genesis_params( // Load the list of addresses that are known to contain system contracts at any point in time. // Not every of these addresses is guaranteed to be present in the genesis state, but we'll iterate through // them and try to fetch the contract bytecode for each of them. - let system_contract_addresses: Vec<_> = get_system_smart_contracts() - .into_iter() - .map(|contract| *contract.account_id.address()) - .collect(); + let system_contract_addresses: Vec<_> = + get_system_smart_contracts(config.evm_simulator_hash.is_some()) + .into_iter() + .map(|contract| *contract.account_id.address()) + .collect(); // These have to be *initial* base contract hashes of main node // (those that were used during genesis), not necessarily the current ones. diff --git a/core/node/state_keeper/src/executor/tests/tester.rs b/core/node/state_keeper/src/executor/tests/tester.rs index 7a1871dbfea9..79072f23aed9 100644 --- a/core/node/state_keeper/src/executor/tests/tester.rs +++ b/core/node/state_keeper/src/executor/tests/tester.rs @@ -259,7 +259,7 @@ impl Tester { patch: 0.into(), }, &BASE_SYSTEM_CONTRACTS, - &get_system_smart_contracts(), + &get_system_smart_contracts(false), Default::default(), ) .await diff --git a/core/node/state_keeper/src/io/tests/tester.rs b/core/node/state_keeper/src/io/tests/tester.rs index 2dc45a5eaaa0..02170283e94b 100644 --- a/core/node/state_keeper/src/io/tests/tester.rs +++ b/core/node/state_keeper/src/io/tests/tester.rs @@ -156,7 +156,7 @@ impl Tester { patch: 0.into(), }, &self.base_system_contracts, - &get_system_smart_contracts(), + &get_system_smart_contracts(false), L1VerifierConfig::default(), ) .await diff --git a/core/tests/test_account/src/lib.rs b/core/tests/test_account/src/lib.rs index d0c97abab729..be722b61c289 100644 --- a/core/tests/test_account/src/lib.rs +++ b/core/tests/test_account/src/lib.rs @@ -154,7 +154,7 @@ impl Account { let max_fee_per_gas = U256::from(0u32); let gas_limit = U256::from(20_000_000); let factory_deps = execute.factory_deps; - abi::Transaction::L1 { + let tx = abi::Transaction::L1 { tx: abi::L2CanonicalTransaction { tx_type: PRIORITY_OPERATION_L2_TX_TYPE.into(), from: address_to_u256(&self.address), @@ -186,9 +186,8 @@ impl Account { .into(), factory_deps, eth_block: 0, - } - .try_into() - .unwrap() + }; + Transaction::from_abi(tx, false).unwrap() } pub fn get_test_contract_transaction( diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 368f398ef346..f61a2d98b9b5 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -8171,7 +8171,6 @@ dependencies = [ "zksync_contracts", "zksync_system_constants", "zksync_types", - "zksync_utils", ] [[package]] From 613abaee0bbd5a8833c852e677e58bd77cfc1992 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 14:28:13 +0300 Subject: [PATCH 42/72] Resolve some nits --- .../dal/migrations/20240911161714_evm-simulator.down.sql | 5 ++--- core/lib/multivm/src/versions/vm_latest/utils/mod.rs | 7 +++---- core/lib/types/src/abi.rs | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql index 999728809a5e..b01433dbbb8e 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql @@ -1,3 +1,2 @@ -ALTER TABLE protocol_versions DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; -ALTER TABLE l1_batches DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; -ALTER TABLE miniblocks DROP COLUMN IF NOT EXISTS evm_simulator_code_hash; +ALTER TABLE protocol_versions DROP COLUMN IF EXISTS evm_simulator_code_hash; +ALTER TABLE l1_batches DROP COLUMN IF EXISTS evm_simulator_code_hash; diff --git a/core/lib/multivm/src/versions/vm_latest/utils/mod.rs b/core/lib/multivm/src/versions/vm_latest/utils/mod.rs index 742434b68970..e07d3eda7c4c 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/mod.rs @@ -1,9 +1,9 @@ -/// Utility functions for the VM. -use ethabi; +//! Utility functions for the VM. + use once_cell::sync::Lazy; -use zk_evm_1_4_1::sha2; use zk_evm_1_5_0::{ aux_structures::MemoryPage, + sha2, zkevm_opcode_defs::{BlobSha256Format, VersionedHashLen32}, }; use zksync_types::{H256, KNOWN_CODES_STORAGE_ADDRESS}; @@ -15,7 +15,6 @@ pub(crate) mod logs; pub mod overhead; pub mod transaction_encoding; -/// TODO: maybe move to a different folder pub(crate) fn hash_evm_bytecode(bytecode: &[u8]) -> H256 { use sha2::{Digest, Sha256}; let mut hasher = Sha256::new(); diff --git a/core/lib/types/src/abi.rs b/core/lib/types/src/abi.rs index c1c0efa66e4c..c1943ec4efdf 100644 --- a/core/lib/types/src/abi.rs +++ b/core/lib/types/src/abi.rs @@ -198,7 +198,7 @@ pub struct ProposedUpgrade { pub factory_deps: Vec>, pub bootloader_hash: [u8; 32], pub default_account_hash: [u8; 32], - pub evm_simulator_hash: [u8; 32], + pub evm_simulator_hash: [u8; 32], // FIXME: is a breaking change here OK? pub verifier: Address, pub verifier_params: VerifierParams, pub l1_contracts_upgrade_calldata: Vec, From 5d21e75d404cb536925852ec6d713ad569723039 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 14:36:23 +0300 Subject: [PATCH 43/72] Change `new_known_factory_deps` type --- .../vm_latest/implementation/execution.rs | 6 +----- core/lib/multivm/src/versions/vm_latest/vm.rs | 19 +++++++++---------- .../src/types/outputs/execution_result.rs | 7 ++++++- core/node/state_keeper/src/io/persistence.rs | 4 ++-- core/node/state_keeper/src/io/tests/mod.rs | 10 +++++----- .../state_keeper/src/seal_criteria/mod.rs | 4 +++- .../src/updates/l1_batch_updates.rs | 4 +++- .../src/updates/l2_block_updates.rs | 11 ++++++----- core/node/state_keeper/src/updates/mod.rs | 6 ++++-- 9 files changed, 39 insertions(+), 32 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index def149770d1e..ded1c3b1ed6d 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -101,11 +101,7 @@ impl Vm { ); let result = tx_tracer.result_tracer.into_result(); let factory_deps_marked_as_known = extract_bytecodes_marked_as_known(&logs.events); - let preimages = self.ask_decommitter(factory_deps_marked_as_known.clone()); - let new_known_factory_deps = factory_deps_marked_as_known - .into_iter() - .zip(preimages) - .collect(); + let new_known_factory_deps = self.decommit_bytecodes(&factory_deps_marked_as_known); *dispatcher = tx_tracer.dispatcher; let result = VmExecutionResultAndLogs { diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index e66ff00e885f..bdf287fe6def 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use circuit_sequencer_api_1_5_0::sort_storage_access::sort_storage_access_queries; use zksync_types::{ l2_to_l1_log::{SystemL2ToL1Log, UserL2ToL1Log}, @@ -79,21 +81,18 @@ impl Vm { self.state.local_state.callstack.current.ergs_remaining } - pub(crate) fn ask_decommitter(&self, hashes: Vec) -> Vec> { - let mut result = vec![]; - for hash in hashes { - let bytecode = self + pub(crate) fn decommit_bytecodes(&self, hashes: &[H256]) -> HashMap> { + let bytecodes = hashes.iter().map(|&hash| { + let bytecode_words = self .state .decommittment_processor .known_bytecodes .inner() .get(&h256_to_u256(hash)) - .expect("Bytecode not found") - .clone(); - result.push(be_words_to_bytes(&bytecode)); - } - - result + .unwrap_or_else(|| panic!("Bytecode with hash {hash:?} not found")); + (hash, be_words_to_bytes(bytecode_words)) + }); + bytecodes.collect() } // visible for testing diff --git a/core/lib/vm_interface/src/types/outputs/execution_result.rs b/core/lib/vm_interface/src/types/outputs/execution_result.rs index 334e7cb74b8f..89e10939704b 100644 --- a/core/lib/vm_interface/src/types/outputs/execution_result.rs +++ b/core/lib/vm_interface/src/types/outputs/execution_result.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; use zksync_system_constants::{ BOOTLOADER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS, L1_MESSENGER_ADDRESS, @@ -118,7 +120,10 @@ pub struct VmExecutionResultAndLogs { pub logs: VmExecutionLogs, pub statistics: VmExecutionStatistics, pub refunds: Refunds, - pub new_known_factory_deps: Option)>>, + /// Bytecodes decommitted during VM execution. `None` if not computed by the VM. + // FIXME: currently, this is only filled up by `vm_latest`; probably makes sense to narrow down + // to *dynamic* factory deps, so that `HashMap::new()` is a valid value for VMs not supporting EVM simulation. + pub new_known_factory_deps: Option>>, } #[derive(Debug, Clone, PartialEq)] diff --git a/core/node/state_keeper/src/io/persistence.rs b/core/node/state_keeper/src/io/persistence.rs index d520fc8c88b6..97340d6496ab 100644 --- a/core/node/state_keeper/src/io/persistence.rs +++ b/core/node/state_keeper/src/io/persistence.rs @@ -347,7 +347,7 @@ impl StateKeeperOutputHandler for TreeWritesPersistence { #[cfg(test)] mod tests { - use std::collections::HashSet; + use std::collections::{HashMap, HashSet}; use assert_matches::assert_matches; use futures::FutureExt; @@ -462,7 +462,7 @@ mod tests { tx, tx_result, vec![], - vec![], + HashMap::new(), BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/io/tests/mod.rs b/core/node/state_keeper/src/io/tests/mod.rs index ef37f3cda75a..e2a90f30691b 100644 --- a/core/node/state_keeper/src/io/tests/mod.rs +++ b/core/node/state_keeper/src/io/tests/mod.rs @@ -1,4 +1,4 @@ -use std::time::Duration; +use std::{collections::HashMap, time::Duration}; use test_casing::test_casing; use zksync_contracts::BaseSystemContractsHashes; @@ -249,7 +249,7 @@ async fn processing_storage_logs_when_sealing_l2_block() { BlockGasCount::default(), VmExecutionMetrics::default(), vec![], - vec![], + HashMap::new(), vec![], ); @@ -268,7 +268,7 @@ async fn processing_storage_logs_when_sealing_l2_block() { BlockGasCount::default(), VmExecutionMetrics::default(), vec![], - vec![], + HashMap::new(), vec![], ); @@ -358,7 +358,7 @@ async fn processing_events_when_sealing_l2_block() { BlockGasCount::default(), VmExecutionMetrics::default(), vec![], - vec![], + HashMap::new(), vec![], ); } @@ -460,7 +460,7 @@ async fn l2_block_processing_after_snapshot_recovery(commitment_mode: L1BatchCom tx.into(), create_execution_result([]), vec![], - vec![], + HashMap::new(), BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/seal_criteria/mod.rs b/core/node/state_keeper/src/seal_criteria/mod.rs index 4919684a70d5..962cc807318b 100644 --- a/core/node/state_keeper/src/seal_criteria/mod.rs +++ b/core/node/state_keeper/src/seal_criteria/mod.rs @@ -277,6 +277,8 @@ impl L2BlockMaxPayloadSizeSealer { #[cfg(test)] mod tests { + use std::collections::HashMap; + use zksync_utils::time::seconds_since_epoch; use super::*; @@ -287,7 +289,7 @@ mod tests { tx, create_execution_result([]), vec![], - vec![], + HashMap::new(), BlockGasCount::default(), VmExecutionMetrics::default(), vec![], diff --git a/core/node/state_keeper/src/updates/l1_batch_updates.rs b/core/node/state_keeper/src/updates/l1_batch_updates.rs index 8a714ed2e815..2979ebbd8c26 100644 --- a/core/node/state_keeper/src/updates/l1_batch_updates.rs +++ b/core/node/state_keeper/src/updates/l1_batch_updates.rs @@ -49,6 +49,8 @@ impl L1BatchUpdates { #[cfg(test)] mod tests { + use std::collections::HashMap; + use zksync_multivm::vm_latest::TransactionVmExt; use zksync_types::{L2BlockNumber, ProtocolVersionId, H256}; @@ -76,7 +78,7 @@ mod tests { BlockGasCount::default(), VmExecutionMetrics::default(), vec![], - vec![], + HashMap::new(), vec![], ); diff --git a/core/node/state_keeper/src/updates/l2_block_updates.rs b/core/node/state_keeper/src/updates/l2_block_updates.rs index 2301016c314a..27995b384abe 100644 --- a/core/node/state_keeper/src/updates/l2_block_updates.rs +++ b/core/node/state_keeper/src/updates/l2_block_updates.rs @@ -88,12 +88,11 @@ impl L2BlockUpdates { tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, compressed_bytecodes: Vec, - new_known_factory_deps: Vec<(H256, Vec)>, + new_known_factory_deps: HashMap>, call_traces: Vec, ) { let saved_factory_deps = extract_bytecodes_marked_as_known(&tx_execution_result.logs.events); - self.new_factory_deps.extend(new_known_factory_deps.clone()); self.events.extend(tx_execution_result.logs.events); self.user_l2_to_l1_logs .extend(tx_execution_result.logs.user_l2_to_l1_logs); @@ -128,9 +127,11 @@ impl L2BlockUpdates { .iter() .map(|bytecode| (hash_bytecode(bytecode), bytecode.clone())) .collect(); + // Ensure that *dynamic* factory deps (ones that may be created when executing EVM contracts) + // are added into the lookup map as well. + tx_factory_deps.extend(new_known_factory_deps); - tx_factory_deps.extend(new_known_factory_deps.clone()); - // Save all bytecodes that were marked as known on the bootloader + // Save all bytecodes that were marked as known in the bootloader let known_bytecodes = saved_factory_deps.into_iter().map(|bytecode_hash| { let bytecode = tx_factory_deps.get(&bytecode_hash).unwrap_or_else(|| { panic!( @@ -210,7 +211,7 @@ mod tests { BlockGasCount::default(), VmExecutionMetrics::default(), vec![], - vec![], + HashMap::new(), vec![], ); diff --git a/core/node/state_keeper/src/updates/mod.rs b/core/node/state_keeper/src/updates/mod.rs index 59267b976dbe..0cebc5d8b471 100644 --- a/core/node/state_keeper/src/updates/mod.rs +++ b/core/node/state_keeper/src/updates/mod.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use zksync_contracts::BaseSystemContractsHashes; use zksync_multivm::{ interface::{ @@ -110,7 +112,7 @@ impl UpdatesManager { tx: Transaction, tx_execution_result: VmExecutionResultAndLogs, compressed_bytecodes: Vec, - new_known_factory_deps: Vec<(H256, Vec)>, + new_known_factory_deps: HashMap>, tx_l1_gas_this_tx: BlockGasCount, execution_metrics: VmExecutionMetrics, call_traces: Vec, @@ -236,7 +238,7 @@ mod tests { tx, create_execution_result([]), vec![], - vec![], + HashMap::new(), new_block_gas_count(), VmExecutionMetrics::default(), vec![], From a80d6499e51c738b85f0fc7d3f77c13479cd353e Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 14:45:57 +0300 Subject: [PATCH 44/72] Revert changes in `multivm` unit tests --- .../versions/vm_fast/tests/l1_tx_execution.rs | 7 +- .../versions/vm_fast/tests/nonce_holder.rs | 11 ++- .../src/versions/vm_fast/tests/rollbacks.rs | 47 +++--------- .../tests/tester/transaction_test_info.rs | 73 +++++++++++-------- .../src/versions/vm_latest/tests/circuits.rs | 2 +- .../vm_latest/tests/l1_tx_execution.rs | 7 +- .../versions/vm_latest/tests/nonce_holder.rs | 11 ++- .../src/versions/vm_latest/tests/rollbacks.rs | 47 +++--------- .../tests/tester/transaction_test_info.rs | 73 ++++++++++--------- 9 files changed, 118 insertions(+), 160 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs index 5897ec5f2662..1abb1e39e19b 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/l1_tx_execution.rs @@ -117,8 +117,9 @@ fn test_l1_tx_execution() { let res = vm.vm.execute(VmExecutionMode::OneTx); let storage_logs = res.logs.storage_logs; let res = StorageWritesDeduplicator::apply_on_empty_state(&storage_logs); - // We changed one slot inside contract. - assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); + // We changed one slot inside contract. However, the rewrite of the `basePubdataSpent` didn't happen, since it was the same + // as the start of the previous tx. Thus we have `+1` slot for the changed counter and `-1` slot for base pubdata spent + assert_eq!(res.initial_storage_writes, basic_initial_writes); // No repeated writes let repeated_writes = res.repeated_storage_writes; @@ -145,7 +146,7 @@ fn test_l1_tx_execution() { assert!(result.result.is_failed(), "The transaction should fail"); let res = StorageWritesDeduplicator::apply_on_empty_state(&result.logs.storage_logs); - assert_eq!(res.initial_storage_writes, basic_initial_writes + 1); + assert_eq!(res.initial_storage_writes, basic_initial_writes); assert_eq!(res.repeated_storage_writes, 1); } diff --git a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs index 6d1e0f016e9e..f72e95da9f87 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/nonce_holder.rs @@ -37,7 +37,6 @@ impl From for u8 { #[test] fn test_nonce_holder() { let mut account = Account::random(); - let hex_addr = hex::encode(account.address.to_fixed_bytes()); let mut vm = VmTesterBuilder::new() .with_empty_in_memory_storage() @@ -93,7 +92,7 @@ fn test_nonce_holder() { run_nonce_test( 1u32, NonceHolderTestMode::SetValueUnderNonce, - Some("Error function_selector = 0x13595475, data = 0x13595475".to_string()), + Some("Previous nonce has not been used".to_string()), "Allowed to set value under non sequential value", ); @@ -134,7 +133,7 @@ fn test_nonce_holder() { run_nonce_test( 10u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000a")), + Some("Reusing the same nonce twice".to_string()), "Allowed to reuse nonce below the minimal one", ); @@ -150,7 +149,7 @@ fn test_nonce_holder() { run_nonce_test( 13u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000d")), + Some("Reusing the same nonce twice".to_string()), "Allowed to reuse the same nonce twice", ); @@ -166,7 +165,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::IncreaseMinNonceTooMuch, - Some("Error function_selector = 0x45ac24a6, data = 0x45ac24a600000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000".to_string()), + Some("The value for incrementing the nonce is too high".to_string()), "Allowed for incrementing min nonce too much", ); @@ -174,7 +173,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::LeaveNonceUnused, - Some(format!("Error function_selector = 0x1f2f8478, data = 0x1f2f8478000000000000000000000000{hex_addr}0000000000000000000000000000000000000000000000000000000000000010")), + Some("The nonce was not set as used".to_string()), "Allowed to leave nonce as unused", ); } diff --git a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs index 548bf8daadfc..e7b3f2043385 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/rollbacks.rs @@ -1,6 +1,6 @@ use ethabi::Token; use zksync_contracts::{get_loadnext_contract, test_contracts::LoadnextContractExecutionParams}; -use zksync_types::{Execute, Nonce, U256}; +use zksync_types::{Execute, U256}; use crate::{ interface::TxExecutionMode, @@ -38,40 +38,22 @@ fn test_vm_rollbacks() { TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongMagicValue.into()), TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongSignature.into()), // The correct nonce is 0, this tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(0)).into(), - ), + TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_0.clone(), false), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(1)).into(), - ), + TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_1, false), // The correct nonce is 2, this tx will fail - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_2.clone(), false), // This tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::NonceReused(tx_2.initiator_account(), tx_2.nonce().unwrap()).into(), - ), - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_2, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected(tx_0, TxModifier::NonceReused.into()), ]); pretty_assertions::assert_eq!(result_without_rollbacks, result_with_rollbacks); @@ -149,23 +131,12 @@ fn test_vm_loadnext_rollbacks() { TransactionTestInfo::new_processed(loadnext_tx_1.clone(), true), TransactionTestInfo::new_rejected( loadnext_deploy_tx.clone(), - TxModifier::NonceReused( - loadnext_deploy_tx.initiator_account(), - loadnext_deploy_tx.nonce().unwrap(), - ) - .into(), + TxModifier::NonceReused.into(), ), TransactionTestInfo::new_processed(loadnext_tx_1, false), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), - TransactionTestInfo::new_rejected( - loadnext_deploy_tx.clone(), - TxModifier::NonceReused( - loadnext_deploy_tx.initiator_account(), - loadnext_deploy_tx.nonce().unwrap(), - ) - .into(), - ), + TransactionTestInfo::new_rejected(loadnext_deploy_tx, TxModifier::NonceReused.into()), TransactionTestInfo::new_processed(loadnext_tx_2, false), ]); diff --git a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs index 46def9e52499..e6506ff225b3 100644 --- a/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs +++ b/core/lib/multivm/src/versions/vm_fast/tests/tester/transaction_test_info.rs @@ -1,6 +1,6 @@ use std::fmt; -use zksync_types::{ExecuteTransactionCommon, Nonce, Transaction, H160, U256}; +use zksync_types::{ExecuteTransactionCommon, Transaction, H160, U256}; use zksync_vm2::interface::{Event, StateInterface}; use super::VmTester; @@ -18,8 +18,8 @@ pub(crate) enum TxModifier { WrongSignatureLength, WrongSignature, WrongMagicValue, - WrongNonce(Nonce, Nonce), - NonceReused(H160, Nonce), + WrongNonce, + NonceReused, } #[derive(Debug, Clone)] @@ -44,9 +44,15 @@ impl From for ExpectedError { fn from(value: TxModifier) -> Self { let revert_reason = match value { TxModifier::WrongSignatureLength => { - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector: vec![144, 240, 73, 201], - data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45], + Halt::ValidationFailed(VmRevertReason::General { + msg: "Signature length is incorrect".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 83, 105, 103, 110, 97, 116, 117, 114, 101, 32, + 108, 101, 110, 103, 116, 104, 32, 105, 115, 32, 105, 110, 99, 111, 114, 114, 101, 99, + 116, 0, 0, 0, + ], }) } TxModifier::WrongSignature => { @@ -56,35 +62,38 @@ impl From for ExpectedError { }) } TxModifier::WrongMagicValue => { - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector: vec![144, 240, 73, 201], - data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + Halt::ValidationFailed(VmRevertReason::General { + msg: "v is neither 27 nor 28".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 118, 32, 105, 115, 32, 110, 101, 105, 116, 104, + 101, 114, 32, 50, 55, 32, 110, 111, 114, 32, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], }) } - TxModifier::WrongNonce(expected, actual) => { - let function_selector = vec![98, 106, 222, 48]; - let expected_nonce_bytes = expected.0.to_be_bytes().to_vec(); - let actual_nonce_bytes = actual.0.to_be_bytes().to_vec(); - // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field - let nonce_padding = vec![0u8; 28]; - let data = [function_selector.clone(), nonce_padding.clone(), expected_nonce_bytes, nonce_padding.clone(), actual_nonce_bytes].concat(); - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector, - data + TxModifier::WrongNonce => { + Halt::ValidationFailed(VmRevertReason::General { + msg: "Incorrect nonce".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 73, 110, 99, 111, 114, 114, 101, 99, 116, 32, 110, + 111, 110, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], }) } - TxModifier::NonceReused(addr, nonce) => { - let function_selector = vec![233, 10, 222, 212]; - let addr = addr.as_bytes().to_vec(); - // padding is 12 because an address takes up 20 bytes and we need it to fill a 32 byte field - let addr_padding = vec![0u8; 12]; - // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field - let nonce_padding = vec![0u8; 28]; - let data = [function_selector.clone(), addr_padding, addr, nonce_padding, nonce.0.to_be_bytes().to_vec()].concat(); - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector, - data, + TxModifier::NonceReused => { + Halt::ValidationFailed(VmRevertReason::General { + msg: "Reusing the same nonce twice".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 82, 101, 117, 115, 105, 110, 103, 32, 116, 104, + 101, 32, 115, 97, 109, 101, 32, 110, 111, 110, 99, 101, 32, 116, 119, 105, 99, 101, 0, + 0, 0, 0, + ], }) } }; @@ -110,10 +119,10 @@ impl TransactionTestInfo { } TxModifier::WrongSignature => data.signature = vec![27u8; 65], TxModifier::WrongMagicValue => data.signature = vec![1u8; 65], - TxModifier::WrongNonce(_, _) => { + TxModifier::WrongNonce => { // Do not need to modify signature for nonce error } - TxModifier::NonceReused(_, _) => { + TxModifier::NonceReused => { // Do not need to modify signature for nonce error } } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs index 8b52bc0f5e17..c3c6816cbd8f 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/circuits.rs @@ -37,7 +37,7 @@ fn test_circuits() { let s = res.statistics.circuit_statistic; // Check `circuit_statistic`. const EXPECTED: [f32; 13] = [ - 1.34935, 0.15026, 1.66666, 0.00315, 1.1799649, 0.00058, 0.00348, 0.00076, 0.11945, 0.14285, + 1.34935, 0.15026, 1.66666, 0.00315, 1.0594, 0.00058, 0.00348, 0.00076, 0.11945, 0.14285, 0.0, 0.0, 0.0, ]; let actual = [ diff --git a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs index b424567aab02..0fc12848227e 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs @@ -112,8 +112,9 @@ fn test_l1_tx_execution() { let res = vm.vm.execute(VmExecutionMode::OneTx); let storage_logs = res.logs.storage_logs; let res = StorageWritesDeduplicator::apply_on_empty_state(&storage_logs); - // We changed one slot inside contract. - assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); + // We changed one slot inside contract. However, the rewrite of the `basePubdataSpent` didn't happen, since it was the same + // as the start of the previous tx. Thus we have `+1` slot for the changed counter and `-1` slot for base pubdata spent + assert_eq!(res.initial_storage_writes - basic_initial_writes, 0); // No repeated writes let repeated_writes = res.repeated_storage_writes; @@ -141,7 +142,7 @@ fn test_l1_tx_execution() { let res = StorageWritesDeduplicator::apply_on_empty_state(&result.logs.storage_logs); // There are only basic initial writes - assert_eq!(res.initial_storage_writes - basic_initial_writes, 2); + assert_eq!(res.initial_storage_writes - basic_initial_writes, 1); } #[test] diff --git a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs index 86d03970f5c3..91d78c69a931 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs @@ -40,7 +40,6 @@ impl From for u8 { #[test] fn test_nonce_holder() { let mut account = Account::random(); - let hex_addr = hex::encode(account.address.to_fixed_bytes()); let mut vm = VmTesterBuilder::new(HistoryEnabled) .with_empty_in_memory_storage() @@ -102,7 +101,7 @@ fn test_nonce_holder() { run_nonce_test( 1u32, NonceHolderTestMode::SetValueUnderNonce, - Some("Error function_selector = 0x13595475, data = 0x13595475".to_string()), + Some("Previous nonce has not been used".to_string()), "Allowed to set value under non sequential value", ); @@ -143,7 +142,7 @@ fn test_nonce_holder() { run_nonce_test( 10u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000a")), + Some("Reusing the same nonce twice".to_string()), "Allowed to reuse nonce below the minimal one", ); @@ -159,7 +158,7 @@ fn test_nonce_holder() { run_nonce_test( 13u32, NonceHolderTestMode::IncreaseMinNonceBy5, - Some(format!("Error function_selector = 0xe90aded4, data = 0xe90aded4000000000000000000000000{hex_addr}000000000000000000000000000000000000000000000000000000000000000d")), + Some("Reusing the same nonce twice".to_string()), "Allowed to reuse the same nonce twice", ); @@ -175,7 +174,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::IncreaseMinNonceTooMuch, - Some("Error function_selector = 0x45ac24a6, data = 0x45ac24a600000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000".to_string()), + Some("The value for incrementing the nonce is too high".to_string()), "Allowed for incrementing min nonce too much", ); @@ -183,7 +182,7 @@ fn test_nonce_holder() { run_nonce_test( 16u32, NonceHolderTestMode::LeaveNonceUnused, - Some(format!("Error function_selector = 0x1f2f8478, data = 0x1f2f8478000000000000000000000000{hex_addr}0000000000000000000000000000000000000000000000000000000000000010")), + Some("The nonce was not set as used".to_string()), "Allowed to leave nonce as unused", ); } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs index 982d9820799d..880f189fd892 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/rollbacks.rs @@ -1,6 +1,6 @@ use ethabi::Token; use zksync_contracts::{get_loadnext_contract, test_contracts::LoadnextContractExecutionParams}; -use zksync_types::{get_nonce_key, Execute, Nonce, U256}; +use zksync_types::{get_nonce_key, Execute, U256}; use crate::{ interface::{ @@ -47,40 +47,22 @@ fn test_vm_rollbacks() { TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongMagicValue.into()), TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::WrongSignature.into()), // The correct nonce is 0, this tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(0)).into(), - ), + TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_0.clone(), false), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), // The correct nonce is 1, this tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::WrongNonce(tx_2.nonce().unwrap(), Nonce(1)).into(), - ), + TransactionTestInfo::new_rejected(tx_2.clone(), TxModifier::WrongNonce.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_1, false), // The correct nonce is 2, this tx will fail - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_0.clone(), TxModifier::NonceReused.into()), // This tx will succeed TransactionTestInfo::new_processed(tx_2.clone(), false), // This tx will fail - TransactionTestInfo::new_rejected( - tx_2.clone(), - TxModifier::NonceReused(tx_2.initiator_account(), tx_2.nonce().unwrap()).into(), - ), - TransactionTestInfo::new_rejected( - tx_0.clone(), - TxModifier::NonceReused(tx_0.initiator_account(), tx_0.nonce().unwrap()).into(), - ), + TransactionTestInfo::new_rejected(tx_2, TxModifier::NonceReused.into()), + TransactionTestInfo::new_rejected(tx_0, TxModifier::NonceReused.into()), ]); assert_eq!(result_without_rollbacks, result_with_rollbacks); @@ -158,23 +140,12 @@ fn test_vm_loadnext_rollbacks() { TransactionTestInfo::new_processed(loadnext_tx_1.clone(), true), TransactionTestInfo::new_rejected( loadnext_deploy_tx.clone(), - TxModifier::NonceReused( - loadnext_deploy_tx.initiator_account(), - loadnext_deploy_tx.nonce().unwrap(), - ) - .into(), + TxModifier::NonceReused.into(), ), TransactionTestInfo::new_processed(loadnext_tx_1, false), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), TransactionTestInfo::new_processed(loadnext_tx_2.clone(), true), - TransactionTestInfo::new_rejected( - loadnext_deploy_tx.clone(), - TxModifier::NonceReused( - loadnext_deploy_tx.initiator_account(), - loadnext_deploy_tx.nonce().unwrap(), - ) - .into(), - ), + TransactionTestInfo::new_rejected(loadnext_deploy_tx, TxModifier::NonceReused.into()), TransactionTestInfo::new_processed(loadnext_tx_2, false), ]); diff --git a/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs b/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs index f07d1602d300..08667ccc625f 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/tester/transaction_test_info.rs @@ -1,4 +1,4 @@ -use zksync_types::{ExecuteTransactionCommon, Nonce, Transaction, H160}; +use zksync_types::{ExecuteTransactionCommon, Transaction}; use crate::{ interface::{ @@ -14,8 +14,8 @@ pub(crate) enum TxModifier { WrongSignatureLength, WrongSignature, WrongMagicValue, - WrongNonce(Nonce, Nonce), - NonceReused(H160, Nonce), + WrongNonce, + NonceReused, } #[derive(Debug, Clone)] @@ -40,11 +40,14 @@ impl From for ExpectedError { fn from(value: TxModifier) -> Self { let revert_reason = match value { TxModifier::WrongSignatureLength => { - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector: vec![144, 240, 73, 201], + Halt::ValidationFailed(VmRevertReason::General { + msg: "Signature length is incorrect".to_string(), data: vec![ - 144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45 + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 83, 105, 103, 110, 97, 116, 117, 114, 101, 32, + 108, 101, 110, 103, 116, 104, 32, 105, 115, 32, 105, 110, 99, 111, 114, 114, 101, 99, + 116, 0, 0, 0, ], }) } @@ -55,34 +58,38 @@ impl From for ExpectedError { }) } TxModifier::WrongMagicValue => { - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector: vec![144, 240, 73, 201], - data: vec![144, 240, 73, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + Halt::ValidationFailed(VmRevertReason::General { + msg: "v is neither 27 nor 28".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 118, 32, 105, 115, 32, 110, 101, 105, 116, 104, + 101, 114, 32, 50, 55, 32, 110, 111, 114, 32, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], }) + } - TxModifier::WrongNonce(expected, actual) => { - let function_selector = vec![98, 106, 222, 48]; - let expected_nonce_bytes = expected.0.to_be_bytes().to_vec(); - let actual_nonce_bytes = actual.0.to_be_bytes().to_vec(); - // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field - let nonce_padding = vec![0u8; 28]; - let data = [function_selector.clone(), nonce_padding.clone(), expected_nonce_bytes, nonce_padding.clone(), actual_nonce_bytes].concat(); - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector, - data + TxModifier::WrongNonce => { + Halt::ValidationFailed(VmRevertReason::General { + msg: "Incorrect nonce".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 73, 110, 99, 111, 114, 114, 101, 99, 116, 32, 110, + 111, 110, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], }) } - TxModifier::NonceReused(addr, nonce) => { - let function_selector = vec![233, 10, 222, 212]; - let addr = addr.as_bytes().to_vec(); - // padding is 12 because an address takes up 20 bytes and we need it to fill a 32 byte field - let addr_padding = vec![0u8; 12]; - // padding is 28 because an address takes up 4 bytes and we need it to fill a 32 byte field - let nonce_padding = vec![0u8; 28]; - let data = [function_selector.clone(), addr_padding, addr, nonce_padding, nonce.0.to_be_bytes().to_vec()].concat(); - Halt::ValidationFailed(VmRevertReason::Unknown { - function_selector, - data, + TxModifier::NonceReused => { + Halt::ValidationFailed(VmRevertReason::General { + msg: "Reusing the same nonce twice".to_string(), + data: vec![ + 8, 195, 121, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 82, 101, 117, 115, 105, 110, 103, 32, 116, 104, + 101, 32, 115, 97, 109, 101, 32, 110, 111, 110, 99, 101, 32, 116, 119, 105, 99, 101, 0, + 0, 0, 0, + ], }) } }; @@ -108,10 +115,10 @@ impl TransactionTestInfo { } TxModifier::WrongSignature => data.signature = vec![27u8; 65], TxModifier::WrongMagicValue => data.signature = vec![1u8; 65], - TxModifier::WrongNonce(_, _) => { + TxModifier::WrongNonce => { // Do not need to modify signature for nonce error } - TxModifier::NonceReused(_, _) => { + TxModifier::NonceReused => { // Do not need to modify signature for nonce error } } From ff0b1e873fb068e9db5cbd549c0b3e596ec37f01 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 14:50:04 +0300 Subject: [PATCH 45/72] Remove `UseEvmSimulator` config --- core/bin/zksync_server/src/main.rs | 2 -- core/lib/config/src/configs/general.rs | 2 -- core/lib/config/src/configs/mod.rs | 1 - .../config/src/configs/use_evm_simulator.rs | 7 ------- core/lib/config/src/testonly.rs | 9 --------- core/lib/env_config/src/lib.rs | 1 - core/lib/env_config/src/use_evm_simulator.rs | 9 --------- core/lib/protobuf_config/src/general.rs | 2 -- core/lib/protobuf_config/src/lib.rs | 12 +++++------ .../src/proto/config/general.proto | 2 -- .../src/proto/config/use_evm_simulator.proto | 7 ------- .../protobuf_config/src/use_evm_simulator.rs | 20 ------------------- .../src/temp_config_store/mod.rs | 4 ---- 13 files changed, 5 insertions(+), 73 deletions(-) delete mode 100644 core/lib/config/src/configs/use_evm_simulator.rs delete mode 100644 core/lib/env_config/src/use_evm_simulator.rs delete mode 100644 core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto delete mode 100644 core/lib/protobuf_config/src/use_evm_simulator.rs diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index 748a9437ed27..84898d6da067 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -11,7 +11,6 @@ use zksync_config::{ }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, - use_evm_simulator::UseEvmSimulator, BasicWitnessInputProducerConfig, ContractsConfig, DatabaseSecrets, ExperimentalVmConfig, ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig, FriProverGatewayConfig, FriWitnessGeneratorConfig, FriWitnessVectorGeneratorConfig, @@ -206,7 +205,6 @@ fn load_env_config() -> anyhow::Result { basic_witness_input_producer_config: BasicWitnessInputProducerConfig::from_env().ok(), core_object_store: ObjectStoreConfig::from_env().ok(), base_token_adjuster_config: BaseTokenAdjusterConfig::from_env().ok(), - use_evm_simulator: UseEvmSimulator::from_env().ok(), commitment_generator: None, pruning: None, snapshot_recovery: None, diff --git a/core/lib/config/src/configs/general.rs b/core/lib/config/src/configs/general.rs index b7c78cbdb700..bb733510f77d 100644 --- a/core/lib/config/src/configs/general.rs +++ b/core/lib/config/src/configs/general.rs @@ -10,7 +10,6 @@ use crate::{ prover_job_monitor::ProverJobMonitorConfig, pruning::PruningConfig, snapshot_recovery::SnapshotRecoveryConfig, - use_evm_simulator::UseEvmSimulator, vm_runner::{BasicWitnessInputProducerConfig, ProtectiveReadsWriterConfig}, CommitmentGeneratorConfig, ExperimentalVmConfig, ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig, FriProverGatewayConfig, @@ -52,7 +51,6 @@ pub struct GeneralConfig { pub pruning: Option, pub core_object_store: Option, pub base_token_adjuster: Option, - pub use_evm_simulator: Option, pub external_price_api_client_config: Option, pub consensus_config: Option, pub external_proof_integration_api_config: Option, diff --git a/core/lib/config/src/configs/mod.rs b/core/lib/config/src/configs/mod.rs index 456749e05a5e..1ad503e0687f 100644 --- a/core/lib/config/src/configs/mod.rs +++ b/core/lib/config/src/configs/mod.rs @@ -65,7 +65,6 @@ pub mod pruning; pub mod secrets; pub mod snapshot_recovery; pub mod snapshots_creator; -pub mod use_evm_simulator; pub mod utils; pub mod vm_runner; pub mod wallets; diff --git a/core/lib/config/src/configs/use_evm_simulator.rs b/core/lib/config/src/configs/use_evm_simulator.rs deleted file mode 100644 index 7309c92a3445..000000000000 --- a/core/lib/config/src/configs/use_evm_simulator.rs +++ /dev/null @@ -1,7 +0,0 @@ -use serde::Deserialize; - -/// Configure whether to enable the EVM simulator on the stack. -#[derive(Debug, Deserialize, Clone, PartialEq)] -pub struct UseEvmSimulator { - pub use_evm_simulator: bool, -} diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index e05459aa7858..1884b30b5f9a 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -40,14 +40,6 @@ impl Sample for Network { } } -impl Distribution for EncodeDist { - fn sample(&self, rng: &mut R) -> configs::use_evm_simulator::UseEvmSimulator { - configs::use_evm_simulator::UseEvmSimulator { - use_evm_simulator: rng.gen(), - } - } -} - impl Distribution for EncodeDist { fn sample(&self, rng: &mut R) -> configs::chain::FeeModelVersion { type T = configs::chain::FeeModelVersion; @@ -1162,7 +1154,6 @@ impl Distribution for EncodeDist { protective_reads_writer_config: self.sample(rng), basic_witness_input_producer_config: self.sample(rng), commitment_generator: self.sample(rng), - use_evm_simulator: self.sample(rng), snapshot_recovery: self.sample(rng), pruning: self.sample(rng), core_object_store: self.sample(rng), diff --git a/core/lib/env_config/src/lib.rs b/core/lib/env_config/src/lib.rs index 701817522d37..b72c2c5d5b94 100644 --- a/core/lib/env_config/src/lib.rs +++ b/core/lib/env_config/src/lib.rs @@ -29,7 +29,6 @@ mod genesis; mod prover_job_monitor; #[cfg(test)] mod test_utils; -mod use_evm_simulator; mod vm_runner; mod wallets; diff --git a/core/lib/env_config/src/use_evm_simulator.rs b/core/lib/env_config/src/use_evm_simulator.rs deleted file mode 100644 index c2a58387e62f..000000000000 --- a/core/lib/env_config/src/use_evm_simulator.rs +++ /dev/null @@ -1,9 +0,0 @@ -use zksync_config::configs::use_evm_simulator::UseEvmSimulator; - -use crate::{envy_load, FromEnv}; - -impl FromEnv for UseEvmSimulator { - fn from_env() -> anyhow::Result { - envy_load("use_evm_simulator", "USE_EVM_SIMULATOR_") - } -} diff --git a/core/lib/protobuf_config/src/general.rs b/core/lib/protobuf_config/src/general.rs index 736420e34268..b73539a0897f 100644 --- a/core/lib/protobuf_config/src/general.rs +++ b/core/lib/protobuf_config/src/general.rs @@ -46,7 +46,6 @@ 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), - use_evm_simulator: read_optional_repr(&self.use_evm_simulator), }) } @@ -103,7 +102,6 @@ impl ProtoRepr for proto::GeneralConfig { .as_ref() .map(ProtoRepr::build), experimental_vm: this.experimental_vm_config.as_ref().map(ProtoRepr::build), - use_evm_simulator: this.use_evm_simulator.as_ref().map(ProtoRepr::build), prover_job_monitor: this .prover_job_monitor_config .as_ref() diff --git a/core/lib/protobuf_config/src/lib.rs b/core/lib/protobuf_config/src/lib.rs index c1a65ee55b6d..e3226d2627a5 100644 --- a/core/lib/protobuf_config/src/lib.rs +++ b/core/lib/protobuf_config/src/lib.rs @@ -12,11 +12,14 @@ mod commitment_generator; mod consensus; mod contract_verifier; mod contracts; +mod da_client; mod da_dispatcher; mod database; mod en; mod eth; mod experimental; +mod external_price_api_client; +mod external_proof_integration_api; mod general; mod genesis; mod house_keeper; @@ -25,16 +28,11 @@ mod observability; mod proof_data_handler; pub mod proto; mod prover; +mod prover_job_monitor; mod pruning; mod secrets; -mod snapshots_creator; -mod use_evm_simulator; - -mod da_client; -mod external_price_api_client; -mod external_proof_integration_api; -mod prover_job_monitor; mod snapshot_recovery; +mod snapshots_creator; #[cfg(test)] mod tests; mod utils; diff --git a/core/lib/protobuf_config/src/proto/config/general.proto b/core/lib/protobuf_config/src/proto/config/general.proto index c3f7c88cf850..ee70b61b18b3 100644 --- a/core/lib/protobuf_config/src/proto/config/general.proto +++ b/core/lib/protobuf_config/src/proto/config/general.proto @@ -26,7 +26,6 @@ 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/use_evm_simulator.proto"; message GeneralConfig { optional database.Postgres postgres = 1; @@ -63,5 +62,4 @@ 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 use_evm_simulator.UseEvmSimulator use_evm_simulator = 47; } diff --git a/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto b/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto deleted file mode 100644 index f0ca7329f903..000000000000 --- a/core/lib/protobuf_config/src/proto/config/use_evm_simulator.proto +++ /dev/null @@ -1,7 +0,0 @@ -syntax = "proto3"; - -package zksync.config.use_evm_simulator; - -message UseEvmSimulator { - optional bool use_evm_simulator = 1; -} diff --git a/core/lib/protobuf_config/src/use_evm_simulator.rs b/core/lib/protobuf_config/src/use_evm_simulator.rs deleted file mode 100644 index 703b8f8cc3ce..000000000000 --- a/core/lib/protobuf_config/src/use_evm_simulator.rs +++ /dev/null @@ -1,20 +0,0 @@ -use zksync_config::configs::{self}; -use zksync_protobuf::ProtoRepr; - -use crate::proto::use_evm_simulator as proto; - -impl ProtoRepr for proto::UseEvmSimulator { - type Type = configs::use_evm_simulator::UseEvmSimulator; - - fn read(&self) -> anyhow::Result { - Ok(configs::use_evm_simulator::UseEvmSimulator { - use_evm_simulator: self.use_evm_simulator.unwrap_or_default(), - }) - } - - fn build(this: &Self::Type) -> Self { - Self { - use_evm_simulator: Some(this.use_evm_simulator), - } - } -} 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 47f6e6a2241c..2d6af705f482 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 @@ -10,7 +10,6 @@ use zksync_config::{ }, fri_prover_group::FriProverGroupConfig, house_keeper::HouseKeeperConfig, - use_evm_simulator::UseEvmSimulator, vm_runner::BasicWitnessInputProducerConfig, wallets::{AddressWallet, EthSender, StateKeeper, TokenMultiplierSetter, Wallet, Wallets}, CommitmentGeneratorConfig, DatabaseSecrets, ExperimentalVmConfig, @@ -76,7 +75,6 @@ pub struct TempConfigStore { pub core_object_store: Option, pub base_token_adjuster_config: Option, pub commitment_generator: Option, - pub use_evm_simulator: Option, pub pruning: Option, pub snapshot_recovery: Option, pub external_price_api_client_config: Option, @@ -119,7 +117,6 @@ impl TempConfigStore { pruning: self.pruning.clone(), external_price_api_client_config: self.external_price_api_client_config.clone(), consensus_config: None, - use_evm_simulator: self.use_evm_simulator.clone(), external_proof_integration_api_config: self .external_proof_integration_api_config .clone(), @@ -199,7 +196,6 @@ fn load_env_config() -> anyhow::Result { basic_witness_input_producer_config: BasicWitnessInputProducerConfig::from_env().ok(), core_object_store: ObjectStoreConfig::from_env().ok(), base_token_adjuster_config: BaseTokenAdjusterConfig::from_env().ok(), - use_evm_simulator: UseEvmSimulator::from_env().ok(), commitment_generator: None, pruning: None, snapshot_recovery: None, From 21ef547348173f3c006be2276be2c8f406c3b18d Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 14:54:46 +0300 Subject: [PATCH 46/72] Revert changes in config files --- etc/env/base/chain.toml | 1 - etc/env/base/use_evm_simulator.toml | 2 -- etc/env/file_based/general.yaml | 3 --- etc/env/file_based/genesis.yaml | 7 ++++--- infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts | 4 ---- 5 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 etc/env/base/use_evm_simulator.toml diff --git a/etc/env/base/chain.toml b/etc/env/base/chain.toml index 15b14c9f2cc1..6cfacb3c72ce 100644 --- a/etc/env/base/chain.toml +++ b/etc/env/base/chain.toml @@ -92,7 +92,6 @@ save_call_traces = true bootloader_hash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e" default_aa_hash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32" -evm_simulator_hash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32" protective_reads_persistence_enabled = false diff --git a/etc/env/base/use_evm_simulator.toml b/etc/env/base/use_evm_simulator.toml deleted file mode 100644 index 0db670361f16..000000000000 --- a/etc/env/base/use_evm_simulator.toml +++ /dev/null @@ -1,2 +0,0 @@ -[use_evm_simulator] -use_evm_simulator = false diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 23455ecc972d..cdf02175458b 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -305,9 +305,6 @@ external_price_api_client: house_keeper: l1_batch_metrics_reporting_interval_ms: 10000 -use_evm_simulator: - use_evm_simulator: false - prometheus: listener_port: 3314 pushgateway_url: http://127.0.0.1:9091 diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 7f0dca74ef79..7ea9322c8452 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -4,8 +4,8 @@ genesis_batch_commitment: 0x2d00e5f8d77afcebf58a6b82ae56ba967566fe7dfbcb6760319f genesis_protocol_semantic_version: '0.24.2' # deprecated genesis_protocol_version: 24 -default_aa_hash: 0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2 -bootloader_hash: 0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1 +default_aa_hash: 0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32 +bootloader_hash: 0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e l1_chain_id: 9 l2_chain_id: 270 fee_account: '0x0000000000000000000000000000000000000001' @@ -13,4 +13,5 @@ prover: recursion_scheduler_level_vk_hash: 0x14f97b81e54b35fe673d8708cc1a19e1ea5b5e348e12d31e39824ed4f42bbca2 dummy_verifier: true l1_batch_commit_data_generator_mode: Rollup -evm_simulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 +# Uncomment to enable EVM simulation (requires to run genesis) +# evm_simulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 diff --git a/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts b/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts index 98a4cf1fbd83..e3b5f364efd9 100644 --- a/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts +++ b/infrastructure/protocol-upgrade/src/l2upgrade/deployer.ts @@ -8,7 +8,6 @@ export async function callSystemContractDeployer( nonce: string, bootloader: boolean, defaultAA: boolean, - evmSimulator: boolean, systemContracts: boolean, file: string ) { @@ -21,9 +20,6 @@ export async function callSystemContractDeployer( if (defaultAA) { argsString += ' --default-aa'; } - if (evmSimulator) { - argsString += '--evm-simulator'; - } if (systemContracts) { argsString += ' --system-contracts'; } From 1a0c00cf3f4a0a97e41f3b86bee28064b9acfa06 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 16:19:13 +0300 Subject: [PATCH 47/72] Sketch EVM simulator switch in API server --- core/lib/contracts/src/lib.rs | 17 ++++++++- core/lib/vm_executor/src/oneshot/block.rs | 22 ++++++++++- core/lib/vm_executor/src/oneshot/contracts.rs | 16 +++++++- .../src/execution_sandbox/execute.rs | 8 ++-- .../api_server/src/execution_sandbox/mod.rs | 19 ++++++++-- core/node/api_server/src/tx_sender/mod.rs | 31 +++++----------- core/node/api_server/src/tx_sender/tests.rs | 3 +- .../api_server/src/web3/namespaces/debug.rs | 7 +++- .../api_server/src/web3/namespaces/eth.rs | 24 +++++++++--- .../api_server/src/web3/namespaces/zks.rs | 37 ++++++++++++++----- core/node/api_server/src/web3/state.rs | 13 +++++-- 11 files changed, 142 insertions(+), 55 deletions(-) diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 8166b29e884c..faa60f8a32dd 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -307,6 +307,7 @@ pub struct SystemContractCode { pub struct BaseSystemContracts { pub bootloader: SystemContractCode, pub default_aa: SystemContractCode, + /// Never filled in constructors for now. The only way to get the EVM simulator enabled is to call [`Self::with_evm_simulator()`]. pub evm_simulator: Option, } @@ -339,7 +340,7 @@ impl BaseSystemContracts { let hash = hash_bytecode(&bytecode); let default_aa = SystemContractCode { - code: bytes_to_be_words(bytecode.clone()), + code: bytes_to_be_words(bytecode), hash, }; @@ -349,12 +350,24 @@ impl BaseSystemContracts { evm_simulator: None, } } - // BaseSystemContracts with proved bootloader - for handling transactions. + + /// BaseSystemContracts with proved bootloader - for handling transactions. pub fn load_from_disk() -> Self { let bootloader_bytecode = read_proved_batch_bootloader_bytecode(); BaseSystemContracts::load_with_bootloader(bootloader_bytecode) } + /// Loads the latest EVM simulator for these base system contracts. Logically, it only makes sense to do for the latest protocol version. + pub fn with_latest_evm_simulator(mut self) -> Self { + let bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); + let hash = hash_bytecode(&bytecode); + self.evm_simulator = Some(SystemContractCode { + code: bytes_to_be_words(bytecode), + hash, + }); + self + } + /// BaseSystemContracts with playground bootloader - used for handling eth_calls. pub fn playground() -> Self { let bootloader_bytecode = read_playground_batch_bootloader_bytecode(); diff --git a/core/lib/vm_executor/src/oneshot/block.rs b/core/lib/vm_executor/src/oneshot/block.rs index 8ba77305ad7d..fa56028264eb 100644 --- a/core/lib/vm_executor/src/oneshot/block.rs +++ b/core/lib/vm_executor/src/oneshot/block.rs @@ -133,13 +133,19 @@ impl BlockInfo { let protocol_version = l2_block_header .protocol_version .unwrap_or(ProtocolVersionId::last_potentially_undefined()); - + // We cannot use the EVM simulator mentioned in the block as is because of batch vs playground settings etc. + // Instead, we just check whether any simulator is enabled for a block, and store this binary flag for further use. + let use_evm_simulator = l2_block_header + .base_system_contracts_hashes + .evm_simulator + .is_some(); Ok(ResolvedBlockInfo { state_l2_block_number, state_l2_block_hash: l2_block_header.hash, vm_l1_batch_number, l1_batch_timestamp, protocol_version, + use_evm_simulator, is_pending: self.is_pending_l2_block(), }) } @@ -153,6 +159,7 @@ pub struct ResolvedBlockInfo { vm_l1_batch_number: L1BatchNumber, l1_batch_timestamp: u64, protocol_version: ProtocolVersionId, + use_evm_simulator: bool, is_pending: bool, } @@ -161,6 +168,14 @@ impl ResolvedBlockInfo { pub fn state_l2_block_number(&self) -> L2BlockNumber { self.state_l2_block_number } + + pub fn protocol_version(&self) -> ProtocolVersionId { + self.protocol_version + } + + pub fn use_evm_simulator(&self) -> bool { + self.use_evm_simulator + } } impl OneshotEnvParameters { @@ -213,7 +228,10 @@ impl OneshotEnvParameters { version: resolved_block_info.protocol_version, base_system_smart_contracts: self .base_system_contracts - .get_by_protocol_version(resolved_block_info.protocol_version) + .get_by_protocol_version( + resolved_block_info.protocol_version, + resolved_block_info.use_evm_simulator, + ) .clone(), bootloader_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, execution_mode, diff --git a/core/lib/vm_executor/src/oneshot/contracts.rs b/core/lib/vm_executor/src/oneshot/contracts.rs index 3b3a65fe30ba..3b9e54039cfd 100644 --- a/core/lib/vm_executor/src/oneshot/contracts.rs +++ b/core/lib/vm_executor/src/oneshot/contracts.rs @@ -26,8 +26,12 @@ pub(super) struct MultiVMBaseSystemContracts { impl MultiVMBaseSystemContracts { /// Gets contracts for a certain version. - pub fn get_by_protocol_version(&self, version: ProtocolVersionId) -> &BaseSystemContracts { - match version { + pub fn get_by_protocol_version( + &self, + version: ProtocolVersionId, + use_evm_simulator: bool, + ) -> BaseSystemContracts { + let base = match version { ProtocolVersionId::Version0 | ProtocolVersionId::Version1 | ProtocolVersionId::Version2 @@ -54,6 +58,14 @@ impl MultiVMBaseSystemContracts { ProtocolVersionId::Version24 | ProtocolVersionId::Version25 => { &self.vm_1_5_0_increased_memory } + }; + let base = base.clone(); + + if version.is_post_1_5_0() && use_evm_simulator { + // EVM simulator is not versioned now; the latest version is always checked out + base.with_latest_evm_simulator() + } else { + base } } diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index d974f2e9aa1d..14ac37e59368 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -175,7 +175,7 @@ impl SandboxExecutor { let initialization_stage = SANDBOX_METRICS.sandbox[&SandboxStage::Initialization].start(); let resolve_started_at = Instant::now(); let resolve_time = resolve_started_at.elapsed(); - let resolved_block_info = block_args.inner.resolve(&mut connection).await?; + let resolved_block_info = &block_args.resolved; // We don't want to emit too many logs. if resolve_time > Duration::from_millis(10) { tracing::debug!("Resolved block numbers (took {resolve_time:?})"); @@ -185,7 +185,7 @@ impl SandboxExecutor { SandboxAction::Execution { fee_input, tx } => { self.options .eth_call - .to_execute_env(&mut connection, &resolved_block_info, *fee_input, tx) + .to_execute_env(&mut connection, resolved_block_info, *fee_input, tx) .await? } &SandboxAction::Call { @@ -197,7 +197,7 @@ impl SandboxExecutor { .eth_call .to_call_env( &mut connection, - &resolved_block_info, + resolved_block_info, fee_input, enforced_base_fee, ) @@ -210,7 +210,7 @@ impl SandboxExecutor { } => { self.options .estimate_gas - .to_env(&mut connection, &resolved_block_info, fee_input, base_fee) + .to_env(&mut connection, resolved_block_info, fee_input, base_fee) .await? } }; diff --git a/core/node/api_server/src/execution_sandbox/mod.rs b/core/node/api_server/src/execution_sandbox/mod.rs index 36f10b8e9b08..8111a75fed50 100644 --- a/core/node/api_server/src/execution_sandbox/mod.rs +++ b/core/node/api_server/src/execution_sandbox/mod.rs @@ -10,7 +10,7 @@ use zksync_multivm::utils::get_eth_call_gas_limit; use zksync_types::{ api, fee_model::BatchFeeInput, L1BatchNumber, L2BlockNumber, ProtocolVersionId, U256, }; -use zksync_vm_executor::oneshot::BlockInfo; +use zksync_vm_executor::oneshot::{BlockInfo, ResolvedBlockInfo}; use self::vm_metrics::SandboxStage; pub(super) use self::{ @@ -285,21 +285,32 @@ pub enum BlockArgsError { } /// Information about a block provided to VM. -#[derive(Debug, Clone, Copy)] +#[derive(Debug)] pub(crate) struct BlockArgs { inner: BlockInfo, + resolved: ResolvedBlockInfo, block_id: api::BlockId, } impl BlockArgs { pub async fn pending(connection: &mut Connection<'_, Core>) -> anyhow::Result { let inner = BlockInfo::pending(connection).await?; + let resolved = inner.resolve(connection).await?; Ok(Self { inner, + resolved, block_id: api::BlockId::Number(api::BlockNumber::Pending), }) } + pub fn protocol_version(&self) -> ProtocolVersionId { + self.resolved.protocol_version() + } + + pub fn use_evm_simulator(&self) -> bool { + self.resolved.use_evm_simulator() + } + /// Loads block information from DB. pub async fn new( connection: &mut Connection<'_, Core>, @@ -326,8 +337,10 @@ impl BlockArgs { return Err(BlockArgsError::Missing); }; + let inner = BlockInfo::for_existing_block(connection, block_number).await?; Ok(Self { - inner: BlockInfo::for_existing_block(connection, block_number).await?, + inner, + resolved: inner.resolve(connection).await?, block_id, }) } diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index e2285c167110..09da35206842 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -287,13 +287,11 @@ impl TxSender { pub async fn submit_tx( &self, tx: L2Tx, + block_args: BlockArgs, ) -> Result<(L2TxSubmissionResult, VmExecutionResultAndLogs), SubmitTxError> { let tx_hash = tx.hash(); let stage_latency = SANDBOX_METRICS.start_tx_submit_stage(tx_hash, SubmitTxStage::Validate); - let mut connection = self.acquire_replica_connection().await?; - let protocol_version = connection.blocks_dal().pending_protocol_version().await?; - drop(connection); - self.validate_tx(&tx, protocol_version).await?; + self.validate_tx(&tx, block_args.protocol_version()).await?; stage_latency.observe(); let stage_latency = SANDBOX_METRICS.start_tx_submit_stage(tx_hash, SubmitTxStage::DryRun); @@ -312,9 +310,7 @@ impl TxSender { tx: tx.clone(), }; let vm_permit = vm_permit.ok_or(SubmitTxError::ServerShuttingDown)?; - let mut connection = self.acquire_replica_connection().await?; - let block_args = BlockArgs::pending(&mut connection).await?; - + let connection = self.acquire_replica_connection().await?; let execution_output = self .0 .executor @@ -567,7 +563,7 @@ impl TxSender { tx_gas_limit: u64, gas_price_per_pubdata: u32, fee_input: BatchFeeInput, - block_args: BlockArgs, + block_args: &BlockArgs, base_fee: u64, vm_version: VmVersion, state_override: Option, @@ -610,7 +606,7 @@ impl TxSender { let execution_output = self .0 .executor - .execute_in_sandbox(vm_permit, connection, action, &block_args, state_override) + .execute_in_sandbox(vm_permit, connection, action, block_args, state_override) .await?; Ok((execution_output.vm, execution_output.metrics)) } @@ -622,21 +618,14 @@ impl TxSender { pub async fn get_txs_fee_in_wei( &self, mut tx: Transaction, + block_args: BlockArgs, estimated_fee_scale_factor: f64, acceptable_overestimation: u64, state_override: Option, ) -> Result { let estimation_started_at = Instant::now(); - - let mut connection = self.acquire_replica_connection().await?; - let block_args = BlockArgs::pending(&mut connection).await?; - let protocol_version = connection - .blocks_dal() - .pending_protocol_version() - .await - .context("failed getting pending protocol version")?; + let protocol_version = block_args.protocol_version(); let max_gas_limit = get_max_batch_gas_limit(protocol_version.into()); - drop(connection); let fee_input = adjust_pubdata_price_for_tx( self.scaled_batch_fee_input().await?, @@ -733,7 +722,7 @@ impl TxSender { max_gas_limit, gas_per_pubdata_byte as u32, fee_input, - block_args, + &block_args, base_fee, protocol_version.into(), state_override.clone(), @@ -769,7 +758,7 @@ impl TxSender { try_gas_limit, gas_per_pubdata_byte as u32, fee_input, - block_args, + &block_args, base_fee, protocol_version.into(), state_override.clone(), @@ -802,7 +791,7 @@ impl TxSender { suggested_gas_limit, gas_per_pubdata_byte as u32, fee_input, - block_args, + &block_args, base_fee, protocol_version.into(), state_override, diff --git a/core/node/api_server/src/tx_sender/tests.rs b/core/node/api_server/src/tx_sender/tests.rs index ece35fbdbdac..02ddbaff02d4 100644 --- a/core/node/api_server/src/tx_sender/tests.rs +++ b/core/node/api_server/src/tx_sender/tests.rs @@ -118,6 +118,7 @@ async fn submitting_tx_requires_one_connection() { insert_genesis_batch(&mut storage, &GenesisParams::mock()) .await .unwrap(); + let block_args = BlockArgs::pending(&mut storage).await.unwrap(); let l2_chain_id = L2ChainId::default(); let fee_input = MockBatchFeeParamsProvider::default() @@ -147,7 +148,7 @@ async fn submitting_tx_requires_one_connection() { let tx_executor = SandboxExecutor::mock(tx_executor).await; let (tx_sender, _) = create_test_tx_sender(pool.clone(), l2_chain_id, tx_executor).await; - let submission_result = tx_sender.submit_tx(tx).await.unwrap(); + 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(); diff --git a/core/node/api_server/src/web3/namespaces/debug.rs b/core/node/api_server/src/web3/namespaces/debug.rs index 1182c1826783..cb4b78411508 100644 --- a/core/node/api_server/src/web3/namespaces/debug.rs +++ b/core/node/api_server/src/web3/namespaces/debug.rs @@ -265,8 +265,11 @@ impl DebugNamespace { drop(connection); let call_overrides = request.get_call_overrides()?; - // FIXME: configure - let call = L2Tx::from_request(request.into(), MAX_ENCODED_TX_SIZE, false)?; + let call = L2Tx::from_request( + request.into(), + MAX_ENCODED_TX_SIZE, + block_args.use_evm_simulator(), + )?; let vm_permit = self .state diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index f153b2197b66..7a9a074c7bbd 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -19,6 +19,7 @@ use zksync_web3_decl::{ }; use crate::{ + execution_sandbox::BlockArgs, utils::open_readonly_transaction, web3::{backend_jsonrpsee::MethodTracer, metrics::API_METRICS, state::RpcState, TypedFilter}, }; @@ -76,8 +77,11 @@ impl EthNamespace { drop(connection); let call_overrides = request.get_call_overrides()?; - // FIXME: configure - let tx = L2Tx::from_request(request.into(), self.state.api_config.max_tx_size, false)?; + let tx = L2Tx::from_request( + request.into(), + self.state.api_config.max_tx_size, + block_args.use_evm_simulator(), + )?; // It is assumed that the previous checks has already enforced that the `max_fee_per_gas` is at most u64. let call_result: Vec = self @@ -108,11 +112,13 @@ impl EthNamespace { let is_eip712 = request_with_gas_per_pubdata_overridden .eip712_meta .is_some(); - + let mut connection = self.state.acquire_connection().await?; + let block_args = BlockArgs::pending(&mut connection).await?; + drop(connection); let mut tx: L2Tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, - false, // FIXME: configure + block_args.use_evm_simulator(), )?; // The user may not include the proper transaction type during the estimation of @@ -137,6 +143,7 @@ impl EthNamespace { .tx_sender .get_txs_fee_in_wei( tx.into(), + block_args, scale_factor, acceptable_overestimation as u64, state_override, @@ -618,10 +625,15 @@ impl EthNamespace { } pub async fn send_raw_transaction_impl(&self, tx_bytes: Bytes) -> Result { - let (mut tx, hash) = self.state.parse_transaction_bytes(&tx_bytes.0)?; + let mut connection = self.state.acquire_connection().await?; + let block_args = BlockArgs::pending(&mut connection).await?; + drop(connection); + let (mut tx, hash) = self + .state + .parse_transaction_bytes(&tx_bytes.0, &block_args)?; tx.set_input(tx_bytes.0, hash); - let submit_result = self.state.tx_sender.submit_tx(tx).await; + let submit_result = self.state.tx_sender.submit_tx(tx, block_args).await; submit_result.map(|_| hash).map_err(|err| { tracing::debug!("Send raw transaction error: {err}"); API_METRICS.submit_tx_error[&err.prom_error_code()].inc(); diff --git a/core/node/api_server/src/web3/namespaces/zks.rs b/core/node/api_server/src/web3/namespaces/zks.rs index dfc1299b0d0a..8c375532c2f7 100644 --- a/core/node/api_server/src/web3/namespaces/zks.rs +++ b/core/node/api_server/src/web3/namespaces/zks.rs @@ -30,6 +30,7 @@ use zksync_web3_decl::{ }; use crate::{ + execution_sandbox::BlockArgs, utils::open_readonly_transaction, web3::{backend_jsonrpsee::MethodTracer, metrics::API_METRICS, RpcState}, }; @@ -62,17 +63,21 @@ impl ZksNamespace { eip712_meta.gas_per_pubdata = U256::from(DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE); } + let mut connection = self.state.acquire_connection().await?; + let block_args = BlockArgs::pending(&mut connection).await?; + drop(connection); let mut tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, - false, // FIXME: configure + block_args.use_evm_simulator(), )?; // When we're estimating fee, we are trying to deduce values related to fee, so we should // not consider provided ones. tx.common_data.fee.max_priority_fee_per_gas = 0u64.into(); tx.common_data.fee.gas_per_pubdata_limit = U256::from(DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE); - self.estimate_fee(tx.into(), state_override).await + self.estimate_fee(tx.into(), block_args, state_override) + .await } pub async fn estimate_l1_to_l2_gas_impl( @@ -89,17 +94,25 @@ impl ZksNamespace { } } - // FIXME: configure - let tx = L1Tx::from_request(request_with_gas_per_pubdata_overridden, false) - .map_err(Web3Error::SerializationError)?; - - let fee = self.estimate_fee(tx.into(), state_override).await?; + let mut connection = self.state.acquire_connection().await?; + let block_args = BlockArgs::pending(&mut connection).await?; + drop(connection); + let tx = L1Tx::from_request( + request_with_gas_per_pubdata_overridden, + block_args.use_evm_simulator(), + ) + .map_err(Web3Error::SerializationError)?; + + let fee = self + .estimate_fee(tx.into(), block_args, state_override) + .await?; Ok(fee.gas_limit) } async fn estimate_fee( &self, tx: Transaction, + block_args: BlockArgs, state_override: Option, ) -> Result { let scale_factor = self.state.api_config.estimate_gas_scale_factor; @@ -111,6 +124,7 @@ impl ZksNamespace { .tx_sender .get_txs_fee_in_wei( tx, + block_args, scale_factor, acceptable_overestimation as u64, state_override, @@ -581,10 +595,15 @@ impl ZksNamespace { &self, tx_bytes: Bytes, ) -> Result<(H256, VmExecutionResultAndLogs), Web3Error> { - let (mut tx, hash) = self.state.parse_transaction_bytes(&tx_bytes.0)?; + let mut connection = self.state.acquire_connection().await?; + let block_args = BlockArgs::pending(&mut connection).await?; + drop(connection); + let (mut tx, hash) = self + .state + .parse_transaction_bytes(&tx_bytes.0, &block_args)?; tx.set_input(tx_bytes.0, hash); - let submit_result = self.state.tx_sender.submit_tx(tx).await; + let submit_result = self.state.tx_sender.submit_tx(tx, block_args).await; submit_result.map(|result| (hash, result.1)).map_err(|err| { tracing::debug!("Send raw transaction error: {err}"); API_METRICS.submit_tx_error[&err.prom_error_code()].inc(); diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 0fe324edd420..909f4528be14 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -259,12 +259,19 @@ pub(crate) struct RpcState { } impl RpcState { - pub fn parse_transaction_bytes(&self, bytes: &[u8]) -> Result<(L2Tx, H256), Web3Error> { + pub fn parse_transaction_bytes( + &self, + bytes: &[u8], + block_args: &BlockArgs, + ) -> Result<(L2Tx, H256), Web3Error> { let chain_id = self.api_config.l2_chain_id; let (tx_request, hash) = api::TransactionRequest::from_bytes(bytes, chain_id)?; - // FIXME: configure Ok(( - L2Tx::from_request(tx_request, self.api_config.max_tx_size, false)?, + L2Tx::from_request( + tx_request, + self.api_config.max_tx_size, + block_args.use_evm_simulator(), + )?, hash, )) } From e63ac212ea23517f95019b2b766d92943e6677f4 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 16:46:32 +0300 Subject: [PATCH 48/72] Disable EVM simulator for some tests --- core/lib/tee_verifier/src/lib.rs | 5 +---- core/node/proof_data_handler/src/tests.rs | 5 +---- core/node/test_utils/src/lib.rs | 2 +- core/node/vm_runner/src/tests/output_handler.rs | 5 +---- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/core/lib/tee_verifier/src/lib.rs b/core/lib/tee_verifier/src/lib.rs index 4301508873f6..10d013ae02e2 100644 --- a/core/lib/tee_verifier/src/lib.rs +++ b/core/lib/tee_verifier/src/lib.rs @@ -306,10 +306,7 @@ mod tests { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: Some(SystemContractCode { - code: vec![U256([1; 4])], - hash: H256([1; 32]), - }), + evm_simulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/node/proof_data_handler/src/tests.rs b/core/node/proof_data_handler/src/tests.rs index a13b3c8063d7..61c76b661ea4 100644 --- a/core/node/proof_data_handler/src/tests.rs +++ b/core/node/proof_data_handler/src/tests.rs @@ -62,10 +62,7 @@ async fn request_tee_proof_inputs() { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: Some(SystemContractCode { - code: vec![U256([1; 4])], - hash: H256([1; 32]), - }), + evm_simulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/node/test_utils/src/lib.rs b/core/node/test_utils/src/lib.rs index 3706231cab0d..203067eae718 100644 --- a/core/node/test_utils/src/lib.rs +++ b/core/node/test_utils/src/lib.rs @@ -56,7 +56,7 @@ pub fn create_l1_batch(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), - evm_simulator: Some(H256::repeat_byte(43)), + evm_simulator: None, }, ProtocolVersionId::latest(), ); diff --git a/core/node/vm_runner/src/tests/output_handler.rs b/core/node/vm_runner/src/tests/output_handler.rs index 2bc881a5f22f..9f29209b5212 100644 --- a/core/node/vm_runner/src/tests/output_handler.rs +++ b/core/node/vm_runner/src/tests/output_handler.rs @@ -66,10 +66,7 @@ impl OutputHandlerTester { code: vec![], hash: Default::default(), }, - evm_simulator: Some(SystemContractCode { - code: vec![], - hash: Default::default(), - }), + evm_simulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, From 634250302bfac24ef7e305ee2ab263deca34ad3e Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 16:46:58 +0300 Subject: [PATCH 49/72] Fix SQL queries with EVM simulator hash --- ...ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json} | 4 ++-- ...9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json} | 4 ++-- ...697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json} | 4 ++-- core/lib/dal/src/blocks_dal.rs | 4 ++-- core/lib/dal/src/sync_dal.rs | 2 +- core/lib/dal/src/tests/mod.rs | 1 + 6 files changed, 10 insertions(+), 9 deletions(-) rename core/lib/dal/.sqlx/{query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json => query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json} (92%) rename core/lib/dal/.sqlx/{query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json => query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json} (92%) rename core/lib/dal/.sqlx/{query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json => query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json} (92%) diff --git a/core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json b/core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json similarity index 92% rename from core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json rename to core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json index 8b323291548b..6a5c6e0744bd 100644 --- a/core/lib/dal/.sqlx/query-f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741.json +++ b/core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -118,5 +118,5 @@ true ] }, - "hash": "f9f2560aacc9cf94c560f3692d0dce25e8b15a8f8c15a3523ef2a04528be2741" + "hash": "7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691" } diff --git a/core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json b/core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json similarity index 92% rename from core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json rename to core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json index b624e45f2bb1..fe43700ca912 100644 --- a/core/lib/dal/.sqlx/query-0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923.json +++ b/core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n INNER JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n LEFT JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", "describe": { "columns": [ { @@ -97,5 +97,5 @@ false ] }, - "hash": "0c9f40c61a37959109319118b9191089c4f64c785f758b3684771073f9967923" + "hash": "c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299" } diff --git a/core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json b/core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json similarity index 92% rename from core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json rename to core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json index c1205a219525..355ad53a1ee7 100644 --- a/core/lib/dal/.sqlx/query-c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718.json +++ b/core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n WHERE\n miniblocks.number = $1\n ", + "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n WHERE\n miniblocks.number = $1\n ", "describe": { "columns": [ { @@ -120,5 +120,5 @@ true ] }, - "hash": "c774df1fd626c38c28abf9fc0fa12ffa59f55223e99383ada49b633428a72718" + "hash": "ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4" } diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 3296b4ee8e00..027090d3d839 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -797,7 +797,7 @@ impl BlocksDal<'_, '_> { miniblocks.logs_bloom FROM miniblocks - INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number + LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number ORDER BY number DESC LIMIT @@ -839,7 +839,7 @@ impl BlocksDal<'_, '_> { miniblocks.logs_bloom FROM miniblocks - INNER JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number + LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number WHERE miniblocks.number = $1 "#, diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index c3120d240c49..9e42d8f93b4f 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -57,7 +57,7 @@ impl SyncDal<'_, '_> { miniblocks.fee_account_address AS "fee_account_address!" FROM miniblocks - INNER JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number + LEFT JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number WHERE miniblocks.number BETWEEN $1 AND $2 "#, diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index 0b22c6283070..5b2b99ccdee4 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -54,6 +54,7 @@ pub(crate) fn create_l2_block_header(number: u32) -> L2BlockHeader { logs_bloom: Default::default(), } } + pub(crate) fn create_l1_batch_header(number: u32) -> L1BatchHeader { L1BatchHeader::new( L1BatchNumber(number), From 68e2647dd2000ebbe3a4eb0f5b133c474e70ff73 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 16:49:00 +0300 Subject: [PATCH 50/72] Fix `creating_block_args_after_snapshot_recovery` test --- .../api_server/src/execution_sandbox/tests.rs | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/core/node/api_server/src/execution_sandbox/tests.rs b/core/node/api_server/src/execution_sandbox/tests.rs index f98ddc2e7965..30797f606af2 100644 --- a/core/node/api_server/src/execution_sandbox/tests.rs +++ b/core/node/api_server/src/execution_sandbox/tests.rs @@ -7,7 +7,7 @@ use test_casing::test_casing; use zksync_dal::ConnectionPool; use zksync_multivm::{interface::ExecutionResult, utils::derive_base_fee_and_gas_per_pubdata}; use zksync_node_genesis::{insert_genesis_batch, GenesisParams}; -use zksync_node_test_utils::{create_l2_block, prepare_recovery_snapshot}; +use zksync_node_test_utils::{create_l1_batch, create_l2_block, prepare_recovery_snapshot}; use zksync_state::PostgresStorageCaches; use zksync_types::{ api::state_override::{OverrideAccount, StateOverride}, @@ -92,17 +92,6 @@ async fn creating_block_args_after_snapshot_recovery() { let snapshot_recovery = prepare_recovery_snapshot(&mut storage, L1BatchNumber(23), L2BlockNumber(42), &[]).await; - let pending_block_args = BlockArgs::pending(&mut storage).await.unwrap(); - assert_eq!( - pending_block_args.block_id, - api::BlockId::Number(api::BlockNumber::Pending) - ); - assert_eq!( - pending_block_args.resolved_block_number(), - snapshot_recovery.l2_block_number + 1 - ); - assert!(pending_block_args.is_pending()); - let start_info = BlockStartInfo::new(&mut storage, Duration::MAX) .await .unwrap(); @@ -121,6 +110,35 @@ async fn creating_block_args_after_snapshot_recovery() { .unwrap_err(); assert_matches!(err, BlockArgsError::Missing); + // Ensure there is a batch in the storage. + let l2_block = create_l2_block(snapshot_recovery.l2_block_number.0 + 1); + storage + .blocks_dal() + .insert_l2_block(&l2_block) + .await + .unwrap(); + storage + .blocks_dal() + .insert_mock_l1_batch(&create_l1_batch(snapshot_recovery.l1_batch_number.0 + 1)) + .await + .unwrap(); + storage + .blocks_dal() + .mark_l2_blocks_as_executed_in_l1_batch(snapshot_recovery.l1_batch_number + 1) + .await + .unwrap(); + + let pending_block_args = BlockArgs::pending(&mut storage).await.unwrap(); + assert_eq!( + pending_block_args.block_id, + api::BlockId::Number(api::BlockNumber::Pending) + ); + assert_eq!( + pending_block_args.resolved_block_number(), + snapshot_recovery.l2_block_number + 2 + ); + assert!(pending_block_args.is_pending()); + let pruned_blocks = [ api::BlockNumber::Earliest, 0.into(), @@ -146,13 +164,6 @@ async fn creating_block_args_after_snapshot_recovery() { assert_matches!(err, BlockArgsError::Missing); } - let l2_block = create_l2_block(snapshot_recovery.l2_block_number.0 + 1); - storage - .blocks_dal() - .insert_l2_block(&l2_block) - .await - .unwrap(); - let latest_block_args = BlockArgs::new(&mut storage, latest_block, &start_info) .await .unwrap(); From 5a9b8e35802646bcfa74b8c2743763c9ce448d0c Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:04:20 +0300 Subject: [PATCH 51/72] Load EVM simulator during genesis if appropriate --- core/lib/contracts/src/lib.rs | 1 + core/node/genesis/src/lib.rs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index faa60f8a32dd..2eacb5ffcae1 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -296,6 +296,7 @@ fn read_zbin_bytecode_from_path(bytecode_path: PathBuf) -> Vec { fs::read(&bytecode_path) .unwrap_or_else(|err| panic!("Can't read .zbin bytecode at {:?}: {}", bytecode_path, err)) } + /// Hash of code and code which consists of 32 bytes words #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SystemContractCode { diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index c33a5e326ee9..5341a460f82a 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -125,7 +125,10 @@ impl GenesisParams { } pub fn load_genesis_params(config: GenesisConfig) -> Result { - let base_system_contracts = BaseSystemContracts::load_from_disk(); + let mut base_system_contracts = BaseSystemContracts::load_from_disk(); + if config.evm_simulator_hash.is_some() { + base_system_contracts = base_system_contracts.with_latest_evm_simulator(); + } let system_contracts = get_system_smart_contracts(config.evm_simulator_hash.is_some()); Self::from_genesis_config(config, base_system_contracts, system_contracts) } From 8b05e378c30bb7379162767b41fd4cc375b8d1e1 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:27:19 +0300 Subject: [PATCH 52/72] Remove unnecessary deps from `contracts` --- Cargo.lock | 2 -- core/lib/contracts/Cargo.toml | 2 -- prover/Cargo.lock | 2 -- 3 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3197b2b934f1..2feeaa4c79ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9592,8 +9592,6 @@ dependencies = [ "once_cell", "serde", "serde_json", - "zksync_config", - "zksync_env_config", "zksync_utils", ] diff --git a/core/lib/contracts/Cargo.toml b/core/lib/contracts/Cargo.toml index 26372a02a096..2b80295cf440 100644 --- a/core/lib/contracts/Cargo.toml +++ b/core/lib/contracts/Cargo.toml @@ -12,8 +12,6 @@ categories.workspace = true [dependencies] zksync_utils.workspace = true -zksync_config.workspace = true -zksync_env_config.workspace = true ethabi.workspace = true serde_json.workspace = true diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 19fad45eb407..5ea25c22c007 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -7498,8 +7498,6 @@ dependencies = [ "once_cell", "serde", "serde_json", - "zksync_config", - "zksync_env_config", "zksync_utils", ] From d0440aaddf4d4d1865a589ad9c06e2d371e39773 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:37:07 +0300 Subject: [PATCH 53/72] Return `miniblocks.evm_simulator_code_hash` It's necessary for blocks in the pending batch. --- ...927c5f5b88725987e82cf3ec5d499c5addbb.json} | 4 +- ...3a6f0a2de9a615e50a94d98d18e47621c709.json} | 4 +- ...bbb0aa11d1c974d6ae7c99d83560bb37357e.json} | 4 +- ...00ff851252dd9da2df5ab7da51324f9258400.json | 31 +++++ ...ba3af74e8e7b5944cb2943b5badb906167046.json | 30 ----- .../20240911161714_evm-simulator.down.sql | 1 + .../20240911161714_evm-simulator.up.sql | 2 + core/lib/dal/src/blocks_dal.rs | 113 ++++++++++++------ .../lib/dal/src/models/storage_transaction.rs | 8 +- core/lib/dal/src/sync_dal.rs | 3 +- 10 files changed, 120 insertions(+), 80 deletions(-) rename core/lib/dal/.sqlx/{query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json => query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json} (90%) rename core/lib/dal/.sqlx/{query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json => query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json} (65%) rename core/lib/dal/.sqlx/{query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json => query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json} (66%) create mode 100644 core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json delete mode 100644 core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json diff --git a/core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json b/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json similarity index 90% rename from core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json rename to core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json index fe43700ca912..7b4fa2793dba 100644 --- a/core/lib/dal/.sqlx/query-c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299.json +++ b/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n LEFT JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", "describe": { "columns": [ { @@ -97,5 +97,5 @@ false ] }, - "hash": "c8ddeebcf10a9197ae98b4986406201af9eb79c1364ff9c6fff45efc7c8ee299" + "hash": "2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb" } diff --git a/core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json b/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json similarity index 65% rename from core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json rename to core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json index 6a5c6e0744bd..16f258cf3047 100644 --- a/core/lib/dal/.sqlx/query-7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691.json +++ b/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -118,5 +118,5 @@ true ] }, - "hash": "7ab5adc5fd35ae709ceb1506329106bb777f29b3cb88d53786c02f2860631691" + "hash": "3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709" } diff --git a/core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json b/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json similarity index 66% rename from core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json rename to core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json index 355ad53a1ee7..287c69687e53 100644 --- a/core/lib/dal/.sqlx/query-ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4.json +++ b/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n miniblocks.timestamp,\n miniblocks.hash,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n miniblocks.base_fee_per_gas,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.gas_per_pubdata_limit,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.virtual_blocks,\n miniblocks.fair_pubdata_price,\n miniblocks.gas_limit,\n miniblocks.logs_bloom\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n WHERE\n miniblocks.number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -120,5 +120,5 @@ true ] }, - "hash": "ff894e84935c697f3aa7bd66cf64b187976f54ddfb69baffc29456da199f76f4" + "hash": "922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e" } diff --git a/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json b/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json new file mode 100644 index 000000000000..52ef95716470 --- /dev/null +++ b/core/lib/dal/.sqlx/query-9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400.json @@ -0,0 +1,31 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Bytea", + "Int4", + "Int4", + "Bytea", + "Numeric", + "Int8", + "Int8", + "Int8", + "Bytea", + "Bytea", + "Bytea", + "Int4", + "Int8", + "Int8", + "Int8", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "9ca8d7418721beb1e9ee4f801a600ff851252dd9da2df5ab7da51324f9258400" +} diff --git a/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json b/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json deleted file mode 100644 index 9ae9d2e50cde..000000000000 --- a/core/lib/dal/.sqlx/query-c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 NOW(),\n NOW()\n )\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8", - "Int8", - "Bytea", - "Int4", - "Int4", - "Bytea", - "Numeric", - "Int8", - "Int8", - "Int8", - "Bytea", - "Bytea", - "Int4", - "Int8", - "Int8", - "Int8", - "Bytea" - ] - }, - "nullable": [] - }, - "hash": "c4835d40921af47bfb4f60102bbba3af74e8e7b5944cb2943b5badb906167046" -} diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql index b01433dbbb8e..19eb8534a3a6 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql @@ -1,2 +1,3 @@ ALTER TABLE protocol_versions DROP COLUMN IF EXISTS evm_simulator_code_hash; ALTER TABLE l1_batches DROP COLUMN IF EXISTS evm_simulator_code_hash; +ALTER TABLE miniblocks DROP COLUMN IF EXISTS evm_simulator_code_hash; diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql index 4bc764b77d7c..426a7a1ac723 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql @@ -1,2 +1,4 @@ ALTER TABLE protocol_versions ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; ALTER TABLE l1_batches ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; +-- We need this column in `miniblocks` as well in order to store data for the pending L1 batch +ALTER TABLE miniblocks ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index 027090d3d839..d72343189f4a 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -712,6 +712,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, + evm_simulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -739,6 +740,7 @@ impl BlocksDal<'_, '_> { $15, $16, $17, + $18, NOW(), NOW() ) @@ -761,6 +763,11 @@ impl BlocksDal<'_, '_> { .base_system_contracts_hashes .default_aa .as_bytes(), + l2_block_header + .base_system_contracts_hashes + .evm_simulator + .as_ref() + .map(H256::as_bytes), l2_block_header.protocol_version.map(|v| v as i32), i64::from(l2_block_header.virtual_blocks), l2_block_header.batch_fee_input.fair_pubdata_price() as i64, @@ -777,27 +784,26 @@ impl BlocksDal<'_, '_> { StorageL2BlockHeader, r#" SELECT - miniblocks.number, - miniblocks.timestamp, - miniblocks.hash, - miniblocks.l1_tx_count, - miniblocks.l2_tx_count, + number, + timestamp, + hash, + l1_tx_count, + l2_tx_count, fee_account_address AS "fee_account_address!", - miniblocks.base_fee_per_gas, - miniblocks.l1_gas_price, - miniblocks.l2_fair_gas_price, - miniblocks.gas_per_pubdata_limit, - miniblocks.bootloader_code_hash, - miniblocks.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, - miniblocks.protocol_version, - miniblocks.virtual_blocks, - miniblocks.fair_pubdata_price, - miniblocks.gas_limit, - miniblocks.logs_bloom + base_fee_per_gas, + l1_gas_price, + l2_fair_gas_price, + gas_per_pubdata_limit, + bootloader_code_hash, + default_aa_code_hash, + evm_simulator_code_hash, + protocol_version, + virtual_blocks, + fair_pubdata_price, + gas_limit, + logs_bloom FROM miniblocks - LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number ORDER BY number DESC LIMIT @@ -819,29 +825,28 @@ impl BlocksDal<'_, '_> { StorageL2BlockHeader, r#" SELECT - miniblocks.number, - miniblocks.timestamp, - miniblocks.hash, - miniblocks.l1_tx_count, - miniblocks.l2_tx_count, + number, + timestamp, + hash, + l1_tx_count, + l2_tx_count, fee_account_address AS "fee_account_address!", - miniblocks.base_fee_per_gas, - miniblocks.l1_gas_price, - miniblocks.l2_fair_gas_price, - miniblocks.gas_per_pubdata_limit, - miniblocks.bootloader_code_hash, - miniblocks.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, - miniblocks.protocol_version, - miniblocks.virtual_blocks, - miniblocks.fair_pubdata_price, - miniblocks.gas_limit, - miniblocks.logs_bloom + base_fee_per_gas, + l1_gas_price, + l2_fair_gas_price, + gas_per_pubdata_limit, + bootloader_code_hash, + default_aa_code_hash, + evm_simulator_code_hash, + protocol_version, + virtual_blocks, + fair_pubdata_price, + gas_limit, + logs_bloom FROM miniblocks - LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number WHERE - miniblocks.number = $1 + number = $1 "#, i64::from(l2_block_number.0), ) @@ -2698,6 +2703,40 @@ mod tests { .is_err()); } + #[tokio::test] + async fn persisting_evm_simulator_hash() { + let pool = ConnectionPool::::test_pool().await; + let mut conn = pool.connection().await.unwrap(); + + conn.protocol_versions_dal() + .save_protocol_version_with_tx(&ProtocolVersion::default()) + .await + .unwrap(); + + let mut l2_block_header = create_l2_block_header(1); + l2_block_header.base_system_contracts_hashes.evm_simulator = Some(H256::repeat_byte(0x23)); + conn.blocks_dal() + .insert_l2_block(&l2_block_header) + .await + .unwrap(); + + let mut fetched_block_header = conn + .blocks_dal() + .get_last_sealed_l2_block_header() + .await + .unwrap() + .expect("no block"); + // Batch fee input isn't restored exactly + fetched_block_header.batch_fee_input = l2_block_header.batch_fee_input; + + assert_eq!(fetched_block_header, l2_block_header); + // ...and a sanity check just to be sure + assert!(fetched_block_header + .base_system_contracts_hashes + .evm_simulator + .is_some()); + } + #[tokio::test] async fn loading_l1_batch_header() { let pool = ConnectionPool::::test_pool().await; diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 8baeaed284d5..0dfbec61b01b 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -508,11 +508,9 @@ impl StorageApiTransaction { .signature .and_then(|signature| PackedEthSignature::deserialize_packed(&signature).ok()); - let to = if let Ok(address) = serde_json::from_value(self.execute_contract_address) { - Some(address) - } else { - Some(Address::zero()) - }; + let to = serde_json::from_value(self.execute_contract_address) + .ok() + .unwrap_or_default(); // For legacy and EIP-2930 transactions it is gas price willing to be paid by the sender in wei. // For other transactions it should be the effective gas price if transaction is included in block, diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index 9e42d8f93b4f..22c72fc4d152 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -50,14 +50,13 @@ impl SyncDal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, + miniblocks.evm_simulator_code_hash, miniblocks.virtual_blocks, miniblocks.hash, miniblocks.protocol_version AS "protocol_version!", miniblocks.fee_account_address AS "fee_account_address!" FROM miniblocks - LEFT JOIN l1_batches ON l1_batches.number = miniblocks.l1_batch_number WHERE miniblocks.number BETWEEN $1 AND $2 "#, From 182875672300ad60a3f792b6ef7c3dc2d88d5bf3 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:38:12 +0300 Subject: [PATCH 54/72] Fix env config test --- core/lib/env_config/src/chain.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/lib/env_config/src/chain.rs b/core/lib/env_config/src/chain.rs index ca2c51803ba2..047f6698374f 100644 --- a/core/lib/env_config/src/chain.rs +++ b/core/lib/env_config/src/chain.rs @@ -102,9 +102,7 @@ mod tests { default_aa_hash: Some(hash( "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2", )), - evm_simulator_hash: Some(hash( - "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", - )), + evm_simulator_hash: None, l1_batch_commit_data_generator_mode, max_circuits_per_batch: 24100, protective_reads_persistence_enabled: true, From 41fa851e9957674752a2c079a49d1d69c07e45ae Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:43:57 +0300 Subject: [PATCH 55/72] Fix witness generator --- .../witness_generator/src/rounds/basic_circuits/utils.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs b/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs index bc571053672e..d02f84d7f677 100644 --- a/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs +++ b/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs @@ -114,6 +114,10 @@ pub(super) async fn generate_witness( } }; + let evm_simulator_code_hash = input.vm_run_data.evm_simulator_code_hash; + // By convention, default AA is used instead of the EVM simulator if the latter is disabled. + let evm_simulator_code_hash = + evm_simulator_code_hash.unwrap_or(input.vm_run_data.default_account_code_hash); let (scheduler_witness, block_witness) = zkevm_test_harness::external_calls::run( Address::zero(), BOOTLOADER_ADDRESS, @@ -121,7 +125,7 @@ pub(super) async fn generate_witness( bootloader_contents, false, input.vm_run_data.default_account_code_hash, - input.vm_run_data.evm_simulator_code_hash, + evm_simulator_code_hash, input.vm_run_data.used_bytecodes, Vec::default(), MAX_CYCLES_FOR_TX as usize, From d242f1340e96bcc2c6d0ed78823e4b7483bafa07 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:56:52 +0300 Subject: [PATCH 56/72] Make EVM simulator optional in toolbox --- .../config/src/forge_interface/deploy_ecosystem/input.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs index a205f640331b..ac79196d3008 100644 --- a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs +++ b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs @@ -146,7 +146,7 @@ impl DeployL1Config { .diamond_init_minimal_l2_gas_price, bootloader_hash: genesis_config.bootloader_hash.unwrap(), default_aa_hash: genesis_config.default_aa_hash.unwrap(), - evm_simulator_hash: genesis_config.evm_simulator_hash.unwrap(), + evm_simulator_hash: genesis_config.evm_simulator_hash, diamond_init_priority_tx_max_pubdata: initial_deployment_config .diamond_init_priority_tx_max_pubdata, diamond_init_pubdata_pricing_mode: initial_deployment_config @@ -195,7 +195,7 @@ pub struct ContractsDeployL1Config { pub diamond_init_minimal_l2_gas_price: u64, pub bootloader_hash: H256, pub default_aa_hash: H256, - pub evm_simulator_hash: H256, + pub evm_simulator_hash: Option, } #[derive(Debug, Deserialize, Serialize, Clone)] From 7784017d157b5536f98fa807c6fd171bd1612d5a Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 27 Sep 2024 17:59:50 +0300 Subject: [PATCH 57/72] Remove unused dependency --- Cargo.lock | 1 - core/lib/types/Cargo.toml | 1 - prover/Cargo.lock | 1 - 3 files changed, 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2feeaa4c79ed..0f5bddab93a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10895,7 +10895,6 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_crypto_primitives", - "zksync_env_config", "zksync_mini_merkle_tree", "zksync_protobuf", "zksync_protobuf_build", diff --git a/core/lib/types/Cargo.toml b/core/lib/types/Cargo.toml index f976c26b71c1..54c38384a7ad 100644 --- a/core/lib/types/Cargo.toml +++ b/core/lib/types/Cargo.toml @@ -17,7 +17,6 @@ zksync_basic_types.workspace = true zksync_contracts.workspace = true zksync_mini_merkle_tree.workspace = true zksync_config.workspace = true -zksync_env_config.workspace = true zksync_protobuf.workspace = true zksync_crypto_primitives.workspace = true diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 5ea25c22c007..a151f87da7ca 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -8047,7 +8047,6 @@ dependencies = [ "zksync_config", "zksync_contracts", "zksync_crypto_primitives", - "zksync_env_config", "zksync_mini_merkle_tree", "zksync_protobuf", "zksync_protobuf_build", From 2046ca48b9868318c44f83180f3833af7aba17e6 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 30 Sep 2024 11:21:36 +0300 Subject: [PATCH 58/72] Fix `eth_sender` tests --- .../src/multicall3/mod.rs | 2 + core/node/eth_sender/src/eth_tx_aggregator.rs | 49 +++--- core/node/eth_sender/src/tester.rs | 10 +- core/node/eth_sender/src/tests.rs | 154 +++++++++++++++--- 4 files changed, 159 insertions(+), 56 deletions(-) diff --git a/core/lib/l1_contract_interface/src/multicall3/mod.rs b/core/lib/l1_contract_interface/src/multicall3/mod.rs index 7d922668f940..52df37e04304 100644 --- a/core/lib/l1_contract_interface/src/multicall3/mod.rs +++ b/core/lib/l1_contract_interface/src/multicall3/mod.rs @@ -7,6 +7,7 @@ use zksync_types::{ }; /// Multicall3 contract aggregate method input vector struct. +#[derive(Debug)] pub struct Multicall3Call { pub target: Address, pub allow_failure: bool, @@ -21,6 +22,7 @@ impl Tokenizable for Multicall3Call { self.calldata.into_token(), ]) } + fn from_token(token: Token) -> Result { let Token::Tuple(mut result_token) = token else { return Err(error(&[token], "Multicall3Call")); diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 18d706759398..270ffb2fef5a 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -144,21 +144,19 @@ impl EthTxAggregator { } pub(super) async fn get_multicall_data(&mut self) -> Result { - const USE_EVM_SIMULATOR: bool = false; // FIXME: define in an adequate way - - let calldata = self.generate_calldata_for_multicall(USE_EVM_SIMULATOR); + let (calldata, evm_simulator_hash_requested) = self.generate_calldata_for_multicall(); let args = CallFunctionArgs::new(&self.functions.aggregate3.name, calldata).for_contract( self.l1_multicall3_address, &self.functions.multicall_contract, ); let aggregate3_result: Token = args.call((*self.eth_client).as_ref()).await?; - self.parse_multicall_data(aggregate3_result, USE_EVM_SIMULATOR) + self.parse_multicall_data(aggregate3_result, evm_simulator_hash_requested) } // Multicall's aggregate function accepts 1 argument - arrays of different contract calls. // The role of the method below is to tokenize input for multicall, which is actually a vector of tokens. // Each token describes a specific contract call. - pub(super) fn generate_calldata_for_multicall(&self, use_evm_simulator: bool) -> Vec { + pub(super) fn generate_calldata_for_multicall(&self) -> (Vec, bool) { const ALLOW_FAILURE: bool = false; // First zksync contract call @@ -185,21 +183,6 @@ impl EthTxAggregator { calldata: get_l2_default_aa_hash_input, }; - let get_l2_evm_simulator_hash_input = self - .functions - .get_evm_simulator_bytecode_hash - .as_ref() - .and_then(|f| f.encode_input(&[]).ok()); - - let get_evm_simulator_hash_call = match get_l2_evm_simulator_hash_input { - Some(input) if use_evm_simulator => Some(Multicall3Call { - target: self.state_transition_chain_contract, - allow_failure: ALLOW_FAILURE, - calldata: input, - }), - _ => None, - }; - // Third zksync contract call let get_verifier_params_input = self .functions @@ -240,11 +223,23 @@ impl EthTxAggregator { get_protocol_version_call.into_token(), ]; - if let Some(call) = get_evm_simulator_hash_call { + let mut evm_simulator_hash_requested = false; + let get_l2_evm_simulator_hash_input = self + .functions + .get_evm_simulator_bytecode_hash + .as_ref() + .and_then(|f| f.encode_input(&[]).ok()); + if let Some(input) = get_l2_evm_simulator_hash_input { + let call = Multicall3Call { + target: self.state_transition_chain_contract, + allow_failure: ALLOW_FAILURE, + calldata: input, + }; token_vec.insert(2, call.into_token()); + evm_simulator_hash_requested = true; } - token_vec + (token_vec, evm_simulator_hash_requested) } // The role of the method below is to de-tokenize multicall call's result, which is actually a token. @@ -252,7 +247,7 @@ impl EthTxAggregator { pub(super) fn parse_multicall_data( &self, token: Token, - use_evm_simulator: bool, + evm_simulator_hash_requested: bool, ) -> Result { let parse_error = |tokens: &[Token]| { Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( @@ -261,8 +256,8 @@ impl EthTxAggregator { }; if let Token::Array(call_results) = token { - let number_of_calls = if use_evm_simulator { 6 } else { 5 }; - // 5 calls are aggregated in multicall + let number_of_calls = if evm_simulator_hash_requested { 6 } else { 5 }; + // 5 or 6 calls are aggregated in multicall if call_results.len() != number_of_calls { return parse_error(&call_results); } @@ -293,7 +288,7 @@ impl EthTxAggregator { } let default_aa = H256::from_slice(&multicall3_default_aa); - let evm_simulator = if use_evm_simulator { + let evm_simulator = if evm_simulator_hash_requested { let multicall3_evm_simulator = Multicall3Result::from_token(call_results_iterator.next().unwrap())? .return_data; @@ -316,7 +311,7 @@ impl EthTxAggregator { evm_simulator, }; - call_results_iterator.next().unwrap(); + call_results_iterator.next().unwrap(); // FIXME: why is this value requested? let multicall3_verifier_address = Multicall3Result::from_token(call_results_iterator.next().unwrap())?.return_data; diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs index 9be1384daae2..86a8c477f9fe 100644 --- a/core/node/eth_sender/src/tester.rs +++ b/core/node/eth_sender/src/tester.rs @@ -23,6 +23,8 @@ use crate::{ Aggregator, EthTxAggregator, EthTxManager, }; +pub(super) const STATE_TRANSITION_CONTRACT_ADDRESS: Address = Address::repeat_byte(0xa0); + // Alias to conveniently call static methods of `ETHSender`. type MockEthTxManager = EthTxManager; @@ -172,7 +174,7 @@ impl EthSenderTester { .with_non_ordering_confirmation(non_ordering_confirmations) .with_call_handler(move |call, _| { assert_eq!(call.to, Some(contracts_config.l1_multicall3_addr)); - crate::tests::mock_multicall_response() + crate::tests::mock_multicall_response(call) }) .build(); gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); @@ -192,7 +194,7 @@ impl EthSenderTester { .with_non_ordering_confirmation(non_ordering_confirmations) .with_call_handler(move |call, _| { assert_eq!(call.to, Some(contracts_config.l1_multicall3_addr)); - crate::tests::mock_multicall_response() + crate::tests::mock_multicall_response(call) }) .build(); l2_gateway.advance_block_number(Self::WAIT_CONFIRMATIONS); @@ -212,7 +214,7 @@ impl EthSenderTester { .with_non_ordering_confirmation(non_ordering_confirmations) .with_call_handler(move |call, _| { assert_eq!(call.to, Some(contracts_config.l1_multicall3_addr)); - crate::tests::mock_multicall_response() + crate::tests::mock_multicall_response(call) }) .build(); gateway_blobs.advance_block_number(Self::WAIT_CONFIRMATIONS); @@ -261,7 +263,7 @@ impl EthSenderTester { // ZKsync contract address Address::random(), contracts_config.l1_multicall3_addr, - Address::random(), + STATE_TRANSITION_CONTRACT_ADDRESS, Default::default(), custom_commit_sender_addr, SettlementMode::SettlesToL1, diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index e051a80252ab..90d37c45c839 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -1,7 +1,9 @@ use assert_matches::assert_matches; use test_casing::{test_casing, Product}; use zksync_dal::{ConnectionPool, Core, CoreDal}; -use zksync_l1_contract_interface::i_executor::methods::ExecuteBatches; +use zksync_l1_contract_interface::{ + i_executor::methods::ExecuteBatches, multicall3::Multicall3Call, Tokenizable, +}; use zksync_node_test_utils::create_l1_batch; use zksync_types::{ aggregated_operations::AggregatedActionType, @@ -9,16 +11,19 @@ use zksync_types::{ commitment::{ L1BatchCommitmentMode, L1BatchMetaParameters, L1BatchMetadata, L1BatchWithMetadata, }, + ethabi, ethabi::Token, helpers::unix_timestamp_ms, + web3, web3::contract::Error, - ProtocolVersionId, H256, + Address, ProtocolVersionId, H256, }; use crate::{ abstract_l1_interface::OperatorType, aggregated_operations::AggregatedOperation, - tester::{EthSenderTester, TestL1Batch}, + tester::{EthSenderTester, TestL1Batch, STATE_TRANSITION_CONTRACT_ADDRESS}, + zksync_functions::ZkSyncFunctions, EthSenderError, }; @@ -37,22 +42,61 @@ const COMMITMENT_MODES: [L1BatchCommitmentMode; 2] = [ L1BatchCommitmentMode::Validium, ]; -pub(crate) fn mock_multicall_response() -> Token { - Token::Array(vec![ - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![1u8; 32])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![2u8; 32])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![3u8; 32])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![4u8; 96])]), - Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![5u8; 32])]), - Token::Tuple(vec![ - Token::Bool(true), - Token::Bytes( +pub(crate) fn mock_multicall_response(call: &web3::CallRequest) -> Token { + let functions = ZkSyncFunctions::default(); + let evm_simulator_getter_signature = functions + .get_evm_simulator_bytecode_hash + .as_ref() + .map(ethabi::Function::short_signature); + let evm_simulator_getter_signature = + evm_simulator_getter_signature.as_ref().map(|sig| &sig[..]); + + let calldata = &call.data.as_ref().expect("no calldata").0; + assert_eq!(calldata[..4], functions.aggregate3.short_signature()); + let mut tokens = functions + .aggregate3 + .decode_input(&calldata[4..]) + .expect("invalid multicall"); + assert_eq!(tokens.len(), 1); + let Token::Array(tokens) = tokens.pop().unwrap() else { + panic!("Unexpected input: {tokens:?}"); + }; + + let calls = tokens.into_iter().map(Multicall3Call::from_token); + let response = calls.map(|call| { + let call = call.unwrap(); + assert_eq!(call.target, STATE_TRANSITION_CONTRACT_ADDRESS); + let output = match &call.calldata[..4] { + selector if selector == functions.get_l2_bootloader_bytecode_hash.short_signature() => { + vec![1u8; 32] + } + selector + if selector + == functions + .get_l2_default_account_bytecode_hash + .short_signature() => + { + vec![2u8; 32] + } + selector if Some(selector) == evm_simulator_getter_signature => { + vec![3u8; 32] + } + selector if selector == functions.get_verifier_params.short_signature() => { + vec![4u8; 96] + } + selector if selector == functions.get_verifier.short_signature() => { + vec![5u8; 32] + } + selector if selector == functions.get_protocol_version.short_signature() => { H256::from_low_u64_be(ProtocolVersionId::default() as u64) .0 - .to_vec(), - ), - ]), - ]) + .to_vec() + } + _ => panic!("unexpected call: {call:?}"), + }; + Token::Tuple(vec![Token::Bool(true), Token::Bytes(output)]) + }); + Token::Array(response.collect()) } pub(crate) fn l1_batch_with_metadata(header: L1BatchHeader) -> L1BatchWithMetadata { @@ -658,22 +702,71 @@ async fn skipped_l1_batch_in_the_middle( Ok(()) } -#[test_casing(2, COMMITMENT_MODES)] +#[test_casing(2, [false, true])] #[test_log::test(tokio::test)] -async fn test_parse_multicall_data(commitment_mode: L1BatchCommitmentMode) { +async fn parsing_multicall_data(with_evm_simulator: bool) { let tester = EthSenderTester::new( ConnectionPool::::test_pool().await, vec![100; 100], false, true, - commitment_mode, + L1BatchCommitmentMode::Rollup, ) .await; - assert!(tester + let mut mock_response = vec![ + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![1u8; 32])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![2u8; 32])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![4u8; 96])]), + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![5u8; 32])]), + Token::Tuple(vec![ + Token::Bool(true), + Token::Bytes( + H256::from_low_u64_be(ProtocolVersionId::latest() as u64) + .0 + .to_vec(), + ), + ]), + ]; + if with_evm_simulator { + mock_response.insert( + 2, + Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![3u8; 32])]), + ); + } + let mock_response = Token::Array(mock_response); + + let parsed = tester .aggregator - .parse_multicall_data(mock_multicall_response(), true) - .is_ok()); + .parse_multicall_data(mock_response, with_evm_simulator) + .unwrap(); + assert_eq!( + parsed.base_system_contracts_hashes.bootloader, + H256::repeat_byte(1) + ); + assert_eq!( + parsed.base_system_contracts_hashes.default_aa, + H256::repeat_byte(2) + ); + let expected_evm_simulator_hash = with_evm_simulator.then(|| H256::repeat_byte(3)); + assert_eq!( + parsed.base_system_contracts_hashes.evm_simulator, + expected_evm_simulator_hash + ); + assert_eq!(parsed.verifier_address, Address::repeat_byte(5)); + assert_eq!(parsed.protocol_version_id, ProtocolVersionId::latest()); +} + +#[test_log::test(tokio::test)] +async fn parsing_multicall_data_errors() { + let tester = EthSenderTester::new( + ConnectionPool::::test_pool().await, + vec![100; 100], + false, + true, + L1BatchCommitmentMode::Rollup, + ) + .await; let original_wrong_form_data = vec![ // should contain 5 tuples @@ -741,6 +834,17 @@ async fn get_multicall_data(commitment_mode: L1BatchCommitmentMode) { commitment_mode, ) .await; - let multicall_data = tester.aggregator.get_multicall_data().await; - assert!(multicall_data.is_ok()); + + let data = tester.aggregator.get_multicall_data().await.unwrap(); + assert_eq!( + data.base_system_contracts_hashes.bootloader, + H256::repeat_byte(1) + ); + assert_eq!( + data.base_system_contracts_hashes.default_aa, + H256::repeat_byte(2) + ); + assert_eq!(data.base_system_contracts_hashes.evm_simulator, None); + assert_eq!(data.verifier_address, Address::repeat_byte(5)); + assert_eq!(data.protocol_version_id, ProtocolVersionId::latest()); } From da16bcb558c6f653b0ee77a9db6f49cae3c76ebe Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 30 Sep 2024 11:28:53 +0300 Subject: [PATCH 59/72] Rename args in tx conversions --- core/lib/types/src/lib.rs | 10 ++++++-- core/lib/types/src/transaction_request.rs | 29 ++++++++++++++++------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/core/lib/types/src/lib.rs b/core/lib/types/src/lib.rs index 1d065de4ea93..9b49221aa60d 100644 --- a/core/lib/types/src/lib.rs +++ b/core/lib/types/src/lib.rs @@ -316,7 +316,13 @@ impl TryFrom for abi::Transaction { } impl Transaction { - pub fn from_abi(tx: abi::Transaction, use_evm_simulator: bool) -> anyhow::Result { + /// Converts a transaction from its ABI representation. + /// + /// # Arguments + /// + /// - `allow_no_target` enables / disables L2 transactions without target (i.e., `to` field). + /// This field can only be absent for EVM deployment transactions. + pub fn from_abi(tx: abi::Transaction, allow_no_target: bool) -> anyhow::Result { Ok(match tx { abi::Transaction::L1 { tx, @@ -388,7 +394,7 @@ impl Transaction { abi::Transaction::L2(raw) => { let (req, hash) = transaction_request::TransactionRequest::from_bytes_unverified(&raw)?; - let mut tx = L2Tx::from_request_unverified(req, use_evm_simulator)?; + let mut tx = L2Tx::from_request_unverified(req, allow_no_target)?; tx.set_input(raw, hash); tx.into() } diff --git a/core/lib/types/src/transaction_request.rs b/core/lib/types/src/transaction_request.rs index 1c0434a66bbe..a8713f301ba6 100644 --- a/core/lib/types/src/transaction_request.rs +++ b/core/lib/types/src/transaction_request.rs @@ -809,7 +809,7 @@ impl TransactionRequest { impl L2Tx { pub(crate) fn from_request_unverified( mut value: TransactionRequest, - use_evm_simulator: bool, + allow_no_target: bool, ) -> Result { let fee = value.get_fee_data_checked()?; let nonce = value.get_nonce_checked()?; @@ -818,8 +818,7 @@ impl L2Tx { let meta = value.eip712_meta.take().unwrap_or_default(); validate_factory_deps(&meta.factory_deps)?; - // TODO: Remove this check when evm equivalence gets enabled - if value.to.is_none() && !use_evm_simulator { + if value.to.is_none() && !allow_no_target { return Err(SerializationTransactionError::ToAddressIsNull); } @@ -849,12 +848,18 @@ impl L2Tx { Ok(tx) } + /// Converts a request into a transaction. + /// + /// # Arguments + /// + /// - `allow_no_target` enables / disables transactions without target (i.e., `to` field). + /// This field can only be absent for EVM deployment transactions. pub fn from_request( - value: TransactionRequest, + request: TransactionRequest, max_tx_size: usize, - use_evm_simulator: bool, + allow_no_target: bool, ) -> Result { - let tx = Self::from_request_unverified(value, use_evm_simulator)?; + let tx = Self::from_request_unverified(request, allow_no_target)?; tx.check_encoded_size(max_tx_size)?; Ok(tx) } @@ -919,12 +924,18 @@ impl From for TransactionRequest { } impl L1Tx { + /// Converts a request into a transaction. + /// + /// # Arguments + /// + /// - `allow_no_target` enables / disables transactions without target (i.e., `to` field). + /// This field can only be absent for EVM deployment transactions. pub fn from_request( - tx: CallRequest, - use_evm_simulator: bool, + request: CallRequest, + allow_no_target: bool, ) -> Result { // L1 transactions have no limitations on the transaction size. - let tx: L2Tx = L2Tx::from_request(tx.into(), MAX_ENCODED_TX_SIZE, use_evm_simulator)?; + let tx: L2Tx = L2Tx::from_request(request.into(), MAX_ENCODED_TX_SIZE, allow_no_target)?; // Note, that while the user has theoretically provided the fee for ETH on L1, // the payment to the operator as well as refunds happen on L2 and so all the ETH From d2bb42c0ec759e86d46964db364a98c25c5ad80d Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 30 Sep 2024 12:43:07 +0300 Subject: [PATCH 60/72] Revert changes in `ProtocolUpgrade` --- core/lib/types/src/abi.rs | 9 +-------- core/lib/types/src/protocol_upgrade.rs | 4 +--- core/node/eth_watch/src/tests.rs | 1 - 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/core/lib/types/src/abi.rs b/core/lib/types/src/abi.rs index c1943ec4efdf..84f8aba64869 100644 --- a/core/lib/types/src/abi.rs +++ b/core/lib/types/src/abi.rs @@ -198,7 +198,6 @@ pub struct ProposedUpgrade { pub factory_deps: Vec>, pub bootloader_hash: [u8; 32], pub default_account_hash: [u8; 32], - pub evm_simulator_hash: [u8; 32], // FIXME: is a breaking change here OK? pub verifier: Address, pub verifier_params: VerifierParams, pub l1_contracts_upgrade_calldata: Vec, @@ -258,7 +257,6 @@ impl ProposedUpgrade { ParamType::Array(ParamType::Bytes.into()), // factory deps ParamType::FixedBytes(32), // bootloader code hash ParamType::FixedBytes(32), // default account code hash - ParamType::FixedBytes(32), // evm simulator code hash ParamType::Address, // verifier address VerifierParams::schema(), // verifier params ParamType::Bytes, // l1 custom data @@ -280,7 +278,6 @@ impl ProposedUpgrade { ), Token::FixedBytes(self.bootloader_hash.into()), Token::FixedBytes(self.default_account_hash.into()), - Token::FixedBytes(self.evm_simulator_hash.into()), Token::Address(self.verifier), self.verifier_params.encode(), Token::Bytes(self.l1_contracts_upgrade_calldata.clone()), @@ -294,7 +291,7 @@ impl ProposedUpgrade { /// Returns an error if token doesn't match the `schema()`. pub fn decode(token: Token) -> anyhow::Result { let tokens = token.into_tuple().context("not a tuple")?; - anyhow::ensure!(tokens.len() == 11); + anyhow::ensure!(tokens.len() == 10); let mut t = tokens.into_iter(); let mut next = || t.next().unwrap(); Ok(Self { @@ -317,10 +314,6 @@ impl ProposedUpgrade { .into_fixed_bytes() .and_then(|b| b.try_into().ok()) .context("default_account_hash")?, - evm_simulator_hash: next() - .into_fixed_bytes() - .and_then(|b| b.try_into().ok()) - .context("evm_simulator_hash")?, verifier: next().into_address().context("verifier")?, verifier_params: VerifierParams::decode(next()).context("verifier_params")?, l1_contracts_upgrade_calldata: next() diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index 3eac7bfd0b47..e67ca7aad289 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -114,15 +114,13 @@ impl ProtocolUpgrade { let upgrade = abi::ProposedUpgrade::decode(upgrade.into_iter().next().unwrap()).unwrap(); let bootloader_hash = H256::from_slice(&upgrade.bootloader_hash); let default_account_hash = H256::from_slice(&upgrade.default_account_hash); - let evm_simulator_hash = H256::from_slice(&upgrade.evm_simulator_hash); Ok(Self { version: ProtocolSemanticVersion::try_from_packed(upgrade.new_protocol_version) .map_err(|err| anyhow::format_err!("Version is not supported: {err}"))?, bootloader_code_hash: (bootloader_hash != H256::zero()).then_some(bootloader_hash), default_account_code_hash: (default_account_hash != H256::zero()) .then_some(default_account_hash), - evm_simulator_code_hash: (evm_simulator_hash != H256::zero()) - .then_some(evm_simulator_hash), + evm_simulator_code_hash: None, // EVM simulator upgrades are not supported yet verifier_params: (upgrade.verifier_params != abi::VerifierParams::default()) .then_some(upgrade.verifier_params.into()), verifier_address: (upgrade.verifier != Address::zero()).then_some(upgrade.verifier), diff --git a/core/node/eth_watch/src/tests.rs b/core/node/eth_watch/src/tests.rs index f7a7082ad4de..d9faf7b664e6 100644 --- a/core/node/eth_watch/src/tests.rs +++ b/core/node/eth_watch/src/tests.rs @@ -760,7 +760,6 @@ fn upgrade_into_diamond_cut(upgrade: ProtocolUpgrade) -> Token { factory_deps, bootloader_hash: upgrade.bootloader_code_hash.unwrap_or_default().into(), default_account_hash: upgrade.default_account_code_hash.unwrap_or_default().into(), - evm_simulator_hash: upgrade.evm_simulator_code_hash.unwrap_or_default().into(), verifier: upgrade.verifier_address.unwrap_or_default(), verifier_params: upgrade.verifier_params.unwrap_or_default().into(), l1_contracts_upgrade_calldata: vec![], From 473c5646194036ef995231375578de06de7f1337 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 30 Sep 2024 13:31:40 +0300 Subject: [PATCH 61/72] Fix commitment unit tests --- core/lib/types/src/commitment/tests/mod.rs | 5 + .../tests/post_boojum_1_4_1_test.json | 6 +- .../tests/post_boojum_1_4_2_test.json | 6 +- .../tests/post_boojum_1_5_0_test.json | 6 +- .../post_boojum_1_5_0_test_with_evm.json | 359 ++++++++++++++++++ .../src/commitment/tests/pre_boojum_test.json | 6 +- 6 files changed, 372 insertions(+), 16 deletions(-) create mode 100644 core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json diff --git a/core/lib/types/src/commitment/tests/mod.rs b/core/lib/types/src/commitment/tests/mod.rs index 34e308cfd0a9..33fb0142b04d 100644 --- a/core/lib/types/src/commitment/tests/mod.rs +++ b/core/lib/types/src/commitment/tests/mod.rs @@ -50,3 +50,8 @@ fn post_boojum_1_4_2() { fn post_boojum_1_5_0() { run_test("post_boojum_1_5_0_test"); } + +#[test] +fn post_boojum_1_5_0_with_evm() { + run_test("post_boojum_1_5_0_test_with_evm"); +} diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json index 74af90ce98f6..c5eccbce038a 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_4_1_test.json @@ -16,7 +16,6 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version20" }, "system_logs": [ @@ -213,7 +212,6 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version20" }, "auxiliary_output": { @@ -263,7 +261,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0x1759d3eff5b7f03b5207418548d2735fd8f70930c2726812f0b077581eb0832f", - "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", - "commitment": "0xfe674b8b0ca1602cf37cedd7bc1fd88ea36fd7a69eeda94c5ee13b2cf3496662" + "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", + "commitment": "0xde52fb0a4b41aa857b0b18a8e5932846a955f60e0921fb99974a9786369e8503" } } diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json index 17744c562fc2..4983bbeca143 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_4_2_test.json @@ -16,7 +16,6 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version21" }, "system_logs": [ @@ -229,7 +228,6 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version21" }, "auxiliary_output": { @@ -279,7 +277,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0xa6410b9d726740cc0e3309565816ed7a929fb2ad7ab69b46cde006e7ea60dd5b", - "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", - "commitment": "0x5885a3c69a01beb06a795f78269c2cc092919e3202f38ac57c2bd498cb1c3f74" + "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", + "commitment": "0x3b2e443dd853fb0c15c5956db1deb2527661c2b2b64011ab345120c620bc5faa" } } diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json index 15d34a21b0f7..59a24b7c90ce 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test.json @@ -16,7 +16,6 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "system_logs": [ @@ -275,7 +274,6 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "auxiliary_output": { @@ -353,7 +351,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0xadc63d9c45f85598f3e3c232970315d1f6ac96222e379e16ced7a204524a4061", - "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", - "commitment": "0x4fdd8c5b231dfc9fc81aba744a90fbec78627f529ac29f9fc758a7b9e62fa321" + "meta_parameters": "0xffdee3e679310760e0320a3f9dea3fa863b0771e4424193752ed803fc2d53d20", + "commitment": "0xbbac3e74f007f28453294acb27e3b5c85e67be1208203bb31db9065fe4305dea" } } diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json new file mode 100644 index 000000000000..15d34a21b0f7 --- /dev/null +++ b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json @@ -0,0 +1,359 @@ +{ + "input": { + "PostBoojum": { + "common": { + "l2_to_l1_logs": [ + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 0, + "sender": "0x0000000000000000000000000000000000008001", + "key": "0x7814f203b8e02f6a676b8f7faefcf732d8b4368bab25239ea4525010aa85d5ee", + "value": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "rollup_last_leaf_index": 89, + "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", + "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", + "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", + "protocol_version": "Version23" + }, + "system_logs": [ + { + "shard_id": 0, + "is_service": false, + "tx_number_in_block": 0, + "sender": "0x000000000000000000000000000000000000800b", + "key": "0x0000000000000000000000000000000000000000000000000000000000000004", + "value": "0x55618db5ff24aee4d236921b6f4272101161137115a3b4c4a65f8677b124c01c" + }, + { + "shard_id": 0, + "is_service": false, + "tx_number_in_block": 1, + "sender": "0x000000000000000000000000000000000000800b", + "key": "0x0000000000000000000000000000000000000000000000000000000000000003", + "value": "0x00000000000000000000000065c22f8000000000000000000000000065c22f81" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008001", + "key": "0x0000000000000000000000000000000000000000000000000000000000000005", + "value": "0x155c82febe94e07df0065c153e8ed403b5351fd64d657c8dffbfbee8ec3d2ba3" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008001", + "key": "0x0000000000000000000000000000000000000000000000000000000000000006", + "value": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008008", + "key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "value": "0x30ba728b1aac22b122de4f32589dd2711da264412cb90e35bf7b1f735dd357ff" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008008", + "key": "0x0000000000000000000000000000000000000000000000000000000000000001", + "value": "0x85a7fb853512ba6575c99ee121dd560559523a4587a2cd7e83cd359cd9ea2aed" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008008", + "key": "0x0000000000000000000000000000000000000000000000000000000000000002", + "value": "0xb18f72a4a5b4b8ce1b7e41095fb1332a211a140376bcc2607910875d236708e0" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000007", + "value": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000008", + "value": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000008", + "value": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000008", + "value": "0x0000000000000000000000000000000000000000000000000000000000000006" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000008", + "value": "0x0000000000000000000000000000000000000000000000000000000000000007" + }, + { + "shard_id": 0, + "is_service": true, + "tx_number_in_block": 1, + "sender": "0x0000000000000000000000000000000000008011", + "key": "0x0000000000000000000000000000000000000000000000000000000000000008", + "value": "0x0000000000000000000000000000000000000000000000000000000000000008" + } + ], + "state_diffs": [ + { + "address": "0x000000000000000000000000000000000000800a", + "key": "0x1", + "derived_key": [ + 113, 233, 23, 33, 249, 145, 133, 118, 215, 96, 240, 47, 3, 202, 196, + 124, 111, 64, 3, 49, 96, 49, 132, 142, 60, 29, 153, 230, 232, 58, + 71, 67 + ], + "enumeration_index": 49, + "initial_value": "0x18776f28c303800", + "final_value": "0x708da482cab20760" + }, + { + "address": "0x000000000000000000000000000000000000800a", + "key": "0x294a00337abeee2b3cd948ffeed92231e2a3acc2eb11210400e0aa9557f23e26", + "derived_key": [ + 45, 90, 105, 98, 204, 206, 229, 212, 173, 180, 138, 54, 187, 191, + 68, 58, 83, 23, 33, 72, 67, 129, 18, 89, 55, 243, 0, 26, 197, 255, + 135, 91 + ], + "enumeration_index": 50, + "initial_value": "0xf5559e28fd66c0", + "final_value": "0xf5a19b324caf80" + }, + { + "address": "0x000000000000000000000000000000000000800a", + "key": "0xeaa2b2fbf0b42c559059e5e9510edc15755f1c1883f0e41d5ba5f9aea4ac201a", + "derived_key": [ + 141, 97, 126, 192, 90, 203, 191, 95, 226, 69, 41, 166, 75, 35, 133, + 169, 106, 173, 67, 240, 155, 225, 173, 169, 44, 112, 64, 49, 220, + 193, 72, 27 + ], + "enumeration_index": 0, + "initial_value": "0x0", + "final_value": "0x6f05e193353286a0" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0x7", + "derived_key": [ + 18, 59, 175, 197, 134, 247, 119, 100, 72, 140, 210, 76, 106, 119, + 84, 110, 90, 15, 232, 189, 251, 79, 162, 3, 207, 175, 252, 54, 204, + 228, 221, 91 + ], + "enumeration_index": 53, + "initial_value": "0x100000000000000000000000065c22e3e", + "final_value": "0x200000000000000000000000065c22f80" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0x9", + "derived_key": [ + 142, 125, 208, 106, 197, 183, 59, 71, 59, 230, 188, 90, 81, 3, 15, + 76, 116, 55, 101, 124, 183, 178, 155, 243, 118, 197, 100, 184, 209, + 103, 90, 94 + ], + "enumeration_index": 54, + "initial_value": "0x200000000000000000000000065c22e3f", + "final_value": "0x400000000000000000000000065c22f81" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0xd", + "derived_key": [ + 235, 221, 239, 221, 164, 142, 178, 170, 127, 102, 236, 247, 148, 10, + 40, 14, 158, 243, 251, 46, 149, 219, 9, 149, 83, 132, 64, 166, 42, + 247, 152, 97 + ], + "enumeration_index": 0, + "initial_value": "0x0", + "final_value": "0xebbe609cd3ccd11f273eb94374d6d3a2f7856c5f1039dc4877c6a334188ac7c1" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0xe", + "derived_key": [ + 70, 64, 215, 56, 69, 54, 78, 198, 145, 246, 222, 251, 96, 106, 58, + 114, 253, 165, 215, 173, 51, 209, 125, 4, 153, 90, 142, 37, 44, 74, + 6, 216 + ], + "enumeration_index": 0, + "initial_value": "0x0", + "final_value": "0x708e7fcf68ebab6c87322686cac4bcdb5f2bd4c71f337b18d147fd9a6c44ad13" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0x10c", + "derived_key": [ + 121, 9, 53, 136, 208, 232, 71, 239, 167, 58, 16, 206, 32, 228, 121, + 159, 177, 228, 102, 66, 214, 86, 23, 199, 229, 33, 63, 160, 73, 137, + 217, 45 + ], + "enumeration_index": 57, + "initial_value": "0x200000000000000000000000065c22e3f", + "final_value": "0x400000000000000000000000065c22f81" + }, + { + "address": "0x000000000000000000000000000000000000800b", + "key": "0xad67d757c34507f157cacfa2e3153e9f260a2244f30428821be7be64587ac55f", + "derived_key": [ + 12, 194, 74, 180, 47, 190, 197, 49, 125, 155, 26, 44, 164, 124, 169, + 185, 59, 158, 195, 109, 121, 142, 253, 124, 218, 167, 57, 36, 22, + 48, 203, 70 + ], + "enumeration_index": 0, + "initial_value": "0x0", + "final_value": "0x55618db5ff24aee4d236921b6f4272101161137115a3b4c4a65f8677b124c01c" + } + ], + "aux_commitments": { + "events_queue_commitment": "0x6193a5098eb140796387bdf40700a3855eeb010474b5478f30bf917172c67883", + "bootloader_initial_content_commitment": "0xf031b4491c37f20516c4ebf428f4765156409f67089e64772f4106fd2d9f3351" + }, + "blob_commitments": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + }, + "pass_through_data": { + "shared_states": [ + { + "last_leaf_index": 89, + "root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b" + }, + { + "last_leaf_index": 0, + "root_hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ] + }, + "meta_parameters": { + "zkporter_is_available": false, + "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", + "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", + "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", + "protocol_version": "Version23" + }, + "auxiliary_output": { + "PostBoojum": { + "common": { + "l2_l1_logs_merkle_root": "0x30ba728b1aac22b122de4f32589dd2711da264412cb90e35bf7b1f735dd357ff", + "protocol_version": "Version23" + }, + "system_logs_linear_hash": "0x602dacc0a26e3347f0679924c4ae151ff5200e7dd80902fe0fc11c806c4d3ffb", + "state_diffs_compressed": [ + 1, 0, 1, 72, 4, 0, 4, 141, 97, 126, 192, 90, 203, 191, 95, 226, 69, 41, + 166, 75, 35, 133, 169, 106, 173, 67, 240, 155, 225, 173, 169, 44, 112, + 64, 49, 220, 193, 72, 27, 65, 111, 5, 225, 147, 53, 50, 134, 160, 235, + 221, 239, 221, 164, 142, 178, 170, 127, 102, 236, 247, 148, 10, 40, 14, + 158, 243, 251, 46, 149, 219, 9, 149, 83, 132, 64, 166, 42, 247, 152, 97, + 0, 235, 190, 96, 156, 211, 204, 209, 31, 39, 62, 185, 67, 116, 214, 211, + 162, 247, 133, 108, 95, 16, 57, 220, 72, 119, 198, 163, 52, 24, 138, + 199, 193, 70, 64, 215, 56, 69, 54, 78, 198, 145, 246, 222, 251, 96, 106, + 58, 114, 253, 165, 215, 173, 51, 209, 125, 4, 153, 90, 142, 37, 44, 74, + 6, 216, 0, 112, 142, 127, 207, 104, 235, 171, 108, 135, 50, 38, 134, + 202, 196, 188, 219, 95, 43, 212, 199, 31, 51, 123, 24, 209, 71, 253, + 154, 108, 68, 173, 19, 12, 194, 74, 180, 47, 190, 197, 49, 125, 155, 26, + 44, 164, 124, 169, 185, 59, 158, 195, 109, 121, 142, 253, 124, 218, 167, + 57, 36, 22, 48, 203, 70, 0, 85, 97, 141, 181, 255, 36, 174, 228, 210, + 54, 146, 27, 111, 66, 114, 16, 17, 97, 19, 113, 21, 163, 180, 196, 166, + 95, 134, 119, 177, 36, 192, 28, 0, 0, 0, 49, 65, 111, 6, 45, 144, 62, + 129, 207, 96, 0, 0, 0, 50, 49, 75, 253, 9, 79, 72, 192, 0, 0, 0, 53, + 137, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 66, 0, 0, 0, 54, + 137, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 66, 0, 0, 0, 57, + 137, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 66 + ], + "state_diffs_hash": "0xb18f72a4a5b4b8ce1b7e41095fb1332a211a140376bcc2607910875d236708e0", + "aux_commitments": { + "events_queue_commitment": "0x6193a5098eb140796387bdf40700a3855eeb010474b5478f30bf917172c67883", + "bootloader_initial_content_commitment": "0xf031b4491c37f20516c4ebf428f4765156409f67089e64772f4106fd2d9f3351" + }, + "blob_linear_hashes": [ + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "blob_commitments": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + }, + "hashes": { + "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", + "aux_output": "0xadc63d9c45f85598f3e3c232970315d1f6ac96222e379e16ced7a204524a4061", + "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", + "commitment": "0x4fdd8c5b231dfc9fc81aba744a90fbec78627f529ac29f9fc758a7b9e62fa321" + } +} diff --git a/core/lib/types/src/commitment/tests/pre_boojum_test.json b/core/lib/types/src/commitment/tests/pre_boojum_test.json index eccd843c08a3..3aa163830330 100644 --- a/core/lib/types/src/commitment/tests/pre_boojum_test.json +++ b/core/lib/types/src/commitment/tests/pre_boojum_test.json @@ -16,7 +16,6 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version17" }, "initial_writes": [ @@ -81,7 +80,6 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version17" }, "auxiliary_output": { @@ -566,7 +564,7 @@ "hashes": { "pass_through_data": "0x6a3ffc0f55d4abce9498b8bcb01a3018bc2b83d96acb27e23772fe9347954725", "aux_output": "0x688566b1fe957584256b3bbdc9f9862a7c98cd0a3fa542b3e73600e7bfcd63a3", - "meta_parameters": "0x02531e5cc22688523a4ac9317e5097743771f6914015cf1152491cf22084bd58", - "commitment": "0xebf93d8addf13e664e78fc287468b8783954d9d92572a734f96f0aa63c536da2" + "meta_parameters": "0x3fec00ec17ecaff24bbbcbc15850ca3528ce1c287d3a35fee97a6c65655866c1", + "commitment": "0x8e0a1f1f866df7d53f0648dc6e642eabd452a1319e4acae8cdf58d364d25ee59" } } From d66ba590ef28fdc6aa1a1bbec1ddcf5c7e2fdb2a Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 30 Sep 2024 14:09:49 +0300 Subject: [PATCH 62/72] Misc brush-up --- core/bin/system-constants-generator/src/utils.rs | 2 +- core/lib/contracts/src/lib.rs | 4 ---- core/lib/env_config/src/chain.rs | 8 ++++---- .../multivm/src/versions/vm_1_4_2/tests/circuits.rs | 2 +- .../versions/vm_latest/tracers/default_tracers.rs | 6 +----- .../protobuf_config/src/proto/config/genesis.proto | 2 +- core/lib/vm_interface/src/storage/in_memory.rs | 1 - core/node/eth_sender/src/tests.rs | 13 ++++++------- 8 files changed, 14 insertions(+), 24 deletions(-) diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index 87fcb7171c5b..fad10f945438 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -216,7 +216,7 @@ pub(super) fn execute_internal_transfer_test() -> u32 { let bytecode = read_sys_contract_bytecode("", "DefaultAccount", ContractLanguage::Sol); let hash = hash_bytecode(&bytecode); let default_aa = SystemContractCode { - code: bytes_to_be_words(bytecode.clone()), + code: bytes_to_be_words(bytecode), hash, }; diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 78b3b6102830..29a0a85504e0 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -194,10 +194,6 @@ pub fn deployer_contract() -> Contract { load_sys_contract("ContractDeployer") } -pub fn known_code_storage_contract() -> Contract { - load_sys_contract("KnownCodesStorage") -} - pub fn l1_messenger_contract() -> Contract { load_sys_contract("L1Messenger") } diff --git a/core/lib/env_config/src/chain.rs b/core/lib/env_config/src/chain.rs index 047f6698374f..af244f673c59 100644 --- a/core/lib/env_config/src/chain.rs +++ b/core/lib/env_config/src/chain.rs @@ -97,10 +97,10 @@ mod tests { validation_computational_gas_limit: 10_000_000, save_call_traces: false, bootloader_hash: Some(hash( - "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1", + "0x010007ede999d096c84553fb514d3d6ca76fbf39789dda76bfeda9f3ae06236e", )), default_aa_hash: Some(hash( - "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2", + "0x0100055b041eb28aff6e3a6e0f37c31fd053fc9ef142683b05e5f0aee6934066", )), evm_simulator_hash: None, l1_batch_commit_data_generator_mode, @@ -136,8 +136,8 @@ mod tests { CHAIN_STATE_KEEPER_FEE_MODEL_VERSION="V2" CHAIN_STATE_KEEPER_VALIDATION_COMPUTATIONAL_GAS_LIMIT="10000000" CHAIN_STATE_KEEPER_SAVE_CALL_TRACES="false" - CHAIN_STATE_KEEPER_BOOTLOADER_HASH=0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1 - CHAIN_STATE_KEEPER_DEFAULT_AA_HASH=0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2 + CHAIN_STATE_KEEPER_BOOTLOADER_HASH=0x010007ede999d096c84553fb514d3d6ca76fbf39789dda76bfeda9f3ae06236e + CHAIN_STATE_KEEPER_DEFAULT_AA_HASH=0x0100055b041eb28aff6e3a6e0f37c31fd053fc9ef142683b05e5f0aee6934066 CHAIN_STATE_KEEPER_PROTECTIVE_READS_PERSISTENCE_ENABLED=true CHAIN_STATE_KEEPER_L1_BATCH_COMMIT_DATA_GENERATOR_MODE="{l1_batch_commit_data_generator_mode}" "# diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs b/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs index 3e2b23999182..7d0dfd1ed0ea 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tests/circuits.rs @@ -33,7 +33,7 @@ fn test_circuits() { let s = res.statistics.circuit_statistic; // Check `circuit_statistic`. const EXPECTED: [f32; 11] = [ - 1.1979, 0.1390, 1.5455, 0.0031, 1.1799649, 0.00059, 0.003438, 0.00077, 0.1195, 0.1429, 0.0, + 1.1979, 0.1390, 1.5455, 0.0031, 1.0573, 0.00059, 0.003438, 0.00077, 0.1195, 0.1429, 0.0, ]; let actual = [ (s.main_vm, "main_vm"), diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs index 2d8e6da4b1a1..e58c0bf4f909 100755 --- a/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/default_tracers.rs @@ -96,11 +96,7 @@ impl DefaultExecutionTracer { pubdata_tracer, ret_from_the_bootloader: None, circuits_tracer: CircuitsTracer::new(), - evm_deploy_tracer: if use_evm_simulator { - Some(EvmDeployTracer::new()) - } else { - None - }, + evm_deploy_tracer: use_evm_simulator.then(EvmDeployTracer::new), storage, _phantom: PhantomData, } diff --git a/core/lib/protobuf_config/src/proto/config/genesis.proto b/core/lib/protobuf_config/src/proto/config/genesis.proto index 5e955bf4f00d..ddce0378d224 100644 --- a/core/lib/protobuf_config/src/proto/config/genesis.proto +++ b/core/lib/protobuf_config/src/proto/config/genesis.proto @@ -28,6 +28,6 @@ message Genesis { optional Prover prover = 10; optional L1BatchCommitDataGeneratorMode l1_batch_commit_data_generator_mode = 29; // optional, default to rollup optional string genesis_protocol_semantic_version = 12; // optional; - optional string evm_simulator_hash = 13; // required; h256 + optional string evm_simulator_hash = 13; // optional; h256 reserved 11; reserved "shared_bridge"; } diff --git a/core/lib/vm_interface/src/storage/in_memory.rs b/core/lib/vm_interface/src/storage/in_memory.rs index 9efda7e00225..d83f675cd54e 100644 --- a/core/lib/vm_interface/src/storage/in_memory.rs +++ b/core/lib/vm_interface/src/storage/in_memory.rs @@ -40,7 +40,6 @@ impl InMemoryStorage { ) } - // TODO: add `(get_deployer_key(1), evm_simulator_hash)` if EVM simulator is enabled (as a separate method?) /// Constructs a storage that contains custom system contracts (provided in a vector). pub fn with_custom_system_contracts_and_chain_id( chain_id: L2ChainId, diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index 90d37c45c839..e368ebe4559d 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -48,6 +48,10 @@ pub(crate) fn mock_multicall_response(call: &web3::CallRequest) -> Token { .get_evm_simulator_bytecode_hash .as_ref() .map(ethabi::Function::short_signature); + let bootloader_signature = functions.get_l2_bootloader_bytecode_hash.short_signature(); + let default_aa_signature = functions + .get_l2_default_account_bytecode_hash + .short_signature(); let evm_simulator_getter_signature = evm_simulator_getter_signature.as_ref().map(|sig| &sig[..]); @@ -67,15 +71,10 @@ pub(crate) fn mock_multicall_response(call: &web3::CallRequest) -> Token { let call = call.unwrap(); assert_eq!(call.target, STATE_TRANSITION_CONTRACT_ADDRESS); let output = match &call.calldata[..4] { - selector if selector == functions.get_l2_bootloader_bytecode_hash.short_signature() => { + selector if selector == bootloader_signature => { vec![1u8; 32] } - selector - if selector - == functions - .get_l2_default_account_bytecode_hash - .short_signature() => - { + selector if selector == default_aa_signature => { vec![2u8; 32] } selector if Some(selector) == evm_simulator_getter_signature => { From 95acb2c804228803d07fc7085f453a5b5c4f0922 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 11:54:00 +0300 Subject: [PATCH 63/72] Restore `migration` unit tests --- .../src/versions/vm_latest/tests/migration.rs | 51 +++++++++++++++++++ .../src/versions/vm_latest/tests/mod.rs | 1 + 2 files changed, 52 insertions(+) create mode 100644 core/lib/multivm/src/versions/vm_latest/tests/migration.rs diff --git a/core/lib/multivm/src/versions/vm_latest/tests/migration.rs b/core/lib/multivm/src/versions/vm_latest/tests/migration.rs new file mode 100644 index 000000000000..5b8da2551808 --- /dev/null +++ b/core/lib/multivm/src/versions/vm_latest/tests/migration.rs @@ -0,0 +1,51 @@ +use zksync_types::{get_code_key, H256, SYSTEM_CONTEXT_ADDRESS}; + +use crate::{ + interface::{TxExecutionMode, VmExecutionMode, VmInterface, VmInterfaceExt}, + vm_latest::{ + tests::{ + tester::{get_empty_storage, DeployContractsTx, TxType, VmTesterBuilder}, + utils::read_test_contract, + }, + HistoryEnabled, + }, +}; + +/// This test checks that the new bootloader will work fine even if the previous system context contract is not +/// compatible with it, i.e. the bootloader will upgrade it before starting any transaction. +#[test] +fn test_migration_for_system_context_aa_interaction() { + let mut storage = get_empty_storage(); + // We will set the system context bytecode to zero. + storage.set_value(get_code_key(&SYSTEM_CONTEXT_ADDRESS), H256::zero()); + + // In this test, we aim to test whether a simple account interaction (without any fee logic) + // will work. The account will try to deploy a simple contract from integration tests. + let mut vm = VmTesterBuilder::new(HistoryEnabled) + .with_storage(storage) + .with_execution_mode(TxExecutionMode::VerifyExecute) + .with_random_rich_accounts(1) + .build(); + + // Now, we will just proceed with standard transaction execution. + // The bootloader should be able to update system context regardless of whether + // the upgrade transaction is there or not. + let account = &mut vm.rich_accounts[0]; + let counter = read_test_contract(); + let DeployContractsTx { tx, .. } = account.get_deploy_tx(&counter, None, TxType::L2); + + vm.vm.push_transaction(tx); + let result = vm.vm.execute(VmExecutionMode::OneTx); + assert!( + !result.result.is_failed(), + "Transaction wasn't successful {:#?}", + result.result + ); + + let batch_result = vm.vm.execute(VmExecutionMode::Batch); + assert!( + !batch_result.result.is_failed(), + "Batch transaction wasn't successful {:#?}", + batch_result.result + ); +} diff --git a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs index bc6d5b0144f1..1203d61b80b7 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs @@ -13,6 +13,7 @@ mod get_used_contracts; mod is_write_initial; mod l1_tx_execution; mod l2_blocks; +mod migration; mod nonce_holder; mod precompiles; mod prestate_tracer; From 636dfaa701fe695b47826f6c9d51d24063273688 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 11:54:26 +0300 Subject: [PATCH 64/72] Brush up `TransactionReceipt` conversion --- .../lib/dal/src/models/storage_transaction.rs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/core/lib/dal/src/models/storage_transaction.rs b/core/lib/dal/src/models/storage_transaction.rs index 0dfbec61b01b..78daaebb335e 100644 --- a/core/lib/dal/src/models/storage_transaction.rs +++ b/core/lib/dal/src/models/storage_transaction.rs @@ -352,6 +352,16 @@ impl From for TransactionReceipt { .index_in_block .map_or_else(Default::default, U64::from); + // For better compatibility with various clients, we never return `None` recipient address. + let to = storage_receipt + .transfer_to + .or(storage_receipt.execute_contract_address) + .and_then(|addr| { + serde_json::from_value::>(addr) + .expect("invalid address value in the database") + }) + .unwrap_or_else(Address::zero); + let block_hash = H256::from_slice(&storage_receipt.block_hash); TransactionReceipt { transaction_hash: H256::from_slice(&storage_receipt.tx_hash), @@ -361,15 +371,7 @@ impl From for TransactionReceipt { l1_batch_tx_index: storage_receipt.l1_batch_tx_index.map(U64::from), l1_batch_number: storage_receipt.l1_batch_number.map(U64::from), from: H160::from_slice(&storage_receipt.initiator_address), - to: storage_receipt - .transfer_to - .or(storage_receipt.execute_contract_address) - .and_then(|addr| { - serde_json::from_value::>(addr) - .expect("invalid address value in the database") - // For better compatibility with various clients, we never return null. - }) - .or_else(|| Some(Address::zero())), + to: Some(to), cumulative_gas_used: Default::default(), // TODO: Should be actually calculated (SMA-1183). gas_used: { let refunded_gas: U256 = storage_receipt.refunded_gas.into(); From 8b7c48c1e8488ba4e73736d30e92354fdd6a41f7 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 12:16:50 +0300 Subject: [PATCH 65/72] Test transaction conversion with `to == None` --- core/lib/dal/src/transactions_web3_dal.rs | 60 ++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/core/lib/dal/src/transactions_web3_dal.rs b/core/lib/dal/src/transactions_web3_dal.rs index f5a3c492f8af..7fc541d7dbcf 100644 --- a/core/lib/dal/src/transactions_web3_dal.rs +++ b/core/lib/dal/src/transactions_web3_dal.rs @@ -603,6 +603,39 @@ mod tests { ); } + #[tokio::test] + async fn getting_evm_deployment_tx() { + let connection_pool = ConnectionPool::::test_pool().await; + let mut conn = connection_pool.connection().await.unwrap(); + conn.protocol_versions_dal() + .save_protocol_version_with_tx(&ProtocolVersion::default()) + .await + .unwrap(); + let mut tx = mock_l2_transaction(); + tx.execute.contract_address = None; + let tx_hash = tx.hash(); + prepare_transactions(&mut conn, vec![tx.clone()]).await; + + let fetched_tx = conn + .transactions_dal() + .get_tx_by_hash(tx_hash) + .await + .unwrap() + .expect("no transaction"); + let mut fetched_tx = L2Tx::try_from(fetched_tx).unwrap(); + assert_eq!(fetched_tx.execute.contract_address, None); + fetched_tx.raw_bytes = tx.raw_bytes.clone(); + assert_eq!(fetched_tx, tx); + + let web3_tx = conn + .transactions_web3_dal() + .get_transaction_by_position(L2BlockNumber(1), 0, L2ChainId::from(270)) + .await; + let web3_tx = web3_tx.unwrap().expect("no transaction"); + assert_eq!(web3_tx.hash, tx_hash); + assert_eq!(web3_tx.to, None); + } + #[tokio::test] async fn getting_receipts() { let connection_pool = ConnectionPool::::test_pool().await; @@ -617,7 +650,7 @@ mod tests { let tx2 = mock_l2_transaction(); let tx2_hash = tx2.hash(); - prepare_transactions(&mut conn, vec![tx1.clone(), tx2.clone()]).await; + prepare_transactions(&mut conn, vec![tx1, tx2]).await; let mut receipts = conn .transactions_web3_dal() @@ -632,6 +665,31 @@ mod tests { assert_eq!(receipts[1].transaction_hash, tx2_hash); } + #[tokio::test] + async fn getting_receipt_for_evm_deployment_tx() { + let connection_pool = ConnectionPool::::test_pool().await; + let mut conn = connection_pool.connection().await.unwrap(); + conn.protocol_versions_dal() + .save_protocol_version_with_tx(&ProtocolVersion::default()) + .await + .unwrap(); + + let mut tx = mock_l2_transaction(); + let tx_hash = tx.hash(); + tx.execute.contract_address = None; + prepare_transactions(&mut conn, vec![tx]).await; + + let receipts = conn + .transactions_web3_dal() + .get_transaction_receipts(&[tx_hash]) + .await + .unwrap(); + assert_eq!(receipts.len(), 1); + let receipt = receipts.into_iter().next().unwrap(); + assert_eq!(receipt.transaction_hash, tx_hash); + assert_eq!(receipt.to, Some(Address::zero())); + } + #[tokio::test] async fn getting_l2_block_transactions() { let connection_pool = ConnectionPool::::test_pool().await; From 875e18cb08de305cc1ecec67746d83a29f40e106 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 15:30:40 +0300 Subject: [PATCH 66/72] Check EVM simulator presence during tx conversion --- .../versions/vm_latest/implementation/tx.rs | 7 +++++- .../vm_latest/tests/l1_tx_execution.rs | 2 +- .../versions/vm_latest/tests/nonce_holder.rs | 24 +++++++++---------- .../src/versions/vm_latest/tests/refunds.rs | 2 +- .../types/internals/transaction_data.rs | 11 +++++++-- .../vm_latest/utils/transaction_encoding.rs | 4 +++- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs b/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs index 98d71efa00f3..c00717b39720 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs @@ -59,7 +59,12 @@ impl Vm { tx: Transaction, with_compression: bool, ) { - let tx: TransactionData = tx.into(); + let use_evm_simulator = self + .system_env + .base_system_smart_contracts + .evm_simulator + .is_some(); + let tx = TransactionData::new(tx, use_evm_simulator); let overhead = tx.overhead_gas(); self.push_raw_transaction(tx, overhead, 0, with_compression); } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs index 0fc12848227e..4bb32cdf7ae0 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/l1_tx_execution.rs @@ -52,7 +52,7 @@ fn test_l1_tx_execution() { let contract_code = read_test_contract(); let account = &mut vm.rich_accounts[0]; let deploy_tx = account.get_deploy_tx(&contract_code, None, TxType::L1 { serial_id: 1 }); - let tx_data: TransactionData = deploy_tx.tx.clone().into(); + let tx_data = TransactionData::new(deploy_tx.tx.clone(), false); let required_l2_to_l1_logs: Vec<_> = vec![L2ToL1Log { shard_id: 0, diff --git a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs index 91d78c69a931..6be49367d39e 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/nonce_holder.rs @@ -61,19 +61,17 @@ fn test_nonce_holder() { // it will fail again and again. At the same time we have to keep the same storage, because we want to keep the nonce holder contract state. // The easiest way in terms of lifetimes is to reuse `vm_builder` to achieve it. vm.reset_state(true); - let mut transaction_data: TransactionData = account - .get_l2_tx_for_execute_with_nonce( - Execute { - contract_address: Some(account.address), - calldata: vec![12], - value: Default::default(), - factory_deps: vec![], - }, - None, - Nonce(nonce), - ) - .into(); - + let tx = account.get_l2_tx_for_execute_with_nonce( + Execute { + contract_address: Some(account.address), + calldata: vec![12], + value: Default::default(), + factory_deps: vec![], + }, + None, + Nonce(nonce), + ); + let mut transaction_data = TransactionData::new(tx, false); transaction_data.signature = vec![test_mode.into()]; vm.vm.push_raw_transaction(transaction_data, 0, 0, true); let result = vm.vm.execute(VmExecutionMode::OneTx); diff --git a/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs b/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs index cc0085f20252..c00192aa8f10 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/refunds.rs @@ -62,7 +62,7 @@ fn test_predetermined_refunded_gas() { .with_rich_accounts(vec![account.clone()]) .build(); - let tx: TransactionData = tx.into(); + let tx = TransactionData::new(tx, false); // Overhead let overhead = tx.overhead_gas(); vm.vm diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs index 0a5ebb37360e..fa12e55f5819 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs @@ -46,8 +46,8 @@ pub(crate) struct TransactionData { pub(crate) raw_bytes: Option>, } -impl From for TransactionData { - fn from(execute_tx: Transaction) -> Self { +impl TransactionData { + pub(crate) fn new(execute_tx: Transaction, use_evm_simulator: bool) -> Self { match execute_tx.common_data { ExecuteTransactionCommon::L2(common_data) => { let nonce = U256::from_big_endian(&common_data.nonce.to_be_bytes()); @@ -63,6 +63,13 @@ impl From for TransactionData { }; let should_deploy_contract = if execute_tx.execute.contract_address.is_none() { + // Transactions with no `contract_address` should be filtered out by the API server, + // so this is more of a sanity check. + assert!( + use_evm_simulator, + "`execute.contract_address` not set for transaction {:?} with EVM simulation disabled", + common_data.hash() + ); U256([1, 0, 0, 0]) } else { U256::zero() diff --git a/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs b/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs index 86c49a3eb15d..aeba735dcba7 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs @@ -10,7 +10,9 @@ pub trait TransactionVmExt { impl TransactionVmExt for Transaction { fn bootloader_encoding_size(&self) -> usize { - let transaction_data: TransactionData = self.clone().into(); + // Since we want to just measure the encoding size, `use_evm_simulator` arg doesn't matter here, + // so we use a more lenient option. + let transaction_data = TransactionData::new(self.clone(), true); transaction_data.into_tokens().len() } } From e726b2744f40cb6d38795e2ac384b7d8010f67dc Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 16:21:22 +0300 Subject: [PATCH 67/72] Test txs with `to == None` for API server --- core/node/api_server/src/web3/tests/vm.rs | 83 +++++++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/core/node/api_server/src/web3/tests/vm.rs b/core/node/api_server/src/web3/tests/vm.rs index a485785009a9..5a7e038cb5f4 100644 --- a/core/node/api_server/src/web3/tests/vm.rs +++ b/core/node/api_server/src/web3/tests/vm.rs @@ -227,12 +227,12 @@ struct SendRawTransactionTest { } impl SendRawTransactionTest { - fn transaction_bytes_and_hash() -> (Vec, H256) { + fn transaction_bytes_and_hash(include_to: bool) -> (Vec, H256) { let private_key = Self::private_key(); let tx_request = api::TransactionRequest { chain_id: Some(L2ChainId::default().as_u64()), from: Some(private_key.address()), - to: Some(Address::repeat_byte(2)), + to: include_to.then(|| Address::repeat_byte(2)), value: 123_456.into(), gas: (get_intrinsic_constants().l2_tx_intrinsic_gas * 2).into(), gas_price: StateKeeperConfig::for_tests().minimal_l2_gas_price.into(), @@ -283,7 +283,7 @@ impl HttpTest for SendRawTransactionTest { L2BlockNumber(1) }; tx_executor.set_tx_responses(move |tx, env| { - assert_eq!(tx.hash(), Self::transaction_bytes_and_hash().1); + assert_eq!(tx.hash(), Self::transaction_bytes_and_hash(true).1); assert_eq!(env.l1_batch.first_l2_block.number, pending_block.0); ExecutionResult::Success { output: vec![] } }); @@ -304,7 +304,7 @@ impl HttpTest for SendRawTransactionTest { .await?; } - let (tx_bytes, tx_hash) = Self::transaction_bytes_and_hash(); + let (tx_bytes, tx_hash) = Self::transaction_bytes_and_hash(true); let send_result = client.send_raw_transaction(tx_bytes.into()).await?; assert_eq!(send_result, tx_hash); Ok(()) @@ -327,6 +327,50 @@ async fn send_raw_transaction_after_snapshot_recovery() { .await; } +fn assert_null_to_address_error(error: &ClientError) { + if let ClientError::Call(error) = error { + assert_eq!(error.code(), 3); + assert!(error.message().contains("toAddressIsNull"), "{error:?}"); + assert!(error.data().is_none(), "{error:?}"); + } else { + panic!("Unexpected error: {error:?}"); + } +} + +#[derive(Debug)] +struct SendRawTransactionWithoutToAddressTest; + +#[async_trait] +impl HttpTest for SendRawTransactionWithoutToAddressTest { + async fn test( + &self, + client: &DynClient, + pool: &ConnectionPool, + ) -> anyhow::Result<()> { + let mut storage = pool.connection().await?; + storage + .storage_logs_dal() + .append_storage_logs( + L2BlockNumber(0), + &[SendRawTransactionTest::balance_storage_log()], + ) + .await?; + + let (tx_bytes, _) = SendRawTransactionTest::transaction_bytes_and_hash(false); + let err = client + .send_raw_transaction(tx_bytes.into()) + .await + .unwrap_err(); + assert_null_to_address_error(&err); + Ok(()) + } +} + +#[tokio::test] +async fn send_raw_transaction_fails_without_to_address() { + test_http_server(SendRawTransactionWithoutToAddressTest).await; +} + #[derive(Debug)] struct SendTransactionWithDetailedOutputTest; @@ -375,7 +419,7 @@ impl SendTransactionWithDetailedOutputTest { impl HttpTest for SendTransactionWithDetailedOutputTest { fn transaction_executor(&self) -> MockOneshotExecutor { let mut tx_executor = MockOneshotExecutor::default(); - let tx_bytes_and_hash = SendRawTransactionTest::transaction_bytes_and_hash(); + let tx_bytes_and_hash = SendRawTransactionTest::transaction_bytes_and_hash(true); let vm_execution_logs = VmExecutionLogs { storage_logs: self.storage_logs(), events: self.vm_events(), @@ -414,7 +458,7 @@ impl HttpTest for SendTransactionWithDetailedOutputTest { ) .await?; - let (tx_bytes, tx_hash) = SendRawTransactionTest::transaction_bytes_and_hash(); + let (tx_bytes, tx_hash) = SendRawTransactionTest::transaction_bytes_and_hash(true); let send_result = client .send_raw_transaction_with_detailed_output(tx_bytes.into()) .await?; @@ -791,3 +835,30 @@ async fn estimate_gas_with_state_override() { let inner = EstimateGasTest::new(false); test_http_server(EstimateGasWithStateOverrideTest { inner }).await; } + +#[derive(Debug)] +struct EstimateGasWithoutToAddessTest; + +#[async_trait] +impl HttpTest for EstimateGasWithoutToAddessTest { + async fn test( + &self, + client: &DynClient, + _pool: &ConnectionPool, + ) -> anyhow::Result<()> { + let mut l2_transaction = create_l2_transaction(10, 100); + l2_transaction.execute.contract_address = None; + l2_transaction.common_data.signature = vec![]; // Remove invalidated signature so that it doesn't trip estimation logic + let err = client + .estimate_gas(l2_transaction.clone().into(), None, None) + .await + .unwrap_err(); + assert_null_to_address_error(&err); + Ok(()) + } +} + +#[tokio::test] +async fn estimate_gas_fails_without_to_address() { + test_http_server(EstimateGasWithoutToAddessTest).await; +} From ff22c20662f6b11122a796d599acc6f745f46ec1 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Tue, 1 Oct 2024 16:24:57 +0300 Subject: [PATCH 68/72] Disallow `to == None` for calls in API server --- core/node/api_server/src/web3/namespaces/debug.rs | 2 +- core/node/api_server/src/web3/namespaces/eth.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/node/api_server/src/web3/namespaces/debug.rs b/core/node/api_server/src/web3/namespaces/debug.rs index cb4b78411508..905b9caf1373 100644 --- a/core/node/api_server/src/web3/namespaces/debug.rs +++ b/core/node/api_server/src/web3/namespaces/debug.rs @@ -268,7 +268,7 @@ impl DebugNamespace { let call = L2Tx::from_request( request.into(), MAX_ENCODED_TX_SIZE, - block_args.use_evm_simulator(), + false, // Even with EVM simulation enabled, calls must specify `to` field )?; let vm_permit = self diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index 7a9a074c7bbd..4ff6022559e4 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -80,7 +80,7 @@ impl EthNamespace { let tx = L2Tx::from_request( request.into(), self.state.api_config.max_tx_size, - block_args.use_evm_simulator(), + false, // Even with EVM simulation enabled, calls must specify `to` field )?; // It is assumed that the previous checks has already enforced that the `max_fee_per_gas` is at most u64. From 0aecc1473faee7d06cb86fd53bf69adffea737fb Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 3 Oct 2024 16:49:01 +0300 Subject: [PATCH 69/72] Sketch far call tracer --- .../vm_latest/tracers/evm_deploy_tracer.rs | 122 +++++++++--------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs b/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs index 28f53d5a46b6..d91ee13a920a 100644 --- a/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs +++ b/core/lib/multivm/src/versions/vm_latest/tracers/evm_deploy_tracer.rs @@ -1,12 +1,15 @@ -use std::marker::PhantomData; +use std::{marker::PhantomData, mem}; use zk_evm_1_5_0::{ aux_structures::Timestamp, - zkevm_opcode_defs::{FatPointer, CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER}, + tracing::{AfterExecutionData, VmLocalStateData}, + zkevm_opcode_defs::{ + FarCallOpcode, FatPointer, Opcode, CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER, + }, }; -use zksync_contracts::known_codes_contract; use zksync_types::{CONTRACT_DEPLOYER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS}; use zksync_utils::{bytes_to_be_words, h256_to_u256}; +use zksync_vm_interface::storage::StoragePtr; use super::{traits::VmTracer, utils::read_pointer}; use crate::{ @@ -19,87 +22,84 @@ use crate::{ /// Tracer responsible for collecting information about EVM deploys and providing those /// to the code decommitter. -#[derive(Debug, Clone)] +#[derive(Debug)] pub(crate) struct EvmDeployTracer { + tracked_signature: [u8; 4], + pending_bytecodes: Vec>, _phantom: PhantomData, } impl EvmDeployTracer { pub(crate) fn new() -> Self { + let tracked_signature = + ethabi::short_signature("publishEVMBytecode", &[ethabi::ParamType::Bytes]); + Self { + tracked_signature, + pending_bytecodes: vec![], _phantom: PhantomData, } } } -impl DynTracer> for EvmDeployTracer {} - -impl VmTracer for EvmDeployTracer { - fn finish_cycle( +impl DynTracer> for EvmDeployTracer { + fn after_execution( &mut self, - state: &mut ZkSyncVmState, - _bootloader_state: &mut BootloaderState, - ) -> TracerExecutionStatus { - // We check if ContractDeployer was called with provided evm bytecode. - // It is assumed that by that time the user has already paid for its size. - // So even if we do not revert the addition of the this bytecode it is not a ddos vector, since - // the payment is the same as if the bytecode publication was reverted. - let current_callstack = &state.local_state.callstack.current; - - // Here we assume that the only case when PC is 0 at the start of the execution of the contract. - let known_code_storage_call = current_callstack.this_address == KNOWN_CODES_STORAGE_ADDRESS - && current_callstack.pc == 0 - && current_callstack.msg_sender == CONTRACT_DEPLOYER_ADDRESS; + state: VmLocalStateData<'_>, + data: AfterExecutionData, + memory: &SimpleMemory, + _storage: StoragePtr, + ) { + if !matches!( + data.opcode.variant.opcode, + Opcode::FarCall(FarCallOpcode::Normal) + ) { + return; + }; - if !known_code_storage_call { - // Just continue executing - return TracerExecutionStatus::Continue; + let current = state.vm_local_state.callstack.current; + let from = current.msg_sender; + let to = current.this_address; + if from != CONTRACT_DEPLOYER_ADDRESS || to != KNOWN_CODES_STORAGE_ADDRESS { + return; } - // Now, we need to check whether it is indeed a call to publish EVM code. let calldata_ptr = - state.local_state.registers[CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER as usize]; - - let data = read_pointer(&state.memory, FatPointer::from_u256(calldata_ptr.value)); - - let contract = known_codes_contract(); - + state.vm_local_state.registers[usize::from(CALL_IMPLICIT_CALLDATA_FAT_PTR_REGISTER)]; + let data = read_pointer(memory, FatPointer::from_u256(calldata_ptr.value)); if data.len() < 4 { - // Not interested - return TracerExecutionStatus::Continue; + return; } - let (signature, data) = data.split_at(4); - - if signature - != contract - .function("publishEVMBytecode") - .unwrap() - .short_signature() - { - // Not interested - return TracerExecutionStatus::Continue; + if signature != self.tracked_signature { + return; } - let Ok(call_params) = contract - .function("publishEVMBytecode") - .unwrap() - .decode_input(data) - else { - // Not interested - return TracerExecutionStatus::Continue; - }; - - let published_bytecode = call_params[0].clone().into_bytes().unwrap(); - - let hash = hash_evm_bytecode(&published_bytecode); - let as_words = bytes_to_be_words(published_bytecode); - - state.decommittment_processor.populate( - vec![(h256_to_u256(hash), as_words)], - Timestamp(state.local_state.timestamp), - ); + match ethabi::decode(&[ethabi::ParamType::Bytes], data) { + Ok(decoded) => { + let published_bytecode = decoded.into_iter().next().unwrap().into_bytes().unwrap(); + self.pending_bytecodes.push(published_bytecode); + } + Err(err) => tracing::error!("Unable to decode `publishEVMBytecode` call: {err}"), + } + } +} +impl VmTracer for EvmDeployTracer { + fn finish_cycle( + &mut self, + state: &mut ZkSyncVmState, + _bootloader_state: &mut BootloaderState, + ) -> TracerExecutionStatus { + for published_bytecode in mem::take(&mut self.pending_bytecodes) { + let hash = hash_evm_bytecode(&published_bytecode); + let as_words = bytes_to_be_words(published_bytecode); + + state.decommittment_processor.populate( + vec![(h256_to_u256(hash), as_words)], + Timestamp(state.local_state.timestamp), + ); + } TracerExecutionStatus::Continue } } From 8d4779d06495181541d27b589ead66413479300f Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Thu, 3 Oct 2024 20:35:01 +0300 Subject: [PATCH 70/72] Test EVM simulator tracing --- .../versions/vm_latest/tests/evm_simulator.rs | 80 +++++++++++++++++++ .../src/versions/vm_latest/tests/mod.rs | 1 + .../contracts/mock-evm/mock-evm.sol | 50 ++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs create mode 100644 etc/contracts-test-data/contracts/mock-evm/mock-evm.sol diff --git a/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs b/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs new file mode 100644 index 000000000000..77ef835475b4 --- /dev/null +++ b/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs @@ -0,0 +1,80 @@ +use ethabi::Token; +use zksync_contracts::read_bytecode; +use zksync_system_constants::{CONTRACT_DEPLOYER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS}; +use zksync_test_account::TxType; +use zksync_types::{get_code_key, get_known_code_key, H256}; +use zksync_utils::{be_words_to_bytes, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; +use zksync_vm_interface::VmInterfaceExt; + +use crate::{ + interface::{storage::InMemoryStorage, TxExecutionMode}, + versions::testonly::default_system_env, + vm_latest::{ + tests::{tester::VmTesterBuilder, utils::read_test_contract}, + utils::hash_evm_bytecode, + HistoryEnabled, + }, +}; + +const MOCK_DEPLOYER_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm//mock-evm.sol/MockContractDeployer.json"; +const MOCK_KNOWN_CODE_STORAGE_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm//mock-evm.sol/MockKnownCodeStorage.json"; + +#[test] +fn tracing_evm_contract_deployment() { + let mock_deployer = read_bytecode(MOCK_DEPLOYER_PATH); + let mock_deployer_hash = hash_bytecode(&mock_deployer); + let mock_known_code_storage = read_bytecode(MOCK_KNOWN_CODE_STORAGE_PATH); + let mock_known_code_storage_hash = hash_bytecode(&mock_known_code_storage); + + // Override + let mut storage = InMemoryStorage::with_system_contracts(hash_bytecode); + storage.set_value(get_code_key(&CONTRACT_DEPLOYER_ADDRESS), mock_deployer_hash); + storage.set_value( + get_known_code_key(&mock_deployer_hash), + H256::from_low_u64_be(1), + ); + storage.set_value( + get_code_key(&KNOWN_CODES_STORAGE_ADDRESS), + mock_known_code_storage_hash, + ); + storage.set_value( + get_known_code_key(&mock_known_code_storage_hash), + H256::from_low_u64_be(1), + ); + storage.store_factory_dep(mock_deployer_hash, mock_deployer); + storage.store_factory_dep(mock_known_code_storage_hash, mock_known_code_storage); + + let mut system_env = default_system_env(); + // The EVM simulator will not be accessed, so we set it to a dummy value. + system_env.base_system_smart_contracts.evm_simulator = + Some(system_env.base_system_smart_contracts.default_aa.clone()); + let mut vm = VmTesterBuilder::new(HistoryEnabled) + .with_system_env(system_env) + .with_storage(storage) + .with_execution_mode(TxExecutionMode::VerifyExecute) + .with_random_rich_accounts(1) + .build(); + let account = &mut vm.rich_accounts[0]; + + let args = [Token::Bytes((0..=u8::MAX).collect())]; + let encoded_args = bytes_to_be_words(ethabi::encode(&args)); + let deploy_tx = account + .get_deploy_tx(&read_test_contract(), Some(&args), TxType::L2) + .tx; + let (_, vm_result) = vm + .vm + .execute_transaction_with_bytecode_compression(deploy_tx, true); + assert!(!vm_result.result.is_failed(), "{:?}", vm_result.result); + + // Check that the surrogate bytecode was added to the decommitter. + let known_bytecodes = vm.vm.state.decommittment_processor.known_bytecodes.inner(); + let (&evm_bytecode_hash, evm_bytecode) = known_bytecodes + .iter() + .find(|(_, bytecode)| bytecode.ends_with(&encoded_args)) + .unwrap(); + let evm_bytecode = be_words_to_bytes(evm_bytecode); + assert_eq!( + evm_bytecode_hash, + h256_to_u256(hash_evm_bytecode(&evm_bytecode)) + ); +} diff --git a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs index 1203d61b80b7..f6d3667c6f82 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/mod.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/mod.rs @@ -8,6 +8,7 @@ mod call_tracer; mod circuits; mod code_oracle; mod constants; +mod evm_simulator; mod gas_limit; mod get_used_contracts; mod is_write_initial; diff --git a/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol new file mode 100644 index 000000000000..823876552426 --- /dev/null +++ b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.0; + +contract MockKnownCodeStorage { + function markFactoryDeps(bool _shouldSendToL1, bytes32[] calldata _hashes) external { + // Do nothing; necessary for system contracts to function correctly + } + + function markBytecodeAsPublished(bytes32 _bytecodeHash) external { + // Do nothing; necessary for system contracts to function correctly + } + + function publishEVMBytecode(bytes calldata _bytecode) external { + // Do nothing; necessary for system contracts to function correctly + } + + function getMarker(bytes32 _hash) public view returns (uint256 marker) { + assembly { + marker := sload(_hash) + } + } +} + +contract MockContractDeployer { + enum AccountAbstractionVersion { + None, + Version1 + } + + address constant CODE_ORACLE_ADDR = address(0x8012); + MockKnownCodeStorage constant KNOWN_CODE_STORAGE_CONTRACT = MockKnownCodeStorage(address(0x8004)); + + function extendedAccountVersion(address _address) public view returns (AccountAbstractionVersion) { + // The returned value is obviously false in the general case, but works well enough in the bootloader context + return AccountAbstractionVersion.Version1; + } + + // Replaces the real deployment by publishing a surrogate EVM "bytecode" obtained by concatenating `_salt` and `_input`. + // The call to publish this bytecode should be intercepted by the tracer. + function create( + bytes32 _salt, + bytes32 _bytecodeHash, + bytes calldata _input + ) external payable returns (address) { + bytes memory evmBytecode = bytes.concat(_salt, _input); + KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(evmBytecode); + return address(0); + } +} From 2d0e37c9cb95f3a34e88f26a887e9e3151e25284 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Fri, 4 Oct 2024 09:12:22 +0300 Subject: [PATCH 71/72] Brush up mock system contracts --- .../versions/vm_latest/tests/evm_simulator.rs | 40 ++++++------- core/lib/types/src/tx/execute.rs | 26 +++++++- .../contracts/mock-evm/mock-evm.sol | 60 ++++++++++++++++--- 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs b/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs index 77ef835475b4..8cf72842655f 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs @@ -1,23 +1,18 @@ use ethabi::Token; use zksync_contracts::read_bytecode; use zksync_system_constants::{CONTRACT_DEPLOYER_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS}; -use zksync_test_account::TxType; -use zksync_types::{get_code_key, get_known_code_key, H256}; -use zksync_utils::{be_words_to_bytes, bytecode::hash_bytecode, bytes_to_be_words, h256_to_u256}; +use zksync_types::{get_code_key, get_known_code_key, Execute, H256}; +use zksync_utils::{be_words_to_bytes, bytecode::hash_bytecode, h256_to_u256}; use zksync_vm_interface::VmInterfaceExt; use crate::{ interface::{storage::InMemoryStorage, TxExecutionMode}, versions::testonly::default_system_env, - vm_latest::{ - tests::{tester::VmTesterBuilder, utils::read_test_contract}, - utils::hash_evm_bytecode, - HistoryEnabled, - }, + vm_latest::{tests::tester::VmTesterBuilder, utils::hash_evm_bytecode, HistoryEnabled}, }; -const MOCK_DEPLOYER_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm//mock-evm.sol/MockContractDeployer.json"; -const MOCK_KNOWN_CODE_STORAGE_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm//mock-evm.sol/MockKnownCodeStorage.json"; +const MOCK_DEPLOYER_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm/mock-evm.sol/MockContractDeployer.json"; +const MOCK_KNOWN_CODE_STORAGE_PATH: &str = "etc/contracts-test-data/artifacts-zk/contracts/mock-evm/mock-evm.sol/MockKnownCodeStorage.json"; #[test] fn tracing_evm_contract_deployment() { @@ -57,24 +52,25 @@ fn tracing_evm_contract_deployment() { let account = &mut vm.rich_accounts[0]; let args = [Token::Bytes((0..=u8::MAX).collect())]; - let encoded_args = bytes_to_be_words(ethabi::encode(&args)); - let deploy_tx = account - .get_deploy_tx(&read_test_contract(), Some(&args), TxType::L2) - .tx; + let evm_bytecode = ethabi::encode(&args); + let expected_bytecode_hash = hash_evm_bytecode(&evm_bytecode); + let execute = Execute::for_deploy(expected_bytecode_hash, vec![0; 32], &args); + let deploy_tx = account.get_l2_tx_for_execute(execute, None); let (_, vm_result) = vm .vm .execute_transaction_with_bytecode_compression(deploy_tx, true); assert!(!vm_result.result.is_failed(), "{:?}", vm_result.result); - // Check that the surrogate bytecode was added to the decommitter. + // Check that the surrogate EVM bytecode was added to the decommitter. let known_bytecodes = vm.vm.state.decommittment_processor.known_bytecodes.inner(); - let (&evm_bytecode_hash, evm_bytecode) = known_bytecodes - .iter() - .find(|(_, bytecode)| bytecode.ends_with(&encoded_args)) - .unwrap(); - let evm_bytecode = be_words_to_bytes(evm_bytecode); + let known_evm_bytecode = + be_words_to_bytes(&known_bytecodes[&h256_to_u256(expected_bytecode_hash)]); + assert_eq!(known_evm_bytecode, evm_bytecode); + + let new_known_factory_deps = vm_result.new_known_factory_deps.unwrap(); + assert_eq!(new_known_factory_deps.len(), 2); // the deployed EraVM contract + EVM contract assert_eq!( - evm_bytecode_hash, - h256_to_u256(hash_evm_bytecode(&evm_bytecode)) + new_known_factory_deps[&expected_bytecode_hash], + evm_bytecode ); } diff --git a/core/lib/types/src/tx/execute.rs b/core/lib/types/src/tx/execute.rs index c133261bc232..0edece9e46b4 100644 --- a/core/lib/types/src/tx/execute.rs +++ b/core/lib/types/src/tx/execute.rs @@ -1,6 +1,7 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use zksync_utils::ZeroPrefixHexSerde; +use zksync_system_constants::CONTRACT_DEPLOYER_ADDRESS; +use zksync_utils::{bytecode::hash_bytecode, ZeroPrefixHexSerde}; use crate::{ethabi, Address, EIP712TypedStructure, StructBuilder, H256, U256}; @@ -89,8 +90,7 @@ impl Execute { &self.calldata } - /// Prepares calldata to invoke deployer contract. - /// This method encodes parameters for the `create` method. + /// Prepares calldata to invoke deployer contract. This method encodes parameters for the `create` method. pub fn encode_deploy_params_create( salt: H256, contract_hash: H256, @@ -116,4 +116,24 @@ impl Execute { FUNCTION_SIGNATURE.iter().copied().chain(params).collect() } + + /// Creates an instance for deploying the specified bytecode without additional dependencies. If necessary, + /// additional deps can be added to `Self.factory_deps` after this call. + pub fn for_deploy( + salt: H256, + contract_bytecode: Vec, + constructor_input: &[ethabi::Token], + ) -> Self { + let bytecode_hash = hash_bytecode(&contract_bytecode); + Self { + contract_address: Some(CONTRACT_DEPLOYER_ADDRESS), + calldata: Self::encode_deploy_params_create( + salt, + bytecode_hash, + ethabi::encode(constructor_input), + ), + value: 0.into(), + factory_deps: vec![contract_bytecode], + } + } } diff --git a/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol index 823876552426..b0f888e10e0b 100644 --- a/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol +++ b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol @@ -1,18 +1,54 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.0; +/** + * Mock `KnownCodeStorage` counterpart producing `MarkedAsKnown` events and having `publishEVMBytecode` method + * added for EVM simulation, calls to which should be traced by the host. + */ contract MockKnownCodeStorage { + event MarkedAsKnown(bytes32 indexed bytecodeHash, bool indexed sendBytecodeToL1); + function markFactoryDeps(bool _shouldSendToL1, bytes32[] calldata _hashes) external { - // Do nothing; necessary for system contracts to function correctly + unchecked { + uint256 hashesLen = _hashes.length; + for (uint256 i = 0; i < hashesLen; ++i) { + _markBytecodeAsPublished(_hashes[i], _shouldSendToL1); + } + } } function markBytecodeAsPublished(bytes32 _bytecodeHash) external { - // Do nothing; necessary for system contracts to function correctly + _markBytecodeAsPublished(_bytecodeHash, false); + } + + function _markBytecodeAsPublished(bytes32 _bytecodeHash, bool _shouldSendToL1) internal { + if (getMarker(_bytecodeHash) == 0) { + assembly { + sstore(_bytecodeHash, 1) + } + emit MarkedAsKnown(_bytecodeHash, _shouldSendToL1); + } + } + + bytes32 evmBytecodeHash; // For tests, it's OK to potentially collide with the marker slot for hash `bytes32(0)` + + /// Sets the EVM bytecode hash to be used in the next `publishEVMBytecode` call. + function setEVMBytecodeHash(bytes32 _bytecodeHash) external { + evmBytecodeHash = _bytecodeHash; } function publishEVMBytecode(bytes calldata _bytecode) external { - // Do nothing; necessary for system contracts to function correctly + bytes32 hash = evmBytecodeHash; + require(hash != bytes32(0), "EVM bytecode hash not set"); + + if (getMarker(evmBytecodeHash) == 0) { + assembly { + sstore(hash, 1) + } + } + emit MarkedAsKnown(hash, getMarker(hash) == 0); + evmBytecodeHash = bytes32(0); } function getMarker(bytes32 _hash) public view returns (uint256 marker) { @@ -22,6 +58,10 @@ contract MockKnownCodeStorage { } } +/** + * Mock `ContractDeployer` counterpart focusing on EVM bytecode deployment (via `create`; this isn't how real EVM bytecode deployment works, + * but it's good enough for low-level tests). + */ contract MockContractDeployer { enum AccountAbstractionVersion { None, @@ -31,20 +71,22 @@ contract MockContractDeployer { address constant CODE_ORACLE_ADDR = address(0x8012); MockKnownCodeStorage constant KNOWN_CODE_STORAGE_CONTRACT = MockKnownCodeStorage(address(0x8004)); + /// The returned value is obviously incorrect in the general case, but works well enough when called by the bootloader. function extendedAccountVersion(address _address) public view returns (AccountAbstractionVersion) { - // The returned value is obviously false in the general case, but works well enough in the bootloader context return AccountAbstractionVersion.Version1; } - // Replaces the real deployment by publishing a surrogate EVM "bytecode" obtained by concatenating `_salt` and `_input`. - // The call to publish this bytecode should be intercepted by the tracer. + /// Replaces real deployment with publishing a surrogate EVM "bytecode". + /// @param _salt bytecode hash + /// @param _bytecodeHash ignored, since it's not possible to set arbitrarily + /// @param _input bytecode to publish function create( bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input ) external payable returns (address) { - bytes memory evmBytecode = bytes.concat(_salt, _input); - KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(evmBytecode); + KNOWN_CODE_STORAGE_CONTRACT.setEVMBytecodeHash(_salt); + KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(_input); return address(0); } } From 71e3dbe362a33cd86216022df1b7821607abaa83 Mon Sep 17 00:00:00 2001 From: Alex Ostrovski Date: Mon, 7 Oct 2024 14:12:33 +0300 Subject: [PATCH 72/72] Rename "EVM simulator" -> "EVM emulator" --- core/bin/genesis_generator/src/main.rs | 2 +- .../system-constants-generator/src/utils.rs | 4 +-- core/lib/config/src/configs/chain.rs | 6 ++-- core/lib/config/src/configs/genesis.rs | 4 +-- core/lib/config/src/testonly.rs | 4 +-- core/lib/contracts/src/lib.rs | 20 +++++------ ...2dba1d37493d4c1db4b957cfec476a791b32.json} | 6 ++-- ...bef013ad12b66bdca7251be2af21e98fe870.json} | 6 ++-- ...fcb3522a0772ac3d2476652df4216d823e04.json} | 4 +-- ...7ca0e4b83f50724a0b18256aafab69909a98.json} | 6 ++-- ...12784694d2f8fe9a67159ad4c7abc2279ca6.json} | 6 ++-- ...7f64d0c9620506bb41890548181bccca9ee5.json} | 6 ++-- ...fe9b944b2dd80eb56965a5874ce3168e8c5e.json} | 6 ++-- ...9749bd5fc78b09578589c26d3017cc6bd192.json} | 6 ++-- ...70e7a5fe02b60d5d23e4d153190138112c5b.json} | 6 ++-- ...9fabba23fa52a17a54146931476681edbd24.json} | 6 ++-- ...76eb8a6a508aea04d93342df50dd9745c361.json} | 6 ++-- ...e0c8a39a49d1cea78ef771d4c64fbbc16756.json} | 6 ++-- ...5e2c2f10d5cbdb03d02c3c541f7eaa1f58a6.json} | 6 ++-- ...b2d1aa6b398c6981c8d4f35e499f42b01731.json} | 6 ++-- ...e82c5aa84c85b9486e81261d17901a786917.json} | 4 +-- ...65162bce330edd9b16587e8f9fdab17a8456.json} | 6 ++-- ...fc5d8943e65a30508898d90a098432050bc7.json} | 6 ++-- ...21ca4cc94c38a7d18023ef1e89de484e60d8.json} | 6 ++-- ...14f15fd7a5fa3d7f7bc56906817c70b04950.json} | 4 +-- ...b243bb067514b67daaf084353e5ada15b23a.json} | 6 ++-- .../20240911161714_evm-simulator.down.sql | 6 ++-- .../20240911161714_evm-simulator.up.sql | 6 ++-- core/lib/dal/src/blocks_dal.rs | 36 +++++++++---------- core/lib/dal/src/blocks_web3_dal.rs | 4 +-- core/lib/dal/src/factory_deps_dal.rs | 18 +++++----- core/lib/dal/src/models/storage_block.rs | 28 +++++++-------- .../src/models/storage_protocol_version.rs | 10 +++--- core/lib/dal/src/models/storage_sync.rs | 8 ++--- core/lib/dal/src/protocol_versions_dal.rs | 10 +++--- .../lib/dal/src/protocol_versions_web3_dal.rs | 2 +- core/lib/dal/src/sync_dal.rs | 2 +- core/lib/dal/src/tests/mod.rs | 2 +- core/lib/env_config/src/chain.rs | 2 +- core/lib/env_config/src/genesis.rs | 2 +- .../vm_1_4_2/tests/get_used_contracts.rs | 2 +- .../tests/get_used_contracts.rs | 2 +- .../vm_fast/tests/get_used_contracts.rs | 4 +-- .../vm_latest/implementation/execution.rs | 2 +- .../versions/vm_latest/implementation/tx.rs | 6 ++-- .../{evm_simulator.rs => evm_emulator.rs} | 4 +-- .../vm_latest/tests/get_used_contracts.rs | 4 +-- .../src/versions/vm_latest/tests/mod.rs | 2 +- .../vm_latest/tracers/default_tracers.rs | 4 +-- .../types/internals/transaction_data.rs | 6 ++-- .../vm_latest/types/internals/vm_state.rs | 12 +++---- .../vm_latest/utils/transaction_encoding.rs | 2 +- .../tests/get_used_contracts.rs | 2 +- .../tests/get_used_contracts.rs | 2 +- core/lib/protobuf_config/src/chain.rs | 2 +- core/lib/protobuf_config/src/genesis.rs | 8 ++--- .../src/proto/config/genesis.proto | 2 +- core/lib/prover_interface/src/inputs.rs | 2 +- core/lib/tee_verifier/src/lib.rs | 2 +- core/lib/types/src/api/mod.rs | 18 +++++----- core/lib/types/src/commitment/mod.rs | 14 ++++---- .../post_boojum_1_5_0_test_with_evm.json | 4 +-- core/lib/types/src/l2/mod.rs | 2 +- core/lib/types/src/protocol_upgrade.rs | 12 +++---- core/lib/types/src/system_contracts.rs | 8 ++--- core/lib/vm_executor/src/oneshot/block.rs | 18 +++++----- core/lib/vm_executor/src/oneshot/contracts.rs | 8 ++--- core/lib/vm_executor/src/storage.rs | 2 +- .../src/types/outputs/execution_result.rs | 2 +- .../api_server/src/execution_sandbox/mod.rs | 4 +-- .../api_server/src/web3/namespaces/debug.rs | 2 +- .../node/api_server/src/web3/namespaces/en.rs | 4 +-- .../api_server/src/web3/namespaces/eth.rs | 4 +-- .../api_server/src/web3/namespaces/zks.rs | 4 +-- core/node/api_server/src/web3/state.rs | 2 +- core/node/commitment_generator/src/lib.rs | 2 +- core/node/eth_sender/src/eth_tx_aggregator.rs | 34 +++++++++--------- core/node/eth_sender/src/tests.rs | 25 +++++++------ core/node/eth_sender/src/zksync_functions.rs | 6 ++-- core/node/genesis/src/lib.rs | 12 +++---- core/node/genesis/src/utils.rs | 2 +- core/node/node_sync/src/external_io.rs | 10 +++--- core/node/node_sync/src/genesis.rs | 8 ++--- core/node/node_sync/src/tests.rs | 6 ++-- core/node/proof_data_handler/src/tests.rs | 2 +- core/node/test_utils/src/lib.rs | 6 ++-- core/node/vm_runner/src/impls/bwip.rs | 23 ++++++------ core/node/vm_runner/src/tests/mod.rs | 7 +--- .../vm_runner/src/tests/output_handler.rs | 2 +- .../contracts/mock-evm/mock-evm.sol | 2 +- etc/env/file_based/genesis.yaml | 4 +-- .../src/rounds/basic_circuits/utils.rs | 10 +++--- .../forge_interface/deploy_ecosystem/input.rs | 4 +-- 93 files changed, 312 insertions(+), 321 deletions(-) rename core/lib/dal/.sqlx/{query-5e3dc38cfdf6635a91c6c31e8927f5a2e963d6f3a063b996c04900a0572d54a6.json => query-05726523bb494b40011c28acd3f52dba1d37493d4c1db4b957cfec476a791b32.json} (75%) rename core/lib/dal/.sqlx/{query-8bfc1062633c037d641b4ab152c5df588a9bd57b7584db28f77caf8003fe6755.json => query-16d4658899c5b604fb794d44a8b3bef013ad12b66bdca7251be2af21e98fe870.json} (75%) rename core/lib/dal/.sqlx/{query-4f2e93503f54803ec9de902656ed7b1461b0732be2cfce8304a82958fa9037ea.json => query-34910600545933d85931d41bfe2dfcb3522a0772ac3d2476652df4216d823e04.json} (50%) rename core/lib/dal/.sqlx/{query-bef01c5f00d0e0c62856420db30e1b53a533d22680efbc6d630a1164f131fa12.json => query-4f5f59bc6fd27bb73c6020b6f0be7ca0e4b83f50724a0b18256aafab69909a98.json} (85%) rename core/lib/dal/.sqlx/{query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json => query-51d5b6fd147fa06ddadb5f8c9c0e12784694d2f8fe9a67159ad4c7abc2279ca6.json} (83%) rename core/lib/dal/.sqlx/{query-9919665c4ca602ed0a1cfe4189963d0ae1ebcfa7e2ebf62d3de242d60461805a.json => query-7240ff1240a2cdae14ab1bbfaad97f64d0c9620506bb41890548181bccca9ee5.json} (75%) rename core/lib/dal/.sqlx/{query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json => query-7cceb18485c0fdeed57b7f279debfe9b944b2dd80eb56965a5874ce3168e8c5e.json} (85%) rename core/lib/dal/.sqlx/{query-daf3a21af6fa4f1bbe6a96b665297ca76d7625285c3dd5b4bbc7a552c3b0a59a.json => query-860de4af5c11c3a7c9eb660ec7049749bd5fc78b09578589c26d3017cc6bd192.json} (82%) rename core/lib/dal/.sqlx/{query-d77dded7cf6443fdae1c4fb7cd0be5ca9c04806077469dcf1e111d06fa88711f.json => query-89e53b297b2b1c0dfb263f9175cb70e7a5fe02b60d5d23e4d153190138112c5b.json} (67%) rename core/lib/dal/.sqlx/{query-442f17499b1107202541a4cf76753368087a6acbd49a3c21f9ce06617b42bcb8.json => query-9ece18b3a36cbaeaa99ca3db466b9fabba23fa52a17a54146931476681edbd24.json} (81%) rename core/lib/dal/.sqlx/{query-e1c6086dff77a88c37e67c3d13b2d4523947c23142bc90903271eb7d78040283.json => query-9f2e976278266ae5845c5188c95876eb8a6a508aea04d93342df50dd9745c361.json} (70%) rename core/lib/dal/.sqlx/{query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json => query-a62f400a5b0b66300f5febf762c7e0c8a39a49d1cea78ef771d4c64fbbc16756.json} (84%) rename core/lib/dal/.sqlx/{query-658e9b370f313b80a9af9d7a67ca03d32c5a4672a1593a8d54de42f267594c9f.json => query-a88b113b5dc06ac990a66202b3c05e2c2f10d5cbdb03d02c3c541f7eaa1f58a6.json} (77%) rename core/lib/dal/.sqlx/{query-f306d13321047a32b07b1f5cd75f0474d27b735d2171d22adc04ea0c0cdd15cc.json => query-b037613a81f7b3cb106cf62205feb2d1aa6b398c6981c8d4f35e499f42b01731.json} (82%) rename core/lib/dal/.sqlx/{query-df63982ec7237c5c48260c3bb1585b3cc042113e59f012c4e4e86707b26de0b1.json => query-b23f9879be394270a0985c082fd2e82c5aa84c85b9486e81261d17901a786917.json} (57%) rename core/lib/dal/.sqlx/{query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json => query-bdd9b56fd8505170125d4e1271f865162bce330edd9b16587e8f9fdab17a8456.json} (70%) rename core/lib/dal/.sqlx/{query-9579fa7246839b2f2a65e2fa0886f40849791e1ad74f26cc8da078c8cb871e50.json => query-da1ea91f3a1189f881020a6cec17fc5d8943e65a30508898d90a098432050bc7.json} (80%) rename core/lib/dal/.sqlx/{query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json => query-f208ac4d454220cdd5cf8fa1405b21ca4cc94c38a7d18023ef1e89de484e60d8.json} (85%) rename core/lib/dal/.sqlx/{query-ced6cdde93462a2ba0df00877f0201a76429e315fd6d7cc6561072c433696410.json => query-f81c5b92cac0466af8a2721b44d914f15fd7a5fa3d7f7bc56906817c70b04950.json} (52%) rename core/lib/dal/.sqlx/{query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json => query-f9a47bd5532fc10dd0bc1be2af45b243bb067514b67daaf084353e5ada15b23a.json} (77%) rename core/lib/multivm/src/versions/vm_latest/tests/{evm_simulator.rs => evm_emulator.rs} (96%) diff --git a/core/bin/genesis_generator/src/main.rs b/core/bin/genesis_generator/src/main.rs index 647ea0f8db1b..2a96cdc6c6cc 100644 --- a/core/bin/genesis_generator/src/main.rs +++ b/core/bin/genesis_generator/src/main.rs @@ -87,7 +87,7 @@ async fn generate_new_config( genesis_commitment: None, bootloader_hash: Some(base_system_contracts.bootloader), default_aa_hash: Some(base_system_contracts.default_aa), - evm_simulator_hash: base_system_contracts.evm_simulator, + evm_emulator_hash: base_system_contracts.evm_emulator, ..genesis_config }; diff --git a/core/bin/system-constants-generator/src/utils.rs b/core/bin/system-constants-generator/src/utils.rs index fad10f945438..8d36f7344676 100644 --- a/core/bin/system-constants-generator/src/utils.rs +++ b/core/bin/system-constants-generator/src/utils.rs @@ -78,7 +78,7 @@ pub static GAS_TEST_SYSTEM_CONTRACTS: Lazy = Lazy::new(|| { hash, }, bootloader, - evm_simulator: None, + evm_emulator: None, } }); @@ -223,7 +223,7 @@ pub(super) fn execute_internal_transfer_test() -> u32 { let base_system_smart_contracts = BaseSystemContracts { bootloader, default_aa, - evm_simulator: None, + evm_emulator: None, }; let system_env = SystemEnv { diff --git a/core/lib/config/src/configs/chain.rs b/core/lib/config/src/configs/chain.rs index e24865fabbbd..c117064dbc40 100644 --- a/core/lib/config/src/configs/chain.rs +++ b/core/lib/config/src/configs/chain.rs @@ -138,8 +138,8 @@ pub struct StateKeeperConfig { pub bootloader_hash: Option, #[deprecated(note = "Use GenesisConfig::default_aa_hash instead")] pub default_aa_hash: Option, - #[deprecated(note = "Use GenesisConfig::evm_simulator_hash instead")] - pub evm_simulator_hash: Option, + #[deprecated(note = "Use GenesisConfig::evm_emulator_hash instead")] + pub evm_emulator_hash: Option, #[deprecated(note = "Use GenesisConfig::l1_batch_commit_data_generator_mode instead")] #[serde(default)] pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode, @@ -180,7 +180,7 @@ impl StateKeeperConfig { protective_reads_persistence_enabled: true, bootloader_hash: None, default_aa_hash: None, - evm_simulator_hash: None, + evm_emulator_hash: None, l1_batch_commit_data_generator_mode: L1BatchCommitmentMode::Rollup, } } diff --git a/core/lib/config/src/configs/genesis.rs b/core/lib/config/src/configs/genesis.rs index 3a962b18410d..9e1ffbd87cb5 100644 --- a/core/lib/config/src/configs/genesis.rs +++ b/core/lib/config/src/configs/genesis.rs @@ -17,7 +17,7 @@ pub struct GenesisConfig { pub genesis_commitment: Option, pub bootloader_hash: Option, pub default_aa_hash: Option, - pub evm_simulator_hash: Option, + pub evm_emulator_hash: Option, pub l1_chain_id: L1ChainId, pub sl_chain_id: Option, pub l2_chain_id: L2ChainId, @@ -50,7 +50,7 @@ impl GenesisConfig { genesis_commitment: Some(H256::repeat_byte(0x17)), bootloader_hash: Default::default(), default_aa_hash: Default::default(), - evm_simulator_hash: Default::default(), + evm_emulator_hash: Default::default(), l1_chain_id: L1ChainId(9), sl_chain_id: None, protocol_version: Some(ProtocolSemanticVersion { diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 90c0b3c2a32c..2598650747a2 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -192,7 +192,7 @@ impl Distribution for EncodeDist { fee_account_addr: None, bootloader_hash: None, default_aa_hash: None, - evm_simulator_hash: None, + evm_emulator_hash: None, l1_batch_commit_data_generator_mode: Default::default(), } } @@ -732,7 +732,7 @@ impl Distribution for EncodeDist { genesis_commitment: Some(rng.gen()), bootloader_hash: Some(rng.gen()), default_aa_hash: Some(rng.gen()), - evm_simulator_hash: Some(rng.gen()), + evm_emulator_hash: Some(rng.gen()), fee_account: rng.gen(), l1_chain_id: L1ChainId(self.sample(rng)), sl_chain_id: None, diff --git a/core/lib/contracts/src/lib.rs b/core/lib/contracts/src/lib.rs index 29a0a85504e0..fb28693887a9 100644 --- a/core/lib/contracts/src/lib.rs +++ b/core/lib/contracts/src/lib.rs @@ -305,23 +305,23 @@ pub struct SystemContractCode { pub struct BaseSystemContracts { pub bootloader: SystemContractCode, pub default_aa: SystemContractCode, - /// Never filled in constructors for now. The only way to get the EVM simulator enabled is to call [`Self::with_evm_simulator()`]. - pub evm_simulator: Option, + /// Never filled in constructors for now. The only way to get the EVM emulator enabled is to call [`Self::with_evm_emulator()`]. + pub evm_emulator: Option, } #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)] pub struct BaseSystemContractsHashes { pub bootloader: H256, pub default_aa: H256, - pub evm_simulator: Option, + pub evm_emulator: Option, } impl PartialEq for BaseSystemContracts { fn eq(&self, other: &Self) -> bool { self.bootloader.hash == other.bootloader.hash && self.default_aa.hash == other.default_aa.hash - && self.evm_simulator.as_ref().map(|contract| contract.hash) - == other.evm_simulator.as_ref().map(|contract| contract.hash) + && self.evm_emulator.as_ref().map(|contract| contract.hash) + == other.evm_emulator.as_ref().map(|contract| contract.hash) } } @@ -345,7 +345,7 @@ impl BaseSystemContracts { BaseSystemContracts { bootloader, default_aa, - evm_simulator: None, + evm_emulator: None, } } @@ -355,11 +355,11 @@ impl BaseSystemContracts { BaseSystemContracts::load_with_bootloader(bootloader_bytecode) } - /// Loads the latest EVM simulator for these base system contracts. Logically, it only makes sense to do for the latest protocol version. - pub fn with_latest_evm_simulator(mut self) -> Self { + /// Loads the latest EVM emulator for these base system contracts. Logically, it only makes sense to do for the latest protocol version. + pub fn with_latest_evm_emulator(mut self) -> Self { let bytecode = read_sys_contract_bytecode("", "EvmInterpreter", ContractLanguage::Yul); let hash = hash_bytecode(&bytecode); - self.evm_simulator = Some(SystemContractCode { + self.evm_emulator = Some(SystemContractCode { code: bytes_to_be_words(bytecode), hash, }); @@ -494,7 +494,7 @@ impl BaseSystemContracts { BaseSystemContractsHashes { bootloader: self.bootloader.hash, default_aa: self.default_aa.hash, - evm_simulator: self.evm_simulator.as_ref().map(|contract| contract.hash), + evm_emulator: self.evm_emulator.as_ref().map(|contract| contract.hash), } } } diff --git a/core/lib/dal/.sqlx/query-5e3dc38cfdf6635a91c6c31e8927f5a2e963d6f3a063b996c04900a0572d54a6.json b/core/lib/dal/.sqlx/query-05726523bb494b40011c28acd3f52dba1d37493d4c1db4b957cfec476a791b32.json similarity index 75% rename from core/lib/dal/.sqlx/query-5e3dc38cfdf6635a91c6c31e8927f5a2e963d6f3a063b996c04900a0572d54a6.json rename to core/lib/dal/.sqlx/query-05726523bb494b40011c28acd3f52dba1d37493d4c1db4b957cfec476a791b32.json index 9c1a3a25a30c..c93e6aef3e7c 100644 --- a/core/lib/dal/.sqlx/query-5e3dc38cfdf6635a91c6c31e8927f5a2e963d6f3a063b996c04900a0572d54a6.json +++ b/core/lib/dal/.sqlx/query-05726523bb494b40011c28acd3f52dba1d37493d4c1db4b957cfec476a791b32.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n system_logs,\n compressed_state_diffs,\n protocol_version,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n (\n SELECT\n l1_batches.*,\n ROW_NUMBER() OVER (\n ORDER BY\n number ASC\n ) AS row_number\n FROM\n l1_batches\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND l1_batches.skip_proof = TRUE\n AND l1_batches.number > $1\n ORDER BY\n number\n LIMIT\n $2\n ) inn\n LEFT JOIN commitments ON commitments.l1_batch_number = inn.number\n WHERE\n number - row_number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n system_logs,\n compressed_state_diffs,\n protocol_version,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n (\n SELECT\n l1_batches.*,\n ROW_NUMBER() OVER (\n ORDER BY\n number ASC\n ) AS row_number\n FROM\n l1_batches\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND l1_batches.skip_proof = TRUE\n AND l1_batches.number > $1\n ORDER BY\n number\n LIMIT\n $2\n ) inn\n LEFT JOIN commitments ON commitments.l1_batch_number = inn.number\n WHERE\n number - row_number = $1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -175,5 +175,5 @@ true ] }, - "hash": "5e3dc38cfdf6635a91c6c31e8927f5a2e963d6f3a063b996c04900a0572d54a6" + "hash": "05726523bb494b40011c28acd3f52dba1d37493d4c1db4b957cfec476a791b32" } diff --git a/core/lib/dal/.sqlx/query-8bfc1062633c037d641b4ab152c5df588a9bd57b7584db28f77caf8003fe6755.json b/core/lib/dal/.sqlx/query-16d4658899c5b604fb794d44a8b3bef013ad12b66bdca7251be2af21e98fe870.json similarity index 75% rename from core/lib/dal/.sqlx/query-8bfc1062633c037d641b4ab152c5df588a9bd57b7584db28f77caf8003fe6755.json rename to core/lib/dal/.sqlx/query-16d4658899c5b604fb794d44a8b3bef013ad12b66bdca7251be2af21e98fe870.json index 3014cb772fa0..a3d356f4bea9 100644 --- a/core/lib/dal/.sqlx/query-8bfc1062633c037d641b4ab152c5df588a9bd57b7584db28f77caf8003fe6755.json +++ b/core/lib/dal/.sqlx/query-16d4658899c5b604fb794d44a8b3bef013ad12b66bdca7251be2af21e98fe870.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n ORDER BY\n number\n LIMIT\n $4\n ", + "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n ORDER BY\n number\n LIMIT\n $4\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -177,5 +177,5 @@ true ] }, - "hash": "8bfc1062633c037d641b4ab152c5df588a9bd57b7584db28f77caf8003fe6755" + "hash": "16d4658899c5b604fb794d44a8b3bef013ad12b66bdca7251be2af21e98fe870" } diff --git a/core/lib/dal/.sqlx/query-4f2e93503f54803ec9de902656ed7b1461b0732be2cfce8304a82958fa9037ea.json b/core/lib/dal/.sqlx/query-34910600545933d85931d41bfe2dfcb3522a0772ac3d2476652df4216d823e04.json similarity index 50% rename from core/lib/dal/.sqlx/query-4f2e93503f54803ec9de902656ed7b1461b0732be2cfce8304a82958fa9037ea.json rename to core/lib/dal/.sqlx/query-34910600545933d85931d41bfe2dfcb3522a0772ac3d2476652df4216d823e04.json index a783f290946b..35c606bf22bb 100644 --- a/core/lib/dal/.sqlx/query-4f2e93503f54803ec9de902656ed7b1461b0732be2cfce8304a82958fa9037ea.json +++ b/core/lib/dal/.sqlx/query-34910600545933d85931d41bfe2dfcb3522a0772ac3d2476652df4216d823e04.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 ", + "query": "\n INSERT INTO\n miniblocks (\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address,\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 ", "describe": { "columns": [], "parameters": { @@ -27,5 +27,5 @@ }, "nullable": [] }, - "hash": "4f2e93503f54803ec9de902656ed7b1461b0732be2cfce8304a82958fa9037ea" + "hash": "34910600545933d85931d41bfe2dfcb3522a0772ac3d2476652df4216d823e04" } diff --git a/core/lib/dal/.sqlx/query-bef01c5f00d0e0c62856420db30e1b53a533d22680efbc6d630a1164f131fa12.json b/core/lib/dal/.sqlx/query-4f5f59bc6fd27bb73c6020b6f0be7ca0e4b83f50724a0b18256aafab69909a98.json similarity index 85% rename from core/lib/dal/.sqlx/query-bef01c5f00d0e0c62856420db30e1b53a533d22680efbc6d630a1164f131fa12.json rename to core/lib/dal/.sqlx/query-4f5f59bc6fd27bb73c6020b6f0be7ca0e4b83f50724a0b18256aafab69909a98.json index f3f4a299f7d9..752e171f58cb 100644 --- a/core/lib/dal/.sqlx/query-bef01c5f00d0e0c62856420db30e1b53a533d22680efbc6d630a1164f131fa12.json +++ b/core/lib/dal/.sqlx/query-4f5f59bc6fd27bb73c6020b6f0be7ca0e4b83f50724a0b18256aafab69909a98.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n system_logs,\n compressed_state_diffs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n system_logs,\n compressed_state_diffs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -174,5 +174,5 @@ true ] }, - "hash": "bef01c5f00d0e0c62856420db30e1b53a533d22680efbc6d630a1164f131fa12" + "hash": "4f5f59bc6fd27bb73c6020b6f0be7ca0e4b83f50724a0b18256aafab69909a98" } diff --git a/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json b/core/lib/dal/.sqlx/query-51d5b6fd147fa06ddadb5f8c9c0e12784694d2f8fe9a67159ad4c7abc2279ca6.json similarity index 83% rename from core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json rename to core/lib/dal/.sqlx/query-51d5b6fd147fa06ddadb5f8c9c0e12784694d2f8fe9a67159ad4c7abc2279ca6.json index 7b4fa2793dba..6f77a656072b 100644 --- a/core/lib/dal/.sqlx/query-2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb.json +++ b/core/lib/dal/.sqlx/query-51d5b6fd147fa06ddadb5f8c9c0e12784694d2f8fe9a67159ad4c7abc2279ca6.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_simulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n ),\n (\n SELECT\n MAX(l1_batch_number) + 1\n FROM\n snapshot_recovery\n )\n ) AS \"l1_batch_number!\",\n (miniblocks.l1_tx_count + miniblocks.l2_tx_count) AS \"tx_count!\",\n miniblocks.timestamp,\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n miniblocks.evm_emulator_code_hash,\n miniblocks.virtual_blocks,\n miniblocks.hash,\n miniblocks.protocol_version AS \"protocol_version!\",\n miniblocks.fee_account_address AS \"fee_account_address!\"\n FROM\n miniblocks\n WHERE\n miniblocks.number BETWEEN $1 AND $2\n ", "describe": { "columns": [ { @@ -50,7 +50,7 @@ }, { "ordinal": 9, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -97,5 +97,5 @@ false ] }, - "hash": "2060d7de5c06f2fd24b43de6eeca927c5f5b88725987e82cf3ec5d499c5addbb" + "hash": "51d5b6fd147fa06ddadb5f8c9c0e12784694d2f8fe9a67159ad4c7abc2279ca6" } diff --git a/core/lib/dal/.sqlx/query-9919665c4ca602ed0a1cfe4189963d0ae1ebcfa7e2ebf62d3de242d60461805a.json b/core/lib/dal/.sqlx/query-7240ff1240a2cdae14ab1bbfaad97f64d0c9620506bb41890548181bccca9ee5.json similarity index 75% rename from core/lib/dal/.sqlx/query-9919665c4ca602ed0a1cfe4189963d0ae1ebcfa7e2ebf62d3de242d60461805a.json rename to core/lib/dal/.sqlx/query-7240ff1240a2cdae14ab1bbfaad97f64d0c9620506bb41890548181bccca9ee5.json index 3c2788db4642..b2f195c4e5c1 100644 --- a/core/lib/dal/.sqlx/query-9919665c4ca602ed0a1cfe4189963d0ae1ebcfa7e2ebf62d3de242d60461805a.json +++ b/core/lib/dal/.sqlx/query-7240ff1240a2cdae14ab1bbfaad97f64d0c9620506bb41890548181bccca9ee5.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx\n ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx\n ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx\n ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", + "query": "\n SELECT\n miniblocks.number,\n COALESCE(\n miniblocks.l1_batch_number,\n (\n SELECT\n (MAX(number) + 1)\n FROM\n l1_batches\n )\n ) AS \"l1_batch_number!\",\n miniblocks.timestamp,\n miniblocks.l1_tx_count,\n miniblocks.l2_tx_count,\n miniblocks.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n miniblocks.l1_gas_price,\n miniblocks.l2_fair_gas_price,\n miniblocks.fair_pubdata_price,\n miniblocks.bootloader_code_hash,\n miniblocks.default_aa_code_hash,\n l1_batches.evm_emulator_code_hash,\n miniblocks.protocol_version,\n miniblocks.fee_account_address\n FROM\n miniblocks\n LEFT JOIN l1_batches ON miniblocks.l1_batch_number = l1_batches.number\n LEFT JOIN eth_txs_history AS commit_tx\n ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx\n ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx\n ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n miniblocks.number = $1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -132,5 +132,5 @@ false ] }, - "hash": "9919665c4ca602ed0a1cfe4189963d0ae1ebcfa7e2ebf62d3de242d60461805a" + "hash": "7240ff1240a2cdae14ab1bbfaad97f64d0c9620506bb41890548181bccca9ee5" } diff --git a/core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json b/core/lib/dal/.sqlx/query-7cceb18485c0fdeed57b7f279debfe9b944b2dd80eb56965a5874ce3168e8c5e.json similarity index 85% rename from core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json rename to core/lib/dal/.sqlx/query-7cceb18485c0fdeed57b7f279debfe9b944b2dd80eb56965a5874ce3168e8c5e.json index cff8a75aeb98..28fbea09998c 100644 --- a/core/lib/dal/.sqlx/query-42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059.json +++ b/core/lib/dal/.sqlx/query-7cceb18485c0fdeed57b7f279debfe9b944b2dd80eb56965a5874ce3168e8c5e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n system_logs,\n pubdata_input\n FROM\n l1_batches\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n protocol_version,\n system_logs,\n pubdata_input\n FROM\n l1_batches\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -55,7 +55,7 @@ }, { "ordinal": 10, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -96,5 +96,5 @@ true ] }, - "hash": "42ae258b55532b0f814af4e5d39e87dde392c0efa13ecd42becfd0e5db79f059" + "hash": "7cceb18485c0fdeed57b7f279debfe9b944b2dd80eb56965a5874ce3168e8c5e" } diff --git a/core/lib/dal/.sqlx/query-daf3a21af6fa4f1bbe6a96b665297ca76d7625285c3dd5b4bbc7a552c3b0a59a.json b/core/lib/dal/.sqlx/query-860de4af5c11c3a7c9eb660ec7049749bd5fc78b09578589c26d3017cc6bd192.json similarity index 82% rename from core/lib/dal/.sqlx/query-daf3a21af6fa4f1bbe6a96b665297ca76d7625285c3dd5b4bbc7a552c3b0a59a.json rename to core/lib/dal/.sqlx/query-860de4af5c11c3a7c9eb660ec7049749bd5fc78b09578589c26d3017cc6bd192.json index 505e4f5b693b..8f41bf3b4916 100644 --- a/core/lib/dal/.sqlx/query-daf3a21af6fa4f1bbe6a96b665297ca76d7625285c3dd5b4bbc7a552c3b0a59a.json +++ b/core/lib/dal/.sqlx/query-860de4af5c11c3a7c9eb660ec7049749bd5fc78b09578589c26d3017cc6bd192.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND eth_prove_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_commit_tx_id IS NOT NULL\n AND eth_prove_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -174,5 +174,5 @@ true ] }, - "hash": "daf3a21af6fa4f1bbe6a96b665297ca76d7625285c3dd5b4bbc7a552c3b0a59a" + "hash": "860de4af5c11c3a7c9eb660ec7049749bd5fc78b09578589c26d3017cc6bd192" } diff --git a/core/lib/dal/.sqlx/query-d77dded7cf6443fdae1c4fb7cd0be5ca9c04806077469dcf1e111d06fa88711f.json b/core/lib/dal/.sqlx/query-89e53b297b2b1c0dfb263f9175cb70e7a5fe02b60d5d23e4d153190138112c5b.json similarity index 67% rename from core/lib/dal/.sqlx/query-d77dded7cf6443fdae1c4fb7cd0be5ca9c04806077469dcf1e111d06fa88711f.json rename to core/lib/dal/.sqlx/query-89e53b297b2b1c0dfb263f9175cb70e7a5fe02b60d5d23e4d153190138112c5b.json index 9d746d6b00f1..d944b6abf9e1 100644 --- a/core/lib/dal/.sqlx/query-d77dded7cf6443fdae1c4fb7cd0be5ca9c04806077469dcf1e111d06fa88711f.json +++ b/core/lib/dal/.sqlx/query-89e53b297b2b1c0dfb263f9175cb70e7a5fe02b60d5d23e4d153190138112c5b.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_versions.evm_simulator_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_versions.evm_emulator_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": [ { @@ -25,7 +25,7 @@ }, { "ordinal": 4, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -54,5 +54,5 @@ false ] }, - "hash": "d77dded7cf6443fdae1c4fb7cd0be5ca9c04806077469dcf1e111d06fa88711f" + "hash": "89e53b297b2b1c0dfb263f9175cb70e7a5fe02b60d5d23e4d153190138112c5b" } diff --git a/core/lib/dal/.sqlx/query-442f17499b1107202541a4cf76753368087a6acbd49a3c21f9ce06617b42bcb8.json b/core/lib/dal/.sqlx/query-9ece18b3a36cbaeaa99ca3db466b9fabba23fa52a17a54146931476681edbd24.json similarity index 81% rename from core/lib/dal/.sqlx/query-442f17499b1107202541a4cf76753368087a6acbd49a3c21f9ce06617b42bcb8.json rename to core/lib/dal/.sqlx/query-9ece18b3a36cbaeaa99ca3db466b9fabba23fa52a17a54146931476681edbd24.json index da88402c2e52..9eb67bb8299a 100644 --- a/core/lib/dal/.sqlx/query-442f17499b1107202541a4cf76753368087a6acbd49a3c21f9ce06617b42bcb8.json +++ b/core/lib/dal/.sqlx/query-9ece18b3a36cbaeaa99ca3db466b9fabba23fa52a17a54146931476681edbd24.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = 0\n OR eth_commit_tx_id IS NOT NULL\n AND commitment IS NOT NULL\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number = 0\n OR eth_commit_tx_id IS NOT NULL\n AND commitment IS NOT NULL\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -172,5 +172,5 @@ true ] }, - "hash": "442f17499b1107202541a4cf76753368087a6acbd49a3c21f9ce06617b42bcb8" + "hash": "9ece18b3a36cbaeaa99ca3db466b9fabba23fa52a17a54146931476681edbd24" } diff --git a/core/lib/dal/.sqlx/query-e1c6086dff77a88c37e67c3d13b2d4523947c23142bc90903271eb7d78040283.json b/core/lib/dal/.sqlx/query-9f2e976278266ae5845c5188c95876eb8a6a508aea04d93342df50dd9745c361.json similarity index 70% rename from core/lib/dal/.sqlx/query-e1c6086dff77a88c37e67c3d13b2d4523947c23142bc90903271eb7d78040283.json rename to core/lib/dal/.sqlx/query-9f2e976278266ae5845c5188c95876eb8a6a508aea04d93342df50dd9745c361.json index f5d0ec5560f8..55d56cc4ab00 100644 --- a/core/lib/dal/.sqlx/query-e1c6086dff77a88c37e67c3d13b2d4523947c23142bc90903271eb7d78040283.json +++ b/core/lib/dal/.sqlx/query-9f2e976278266ae5845c5188c95876eb8a6a508aea04d93342df50dd9745c361.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n LEFT JOIN\n data_availability\n ON data_availability.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n AND events_queue_commitment IS NOT NULL\n AND bootloader_initial_content_commitment IS NOT NULL\n AND (\n data_availability.inclusion_data IS NOT NULL\n OR $4 IS FALSE\n )\n ORDER BY\n number\n LIMIT\n $5\n ", + "query": "\n SELECT\n number,\n l1_batches.timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n LEFT JOIN\n data_availability\n ON data_availability.l1_batch_number = l1_batches.number\n JOIN protocol_versions ON protocol_versions.id = l1_batches.protocol_version\n WHERE\n eth_commit_tx_id IS NULL\n AND number != 0\n AND protocol_versions.bootloader_code_hash = $1\n AND protocol_versions.default_account_code_hash = $2\n AND commitment IS NOT NULL\n AND (\n protocol_versions.id = $3\n OR protocol_versions.upgrade_tx_hash IS NULL\n )\n AND events_queue_commitment IS NOT NULL\n AND bootloader_initial_content_commitment IS NOT NULL\n AND (\n data_availability.inclusion_data IS NOT NULL\n OR $4 IS FALSE\n )\n ORDER BY\n number\n LIMIT\n $5\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -178,5 +178,5 @@ true ] }, - "hash": "e1c6086dff77a88c37e67c3d13b2d4523947c23142bc90903271eb7d78040283" + "hash": "9f2e976278266ae5845c5188c95876eb8a6a508aea04d93342df50dd9745c361" } diff --git a/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json b/core/lib/dal/.sqlx/query-a62f400a5b0b66300f5febf762c7e0c8a39a49d1cea78ef771d4c64fbbc16756.json similarity index 84% rename from core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json rename to core/lib/dal/.sqlx/query-a62f400a5b0b66300f5febf762c7e0c8a39a49d1cea78ef771d4c64fbbc16756.json index 16f258cf3047..c8c438295e49 100644 --- a/core/lib/dal/.sqlx/query-3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709.json +++ b/core/lib/dal/.sqlx/query-a62f400a5b0b66300f5febf762c7e0c8a39a49d1cea78ef771d4c64fbbc16756.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n ORDER BY\n number DESC\n LIMIT\n 1\n ", "describe": { "columns": [ { @@ -65,7 +65,7 @@ }, { "ordinal": 12, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -118,5 +118,5 @@ true ] }, - "hash": "3a7b285d40bf7aaa8f6251f69a4e3a6f0a2de9a615e50a94d98d18e47621c709" + "hash": "a62f400a5b0b66300f5febf762c7e0c8a39a49d1cea78ef771d4c64fbbc16756" } diff --git a/core/lib/dal/.sqlx/query-658e9b370f313b80a9af9d7a67ca03d32c5a4672a1593a8d54de42f267594c9f.json b/core/lib/dal/.sqlx/query-a88b113b5dc06ac990a66202b3c05e2c2f10d5cbdb03d02c3c541f7eaa1f58a6.json similarity index 77% rename from core/lib/dal/.sqlx/query-658e9b370f313b80a9af9d7a67ca03d32c5a4672a1593a8d54de42f267594c9f.json rename to core/lib/dal/.sqlx/query-a88b113b5dc06ac990a66202b3c05e2c2f10d5cbdb03d02c3c541f7eaa1f58a6.json index a23a90d2ada5..28ffcc5ae468 100644 --- a/core/lib/dal/.sqlx/query-658e9b370f313b80a9af9d7a67ca03d32c5a4672a1593a8d54de42f267594c9f.json +++ b/core/lib/dal/.sqlx/query-a88b113b5dc06ac990a66202b3c05e2c2f10d5cbdb03d02c3c541f7eaa1f58a6.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n WITH\n mb AS (\n SELECT\n l1_gas_price,\n l2_fair_gas_price,\n fair_pubdata_price\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n LIMIT\n 1\n )\n \n SELECT\n l1_batches.number,\n l1_batches.timestamp,\n l1_batches.l1_tx_count,\n l1_batches.l2_tx_count,\n l1_batches.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n mb.l1_gas_price,\n mb.l2_fair_gas_price,\n mb.fair_pubdata_price,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_simulator_code_hash\n FROM\n l1_batches\n INNER JOIN mb ON TRUE\n LEFT JOIN eth_txs_history AS commit_tx\n ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx\n ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx\n ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n l1_batches.number = $1\n ", + "query": "\n WITH\n mb AS (\n SELECT\n l1_gas_price,\n l2_fair_gas_price,\n fair_pubdata_price\n FROM\n miniblocks\n WHERE\n l1_batch_number = $1\n LIMIT\n 1\n )\n \n SELECT\n l1_batches.number,\n l1_batches.timestamp,\n l1_batches.l1_tx_count,\n l1_batches.l2_tx_count,\n l1_batches.hash AS \"root_hash?\",\n commit_tx.tx_hash AS \"commit_tx_hash?\",\n commit_tx.confirmed_at AS \"committed_at?\",\n prove_tx.tx_hash AS \"prove_tx_hash?\",\n prove_tx.confirmed_at AS \"proven_at?\",\n execute_tx.tx_hash AS \"execute_tx_hash?\",\n execute_tx.confirmed_at AS \"executed_at?\",\n mb.l1_gas_price,\n mb.l2_fair_gas_price,\n mb.fair_pubdata_price,\n l1_batches.bootloader_code_hash,\n l1_batches.default_aa_code_hash,\n l1_batches.evm_emulator_code_hash\n FROM\n l1_batches\n INNER JOIN mb ON TRUE\n LEFT JOIN eth_txs_history AS commit_tx\n ON (\n l1_batches.eth_commit_tx_id = commit_tx.eth_tx_id\n AND commit_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS prove_tx\n ON (\n l1_batches.eth_prove_tx_id = prove_tx.eth_tx_id\n AND prove_tx.confirmed_at IS NOT NULL\n )\n LEFT JOIN eth_txs_history AS execute_tx\n ON (\n l1_batches.eth_execute_tx_id = execute_tx.eth_tx_id\n AND execute_tx.confirmed_at IS NOT NULL\n )\n WHERE\n l1_batches.number = $1\n ", "describe": { "columns": [ { @@ -85,7 +85,7 @@ }, { "ordinal": 16, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" } ], @@ -114,5 +114,5 @@ true ] }, - "hash": "658e9b370f313b80a9af9d7a67ca03d32c5a4672a1593a8d54de42f267594c9f" + "hash": "a88b113b5dc06ac990a66202b3c05e2c2f10d5cbdb03d02c3c541f7eaa1f58a6" } diff --git a/core/lib/dal/.sqlx/query-f306d13321047a32b07b1f5cd75f0474d27b735d2171d22adc04ea0c0cdd15cc.json b/core/lib/dal/.sqlx/query-b037613a81f7b3cb106cf62205feb2d1aa6b398c6981c8d4f35e499f42b01731.json similarity index 82% rename from core/lib/dal/.sqlx/query-f306d13321047a32b07b1f5cd75f0474d27b735d2171d22adc04ea0c0cdd15cc.json rename to core/lib/dal/.sqlx/query-b037613a81f7b3cb106cf62205feb2d1aa6b398c6981c8d4f35e499f42b01731.json index 74e73f67cd9c..6588ee2f11ef 100644 --- a/core/lib/dal/.sqlx/query-f306d13321047a32b07b1f5cd75f0474d27b735d2171d22adc04ea0c0cdd15cc.json +++ b/core/lib/dal/.sqlx/query-b037613a81f7b3cb106cf62205feb2d1aa6b398c6981c8d4f35e499f42b01731.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number BETWEEN $1 AND $2\n ORDER BY\n number\n LIMIT\n $3\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n number BETWEEN $1 AND $2\n ORDER BY\n number\n LIMIT\n $3\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -176,5 +176,5 @@ true ] }, - "hash": "f306d13321047a32b07b1f5cd75f0474d27b735d2171d22adc04ea0c0cdd15cc" + "hash": "b037613a81f7b3cb106cf62205feb2d1aa6b398c6981c8d4f35e499f42b01731" } diff --git a/core/lib/dal/.sqlx/query-df63982ec7237c5c48260c3bb1585b3cc042113e59f012c4e4e86707b26de0b1.json b/core/lib/dal/.sqlx/query-b23f9879be394270a0985c082fd2e82c5aa84c85b9486e81261d17901a786917.json similarity index 57% rename from core/lib/dal/.sqlx/query-df63982ec7237c5c48260c3bb1585b3cc042113e59f012c4e4e86707b26de0b1.json rename to core/lib/dal/.sqlx/query-b23f9879be394270a0985c082fd2e82c5aa84c85b9486e81261d17901a786917.json index c326ddbc614a..9d9fa72595db 100644 --- a/core/lib/dal/.sqlx/query-df63982ec7237c5c48260c3bb1585b3cc042113e59f012c4e4e86707b26de0b1.json +++ b/core/lib/dal/.sqlx/query-b23f9879be394270a0985c082fd2e82c5aa84c85b9486e81261d17901a786917.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n protocol_versions (\n id,\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash,\n upgrade_tx_hash,\n created_at\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, NOW())\n ON CONFLICT DO NOTHING\n ", + "query": "\n INSERT INTO\n protocol_versions (\n id,\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_emulator_code_hash,\n upgrade_tx_hash,\n created_at\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, NOW())\n ON CONFLICT DO NOTHING\n ", "describe": { "columns": [], "parameters": { @@ -15,5 +15,5 @@ }, "nullable": [] }, - "hash": "df63982ec7237c5c48260c3bb1585b3cc042113e59f012c4e4e86707b26de0b1" + "hash": "b23f9879be394270a0985c082fd2e82c5aa84c85b9486e81261d17901a786917" } diff --git a/core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json b/core/lib/dal/.sqlx/query-bdd9b56fd8505170125d4e1271f865162bce330edd9b16587e8f9fdab17a8456.json similarity index 70% rename from core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json rename to core/lib/dal/.sqlx/query-bdd9b56fd8505170125d4e1271f865162bce330edd9b16587e8f9fdab17a8456.json index 57e92a2dfa3f..2689716c38ac 100644 --- a/core/lib/dal/.sqlx/query-e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554.json +++ b/core/lib/dal/.sqlx/query-bdd9b56fd8505170125d4e1271f865162bce330edd9b16587e8f9fdab17a8456.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", + "query": "\n SELECT\n bootloader_code_hash,\n default_account_code_hash,\n evm_emulator_code_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", "describe": { "columns": [ { @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" } ], @@ -30,5 +30,5 @@ true ] }, - "hash": "e4736015a313f552d6763b9a82c3412e502df24849331486c604fb0d36d99554" + "hash": "bdd9b56fd8505170125d4e1271f865162bce330edd9b16587e8f9fdab17a8456" } diff --git a/core/lib/dal/.sqlx/query-9579fa7246839b2f2a65e2fa0886f40849791e1ad74f26cc8da078c8cb871e50.json b/core/lib/dal/.sqlx/query-da1ea91f3a1189f881020a6cec17fc5d8943e65a30508898d90a098432050bc7.json similarity index 80% rename from core/lib/dal/.sqlx/query-9579fa7246839b2f2a65e2fa0886f40849791e1ad74f26cc8da078c8cb871e50.json rename to core/lib/dal/.sqlx/query-da1ea91f3a1189f881020a6cec17fc5d8943e65a30508898d90a098432050bc7.json index d46a8851e90b..032cf987fc0b 100644 --- a/core/lib/dal/.sqlx/query-9579fa7246839b2f2a65e2fa0886f40849791e1ad74f26cc8da078c8cb871e50.json +++ b/core/lib/dal/.sqlx/query-da1ea91f3a1189f881020a6cec17fc5d8943e65a30508898d90a098432050bc7.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_prove_tx_id IS NOT NULL\n AND eth_execute_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n l1_tx_count,\n l2_tx_count,\n bloom,\n priority_ops_onchain_data,\n hash,\n commitment,\n l2_to_l1_messages,\n used_contract_hashes,\n compressed_initial_writes,\n compressed_repeated_writes,\n l2_l1_merkle_root,\n rollup_last_leaf_index,\n zkporter_is_available,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n aux_data_hash,\n pass_through_data_hash,\n meta_parameters_hash,\n protocol_version,\n compressed_state_diffs,\n system_logs,\n events_queue_commitment,\n bootloader_initial_content_commitment,\n pubdata_input\n FROM\n l1_batches\n LEFT JOIN commitments ON commitments.l1_batch_number = l1_batches.number\n WHERE\n eth_prove_tx_id IS NOT NULL\n AND eth_execute_tx_id IS NULL\n ORDER BY\n number\n LIMIT\n $1\n ", "describe": { "columns": [ { @@ -90,7 +90,7 @@ }, { "ordinal": 17, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -174,5 +174,5 @@ true ] }, - "hash": "9579fa7246839b2f2a65e2fa0886f40849791e1ad74f26cc8da078c8cb871e50" + "hash": "da1ea91f3a1189f881020a6cec17fc5d8943e65a30508898d90a098432050bc7" } diff --git a/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json b/core/lib/dal/.sqlx/query-f208ac4d454220cdd5cf8fa1405b21ca4cc94c38a7d18023ef1e89de484e60d8.json similarity index 85% rename from core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json rename to core/lib/dal/.sqlx/query-f208ac4d454220cdd5cf8fa1405b21ca4cc94c38a7d18023ef1e89de484e60d8.json index 287c69687e53..700352c1a8bf 100644 --- a/core/lib/dal/.sqlx/query-922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e.json +++ b/core/lib/dal/.sqlx/query-f208ac4d454220cdd5cf8fa1405b21ca4cc94c38a7d18023ef1e89de484e60d8.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", + "query": "\n SELECT\n number,\n timestamp,\n hash,\n l1_tx_count,\n l2_tx_count,\n fee_account_address AS \"fee_account_address!\",\n base_fee_per_gas,\n l1_gas_price,\n l2_fair_gas_price,\n gas_per_pubdata_limit,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n protocol_version,\n virtual_blocks,\n fair_pubdata_price,\n gas_limit,\n logs_bloom\n FROM\n miniblocks\n WHERE\n number = $1\n ", "describe": { "columns": [ { @@ -65,7 +65,7 @@ }, { "ordinal": 12, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -120,5 +120,5 @@ true ] }, - "hash": "922dde793d7846594feaf13d475bbbb0aa11d1c974d6ae7c99d83560bb37357e" + "hash": "f208ac4d454220cdd5cf8fa1405b21ca4cc94c38a7d18023ef1e89de484e60d8" } diff --git a/core/lib/dal/.sqlx/query-ced6cdde93462a2ba0df00877f0201a76429e315fd6d7cc6561072c433696410.json b/core/lib/dal/.sqlx/query-f81c5b92cac0466af8a2721b44d914f15fd7a5fa3d7f7bc56906817c70b04950.json similarity index 52% rename from core/lib/dal/.sqlx/query-ced6cdde93462a2ba0df00877f0201a76429e315fd6d7cc6561072c433696410.json rename to core/lib/dal/.sqlx/query-f81c5b92cac0466af8a2721b44d914f15fd7a5fa3d7f7bc56906817c70b04950.json index da2cd5a54ed1..4fe32531a3f1 100644 --- a/core/lib/dal/.sqlx/query-ced6cdde93462a2ba0df00877f0201a76429e315fd6d7cc6561072c433696410.json +++ b/core/lib/dal/.sqlx/query-f81c5b92cac0466af8a2721b44d914f15fd7a5fa3d7f7bc56906817c70b04950.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO\n l1_batches (\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n predicted_commit_gas_cost,\n predicted_prove_gas_cost,\n predicted_execute_gas_cost,\n initial_bootloader_heap_content,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_simulator_code_hash,\n protocol_version,\n system_logs,\n storage_refunds,\n pubdata_costs,\n pubdata_input,\n predicted_circuits_by_type,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 $19,\n $20,\n $21,\n NOW(),\n NOW()\n )\n ", + "query": "\n INSERT INTO\n l1_batches (\n number,\n l1_tx_count,\n l2_tx_count,\n timestamp,\n l2_to_l1_messages,\n bloom,\n priority_ops_onchain_data,\n predicted_commit_gas_cost,\n predicted_prove_gas_cost,\n predicted_execute_gas_cost,\n initial_bootloader_heap_content,\n used_contract_hashes,\n bootloader_code_hash,\n default_aa_code_hash,\n evm_emulator_code_hash,\n protocol_version,\n system_logs,\n storage_refunds,\n pubdata_costs,\n pubdata_input,\n predicted_circuits_by_type,\n created_at,\n updated_at\n )\n VALUES\n (\n $1,\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 $19,\n $20,\n $21,\n NOW(),\n NOW()\n )\n ", "describe": { "columns": [], "parameters": { @@ -30,5 +30,5 @@ }, "nullable": [] }, - "hash": "ced6cdde93462a2ba0df00877f0201a76429e315fd6d7cc6561072c433696410" + "hash": "f81c5b92cac0466af8a2721b44d914f15fd7a5fa3d7f7bc56906817c70b04950" } diff --git a/core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json b/core/lib/dal/.sqlx/query-f9a47bd5532fc10dd0bc1be2af45b243bb067514b67daaf084353e5ada15b23a.json similarity index 77% rename from core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json rename to core/lib/dal/.sqlx/query-f9a47bd5532fc10dd0bc1be2af45b243bb067514b67daaf084353e5ada15b23a.json index 56a31f74b835..1b50a750dacf 100644 --- a/core/lib/dal/.sqlx/query-5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde.json +++ b/core/lib/dal/.sqlx/query-f9a47bd5532fc10dd0bc1be2af45b243bb067514b67daaf084353e5ada15b23a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n id AS \"minor!\",\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_simulator_code_hash,\n upgrade_tx_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", + "query": "\n SELECT\n id AS \"minor!\",\n timestamp,\n bootloader_code_hash,\n default_account_code_hash,\n evm_emulator_code_hash,\n upgrade_tx_hash\n FROM\n protocol_versions\n WHERE\n id = $1\n ", "describe": { "columns": [ { @@ -25,7 +25,7 @@ }, { "ordinal": 4, - "name": "evm_simulator_code_hash", + "name": "evm_emulator_code_hash", "type_info": "Bytea" }, { @@ -48,5 +48,5 @@ true ] }, - "hash": "5b623ec03908aef2f9f4de80ccd108525bf32965ca06e847082c0fc3c54a1dde" + "hash": "f9a47bd5532fc10dd0bc1be2af45b243bb067514b67daaf084353e5ada15b23a" } diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql index 19eb8534a3a6..74ac4e603830 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.down.sql @@ -1,3 +1,3 @@ -ALTER TABLE protocol_versions DROP COLUMN IF EXISTS evm_simulator_code_hash; -ALTER TABLE l1_batches DROP COLUMN IF EXISTS evm_simulator_code_hash; -ALTER TABLE miniblocks DROP COLUMN IF EXISTS evm_simulator_code_hash; +ALTER TABLE protocol_versions DROP COLUMN IF EXISTS evm_emulator_code_hash; +ALTER TABLE l1_batches DROP COLUMN IF EXISTS evm_emulator_code_hash; +ALTER TABLE miniblocks DROP COLUMN IF EXISTS evm_emulator_code_hash; diff --git a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql index 426a7a1ac723..43ae361e7ee2 100644 --- a/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql +++ b/core/lib/dal/migrations/20240911161714_evm-simulator.up.sql @@ -1,4 +1,4 @@ -ALTER TABLE protocol_versions ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; -ALTER TABLE l1_batches ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; +ALTER TABLE protocol_versions ADD COLUMN IF NOT EXISTS evm_emulator_code_hash BYTEA; +ALTER TABLE l1_batches ADD COLUMN IF NOT EXISTS evm_emulator_code_hash BYTEA; -- We need this column in `miniblocks` as well in order to store data for the pending L1 batch -ALTER TABLE miniblocks ADD COLUMN IF NOT EXISTS evm_simulator_code_hash BYTEA; +ALTER TABLE miniblocks ADD COLUMN IF NOT EXISTS evm_emulator_code_hash BYTEA; diff --git a/core/lib/dal/src/blocks_dal.rs b/core/lib/dal/src/blocks_dal.rs index ba24913226b9..59cc557f36ec 100644 --- a/core/lib/dal/src/blocks_dal.rs +++ b/core/lib/dal/src/blocks_dal.rs @@ -325,7 +325,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -367,7 +367,7 @@ impl BlocksDal<'_, '_> { used_contract_hashes, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, protocol_version, system_logs, pubdata_input @@ -612,7 +612,7 @@ impl BlocksDal<'_, '_> { used_contract_hashes, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, protocol_version, system_logs, storage_refunds, @@ -665,7 +665,7 @@ impl BlocksDal<'_, '_> { header.base_system_contracts_hashes.default_aa.as_bytes(), header .base_system_contracts_hashes - .evm_simulator + .evm_emulator .as_ref() .map(H256::as_bytes), header.protocol_version.map(|v| v as i32), @@ -712,7 +712,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -765,7 +765,7 @@ impl BlocksDal<'_, '_> { .as_bytes(), l2_block_header .base_system_contracts_hashes - .evm_simulator + .evm_emulator .as_ref() .map(H256::as_bytes), l2_block_header.protocol_version.map(|v| v as i32), @@ -796,7 +796,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -837,7 +837,7 @@ impl BlocksDal<'_, '_> { gas_per_pubdata_limit, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, protocol_version, virtual_blocks, fair_pubdata_price, @@ -1056,7 +1056,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1243,7 +1243,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1324,7 +1324,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1398,7 +1398,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1526,7 +1526,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, bootloader_code_hash, default_aa_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1591,7 +1591,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, l1_batches.bootloader_code_hash, l1_batches.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, + l1_batches.evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -1670,7 +1670,7 @@ impl BlocksDal<'_, '_> { zkporter_is_available, l1_batches.bootloader_code_hash, l1_batches.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, + l1_batches.evm_emulator_code_hash, aux_data_hash, pass_through_data_hash, meta_parameters_hash, @@ -2721,7 +2721,7 @@ mod tests { } #[tokio::test] - async fn persisting_evm_simulator_hash() { + async fn persisting_evm_emulator_hash() { let pool = ConnectionPool::::test_pool().await; let mut conn = pool.connection().await.unwrap(); @@ -2731,7 +2731,7 @@ mod tests { .unwrap(); let mut l2_block_header = create_l2_block_header(1); - l2_block_header.base_system_contracts_hashes.evm_simulator = Some(H256::repeat_byte(0x23)); + l2_block_header.base_system_contracts_hashes.evm_emulator = Some(H256::repeat_byte(0x23)); conn.blocks_dal() .insert_l2_block(&l2_block_header) .await @@ -2750,7 +2750,7 @@ mod tests { // ...and a sanity check just to be sure assert!(fetched_block_header .base_system_contracts_hashes - .evm_simulator + .evm_emulator .is_some()); } diff --git a/core/lib/dal/src/blocks_web3_dal.rs b/core/lib/dal/src/blocks_web3_dal.rs index 66acaf9868fa..c1a1e6765b69 100644 --- a/core/lib/dal/src/blocks_web3_dal.rs +++ b/core/lib/dal/src/blocks_web3_dal.rs @@ -673,7 +673,7 @@ impl BlocksWeb3Dal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, - l1_batches.evm_simulator_code_hash, + l1_batches.evm_emulator_code_hash, miniblocks.protocol_version, miniblocks.fee_account_address FROM @@ -746,7 +746,7 @@ impl BlocksWeb3Dal<'_, '_> { mb.fair_pubdata_price, l1_batches.bootloader_code_hash, l1_batches.default_aa_code_hash, - l1_batches.evm_simulator_code_hash + l1_batches.evm_emulator_code_hash FROM l1_batches INNER JOIN mb ON TRUE diff --git a/core/lib/dal/src/factory_deps_dal.rs b/core/lib/dal/src/factory_deps_dal.rs index 43a4a01f6e2b..857e2973ae33 100644 --- a/core/lib/dal/src/factory_deps_dal.rs +++ b/core/lib/dal/src/factory_deps_dal.rs @@ -94,7 +94,7 @@ impl FactoryDepsDal<'_, '_> { &mut self, bootloader_hash: H256, default_aa_hash: H256, - evm_simulator_hash: Option, + evm_emulator_hash: Option, ) -> anyhow::Result { let bootloader_bytecode = self .get_sealed_factory_dep(bootloader_hash) @@ -117,16 +117,16 @@ impl FactoryDepsDal<'_, '_> { hash: default_aa_hash, }; - let evm_simulator_code = if let Some(evm_simulator_hash) = evm_simulator_hash { - let evm_simulator_bytecode = self - .get_sealed_factory_dep(evm_simulator_hash) + let evm_emulator_code = if let Some(evm_emulator_hash) = evm_emulator_hash { + let evm_emulator_bytecode = self + .get_sealed_factory_dep(evm_emulator_hash) .await - .context("failed loading evm simulator code")? - .with_context(|| format!("evm simulator code with hash {default_aa_hash:?} should be present in the database"))?; + .context("failed loading EVM emulator code")? + .with_context(|| format!("EVM emulator code with hash {evm_emulator_hash:?} should be present in the database"))?; Some(SystemContractCode { - code: bytes_to_be_words(evm_simulator_bytecode), - hash: evm_simulator_hash, + code: bytes_to_be_words(evm_emulator_bytecode), + hash: evm_emulator_hash, }) } else { None @@ -135,7 +135,7 @@ impl FactoryDepsDal<'_, '_> { Ok(BaseSystemContracts { bootloader: bootloader_code, default_aa: default_aa_code, - evm_simulator: evm_simulator_code, + evm_emulator: evm_emulator_code, }) } diff --git a/core/lib/dal/src/models/storage_block.rs b/core/lib/dal/src/models/storage_block.rs index 71296c87e4ff..7e9a9eca9d41 100644 --- a/core/lib/dal/src/models/storage_block.rs +++ b/core/lib/dal/src/models/storage_block.rs @@ -44,7 +44,7 @@ pub(crate) struct StorageL1BatchHeader { pub used_contract_hashes: serde_json::Value, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub protocol_version: Option, // `system_logs` are introduced as part of boojum and will be absent in all batches generated prior to boojum. @@ -83,7 +83,7 @@ impl StorageL1BatchHeader { base_system_contracts_hashes: convert_base_system_contracts_hashes( self.bootloader_code_hash, self.default_aa_code_hash, - self.evm_simulator_code_hash, + self.evm_emulator_code_hash, ), system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: self @@ -105,7 +105,7 @@ fn convert_l2_to_l1_logs(raw_logs: Vec>) -> Vec { fn convert_base_system_contracts_hashes( bootloader_code_hash: Option>, default_aa_code_hash: Option>, - evm_simulator_code_hash: Option>, + evm_emulator_code_hash: Option>, ) -> BaseSystemContractsHashes { BaseSystemContractsHashes { bootloader: bootloader_code_hash @@ -114,7 +114,7 @@ fn convert_base_system_contracts_hashes( default_aa: default_aa_code_hash .map(|hash| H256::from_slice(&hash)) .expect("should not be none"), - evm_simulator: evm_simulator_code_hash.map(|hash| H256::from_slice(&hash)), + evm_emulator: evm_emulator_code_hash.map(|hash| H256::from_slice(&hash)), } } @@ -138,7 +138,7 @@ pub(crate) struct StorageL1Batch { pub zkporter_is_available: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub l2_to_l1_messages: Vec>, pub l2_l1_merkle_root: Option>, @@ -182,7 +182,7 @@ impl StorageL1Batch { base_system_contracts_hashes: convert_base_system_contracts_hashes( self.bootloader_code_hash, self.default_aa_code_hash, - self.evm_simulator_code_hash, + self.evm_emulator_code_hash, ), system_logs: system_logs.into_iter().map(SystemL2ToL1Log).collect(), protocol_version: self @@ -246,8 +246,8 @@ impl TryFrom for L1BatchMetadata { .default_aa_code_hash .ok_or(L1BatchMetadataError::Incomplete("default_aa_code_hash"))?, ), - evm_simulator_code_hash: batch - .evm_simulator_code_hash + evm_emulator_code_hash: batch + .evm_emulator_code_hash .as_deref() .map(H256::from_slice), protocol_version: batch @@ -285,7 +285,7 @@ pub(crate) struct StorageBlockDetails { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub fee_account_address: Vec, pub protocol_version: Option, } @@ -331,7 +331,7 @@ impl From for api::BlockDetails { base_system_contracts_hashes: convert_base_system_contracts_hashes( details.bootloader_code_hash, details.default_aa_code_hash, - details.evm_simulator_code_hash, + details.evm_emulator_code_hash, ), }; api::BlockDetails { @@ -364,7 +364,7 @@ pub(crate) struct StorageL1BatchDetails { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, } impl From for api::L1BatchDetails { @@ -408,7 +408,7 @@ impl From for api::L1BatchDetails { base_system_contracts_hashes: convert_base_system_contracts_hashes( details.bootloader_code_hash, details.default_aa_code_hash, - details.evm_simulator_code_hash, + details.evm_emulator_code_hash, ), }; api::L1BatchDetails { @@ -432,7 +432,7 @@ pub(crate) struct StorageL2BlockHeader { // L2 gas price assumed in the corresponding batch pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub protocol_version: Option, pub fair_pubdata_price: Option, @@ -486,7 +486,7 @@ impl From for L2BlockHeader { base_system_contracts_hashes: convert_base_system_contracts_hashes( row.bootloader_code_hash, row.default_aa_code_hash, - row.evm_simulator_code_hash, + row.evm_emulator_code_hash, ), gas_per_pubdata_limit: row.gas_per_pubdata_limit as u64, protocol_version, diff --git a/core/lib/dal/src/models/storage_protocol_version.rs b/core/lib/dal/src/models/storage_protocol_version.rs index 3dcb64f1b147..a833236a7b62 100644 --- a/core/lib/dal/src/models/storage_protocol_version.rs +++ b/core/lib/dal/src/models/storage_protocol_version.rs @@ -16,7 +16,7 @@ pub struct StorageProtocolVersion { pub snark_wrapper_vk_hash: Vec, pub bootloader_code_hash: Vec, pub default_account_code_hash: Vec, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, } pub(crate) fn protocol_version_from_storage( @@ -35,8 +35,8 @@ pub(crate) fn protocol_version_from_storage( base_system_contracts_hashes: BaseSystemContractsHashes { bootloader: H256::from_slice(&storage_version.bootloader_code_hash), default_aa: H256::from_slice(&storage_version.default_account_code_hash), - evm_simulator: storage_version - .evm_simulator_code_hash + evm_emulator: storage_version + .evm_emulator_code_hash .as_deref() .map(H256::from_slice), }, @@ -50,7 +50,7 @@ pub struct StorageApiProtocolVersion { pub timestamp: i64, pub bootloader_code_hash: Vec, pub default_account_code_hash: Vec, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub upgrade_tx_hash: Option>, } @@ -67,7 +67,7 @@ impl From for api::ProtocolVersion { H256::from_slice(&storage_protocol_version.bootloader_code_hash), H256::from_slice(&storage_protocol_version.default_account_code_hash), storage_protocol_version - .evm_simulator_code_hash + .evm_emulator_code_hash .as_deref() .map(H256::from_slice), l2_system_upgrade_tx_hash, diff --git a/core/lib/dal/src/models/storage_sync.rs b/core/lib/dal/src/models/storage_sync.rs index a3f2ee9a4f0a..cf7b76d81633 100644 --- a/core/lib/dal/src/models/storage_sync.rs +++ b/core/lib/dal/src/models/storage_sync.rs @@ -22,7 +22,7 @@ pub(crate) struct StorageSyncBlock { pub fair_pubdata_price: Option, pub bootloader_code_hash: Option>, pub default_aa_code_hash: Option>, - pub evm_simulator_code_hash: Option>, + pub evm_emulator_code_hash: Option>, pub fee_account_address: Vec, pub protocol_version: i32, pub virtual_blocks: i64, @@ -76,12 +76,12 @@ impl TryFrom for SyncBlock { .decode_column("bootloader_code_hash")?, default_aa: parse_h256_opt(block.default_aa_code_hash.as_deref()) .decode_column("default_aa_code_hash")?, - evm_simulator: block - .evm_simulator_code_hash + evm_emulator: block + .evm_emulator_code_hash .as_deref() .map(parse_h256) .transpose() - .decode_column("evm_simulator_code_hash")?, + .decode_column("evm_emulator_code_hash")?, }, fee_account_address: parse_h160(&block.fee_account_address) .decode_column("fee_account_address")?, diff --git a/core/lib/dal/src/protocol_versions_dal.rs b/core/lib/dal/src/protocol_versions_dal.rs index 2c415b421bd7..3b500e07a08a 100644 --- a/core/lib/dal/src/protocol_versions_dal.rs +++ b/core/lib/dal/src/protocol_versions_dal.rs @@ -45,7 +45,7 @@ impl ProtocolVersionsDal<'_, '_> { timestamp, bootloader_code_hash, default_account_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, upgrade_tx_hash, created_at ) @@ -58,7 +58,7 @@ impl ProtocolVersionsDal<'_, '_> { base_system_contracts_hashes.bootloader.as_bytes(), base_system_contracts_hashes.default_aa.as_bytes(), base_system_contracts_hashes - .evm_simulator + .evm_emulator .as_ref() .map(H256::as_bytes), tx_hash.as_ref().map(H256::as_bytes), @@ -199,7 +199,7 @@ impl ProtocolVersionsDal<'_, '_> { SELECT bootloader_code_hash, default_account_code_hash, - evm_simulator_code_hash + evm_emulator_code_hash FROM protocol_versions WHERE @@ -218,7 +218,7 @@ impl ProtocolVersionsDal<'_, '_> { .get_base_system_contracts( H256::from_slice(&row.bootloader_code_hash), H256::from_slice(&row.default_account_code_hash), - row.evm_simulator_code_hash.as_deref().map(H256::from_slice), + row.evm_emulator_code_hash.as_deref().map(H256::from_slice), ) .await?; Some(contracts) @@ -239,7 +239,7 @@ impl ProtocolVersionsDal<'_, '_> { protocol_versions.timestamp, protocol_versions.bootloader_code_hash, protocol_versions.default_account_code_hash, - protocol_versions.evm_simulator_code_hash, + protocol_versions.evm_emulator_code_hash, protocol_patches.patch, protocol_patches.snark_wrapper_vk_hash FROM diff --git a/core/lib/dal/src/protocol_versions_web3_dal.rs b/core/lib/dal/src/protocol_versions_web3_dal.rs index 05a93ea1b098..adc3957f8722 100644 --- a/core/lib/dal/src/protocol_versions_web3_dal.rs +++ b/core/lib/dal/src/protocol_versions_web3_dal.rs @@ -21,7 +21,7 @@ impl ProtocolVersionsWeb3Dal<'_, '_> { timestamp, bootloader_code_hash, default_account_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, upgrade_tx_hash FROM protocol_versions diff --git a/core/lib/dal/src/sync_dal.rs b/core/lib/dal/src/sync_dal.rs index 22c72fc4d152..ab5684007d0b 100644 --- a/core/lib/dal/src/sync_dal.rs +++ b/core/lib/dal/src/sync_dal.rs @@ -50,7 +50,7 @@ impl SyncDal<'_, '_> { miniblocks.fair_pubdata_price, miniblocks.bootloader_code_hash, miniblocks.default_aa_code_hash, - miniblocks.evm_simulator_code_hash, + miniblocks.evm_emulator_code_hash, miniblocks.virtual_blocks, miniblocks.hash, miniblocks.protocol_version AS "protocol_version!", diff --git a/core/lib/dal/src/tests/mod.rs b/core/lib/dal/src/tests/mod.rs index 5b2b99ccdee4..bf85008f7b58 100644 --- a/core/lib/dal/src/tests/mod.rs +++ b/core/lib/dal/src/tests/mod.rs @@ -62,7 +62,7 @@ pub(crate) fn create_l1_batch_header(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), - evm_simulator: Some(H256::repeat_byte(43)), + evm_emulator: Some(H256::repeat_byte(43)), }, ProtocolVersionId::latest(), ) diff --git a/core/lib/env_config/src/chain.rs b/core/lib/env_config/src/chain.rs index af244f673c59..a125f3314961 100644 --- a/core/lib/env_config/src/chain.rs +++ b/core/lib/env_config/src/chain.rs @@ -102,7 +102,7 @@ mod tests { default_aa_hash: Some(hash( "0x0100055b041eb28aff6e3a6e0f37c31fd053fc9ef142683b05e5f0aee6934066", )), - evm_simulator_hash: None, + evm_emulator_hash: None, l1_batch_commit_data_generator_mode, max_circuits_per_batch: 24100, protective_reads_persistence_enabled: true, diff --git a/core/lib/env_config/src/genesis.rs b/core/lib/env_config/src/genesis.rs index 6d1927828641..55c79eceb502 100644 --- a/core/lib/env_config/src/genesis.rs +++ b/core/lib/env_config/src/genesis.rs @@ -68,7 +68,7 @@ impl FromEnv for GenesisConfig { genesis_commitment: contracts_config.genesis_batch_commitment, bootloader_hash: state_keeper.bootloader_hash, default_aa_hash: state_keeper.default_aa_hash, - evm_simulator_hash: state_keeper.evm_simulator_hash, + evm_emulator_hash: state_keeper.evm_emulator_hash, // TODO(EVM-676): for now, the settlement layer is always the same as the L1 network l1_chain_id: L1ChainId(network_config.network.chain_id().0), sl_chain_id: Some(network_config.network.chain_id()), diff --git a/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs index 2054bf6a0fc6..433ea1bf1aa7 100644 --- a/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_1_4_2/tests/get_used_contracts.rs @@ -106,7 +106,7 @@ fn known_bytecodes_without_base_system_contracts(vm: &Vm) -> .collect::>(); known_bytecodes_without_base_system_contracts .remove(&h256_to_u256(BASE_SYSTEM_CONTRACTS.default_aa.hash)); - if let Some(evm_simulator) = &BASE_SYSTEM_CONTRACTS.evm_simulator { + if let Some(evm_emulator) = &BASE_SYSTEM_CONTRACTS.evm_emulator { let was_removed = - known_bytecodes_without_base_system_contracts.remove(&h256_to_u256(evm_simulator.hash)); + known_bytecodes_without_base_system_contracts.remove(&h256_to_u256(evm_emulator.hash)); assert!(was_removed); } known_bytecodes_without_base_system_contracts diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index ded1c3b1ed6d..e70f05f85ef2 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -58,7 +58,7 @@ impl Vm { self.system_env.default_validation_computational_gas_limit, self.system_env .base_system_smart_contracts - .evm_simulator + .evm_emulator .is_some(), execution_mode, mem::take(dispatcher), diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs b/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs index c00717b39720..6dd73866adf2 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/tx.rs @@ -59,12 +59,12 @@ impl Vm { tx: Transaction, with_compression: bool, ) { - let use_evm_simulator = self + let use_evm_emulator = self .system_env .base_system_smart_contracts - .evm_simulator + .evm_emulator .is_some(); - let tx = TransactionData::new(tx, use_evm_simulator); + let tx = TransactionData::new(tx, use_evm_emulator); let overhead = tx.overhead_gas(); self.push_raw_transaction(tx, overhead, 0, with_compression); } diff --git a/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs b/core/lib/multivm/src/versions/vm_latest/tests/evm_emulator.rs similarity index 96% rename from core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs rename to core/lib/multivm/src/versions/vm_latest/tests/evm_emulator.rs index 8cf72842655f..ca8157b170d4 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/evm_simulator.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/evm_emulator.rs @@ -40,8 +40,8 @@ fn tracing_evm_contract_deployment() { storage.store_factory_dep(mock_known_code_storage_hash, mock_known_code_storage); let mut system_env = default_system_env(); - // The EVM simulator will not be accessed, so we set it to a dummy value. - system_env.base_system_smart_contracts.evm_simulator = + // The EVM emulator will not be accessed, so we set it to a dummy value. + system_env.base_system_smart_contracts.evm_emulator = Some(system_env.base_system_smart_contracts.default_aa.clone()); let mut vm = VmTesterBuilder::new(HistoryEnabled) .with_system_env(system_env) diff --git a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs index 5d1ccc52a5a4..d7cadc54b442 100644 --- a/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_latest/tests/get_used_contracts.rs @@ -159,9 +159,9 @@ fn known_bytecodes_without_base_system_contracts DefaultExecutionTracer { #[allow(clippy::too_many_arguments)] pub(crate) fn new( computational_gas_limit: u32, - use_evm_simulator: bool, + use_evm_emulator: bool, execution_mode: VmExecutionMode, dispatcher: TracerDispatcher, storage: StoragePtr, @@ -96,7 +96,7 @@ impl DefaultExecutionTracer { pubdata_tracer, ret_from_the_bootloader: None, circuits_tracer: CircuitsTracer::new(), - evm_deploy_tracer: use_evm_simulator.then(EvmDeployTracer::new), + evm_deploy_tracer: use_evm_emulator.then(EvmDeployTracer::new), storage, _phantom: PhantomData, } diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs index fa12e55f5819..90948f2f89fd 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/transaction_data.rs @@ -47,7 +47,7 @@ pub(crate) struct TransactionData { } impl TransactionData { - pub(crate) fn new(execute_tx: Transaction, use_evm_simulator: bool) -> Self { + pub(crate) fn new(execute_tx: Transaction, use_evm_emulator: bool) -> Self { match execute_tx.common_data { ExecuteTransactionCommon::L2(common_data) => { let nonce = U256::from_big_endian(&common_data.nonce.to_be_bytes()); @@ -66,8 +66,8 @@ impl TransactionData { // Transactions with no `contract_address` should be filtered out by the API server, // so this is more of a sanity check. assert!( - use_evm_simulator, - "`execute.contract_address` not set for transaction {:?} with EVM simulation disabled", + use_evm_emulator, + "`execute.contract_address` not set for transaction {:?} with EVM emulation disabled", common_data.hash() ); U256([1, 0, 0, 0]) diff --git a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs index 4a295c31aa1e..cb4b13eecdf0 100644 --- a/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs +++ b/core/lib/multivm/src/versions/vm_latest/types/internals/vm_state.rs @@ -98,9 +98,9 @@ pub(crate) fn new_vm_state( Timestamp(0), ); - if let Some(evm_simulator) = &system_env.base_system_smart_contracts.evm_simulator { + if let Some(evm_emulator) = &system_env.base_system_smart_contracts.evm_emulator { decommittment_processor.populate( - vec![(h256_to_u256(evm_simulator.hash), evm_simulator.code.clone())], + vec![(h256_to_u256(evm_emulator.hash), evm_emulator.code.clone())], Timestamp(0), ); } @@ -124,10 +124,10 @@ pub(crate) fn new_vm_state( Timestamp(0), ); - // By convention, default AA is used as a fallback if the EVM simulator is not available. - let evm_simulator_code_hash = system_env + // By convention, default AA is used as a fallback if the EVM emulator is not available. + let evm_emulator_code_hash = system_env .base_system_smart_contracts - .evm_simulator + .evm_emulator .as_ref() .unwrap_or(&system_env.base_system_smart_contracts.default_aa) .hash; @@ -142,7 +142,7 @@ pub(crate) fn new_vm_state( default_aa_code_hash: h256_to_u256( system_env.base_system_smart_contracts.default_aa.hash, ), - evm_simulator_code_hash: h256_to_u256(evm_simulator_code_hash), + evm_simulator_code_hash: h256_to_u256(evm_emulator_code_hash), zkporter_is_available: system_env.zk_porter_available, }, ); diff --git a/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs b/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs index aeba735dcba7..ed532f89dbc6 100644 --- a/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs +++ b/core/lib/multivm/src/versions/vm_latest/utils/transaction_encoding.rs @@ -10,7 +10,7 @@ pub trait TransactionVmExt { impl TransactionVmExt for Transaction { fn bootloader_encoding_size(&self) -> usize { - // Since we want to just measure the encoding size, `use_evm_simulator` arg doesn't matter here, + // Since we want to just measure the encoding size, `use_evm_emulator` arg doesn't matter here, // so we use a more lenient option. let transaction_data = TransactionData::new(self.clone(), true); transaction_data.into_tokens().len() diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs index 8f8678167667..e95bb33d4831 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/tests/get_used_contracts.rs @@ -97,7 +97,7 @@ fn known_bytecodes_without_base_system_contracts, pub default_account_code_hash: U256, #[serde(default, skip_serializing_if = "Option::is_none")] - pub evm_simulator_code_hash: Option, + pub evm_emulator_code_hash: Option, pub storage_refunds: Vec, pub pubdata_costs: Vec, pub witness_block_state: WitnessStorageState, diff --git a/core/lib/tee_verifier/src/lib.rs b/core/lib/tee_verifier/src/lib.rs index 10d013ae02e2..86b563f823e8 100644 --- a/core/lib/tee_verifier/src/lib.rs +++ b/core/lib/tee_verifier/src/lib.rs @@ -306,7 +306,7 @@ mod tests { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: None, + evm_emulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/lib/types/src/api/mod.rs b/core/lib/types/src/api/mod.rs index ef9a7dad26fd..103b6de1fb38 100644 --- a/core/lib/types/src/api/mod.rs +++ b/core/lib/types/src/api/mod.rs @@ -652,9 +652,9 @@ pub struct ProtocolVersion { /// Default account code hash #[serde(rename = "defaultAccountCodeHash")] pub default_account_code_hash: Option, - /// Evm simulator code hash + /// EVM emulator code hash #[serde(rename = "evmSimulatorCodeHash")] - pub evm_simulator_code_hash: Option, + pub evm_emulator_code_hash: Option, /// L2 Upgrade transaction hash #[deprecated] pub l2_system_upgrade_tx_hash: Option, @@ -670,7 +670,7 @@ impl ProtocolVersion { timestamp: u64, bootloader_code_hash: H256, default_account_code_hash: H256, - evm_simulator_code_hash: Option, + evm_emulator_code_hash: Option, l2_system_upgrade_tx_hash: Option, ) -> Self { Self { @@ -681,11 +681,11 @@ impl ProtocolVersion { base_system_contracts: Some(BaseSystemContractsHashes { bootloader: bootloader_code_hash, default_aa: default_account_code_hash, - evm_simulator: evm_simulator_code_hash, + evm_emulator: evm_emulator_code_hash, }), bootloader_code_hash: Some(bootloader_code_hash), default_account_code_hash: Some(default_account_code_hash), - evm_simulator_code_hash, + evm_emulator_code_hash, l2_system_upgrade_tx_hash, l2_system_upgrade_tx_hash_new: l2_system_upgrade_tx_hash, } @@ -701,10 +701,10 @@ impl ProtocolVersion { .or_else(|| self.base_system_contracts.map(|hashes| hashes.default_aa)) } - pub fn evm_simulator_code_hash(&self) -> Option { - self.evm_simulator_code_hash.or_else(|| { + pub fn evm_emulator_code_hash(&self) -> Option { + self.evm_emulator_code_hash.or_else(|| { self.base_system_contracts - .and_then(|hashes| hashes.evm_simulator) + .and_then(|hashes| hashes.evm_emulator) }) } @@ -930,7 +930,7 @@ mod tests { base_system_contracts: Some(Default::default()), bootloader_code_hash: Some(Default::default()), default_account_code_hash: Some(Default::default()), - evm_simulator_code_hash: Some(Default::default()), + evm_emulator_code_hash: Some(Default::default()), l2_system_upgrade_tx_hash: Default::default(), l2_system_upgrade_tx_hash_new: Default::default(), }; diff --git a/core/lib/types/src/commitment/mod.rs b/core/lib/types/src/commitment/mod.rs index 1c823d7fee1b..759ee8947ba9 100644 --- a/core/lib/types/src/commitment/mod.rs +++ b/core/lib/types/src/commitment/mod.rs @@ -467,7 +467,7 @@ pub struct L1BatchMetaParameters { pub zkporter_is_available: bool, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, - pub evm_simulator_code_hash: Option, + pub evm_emulator_code_hash: Option, pub protocol_version: Option, } @@ -483,10 +483,10 @@ impl L1BatchMetaParameters { .protocol_version .map_or(false, |ver| ver.is_post_1_5_0()) { - let evm_simulator_code_hash = self - .evm_simulator_code_hash + let evm_emulator_code_hash = self + .evm_emulator_code_hash .unwrap_or(self.default_aa_code_hash); - result.extend(evm_simulator_code_hash.as_bytes()); + result.extend(evm_emulator_code_hash.as_bytes()); } result } @@ -553,7 +553,7 @@ impl L1BatchCommitment { zkporter_is_available: ZKPORTER_IS_AVAILABLE, bootloader_code_hash: input.common().bootloader_code_hash, default_aa_code_hash: input.common().default_aa_code_hash, - evm_simulator_code_hash: input.common().evm_simulator_code_hash, + evm_emulator_code_hash: input.common().evm_emulator_code_hash, protocol_version: Some(input.common().protocol_version), }; @@ -656,7 +656,7 @@ pub struct CommitmentCommonInput { pub rollup_root_hash: H256, pub bootloader_code_hash: H256, pub default_aa_code_hash: H256, - pub evm_simulator_code_hash: Option, + pub evm_emulator_code_hash: Option, pub protocol_version: ProtocolVersionId, } @@ -697,7 +697,7 @@ impl CommitmentInput { rollup_root_hash, bootloader_code_hash: base_system_contracts_hashes.bootloader, default_aa_code_hash: base_system_contracts_hashes.default_aa, - evm_simulator_code_hash: base_system_contracts_hashes.evm_simulator, + evm_emulator_code_hash: base_system_contracts_hashes.evm_emulator, protocol_version, }; if protocol_version.is_pre_boojum() { diff --git a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json index 15d34a21b0f7..4e8c0e0814a0 100644 --- a/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json +++ b/core/lib/types/src/commitment/tests/post_boojum_1_5_0_test_with_evm.json @@ -16,7 +16,7 @@ "rollup_root_hash": "0xe47f013d1ecd4ce53b6872f6b762670b393815e7ddacdf2b0886af9c7f3a555b", "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", + "evm_emulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "system_logs": [ @@ -275,7 +275,7 @@ "zkporter_is_available": false, "bootloader_code_hash": "0x010007ed0e328b940e241f7666a6303b7ffd4e3fd7e8c154d6e7556befe6cd6d", "default_aa_code_hash": "0x0100055b7a8be90522251be8be1a186464d056462973502ac8a0437c85e4d2a9", - "evm_simulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", + "evm_emulator_code_hash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", "protocol_version": "Version23" }, "auxiliary_output": { diff --git a/core/lib/types/src/l2/mod.rs b/core/lib/types/src/l2/mod.rs index f08fd72f66a8..48e813e571d2 100644 --- a/core/lib/types/src/l2/mod.rs +++ b/core/lib/types/src/l2/mod.rs @@ -216,7 +216,7 @@ impl L2Tx { let raw = req.get_signed_bytes(&sig).context("get_signed_bytes")?; let (req, hash) = TransactionRequest::from_bytes_unverified(&raw).context("from_bytes_unverified()")?; - // Since we allow users to specify `None` recipient, EVM simulation is implicitly enabled. + // Since we allow users to specify `None` recipient, EVM emulation is implicitly enabled. let mut tx = L2Tx::from_request_unverified(req, true).context("from_request_unverified()")?; tx.set_input(raw, hash); diff --git a/core/lib/types/src/protocol_upgrade.rs b/core/lib/types/src/protocol_upgrade.rs index e67ca7aad289..48f26dfd5c7f 100644 --- a/core/lib/types/src/protocol_upgrade.rs +++ b/core/lib/types/src/protocol_upgrade.rs @@ -62,8 +62,8 @@ pub struct ProtocolUpgrade { pub bootloader_code_hash: Option, /// New default account code hash. pub default_account_code_hash: Option, - /// New evm simulator code hash - pub evm_simulator_code_hash: Option, + /// New EVM emulator code hash + pub evm_emulator_code_hash: Option, /// New verifier params. pub verifier_params: Option, /// New verifier address. @@ -120,7 +120,7 @@ impl ProtocolUpgrade { bootloader_code_hash: (bootloader_hash != H256::zero()).then_some(bootloader_hash), default_account_code_hash: (default_account_hash != H256::zero()) .then_some(default_account_hash), - evm_simulator_code_hash: None, // EVM simulator upgrades are not supported yet + evm_emulator_code_hash: None, // EVM emulator upgrades are not supported yet verifier_params: (upgrade.verifier_params != abi::VerifierParams::default()) .then_some(upgrade.verifier_params.into()), verifier_address: (upgrade.verifier != Address::zero()).then_some(upgrade.verifier), @@ -307,9 +307,9 @@ impl ProtocolVersion { default_aa: upgrade .default_account_code_hash .unwrap_or(self.base_system_contracts_hashes.default_aa), - evm_simulator: upgrade - .evm_simulator_code_hash - .or(self.base_system_contracts_hashes.evm_simulator), + evm_emulator: upgrade + .evm_emulator_code_hash + .or(self.base_system_contracts_hashes.evm_emulator), }, tx: upgrade.tx, } diff --git a/core/lib/types/src/system_contracts.rs b/core/lib/types/src/system_contracts.rs index 88743fdc9b1a..4329680991c8 100644 --- a/core/lib/types/src/system_contracts.rs +++ b/core/lib/types/src/system_contracts.rs @@ -177,11 +177,11 @@ static SYSTEM_CONTRACT_LIST: [(&str, &str, Address, ContractLanguage); 26] = [ ]; /// Gets default set of system contracts, based on Cargo workspace location. -pub fn get_system_smart_contracts(use_evm_simulator: bool) -> Vec { +pub fn get_system_smart_contracts(use_evm_emulator: bool) -> Vec { SYSTEM_CONTRACT_LIST .iter() .filter_map(|(path, name, address, contract_lang)| { - if *name == "EvmGasManager" && !use_evm_simulator { + if *name == "EvmGasManager" && !use_evm_emulator { None } else { Some(DeployedContract { @@ -196,13 +196,13 @@ pub fn get_system_smart_contracts(use_evm_simulator: bool) -> Vec Vec { let repo = SystemContractsRepo { root: path }; SYSTEM_CONTRACT_LIST .iter() .filter_map(|(path, name, address, contract_lang)| { - if *name == "EvmGasManager" && !use_evm_simulator { + if *name == "EvmGasManager" && !use_evm_emulator { None } else { Some(DeployedContract { diff --git a/core/lib/vm_executor/src/oneshot/block.rs b/core/lib/vm_executor/src/oneshot/block.rs index 0052582c6f54..c820ea794fe3 100644 --- a/core/lib/vm_executor/src/oneshot/block.rs +++ b/core/lib/vm_executor/src/oneshot/block.rs @@ -133,11 +133,11 @@ impl BlockInfo { let protocol_version = l2_block_header .protocol_version .unwrap_or(ProtocolVersionId::last_potentially_undefined()); - // We cannot use the EVM simulator mentioned in the block as is because of batch vs playground settings etc. - // Instead, we just check whether any simulator is enabled for a block, and store this binary flag for further use. - let use_evm_simulator = l2_block_header + // We cannot use the EVM emulator mentioned in the block as is because of batch vs playground settings etc. + // Instead, we just check whether EVM emulation in general is enabled for a block, and store this binary flag for further use. + let use_evm_emulator = l2_block_header .base_system_contracts_hashes - .evm_simulator + .evm_emulator .is_some(); Ok(ResolvedBlockInfo { state_l2_block_number, @@ -145,7 +145,7 @@ impl BlockInfo { vm_l1_batch_number, l1_batch_timestamp, protocol_version, - use_evm_simulator, + use_evm_emulator, is_pending: self.is_pending_l2_block(), }) } @@ -159,7 +159,7 @@ pub struct ResolvedBlockInfo { vm_l1_batch_number: L1BatchNumber, l1_batch_timestamp: u64, protocol_version: ProtocolVersionId, - use_evm_simulator: bool, + use_evm_emulator: bool, is_pending: bool, } @@ -173,8 +173,8 @@ impl ResolvedBlockInfo { self.protocol_version } - pub fn use_evm_simulator(&self) -> bool { - self.use_evm_simulator + pub fn use_evm_emulator(&self) -> bool { + self.use_evm_emulator } } @@ -230,7 +230,7 @@ impl OneshotEnvParameters { .base_system_contracts .get_by_protocol_version( resolved_block_info.protocol_version, - resolved_block_info.use_evm_simulator, + resolved_block_info.use_evm_emulator, ) .clone(), bootloader_gas_limit: BATCH_COMPUTATIONAL_GAS_LIMIT, diff --git a/core/lib/vm_executor/src/oneshot/contracts.rs b/core/lib/vm_executor/src/oneshot/contracts.rs index 3b9e54039cfd..0e1fb9b2762f 100644 --- a/core/lib/vm_executor/src/oneshot/contracts.rs +++ b/core/lib/vm_executor/src/oneshot/contracts.rs @@ -29,7 +29,7 @@ impl MultiVMBaseSystemContracts { pub fn get_by_protocol_version( &self, version: ProtocolVersionId, - use_evm_simulator: bool, + use_evm_emulator: bool, ) -> BaseSystemContracts { let base = match version { ProtocolVersionId::Version0 @@ -61,9 +61,9 @@ impl MultiVMBaseSystemContracts { }; let base = base.clone(); - if version.is_post_1_5_0() && use_evm_simulator { - // EVM simulator is not versioned now; the latest version is always checked out - base.with_latest_evm_simulator() + if version.is_post_1_5_0() && use_evm_emulator { + // EVM emulator is not versioned now; the latest version is always checked out + base.with_latest_evm_emulator() } else { base } diff --git a/core/lib/vm_executor/src/storage.rs b/core/lib/vm_executor/src/storage.rs index 87fdd5fcb8a0..fa0e530c1909 100644 --- a/core/lib/vm_executor/src/storage.rs +++ b/core/lib/vm_executor/src/storage.rs @@ -312,7 +312,7 @@ impl L1BatchParamsProvider { .get_base_system_contracts( contract_hashes.bootloader, contract_hashes.default_aa, - contract_hashes.evm_simulator, + contract_hashes.evm_emulator, ) .await .context("failed getting base system contracts")?; diff --git a/core/lib/vm_interface/src/types/outputs/execution_result.rs b/core/lib/vm_interface/src/types/outputs/execution_result.rs index 89e10939704b..018ea075db51 100644 --- a/core/lib/vm_interface/src/types/outputs/execution_result.rs +++ b/core/lib/vm_interface/src/types/outputs/execution_result.rs @@ -122,7 +122,7 @@ pub struct VmExecutionResultAndLogs { pub refunds: Refunds, /// Bytecodes decommitted during VM execution. `None` if not computed by the VM. // FIXME: currently, this is only filled up by `vm_latest`; probably makes sense to narrow down - // to *dynamic* factory deps, so that `HashMap::new()` is a valid value for VMs not supporting EVM simulation. + // to *dynamic* factory deps, so that `HashMap::new()` is a valid value for VMs not supporting EVM emulation. pub new_known_factory_deps: Option>>, } diff --git a/core/node/api_server/src/execution_sandbox/mod.rs b/core/node/api_server/src/execution_sandbox/mod.rs index b5680ae76481..b560d161ab52 100644 --- a/core/node/api_server/src/execution_sandbox/mod.rs +++ b/core/node/api_server/src/execution_sandbox/mod.rs @@ -307,8 +307,8 @@ impl BlockArgs { self.resolved.protocol_version() } - pub fn use_evm_simulator(&self) -> bool { - self.resolved.use_evm_simulator() + pub fn use_evm_emulator(&self) -> bool { + self.resolved.use_evm_emulator() } /// Loads block information from DB. diff --git a/core/node/api_server/src/web3/namespaces/debug.rs b/core/node/api_server/src/web3/namespaces/debug.rs index e22c0d0eebdf..7e99808dbc77 100644 --- a/core/node/api_server/src/web3/namespaces/debug.rs +++ b/core/node/api_server/src/web3/namespaces/debug.rs @@ -262,7 +262,7 @@ impl DebugNamespace { let call = L2Tx::from_request( request.into(), MAX_ENCODED_TX_SIZE, - false, // Even with EVM simulation enabled, calls must specify `to` field + false, // Even with EVM emulation enabled, calls must specify `to` field )?; let vm_permit = self diff --git a/core/node/api_server/src/web3/namespaces/en.rs b/core/node/api_server/src/web3/namespaces/en.rs index 78ee7f1e6cad..721ca985ceb1 100644 --- a/core/node/api_server/src/web3/namespaces/en.rs +++ b/core/node/api_server/src/web3/namespaces/en.rs @@ -177,10 +177,10 @@ impl EnNamespace { genesis_commitment: Some(genesis_batch.metadata.commitment), bootloader_hash: Some(genesis_batch.header.base_system_contracts_hashes.bootloader), default_aa_hash: Some(genesis_batch.header.base_system_contracts_hashes.default_aa), - evm_simulator_hash: genesis_batch + evm_emulator_hash: genesis_batch .header .base_system_contracts_hashes - .evm_simulator, + .evm_emulator, l1_chain_id: self.state.api_config.l1_chain_id, sl_chain_id: Some(self.state.api_config.l1_chain_id.into()), l2_chain_id: self.state.api_config.l2_chain_id, diff --git a/core/node/api_server/src/web3/namespaces/eth.rs b/core/node/api_server/src/web3/namespaces/eth.rs index ee07dc35aaa3..44362dd098e0 100644 --- a/core/node/api_server/src/web3/namespaces/eth.rs +++ b/core/node/api_server/src/web3/namespaces/eth.rs @@ -81,7 +81,7 @@ impl EthNamespace { let tx = L2Tx::from_request( request.into(), self.state.api_config.max_tx_size, - false, // Even with EVM simulation enabled, calls must specify `to` field + false, // Even with EVM emulation enabled, calls must specify `to` field )?; // It is assumed that the previous checks has already enforced that the `max_fee_per_gas` is at most u64. @@ -119,7 +119,7 @@ impl EthNamespace { let mut tx: L2Tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, - block_args.use_evm_simulator(), + block_args.use_evm_emulator(), )?; // The user may not include the proper transaction type during the estimation of diff --git a/core/node/api_server/src/web3/namespaces/zks.rs b/core/node/api_server/src/web3/namespaces/zks.rs index c85c2ee39655..62aca045f581 100644 --- a/core/node/api_server/src/web3/namespaces/zks.rs +++ b/core/node/api_server/src/web3/namespaces/zks.rs @@ -70,7 +70,7 @@ impl ZksNamespace { let mut tx = L2Tx::from_request( request_with_gas_per_pubdata_overridden.into(), self.state.api_config.max_tx_size, - block_args.use_evm_simulator(), + block_args.use_evm_emulator(), )?; // When we're estimating fee, we are trying to deduce values related to fee, so we should @@ -100,7 +100,7 @@ impl ZksNamespace { drop(connection); let tx = L1Tx::from_request( request_with_gas_per_pubdata_overridden, - block_args.use_evm_simulator(), + block_args.use_evm_emulator(), ) .map_err(Web3Error::SerializationError)?; diff --git a/core/node/api_server/src/web3/state.rs b/core/node/api_server/src/web3/state.rs index 7046e60def4a..b7c40c545416 100644 --- a/core/node/api_server/src/web3/state.rs +++ b/core/node/api_server/src/web3/state.rs @@ -272,7 +272,7 @@ impl RpcState { L2Tx::from_request( tx_request, self.api_config.max_tx_size, - block_args.use_evm_simulator(), + block_args.use_evm_emulator(), )?, hash, )) diff --git a/core/node/commitment_generator/src/lib.rs b/core/node/commitment_generator/src/lib.rs index f9235531b813..cf6971b041c6 100644 --- a/core/node/commitment_generator/src/lib.rs +++ b/core/node/commitment_generator/src/lib.rs @@ -176,7 +176,7 @@ impl CommitmentGenerator { rollup_root_hash: tree_data.hash, bootloader_code_hash: header.base_system_contracts_hashes.bootloader, default_aa_code_hash: header.base_system_contracts_hashes.default_aa, - evm_simulator_code_hash: header.base_system_contracts_hashes.evm_simulator, + evm_emulator_code_hash: header.base_system_contracts_hashes.evm_emulator, protocol_version, }; let touched_slots = connection diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs index 270ffb2fef5a..a08d16f456a9 100644 --- a/core/node/eth_sender/src/eth_tx_aggregator.rs +++ b/core/node/eth_sender/src/eth_tx_aggregator.rs @@ -144,13 +144,13 @@ impl EthTxAggregator { } pub(super) async fn get_multicall_data(&mut self) -> Result { - let (calldata, evm_simulator_hash_requested) = self.generate_calldata_for_multicall(); + let (calldata, evm_emulator_hash_requested) = self.generate_calldata_for_multicall(); let args = CallFunctionArgs::new(&self.functions.aggregate3.name, calldata).for_contract( self.l1_multicall3_address, &self.functions.multicall_contract, ); let aggregate3_result: Token = args.call((*self.eth_client).as_ref()).await?; - self.parse_multicall_data(aggregate3_result, evm_simulator_hash_requested) + self.parse_multicall_data(aggregate3_result, evm_emulator_hash_requested) } // Multicall's aggregate function accepts 1 argument - arrays of different contract calls. @@ -223,23 +223,23 @@ impl EthTxAggregator { get_protocol_version_call.into_token(), ]; - let mut evm_simulator_hash_requested = false; - let get_l2_evm_simulator_hash_input = self + let mut evm_emulator_hash_requested = false; + let get_l2_evm_emulator_hash_input = self .functions - .get_evm_simulator_bytecode_hash + .get_evm_emulator_bytecode_hash .as_ref() .and_then(|f| f.encode_input(&[]).ok()); - if let Some(input) = get_l2_evm_simulator_hash_input { + if let Some(input) = get_l2_evm_emulator_hash_input { let call = Multicall3Call { target: self.state_transition_chain_contract, allow_failure: ALLOW_FAILURE, calldata: input, }; token_vec.insert(2, call.into_token()); - evm_simulator_hash_requested = true; + evm_emulator_hash_requested = true; } - (token_vec, evm_simulator_hash_requested) + (token_vec, evm_emulator_hash_requested) } // The role of the method below is to de-tokenize multicall call's result, which is actually a token. @@ -247,7 +247,7 @@ impl EthTxAggregator { pub(super) fn parse_multicall_data( &self, token: Token, - evm_simulator_hash_requested: bool, + evm_emulator_hash_requested: bool, ) -> Result { let parse_error = |tokens: &[Token]| { Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( @@ -256,7 +256,7 @@ impl EthTxAggregator { }; if let Token::Array(call_results) = token { - let number_of_calls = if evm_simulator_hash_requested { 6 } else { 5 }; + let number_of_calls = if evm_emulator_hash_requested { 6 } else { 5 }; // 5 or 6 calls are aggregated in multicall if call_results.len() != number_of_calls { return parse_error(&call_results); @@ -288,19 +288,19 @@ impl EthTxAggregator { } let default_aa = H256::from_slice(&multicall3_default_aa); - let evm_simulator = if evm_simulator_hash_requested { - let multicall3_evm_simulator = + let evm_emulator = if evm_emulator_hash_requested { + let multicall3_evm_emulator = Multicall3Result::from_token(call_results_iterator.next().unwrap())? .return_data; - if multicall3_evm_simulator.len() != 32 { + if multicall3_evm_emulator.len() != 32 { return Err(EthSenderError::Parse(Web3ContractError::InvalidOutputType( format!( - "multicall3 evm simulator hash data is not of the len of 32: {:?}", - multicall3_evm_simulator + "multicall3 EVM emulator hash data is not of the len of 32: {:?}", + multicall3_evm_emulator ), ))); } - Some(H256::from_slice(&multicall3_evm_simulator)) + Some(H256::from_slice(&multicall3_evm_emulator)) } else { None }; @@ -308,7 +308,7 @@ impl EthTxAggregator { let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader, default_aa, - evm_simulator, + evm_emulator, }; call_results_iterator.next().unwrap(); // FIXME: why is this value requested? diff --git a/core/node/eth_sender/src/tests.rs b/core/node/eth_sender/src/tests.rs index e368ebe4559d..9e844a8b8537 100644 --- a/core/node/eth_sender/src/tests.rs +++ b/core/node/eth_sender/src/tests.rs @@ -44,16 +44,15 @@ const COMMITMENT_MODES: [L1BatchCommitmentMode; 2] = [ pub(crate) fn mock_multicall_response(call: &web3::CallRequest) -> Token { let functions = ZkSyncFunctions::default(); - let evm_simulator_getter_signature = functions - .get_evm_simulator_bytecode_hash + let evm_emulator_getter_signature = functions + .get_evm_emulator_bytecode_hash .as_ref() .map(ethabi::Function::short_signature); let bootloader_signature = functions.get_l2_bootloader_bytecode_hash.short_signature(); let default_aa_signature = functions .get_l2_default_account_bytecode_hash .short_signature(); - let evm_simulator_getter_signature = - evm_simulator_getter_signature.as_ref().map(|sig| &sig[..]); + let evm_emulator_getter_signature = evm_emulator_getter_signature.as_ref().map(|sig| &sig[..]); let calldata = &call.data.as_ref().expect("no calldata").0; assert_eq!(calldata[..4], functions.aggregate3.short_signature()); @@ -77,7 +76,7 @@ pub(crate) fn mock_multicall_response(call: &web3::CallRequest) -> Token { selector if selector == default_aa_signature => { vec![2u8; 32] } - selector if Some(selector) == evm_simulator_getter_signature => { + selector if Some(selector) == evm_emulator_getter_signature => { vec![3u8; 32] } selector if selector == functions.get_verifier_params.short_signature() => { @@ -118,7 +117,7 @@ pub(crate) fn default_l1_batch_metadata() -> L1BatchMetadata { zkporter_is_available: false, bootloader_code_hash: H256::default(), default_aa_code_hash: H256::default(), - evm_simulator_code_hash: None, + evm_emulator_code_hash: None, protocol_version: Some(ProtocolVersionId::default()), }, aux_data_hash: H256::default(), @@ -703,7 +702,7 @@ async fn skipped_l1_batch_in_the_middle( #[test_casing(2, [false, true])] #[test_log::test(tokio::test)] -async fn parsing_multicall_data(with_evm_simulator: bool) { +async fn parsing_multicall_data(with_evm_emulator: bool) { let tester = EthSenderTester::new( ConnectionPool::::test_pool().await, vec![100; 100], @@ -727,7 +726,7 @@ async fn parsing_multicall_data(with_evm_simulator: bool) { ), ]), ]; - if with_evm_simulator { + if with_evm_emulator { mock_response.insert( 2, Token::Tuple(vec![Token::Bool(true), Token::Bytes(vec![3u8; 32])]), @@ -737,7 +736,7 @@ async fn parsing_multicall_data(with_evm_simulator: bool) { let parsed = tester .aggregator - .parse_multicall_data(mock_response, with_evm_simulator) + .parse_multicall_data(mock_response, with_evm_emulator) .unwrap(); assert_eq!( parsed.base_system_contracts_hashes.bootloader, @@ -747,10 +746,10 @@ async fn parsing_multicall_data(with_evm_simulator: bool) { parsed.base_system_contracts_hashes.default_aa, H256::repeat_byte(2) ); - let expected_evm_simulator_hash = with_evm_simulator.then(|| H256::repeat_byte(3)); + let expected_evm_emulator_hash = with_evm_emulator.then(|| H256::repeat_byte(3)); assert_eq!( - parsed.base_system_contracts_hashes.evm_simulator, - expected_evm_simulator_hash + parsed.base_system_contracts_hashes.evm_emulator, + expected_evm_emulator_hash ); assert_eq!(parsed.verifier_address, Address::repeat_byte(5)); assert_eq!(parsed.protocol_version_id, ProtocolVersionId::latest()); @@ -843,7 +842,7 @@ async fn get_multicall_data(commitment_mode: L1BatchCommitmentMode) { data.base_system_contracts_hashes.default_aa, H256::repeat_byte(2) ); - assert_eq!(data.base_system_contracts_hashes.evm_simulator, None); + assert_eq!(data.base_system_contracts_hashes.evm_emulator, None); assert_eq!(data.verifier_address, Address::repeat_byte(5)); assert_eq!(data.protocol_version_id, ProtocolVersionId::latest()); } diff --git a/core/node/eth_sender/src/zksync_functions.rs b/core/node/eth_sender/src/zksync_functions.rs index 6779ac24836c..85508c71c03d 100644 --- a/core/node/eth_sender/src/zksync_functions.rs +++ b/core/node/eth_sender/src/zksync_functions.rs @@ -12,7 +12,7 @@ pub(super) struct ZkSyncFunctions { pub(super) get_l2_bootloader_bytecode_hash: Function, pub(super) get_l2_default_account_bytecode_hash: Function, pub(super) get_verifier: Function, - pub(super) get_evm_simulator_bytecode_hash: Option, + pub(super) get_evm_emulator_bytecode_hash: Option, pub(super) get_verifier_params: Function, pub(super) get_protocol_version: Function, @@ -60,7 +60,7 @@ impl Default for ZkSyncFunctions { get_function(&zksync_contract, "getL2BootloaderBytecodeHash"); let get_l2_default_account_bytecode_hash = get_function(&zksync_contract, "getL2DefaultAccountBytecodeHash"); - let get_evm_simulator_bytecode_hash = + let get_evm_emulator_bytecode_hash = get_optional_function(&zksync_contract, "getL2EvmSimulatorBytecodeHash"); let get_verifier = get_function(&zksync_contract, "getVerifier"); let get_verifier_params = get_function(&zksync_contract, "getVerifierParams"); @@ -77,7 +77,7 @@ impl Default for ZkSyncFunctions { post_shared_bridge_execute, get_l2_bootloader_bytecode_hash, get_l2_default_account_bytecode_hash, - get_evm_simulator_bytecode_hash, + get_evm_emulator_bytecode_hash, get_verifier, get_verifier_params, get_protocol_version, diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 5341a460f82a..5c17add2e987 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -104,7 +104,7 @@ impl GenesisParams { default_aa: config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, - evm_simulator: config.evm_simulator_hash, + evm_emulator: config.evm_emulator_hash, }; if base_system_contracts_hashes != base_system_contracts.hashes() { return Err(GenesisError::BaseSystemContractsHashes(Box::new( @@ -126,10 +126,10 @@ impl GenesisParams { pub fn load_genesis_params(config: GenesisConfig) -> Result { let mut base_system_contracts = BaseSystemContracts::load_from_disk(); - if config.evm_simulator_hash.is_some() { - base_system_contracts = base_system_contracts.with_latest_evm_simulator(); + if config.evm_emulator_hash.is_some() { + base_system_contracts = base_system_contracts.with_latest_evm_emulator(); } - let system_contracts = get_system_smart_contracts(config.evm_simulator_hash.is_some()); + let system_contracts = get_system_smart_contracts(config.evm_emulator_hash.is_some()); Self::from_genesis_config(config, base_system_contracts, system_contracts) } @@ -176,7 +176,7 @@ pub fn mock_genesis_config() -> GenesisConfig { genesis_commitment: Some(H256::default()), bootloader_hash: Some(base_system_contracts_hashes.bootloader), default_aa_hash: Some(base_system_contracts_hashes.default_aa), - evm_simulator_hash: base_system_contracts_hashes.evm_simulator, + evm_emulator_hash: base_system_contracts_hashes.evm_emulator, l1_chain_id: L1ChainId(9), sl_chain_id: None, l2_chain_id: L2ChainId::default(), @@ -240,7 +240,7 @@ pub async fn insert_genesis_batch( .config .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, - evm_simulator: genesis_params.config.evm_simulator_hash, + evm_emulator: genesis_params.config.evm_emulator_hash, }; let commitment_input = CommitmentInput::for_genesis_batch( genesis_root_hash, diff --git a/core/node/genesis/src/utils.rs b/core/node/genesis/src/utils.rs index c1c43f654081..6042513537cd 100644 --- a/core/node/genesis/src/utils.rs +++ b/core/node/genesis/src/utils.rs @@ -131,7 +131,7 @@ pub(super) async fn insert_base_system_contracts_to_factory_deps( ) -> Result<(), GenesisError> { let factory_deps = [&contracts.bootloader, &contracts.default_aa] .into_iter() - .chain(contracts.evm_simulator.as_ref()) + .chain(contracts.evm_emulator.as_ref()) .map(|c| (c.hash, be_words_to_bytes(&c.code))) .collect(); diff --git a/core/node/node_sync/src/external_io.rs b/core/node/node_sync/src/external_io.rs index 1972496b048a..7687595740a8 100644 --- a/core/node/node_sync/src/external_io.rs +++ b/core/node/node_sync/src/external_io.rs @@ -345,7 +345,7 @@ impl StateKeeperIO for ExternalIO { let default_account_code_hash = protocol_version .default_account_code_hash() .context("Missing default account code hash")?; - let evm_simulator_code_hash = protocol_version.evm_simulator_code_hash(); + let evm_emulator_code_hash = protocol_version.evm_emulator_code_hash(); let l2_system_upgrade_tx_hash = protocol_version.l2_system_upgrade_tx_hash(); self.pool .connection_tagged("sync_layer") @@ -363,7 +363,7 @@ impl StateKeeperIO for ExternalIO { BaseSystemContractsHashes { bootloader: bootloader_code_hash, default_aa: default_account_code_hash, - evm_simulator: evm_simulator_code_hash, + evm_emulator: evm_emulator_code_hash, }, l2_system_upgrade_tx_hash, ) @@ -377,12 +377,12 @@ impl StateKeeperIO for ExternalIO { .get_base_system_contract(default_account_code_hash, cursor.next_l2_block) .await .with_context(|| format!("cannot fetch default AA code for {protocol_version:?}"))?; - let evm_simulator = if let Some(hash) = evm_simulator_code_hash { + let evm_emulator = if let Some(hash) = evm_emulator_code_hash { Some( self.get_base_system_contract(hash, cursor.next_l2_block) .await .with_context(|| { - format!("cannot fetch EVM simulator code for {protocol_version:?}") + format!("cannot fetch EVM emulator code for {protocol_version:?}") })?, ) } else { @@ -392,7 +392,7 @@ impl StateKeeperIO for ExternalIO { Ok(BaseSystemContracts { bootloader, default_aa, - evm_simulator, + evm_emulator, }) } diff --git a/core/node/node_sync/src/genesis.rs b/core/node/node_sync/src/genesis.rs index 07fb7b423eb0..0ff8d0d448c0 100644 --- a/core/node/node_sync/src/genesis.rs +++ b/core/node/node_sync/src/genesis.rs @@ -38,7 +38,7 @@ async fn create_genesis_params( let base_system_contracts_hashes = BaseSystemContractsHashes { bootloader: config.bootloader_hash.context("Genesis is not finished")?, default_aa: config.default_aa_hash.context("Genesis is not finished")?, - evm_simulator: config.evm_simulator_hash, + evm_emulator: config.evm_emulator_hash, }; if zksync_chain_id != config.l2_chain_id { @@ -49,7 +49,7 @@ async fn create_genesis_params( // Not every of these addresses is guaranteed to be present in the genesis state, but we'll iterate through // them and try to fetch the contract bytecode for each of them. let system_contract_addresses: Vec<_> = - get_system_smart_contracts(config.evm_simulator_hash.is_some()) + get_system_smart_contracts(config.evm_emulator_hash.is_some()) .into_iter() .map(|contract| *contract.account_id.address()) .collect(); @@ -105,7 +105,7 @@ async fn fetch_base_system_contracts( .fetch_system_contract_by_hash(contract_hashes.default_aa) .await? .context("default AA bytecode is missing on main node")?; - let evm_simulator = if let Some(hash) = contract_hashes.evm_simulator { + let evm_emulator = if let Some(hash) = contract_hashes.evm_emulator { let bytes = client .fetch_system_contract_by_hash(hash) .await? @@ -126,6 +126,6 @@ async fn fetch_base_system_contracts( code: zksync_utils::bytes_to_be_words(default_aa_bytecode), hash: contract_hashes.default_aa, }, - evm_simulator, + evm_emulator, }) } diff --git a/core/node/node_sync/src/tests.rs b/core/node/node_sync/src/tests.rs index 620b0331bd8f..3f5791cdf24c 100644 --- a/core/node/node_sync/src/tests.rs +++ b/core/node/node_sync/src/tests.rs @@ -304,7 +304,7 @@ async fn external_io_works_without_local_protocol_version(snapshot_recovery: boo timestamp: snapshot.l2_block_timestamp + 1, bootloader_code_hash: Some(H256::repeat_byte(1)), default_account_code_hash: Some(H256::repeat_byte(1)), - evm_simulator_code_hash: Some(H256::repeat_byte(1)), + evm_emulator_code_hash: Some(H256::repeat_byte(1)), ..api::ProtocolVersion::default() }; client.insert_protocol_version(next_protocol_version.clone()); @@ -349,8 +349,8 @@ async fn external_io_works_without_local_protocol_version(snapshot_recovery: boo assert_eq!( persisted_protocol_version .base_system_contracts_hashes - .evm_simulator, - next_protocol_version.evm_simulator_code_hash + .evm_emulator, + next_protocol_version.evm_emulator_code_hash ); let l2_block = storage diff --git a/core/node/proof_data_handler/src/tests.rs b/core/node/proof_data_handler/src/tests.rs index 61c76b661ea4..8220aef5da0b 100644 --- a/core/node/proof_data_handler/src/tests.rs +++ b/core/node/proof_data_handler/src/tests.rs @@ -62,7 +62,7 @@ async fn request_tee_proof_inputs() { code: vec![U256([1; 4])], hash: H256([1; 32]), }, - evm_simulator: None, + evm_emulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/core/node/test_utils/src/lib.rs b/core/node/test_utils/src/lib.rs index 203067eae718..9eb53994eee5 100644 --- a/core/node/test_utils/src/lib.rs +++ b/core/node/test_utils/src/lib.rs @@ -56,7 +56,7 @@ pub fn create_l1_batch(number: u32) -> L1BatchHeader { BaseSystemContractsHashes { bootloader: H256::repeat_byte(1), default_aa: H256::repeat_byte(42), - evm_simulator: None, + evm_emulator: None, }, ProtocolVersionId::latest(), ); @@ -89,7 +89,7 @@ pub fn create_l1_batch_metadata(number: u32) -> L1BatchMetadata { zkporter_is_available: ZKPORTER_IS_AVAILABLE, bootloader_code_hash: BaseSystemContractsHashes::default().bootloader, default_aa_code_hash: BaseSystemContractsHashes::default().default_aa, - evm_simulator_code_hash: BaseSystemContractsHashes::default().evm_simulator, + evm_emulator_code_hash: BaseSystemContractsHashes::default().evm_emulator, protocol_version: Some(ProtocolVersionId::latest()), }, aux_data_hash: H256::zero(), @@ -219,7 +219,7 @@ impl Snapshot { l2_block, factory_deps: [&contracts.bootloader, &contracts.default_aa] .into_iter() - .chain(contracts.evm_simulator.as_ref()) + .chain(contracts.evm_emulator.as_ref()) .map(|c| (c.hash, zksync_utils::be_words_to_bytes(&c.code))) .collect(), storage_logs, diff --git a/core/node/vm_runner/src/impls/bwip.rs b/core/node/vm_runner/src/impls/bwip.rs index f6ffd8520268..dc94752d9886 100644 --- a/core/node/vm_runner/src/impls/bwip.rs +++ b/core/node/vm_runner/src/impls/bwip.rs @@ -209,10 +209,7 @@ async fn get_updates_manager_witness_input_data( ) -> anyhow::Result { let initial_heap_content = output.batch.final_bootloader_memory.clone().unwrap(); // might be just empty let default_aa = system_env.base_system_smart_contracts.hashes().default_aa; - let evm_simulator = system_env - .base_system_smart_contracts - .hashes() - .evm_simulator; + let evm_emulator = system_env.base_system_smart_contracts.hashes().evm_emulator; let bootloader = system_env.base_system_smart_contracts.hashes().bootloader; let bootloader_code_bytes = connection .factory_deps_dal() @@ -244,18 +241,18 @@ async fn get_updates_manager_witness_input_data( used_bytecodes.insert(account_code_hash, account_bytecode); } - let evm_simulator_code_hash = if let Some(evm_simulator) = evm_simulator { - let evm_simulator_code_hash = h256_to_u256(evm_simulator); - if used_contract_hashes.contains(&evm_simulator_code_hash) { - let simulator_bytecode_bytes = connection + let evm_emulator_code_hash = if let Some(evm_emulator) = evm_emulator { + let evm_emulator_code_hash = h256_to_u256(evm_emulator); + if used_contract_hashes.contains(&evm_emulator_code_hash) { + let evm_emulator_bytecode = connection .factory_deps_dal() - .get_sealed_factory_dep(evm_simulator) + .get_sealed_factory_dep(evm_emulator) .await? .ok_or_else(|| anyhow!("EVM Simulator bytecode should exist"))?; - let evm_simulator_bytecode = bytes_to_chunks(&simulator_bytecode_bytes); - used_bytecodes.insert(evm_simulator_code_hash, evm_simulator_bytecode); + let evm_emulator_bytecode = bytes_to_chunks(&evm_emulator_bytecode); + used_bytecodes.insert(evm_emulator_code_hash, evm_emulator_bytecode); } - Some(evm_simulator_code_hash) + Some(evm_emulator_code_hash) } else { None }; @@ -274,7 +271,7 @@ async fn get_updates_manager_witness_input_data( protocol_version: system_env.version, bootloader_code, default_account_code_hash: account_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, storage_refunds, pubdata_costs, witness_block_state, diff --git a/core/node/vm_runner/src/tests/mod.rs b/core/node/vm_runner/src/tests/mod.rs index 7202f83d5949..575fd59be042 100644 --- a/core/node/vm_runner/src/tests/mod.rs +++ b/core/node/vm_runner/src/tests/mod.rs @@ -322,12 +322,7 @@ async fn store_l1_batches( .iter() .map(|contract| hash_bytecode(&contract.bytecode)) .chain([genesis_params.base_system_contracts().hashes().default_aa]) - .chain( - genesis_params - .base_system_contracts() - .hashes() - .evm_simulator, - ) + .chain(genesis_params.base_system_contracts().hashes().evm_emulator) .map(h256_to_u256) .collect(); diff --git a/core/node/vm_runner/src/tests/output_handler.rs b/core/node/vm_runner/src/tests/output_handler.rs index 9f29209b5212..f57814ea4491 100644 --- a/core/node/vm_runner/src/tests/output_handler.rs +++ b/core/node/vm_runner/src/tests/output_handler.rs @@ -66,7 +66,7 @@ impl OutputHandlerTester { code: vec![], hash: Default::default(), }, - evm_simulator: None, + evm_emulator: None, }, bootloader_gas_limit: 0, execution_mode: TxExecutionMode::VerifyExecute, diff --git a/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol index b0f888e10e0b..5f4de59681fd 100644 --- a/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol +++ b/etc/contracts-test-data/contracts/mock-evm/mock-evm.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; /** * Mock `KnownCodeStorage` counterpart producing `MarkedAsKnown` events and having `publishEVMBytecode` method - * added for EVM simulation, calls to which should be traced by the host. + * added for EVM emulation, calls to which should be traced by the host. */ contract MockKnownCodeStorage { event MarkedAsKnown(bytes32 indexed bytecodeHash, bool indexed sendBytecodeToL1); diff --git a/etc/env/file_based/genesis.yaml b/etc/env/file_based/genesis.yaml index 7ea9322c8452..b7d4ffebcf98 100644 --- a/etc/env/file_based/genesis.yaml +++ b/etc/env/file_based/genesis.yaml @@ -13,5 +13,5 @@ prover: recursion_scheduler_level_vk_hash: 0x14f97b81e54b35fe673d8708cc1a19e1ea5b5e348e12d31e39824ed4f42bbca2 dummy_verifier: true l1_batch_commit_data_generator_mode: Rollup -# Uncomment to enable EVM simulation (requires to run genesis) -# evm_simulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 +# Uncomment to enable EVM emulation (requires to run genesis) +# evm_emulator_hash: 0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91 diff --git a/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs b/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs index d02f84d7f677..a8bc59bd45e5 100644 --- a/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs +++ b/prover/crates/bin/witness_generator/src/rounds/basic_circuits/utils.rs @@ -114,10 +114,10 @@ pub(super) async fn generate_witness( } }; - let evm_simulator_code_hash = input.vm_run_data.evm_simulator_code_hash; - // By convention, default AA is used instead of the EVM simulator if the latter is disabled. - let evm_simulator_code_hash = - evm_simulator_code_hash.unwrap_or(input.vm_run_data.default_account_code_hash); + let evm_emulator_code_hash = input.vm_run_data.evm_emulator_code_hash; + // By convention, default AA is used instead of the EVM emulator if the latter is disabled. + let evm_emulator_code_hash = + evm_emulator_code_hash.unwrap_or(input.vm_run_data.default_account_code_hash); let (scheduler_witness, block_witness) = zkevm_test_harness::external_calls::run( Address::zero(), BOOTLOADER_ADDRESS, @@ -125,7 +125,7 @@ pub(super) async fn generate_witness( bootloader_contents, false, input.vm_run_data.default_account_code_hash, - evm_simulator_code_hash, + evm_emulator_code_hash, input.vm_run_data.used_bytecodes, Vec::default(), MAX_CYCLES_FOR_TX as usize, diff --git a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs index ac79196d3008..41ce906f455b 100644 --- a/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs +++ b/zk_toolbox/crates/config/src/forge_interface/deploy_ecosystem/input.rs @@ -146,7 +146,7 @@ impl DeployL1Config { .diamond_init_minimal_l2_gas_price, bootloader_hash: genesis_config.bootloader_hash.unwrap(), default_aa_hash: genesis_config.default_aa_hash.unwrap(), - evm_simulator_hash: genesis_config.evm_simulator_hash, + evm_emulator_hash: genesis_config.evm_emulator_hash, diamond_init_priority_tx_max_pubdata: initial_deployment_config .diamond_init_priority_tx_max_pubdata, diamond_init_pubdata_pricing_mode: initial_deployment_config @@ -195,7 +195,7 @@ pub struct ContractsDeployL1Config { pub diamond_init_minimal_l2_gas_price: u64, pub bootloader_hash: H256, pub default_aa_hash: H256, - pub evm_simulator_hash: Option, + pub evm_emulator_hash: Option, } #[derive(Debug, Deserialize, Serialize, Clone)]