diff --git a/.gitmodules b/.gitmodules index 445344c3f204..4ef912242537 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "contracts"] path = contracts -url = https://github.com/matter-labs/era-contracts.git +url = https://github.com/matter-labs/era-contracts +branch = consensus_contracts \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ced1b4bf27ef..571b3f4083de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8873,6 +8873,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "hex", "rand 0.8.5", "secrecy", "tempfile", diff --git a/core/node/api_server/src/execution_sandbox/execute.rs b/core/node/api_server/src/execution_sandbox/execute.rs index d15cf7a91439..6402014aa373 100644 --- a/core/node/api_server/src/execution_sandbox/execute.rs +++ b/core/node/api_server/src/execution_sandbox/execute.rs @@ -88,7 +88,7 @@ pub(crate) struct TransactionExecutionOutput { /// Executor of transactions. #[derive(Debug)] -pub(crate) enum TransactionExecutor { +pub enum TransactionExecutor { Real, #[doc(hidden)] // Intended for tests only Mock(MockTransactionExecutor), diff --git a/core/node/api_server/src/execution_sandbox/mod.rs b/core/node/api_server/src/execution_sandbox/mod.rs index 72c6ba9789f5..35790a291489 100644 --- a/core/node/api_server/src/execution_sandbox/mod.rs +++ b/core/node/api_server/src/execution_sandbox/mod.rs @@ -12,10 +12,11 @@ use zksync_types::{ api, fee_model::BatchFeeInput, AccountTreeId, Address, L1BatchNumber, L2BlockNumber, L2ChainId, }; +pub use self::execute::TransactionExecutor; use self::vm_metrics::SandboxStage; pub(super) use self::{ error::SandboxExecutionError, - execute::{TransactionExecutor, TxExecutionArgs}, + execute::TxExecutionArgs, tracers::ApiTracer, validate::ValidationError, vm_metrics::{SubmitTxStage, SANDBOX_METRICS}, @@ -214,7 +215,7 @@ impl BlockStartInfoInner { /// Information about first L1 batch / L2 block in the node storage. #[derive(Debug, Clone)] -pub(crate) struct BlockStartInfo { +pub struct BlockStartInfo { cached_pruning_info: Arc>, max_cache_age: Duration, } @@ -330,7 +331,7 @@ impl BlockStartInfo { } #[derive(Debug, thiserror::Error)] -pub(crate) enum BlockArgsError { +pub enum BlockArgsError { #[error("Block is pruned; first retained block is {0}")] Pruned(L2BlockNumber), #[error("Block is missing, but can appear in the future")] @@ -341,7 +342,7 @@ pub(crate) enum BlockArgsError { /// Information about a block provided to VM. #[derive(Debug, Clone, Copy)] -pub(crate) struct BlockArgs { +pub struct BlockArgs { block_id: api::BlockId, resolved_block_number: L2BlockNumber, l1_batch_timestamp_s: Option, diff --git a/core/node/api_server/src/tx_sender/mod.rs b/core/node/api_server/src/tx_sender/mod.rs index 50b0be541bf0..3465a2a04fbd 100644 --- a/core/node/api_server/src/tx_sender/mod.rs +++ b/core/node/api_server/src/tx_sender/mod.rs @@ -968,7 +968,7 @@ impl TxSender { .await } - pub(super) async fn eth_call( + pub async fn eth_call( &self, block_args: BlockArgs, call_overrides: CallOverrides, diff --git a/core/node/api_server/src/web3/testonly.rs b/core/node/api_server/src/web3/testonly.rs index 0f8c71aa6281..d7579cd71054 100644 --- a/core/node/api_server/src/web3/testonly.rs +++ b/core/node/api_server/src/web3/testonly.rs @@ -19,7 +19,7 @@ use crate::{ const TEST_TIMEOUT: Duration = Duration::from_secs(90); const POLL_INTERVAL: Duration = Duration::from_millis(50); -pub(crate) async fn create_test_tx_sender( +pub async fn create_test_tx_sender( pool: ConnectionPool, l2_chain_id: L2ChainId, tx_executor: TransactionExecutor, diff --git a/core/node/consensus/Cargo.toml b/core/node/consensus/Cargo.toml index 6332ac8c1a9d..445a8a05a18a 100644 --- a/core/node/consensus/Cargo.toml +++ b/core/node/consensus/Cargo.toml @@ -31,13 +31,15 @@ zksync_system_constants.workspace = true zksync_types.workspace = true zksync_utils.workspace = true zksync_web3_decl.workspace = true - +zksync_node_api_server.workspace = true anyhow.workspace = true async-trait.workspace = true secrecy.workspace = true tempfile.workspace = true thiserror.workspace = true tracing.workspace = true +zksync_contracts.workspace = true +hex.workspace = true [dev-dependencies] zksync_node_genesis.workspace = true diff --git a/core/node/consensus/src/storage/mod.rs b/core/node/consensus/src/storage/mod.rs index 6660f75332bc..2bea5218ee62 100644 --- a/core/node/consensus/src/storage/mod.rs +++ b/core/node/consensus/src/storage/mod.rs @@ -18,6 +18,9 @@ pub(crate) use store::*; #[cfg(test)] pub(crate) mod testonly; +#[cfg(test)] +mod tests; +mod vm_reader; #[derive(thiserror::Error, Debug)] pub enum InsertCertificateError { diff --git a/core/node/consensus/src/storage/testonly.rs b/core/node/consensus/src/storage/testonly.rs index 2f632b84a4d5..aae248f63dc2 100644 --- a/core/node/consensus/src/storage/testonly.rs +++ b/core/node/consensus/src/storage/testonly.rs @@ -1,18 +1,24 @@ //! Storage test helpers. use anyhow::Context as _; -use zksync_concurrency::{ctx, error::Wrap as _, time}; +use zksync_concurrency::{ctx, ctx::Ctx, error::Wrap as _, time}; use zksync_consensus_roles::validator; -use zksync_contracts::BaseSystemContracts; +use zksync_contracts::{load_contract, read_bytecode, BaseSystemContracts}; use zksync_dal::CoreDal as _; use zksync_node_genesis::{insert_genesis_batch, mock_genesis_config, GenesisParams}; use zksync_node_test_utils::{recover, snapshot, Snapshot}; +use zksync_state_keeper::testonly::fee; +use zksync_test_account::{Account, TxType}; use zksync_types::{ - commitment::L1BatchWithMetadata, protocol_version::ProtocolSemanticVersion, - system_contracts::get_system_smart_contracts, L1BatchNumber, L2BlockNumber, ProtocolVersionId, + commitment::L1BatchWithMetadata, + ethabi::{Address, Contract, Token}, + protocol_version::ProtocolSemanticVersion, + system_contracts::get_system_smart_contracts, + Execute, L1BatchNumber, L2BlockNumber, L2ChainId, Nonce, ProtocolVersionId, Transaction, U256, }; use super::ConnectionPool; +use crate::testonly::StateKeeper; pub(crate) fn mock_genesis_params(protocol_version: ProtocolVersionId) -> GenesisParams { let mut cfg = mock_genesis_config(); @@ -189,3 +195,110 @@ impl ConnectionPool { Ok(()) } } + +pub struct VMWriter { + pool: ConnectionPool, + node: StateKeeper, + account: Account, +} + +impl VMWriter { + pub fn new(pool: ConnectionPool, node: StateKeeper, account: Account) -> Self { + Self { + pool, + node, + account, + } + } + + pub async fn deploy_and_add_nodes( + &mut self, + ctx: &Ctx, + owner: Address, + nodes: &[&[Token]], + ) -> Address { + let consensus_authority_bytecode = read_bytecode("contracts/l2-contracts/artifacts-zk/contracts/ConsensusAuthority.sol/ConsensusAuthority.json"); + let consensus_authority_contract = load_contract("contracts/l2-contracts/artifacts-zk/contracts/ConsensusAuthority.sol/ConsensusAuthority.json"); + let validator_registry_bytecode = read_bytecode("contracts/l2-contracts/artifacts-zk/contracts/ValidatorRegistry.sol/ValidatorRegistry.json"); + let attester_registry_bytecode = read_bytecode("contracts/l2-contracts/artifacts-zk/contracts/AttesterRegistry.sol/AttesterRegistry.json"); + + let mut txs: Vec = vec![]; + let deploy_tx = self.account.get_deploy_tx_with_factory_deps( + &consensus_authority_bytecode, + Some(&[Token::Address(owner)]), + vec![validator_registry_bytecode, attester_registry_bytecode], + TxType::L2, + ); + txs.push(deploy_tx.tx); + for node in nodes { + let tx = self.gen_tx_add(&consensus_authority_contract, deploy_tx.address, node); + txs.push(tx); + } + txs.push( + self.gen_tx_set_validator_committee(deploy_tx.address, &consensus_authority_contract), + ); + txs.push( + self.gen_tx_set_attester_committee(deploy_tx.address, &consensus_authority_contract), + ); + + self.node.push_block(&txs).await; + self.pool + .wait_for_payload(ctx, self.node.last_block()) + .await + .unwrap(); + + deploy_tx.address + } + + fn gen_tx_add( + &mut self, + contract: &Contract, + contract_address: Address, + input: &[Token], + ) -> Transaction { + let calldata = contract + .function("add") + .unwrap() + .encode_input(input) + .unwrap(); + self.gen_tx(contract_address, calldata) + } + + fn gen_tx_set_validator_committee( + &mut self, + contract_address: Address, + contract: &Contract, + ) -> Transaction { + let calldata = contract + .function("setValidatorCommittee") + .unwrap() + .short_signature() + .to_vec(); + self.gen_tx(contract_address, calldata) + } + + fn gen_tx_set_attester_committee( + &mut self, + contract_address: Address, + contract: &Contract, + ) -> Transaction { + let calldata = contract + .function("setAttesterCommittee") + .unwrap() + .short_signature() + .to_vec(); + self.gen_tx(contract_address, calldata) + } + + fn gen_tx(&mut self, contract_address: Address, calldata: Vec) -> Transaction { + self.account.get_l2_tx_for_execute( + Execute { + contract_address, + calldata, + value: Default::default(), + factory_deps: vec![], + }, + Some(fee(1_000_000)), + ) + } +} diff --git a/core/node/consensus/src/storage/tests.rs b/core/node/consensus/src/storage/tests.rs new file mode 100644 index 000000000000..32e7c074a435 --- /dev/null +++ b/core/node/consensus/src/storage/tests.rs @@ -0,0 +1,98 @@ +use rand::Rng; +use zksync_concurrency::{ctx, scope}; +use zksync_types::{ + api::{BlockId, BlockNumber}, + ethabi::{Address, Token}, + L2ChainId, ProtocolVersionId, U256, +}; + +use crate::storage::ConnectionPool; + +#[tokio::test(flavor = "multi_thread")] +async fn test_vm_reader() { + zksync_concurrency::testonly::abort_on_panic(); + let ctx = &ctx::test_root(&ctx::RealClock); + let rng = &mut ctx.rng(); + + scope::run!(ctx, |ctx, s| async { + let pool = ConnectionPool::test(false, ProtocolVersionId::latest()).await; + let (node, runner) = crate::testonly::StateKeeper::new(ctx, pool.clone()).await?; + let account = runner.account.clone(); + s.spawn_bg(runner.run_real(ctx)); + + let mut writer = super::testonly::VMWriter::new(pool.clone(), node, account.clone()); + + let mut nodes: Vec> = Vec::new(); + let num_nodes = 5; + for _ in 0..num_nodes { + let item = vec![ + Token::Address(Address::random()), + Token::Uint(U256::from(rng.gen::())), + Token::Bytes((0..256).map(|_| rng.gen()).collect()), + Token::Bytes((0..256).map(|_| rng.gen()).collect()), + Token::Uint(U256::from(rng.gen::())), + Token::Bytes((0..256).map(|_| rng.gen()).collect()), + ]; + nodes.push(item); + } + let nodes_ref: Vec<&[Token]> = nodes.iter().map(|v| v.as_slice()).collect(); + let nodes_slice: &[&[Token]] = nodes_ref.as_slice(); + let consensus_authority_address = writer + .deploy_and_add_nodes(ctx, account.address, nodes_slice) + .await; + + let (tx_sender, _) = zksync_node_api_server::web3::testonly::create_test_tx_sender( + pool.0.clone(), + L2ChainId::default(), + zksync_node_api_server::execution_sandbox::TransactionExecutor::Real, + ) + .await; + let block_id = BlockId::Number(BlockNumber::Pending); + let mut reader = super::vm_reader::VMReader::new( + ctx, + block_id, + pool.clone(), + tx_sender.clone(), + consensus_authority_address, + ) + .await; + + let validators = reader.read_validator_committee(ctx, block_id).await; + assert_eq!(validators.len(), num_nodes); + let attesters = reader.read_attester_committee(ctx, block_id).await; + assert_eq!(attesters.len(), num_nodes); + + for i in 0..nodes.len() { + assert_eq!( + nodes[i][0].clone().into_address().unwrap(), + validators[i].node_owner + ); + assert_eq!( + nodes[i][1].clone().into_uint().unwrap().as_usize(), + validators[i].weight + ); + assert_eq!( + nodes[i][2].clone().into_bytes().unwrap(), + validators[i].pub_key + ); + assert_eq!(nodes[i][3].clone().into_bytes().unwrap(), validators[i].pop); + + assert_eq!( + nodes[i][0].clone().into_address().unwrap(), + attesters[i].node_owner + ); + assert_eq!( + nodes[i][4].clone().into_uint().unwrap().as_usize(), + attesters[i].weight + ); + assert_eq!( + nodes[i][5].clone().into_bytes().unwrap(), + attesters[i].pub_key + ); + } + + Ok(()) + }) + .await + .unwrap(); +} diff --git a/core/node/consensus/src/storage/vm_reader.rs b/core/node/consensus/src/storage/vm_reader.rs new file mode 100644 index 000000000000..b993a78e3064 --- /dev/null +++ b/core/node/consensus/src/storage/vm_reader.rs @@ -0,0 +1,341 @@ +use std::time::Duration; + +use zksync_concurrency::ctx::Ctx; +use zksync_contracts::load_contract; +use zksync_node_api_server::{execution_sandbox::BlockStartInfo, tx_sender::TxSender}; +use zksync_system_constants::DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE; +use zksync_types::{ + api::BlockId, + ethabi::{Address, Contract, Function, Token}, + fee::Fee, + l2::L2Tx, + transaction_request::CallOverrides, + Nonce, U256, +}; + +use crate::storage::ConnectionPool; + +pub struct VMReader { + pool: ConnectionPool, + tx_sender: TxSender, + consensus_authority_contract: Contract, + validator_registry_address: Option
, + validator_registry_contract: Contract, + attester_registry_address: Option
, + attester_registry_contract: Contract, +} + +impl VMReader { + pub async fn new( + ctx: &Ctx, + block_id: BlockId, + pool: ConnectionPool, + tx_sender: TxSender, + consensus_authority_address: Address, + ) -> Self { + let consensus_authority_contract = load_contract("contracts/l2-contracts/artifacts-zk/contracts/ConsensusAuthority.sol/ConsensusAuthority.json"); + let validator_registry_contract = load_contract("contracts/l2-contracts/artifacts-zk/contracts/ValidatorRegistry.sol/ValidatorRegistry.json"); + let attester_registry_contract = load_contract("contracts/l2-contracts/artifacts-zk/contracts/AttesterRegistry.sol/AttesterRegistry.json"); + + let mut reader = Self { + pool, + tx_sender, + consensus_authority_contract, + validator_registry_address: None, + validator_registry_contract, + attester_registry_address: None, + attester_registry_contract, + }; + + reader.validator_registry_address = Some( + reader + .read_address( + ctx, + block_id, + consensus_authority_address, + reader + .consensus_authority_contract + .function("validatorRegistry") + .unwrap() + .clone(), + ) + .await, + ); + + reader.attester_registry_address = Some( + reader + .read_address( + ctx, + block_id, + consensus_authority_address, + reader + .consensus_authority_contract + .function("attesterRegistry") + .unwrap() + .clone(), + ) + .await, + ); + + reader + } + + pub async fn read_validator_committee( + &mut self, + ctx: &Ctx, + block_id: BlockId, + ) -> Vec { + let mut validators = vec![]; + let num_committee_validators = self.read_num_committee_validators(ctx, block_id).await; + for i in 0..num_committee_validators { + let committee_validator = self.read_committee_validator(ctx, block_id, i).await; + let validator = self + .read_validator(ctx, block_id, committee_validator.0) + .await; + + validators.push(CommitteeValidator { + node_owner: committee_validator.0, + weight: committee_validator.1, + pub_key: committee_validator.2, + pop: validator.2, + }) + } + + validators + } + + pub async fn read_attester_committee( + &mut self, + ctx: &Ctx, + block_id: BlockId, + ) -> Vec { + let mut attesters = vec![]; + let num_committee_attesters = self.read_num_committee_attesters(ctx, block_id).await; + for i in 0..num_committee_attesters { + let committee_attester = self.read_committee_attester(ctx, block_id, i).await; + let attester = self + .read_attester(ctx, block_id, committee_attester.1) + .await; + + attesters.push(CommitteeAttester { + node_owner: committee_attester.1, + weight: committee_attester.0, + pub_key: attester.1, + }) + } + attesters + } + + async fn read_num_committee_validators(&mut self, ctx: &Ctx, block_id: BlockId) -> usize { + let func = self + .validator_registry_contract + .function("numCommitteeValidators") + .unwrap() + .clone(); + + let tx = self.gen_l2_call_tx( + self.validator_registry_address.unwrap(), + func.short_signature().to_vec(), + ); + + let res = self.eth_call(ctx, block_id, tx).await; + + func.decode_output(&res).unwrap()[0] + .clone() + .into_uint() + .unwrap() + .as_usize() + } + + async fn read_num_committee_attesters(&mut self, ctx: &Ctx, block_id: BlockId) -> usize { + let func = self + .attester_registry_contract + .function("numCommitteeAttesters") + .unwrap() + .clone(); + let tx = self.gen_l2_call_tx( + self.attester_registry_address.unwrap(), + func.short_signature().to_vec(), + ); + + let res = self.eth_call(ctx, block_id, tx).await; + func.decode_output(&res).unwrap()[0] + .clone() + .into_uint() + .unwrap() + .as_usize() + } + + async fn read_validator( + &mut self, + ctx: &Ctx, + block_id: BlockId, + node_owner: zksync_types::ethabi::Address, + ) -> (usize, Vec, Vec, bool) { + let func = self + .validator_registry_contract + .function("validators") + .unwrap() + .clone(); + let tx = self.gen_l2_call_tx( + self.validator_registry_address.unwrap(), + func.encode_input(&[Token::Address(node_owner)]).unwrap(), + ); + let res = self.eth_call(ctx, block_id, tx).await; + let tokens = func.decode_output(&res).unwrap(); + ( + tokens[0].clone().into_uint().unwrap().as_usize(), + tokens[1].clone().into_bytes().unwrap(), + tokens[2].clone().into_bytes().unwrap(), + tokens[3].clone().into_bool().unwrap(), + ) + } + + async fn read_attester( + &mut self, + ctx: &Ctx, + block_id: BlockId, + node_owner: Address, + ) -> (usize, Vec, bool) { + let func = self + .attester_registry_contract + .function("attesters") + .unwrap() + .clone(); + let tx = self.gen_l2_call_tx( + self.attester_registry_address.unwrap(), + func.encode_input(&[Token::Address(node_owner)]).unwrap(), + ); + let res = self.eth_call(ctx, block_id, tx).await; + let tokens = func.decode_output(&res).unwrap(); + ( + tokens[0].clone().into_uint().unwrap().as_usize(), + tokens[1].clone().into_bytes().unwrap(), + tokens[2].clone().into_bool().unwrap(), + ) + } + + async fn read_committee_validator( + &mut self, + ctx: &Ctx, + block_id: BlockId, + idx: usize, + ) -> (Address, usize, Vec) { + let func = self + .validator_registry_contract + .function("committee") + .unwrap() + .clone(); + let tx = self.gen_l2_call_tx( + self.validator_registry_address.unwrap(), + func.encode_input(&[Token::Uint(zksync_types::U256::from(idx))]) + .unwrap(), + ); + + let res = self.eth_call(ctx, block_id, tx).await; + let tokens = func.decode_output(&res).unwrap(); + ( + tokens[0].clone().into_address().unwrap(), + tokens[1].clone().into_uint().unwrap().as_usize(), + tokens[2].clone().into_bytes().unwrap(), + ) + } + + async fn read_committee_attester( + &mut self, + ctx: &Ctx, + block_id: BlockId, + idx: usize, + ) -> (usize, Address, Vec) { + let func = self + .attester_registry_contract + .function("committee") + .unwrap() + .clone(); + let tx = self.gen_l2_call_tx( + self.attester_registry_address.unwrap(), + func.encode_input(&[Token::Uint(zksync_types::U256::from(idx))]) + .unwrap(), + ); + + let res = self.eth_call(ctx, block_id, tx).await; + let tokens = func.decode_output(&res).unwrap(); + ( + tokens[0].clone().into_uint().unwrap().as_usize(), + tokens[1].clone().into_address().unwrap(), + tokens[2].clone().into_bytes().unwrap(), + ) + } + + async fn read_address( + &mut self, + ctx: &Ctx, + block_id: BlockId, + contract_address: Address, + func: Function, + ) -> Address { + let tx = self.gen_l2_call_tx(contract_address, func.encode_input(&vec![]).unwrap()); + + let res = self.eth_call(ctx, block_id, tx).await; + let tokens = func.decode_output(&res).unwrap(); + tokens[0].clone().into_address().unwrap() + } + + async fn eth_call(&mut self, ctx: &Ctx, block_id: BlockId, tx: L2Tx) -> Vec { + let mut conn = self.pool.connection(ctx).await.unwrap().0; + let start_info = BlockStartInfo::new(&mut conn, Duration::from_secs(10)) + .await + .unwrap(); + let block_args = zksync_node_api_server::execution_sandbox::BlockArgs::new( + &mut conn, + block_id, + &start_info, + ) + .await + .unwrap(); + let call_overrides = CallOverrides { + enforced_base_fee: None, + }; + + let res = self + .tx_sender + .eth_call(block_args, call_overrides, tx) + .await + .unwrap(); + + res + } + + fn gen_l2_call_tx(&mut self, contract_address: Address, calldata: Vec) -> L2Tx { + L2Tx::new( + contract_address, + calldata, + Nonce(0), + Fee { + gas_limit: U256::from(2000000000u32), + max_fee_per_gas: U256::zero(), + max_priority_fee_per_gas: U256::zero(), + gas_per_pubdata_limit: U256::from(DEFAULT_L2_TX_GAS_PER_PUBDATA_BYTE), + }, + Address::zero(), + U256::zero(), + vec![], + Default::default(), + ) + } +} + +#[derive(Debug, Default)] +pub struct CommitteeValidator { + pub node_owner: Address, + pub weight: usize, + pub pub_key: Vec, + pub pop: Vec, +} + +#[derive(Debug, Default)] +pub struct CommitteeAttester { + pub node_owner: Address, + pub weight: usize, + pub pub_key: Vec, +} diff --git a/core/node/consensus/src/testonly.rs b/core/node/consensus/src/testonly.rs index 81084b8f599a..2fdc104d5f84 100644 --- a/core/node/consensus/src/testonly.rs +++ b/core/node/consensus/src/testonly.rs @@ -42,8 +42,9 @@ use zksync_state_keeper::{ }; use zksync_test_account::Account; use zksync_types::{ + ethabi::{Function, Token}, fee_model::{BatchFeeInput, L1PeggedBatchFeeModelInput}, - Address, L1BatchNumber, L2BlockNumber, L2ChainId, PriorityOpId, ProtocolVersionId, + Address, L1BatchNumber, L2BlockNumber, L2ChainId, PriorityOpId, ProtocolVersionId, Transaction, }; use zksync_web3_decl::client::{Client, DynClient, L2}; @@ -122,7 +123,7 @@ pub(super) struct StateKeeperRunner { addr: sync::watch::Sender>, rocksdb_dir: tempfile::TempDir, metadata_calculator: MetadataCalculator, - account: Account, + pub account: Account, } impl StateKeeper { @@ -245,6 +246,16 @@ impl StateKeeper { } } + pub async fn push_block(&mut self, txs: &[Transaction]) { + let mut actions = vec![self.open_block()]; + actions.extend( + txs.iter() + .map(|tx| FetchedTransaction::new(tx.clone()).into()), + ); + actions.push(SyncAction::SealL2Block); + self.actions_sender.push_actions(actions).await.unwrap(); + } + /// Pushes a new L2 block with `transactions` transactions to the `StateKeeper`. pub async fn push_random_block(&mut self, rng: &mut impl Rng) { let mut actions = vec![self.open_block()]; diff --git a/core/node/state_keeper/src/testonly/mod.rs b/core/node/state_keeper/src/testonly/mod.rs index c287bc97407f..1fb30e69a01f 100644 --- a/core/node/state_keeper/src/testonly/mod.rs +++ b/core/node/state_keeper/src/testonly/mod.rs @@ -158,7 +158,7 @@ pub async fn fund(pool: &ConnectionPool, addresses: &[Address]) { pub(crate) const DEFAULT_GAS_PER_PUBDATA: u32 = 10000; -pub(crate) fn fee(gas_limit: u32) -> Fee { +pub fn fee(gas_limit: u32) -> Fee { Fee { gas_limit: U256::from(gas_limit), max_fee_per_gas: SYSTEM_CONTEXT_MINIMAL_BASE_FEE.into(), diff --git a/infrastructure/zk/src/init.ts b/infrastructure/zk/src/init.ts index 9ed6e178e51e..9f30915cf1fa 100644 --- a/infrastructure/zk/src/init.ts +++ b/infrastructure/zk/src/init.ts @@ -34,7 +34,7 @@ const checkEnv = async (): Promise => { // Initializes and updates the git submodule const submoduleUpdate = async (): Promise => { await utils.exec('git submodule init'); - await utils.exec('git submodule update'); + await utils.exec('git submodule update --remote'); }; // Sets up docker environment and compiles contracts