anvil_zksync_core/node/
eth.rs

1use crate::formatter::errors::view::ExecutionErrorReport;
2use crate::node::error::{ToHaltError, ToRevertReason};
3use anvil_zksync_common::{sh_err, sh_println, sh_warn};
4use anyhow::Context as _;
5use std::collections::HashSet;
6use zksync_error::anvil_zksync::node::AnvilNodeResult;
7use zksync_error::anvil_zksync::{halt::HaltError, revert::RevertError};
8use zksync_multivm::interface::ExecutionResult;
9use zksync_multivm::vm_latest::constants::ETH_CALL_GAS_LIMIT;
10use zksync_types::api::state_override::StateOverride;
11use zksync_types::utils::decompose_full_nonce;
12use zksync_types::{
13    api,
14    api::{Block, BlockIdVariant, BlockNumber, TransactionVariant},
15    get_code_key, get_is_account_key,
16    l2::L2Tx,
17    transaction_request::TransactionRequest,
18    PackedEthSignature, MAX_L1_TRANSACTION_GAS_LIMIT,
19};
20use zksync_types::{h256_to_u256, Transaction};
21use zksync_types::{
22    web3::{self, Bytes},
23    Address, H160, H256, U256, U64,
24};
25use zksync_web3_decl::{
26    error::Web3Error,
27    types::{FeeHistory, Filter, FilterChanges, SyncState},
28};
29
30use crate::{
31    filters::{FilterType, LogFilter},
32    node::{InMemoryNode, MAX_TX_SIZE, PROTOCOL_VERSION},
33    utils::TransparentError,
34};
35
36use super::boojumos::BOOJUM_CALL_GAS_LIMIT;
37
38impl InMemoryNode {
39    pub async fn call_impl(
40        &self,
41        req: zksync_types::transaction_request::CallRequest,
42        state_override: Option<StateOverride>,
43    ) -> Result<Bytes, Web3Error> {
44        let system_contracts = self.system_contracts.contracts_for_l2_call().clone();
45        let mut tx = L2Tx::from_request(
46            req.into(),
47            MAX_TX_SIZE,
48            self.system_contracts.allow_no_target(),
49        )?;
50
51        // Warn if target address has no code
52        if let Some(to_address) = tx.execute.contract_address {
53            let code_key = get_code_key(&to_address);
54            if self.storage.read_value_alt(&code_key).await?.is_zero() {
55                sh_warn!(
56                    "Read only call to address {to_address}, which is not associated with any contract."
57                )
58            }
59        }
60
61        if self.system_contracts.boojum.use_boojum {
62            tx.common_data.fee.gas_limit = BOOJUM_CALL_GAS_LIMIT.into();
63        } else {
64            tx.common_data.fee.gas_limit = ETH_CALL_GAS_LIMIT.into();
65        }
66        let call_result = self
67            .run_l2_call(tx.clone(), system_contracts, state_override)
68            .await
69            .context("Invalid data due to invalid name")?;
70
71        match call_result {
72            ExecutionResult::Success { output } => Ok(output.into()),
73            ExecutionResult::Revert { output } => {
74                let message = output.to_user_friendly_string();
75                let pretty_message = format!(
76                    "execution reverted{}{}",
77                    if message.is_empty() { "" } else { ": " },
78                    message
79                );
80
81                let revert_reason: RevertError = output.clone().to_revert_reason().await;
82                let tx = Transaction::from(tx);
83                let error_report = ExecutionErrorReport::new(&revert_reason, &tx);
84                sh_println!("{}", error_report);
85
86                Err(Web3Error::SubmitTransactionError(
87                    pretty_message,
88                    output.encoded_data(),
89                ))
90            }
91            ExecutionResult::Halt { reason } => {
92                let message = reason.to_string();
93                let pretty_message = format!(
94                    "execution halted {}{}",
95                    if message.is_empty() { "" } else { ": " },
96                    message
97                );
98
99                let halt_error: HaltError = reason.clone().to_halt_error().await;
100                let tx = Transaction::from(tx);
101                let error_report = ExecutionErrorReport::new(&halt_error, &tx);
102                sh_println!("{}", error_report);
103
104                Err(Web3Error::SubmitTransactionError(pretty_message, vec![]))
105            }
106        }
107    }
108
109    pub async fn send_raw_transaction_impl(&self, tx_bytes: Bytes) -> Result<H256, Web3Error> {
110        let chain_id = self.chain_id().await;
111
112        let (tx_req, hash) = TransactionRequest::from_bytes(&tx_bytes.0, chain_id)?;
113        let mut l2_tx =
114            L2Tx::from_request(tx_req, MAX_TX_SIZE, self.system_contracts.allow_no_target())?;
115
116        l2_tx.set_input(tx_bytes.0, hash);
117        if hash != l2_tx.hash() {
118            let err = anyhow::anyhow!(
119                "Invalid transaction data: computed hash does not match the provided hash."
120            );
121            return Err(err.into());
122        };
123
124        self.pool.add_tx(l2_tx.into());
125        Ok(hash)
126    }
127
128    pub async fn send_transaction_impl(
129        &self,
130        mut tx: zksync_types::transaction_request::CallRequest,
131    ) -> Result<H256, Web3Error> {
132        let (chain_id, l2_gas_price) = {
133            let reader = self.inner.read().await;
134            (self.chain_id().await, reader.fee_input_provider.gas_price())
135        };
136
137        // Users might expect a "sensible default"
138        if tx.gas.is_none() {
139            tx.gas = Some(U256::from(MAX_L1_TRANSACTION_GAS_LIMIT));
140        }
141
142        // EIP-1559 gas fields should be processed separately
143        if tx.gas_price.is_some() {
144            if tx.max_fee_per_gas.is_some() || tx.max_priority_fee_per_gas.is_some() {
145                let err = "Transaction contains unsupported fields: max_fee_per_gas or max_priority_fee_per_gas";
146                sh_err!("{err}");
147                return Err(TransparentError(err.into()).into());
148            }
149        } else {
150            tx.gas_price = Some(tx.max_fee_per_gas.unwrap_or(U256::from(l2_gas_price)));
151            tx.max_priority_fee_per_gas = Some(tx.max_priority_fee_per_gas.unwrap_or(U256::zero()));
152            if tx.transaction_type.is_none() {
153                tx.transaction_type = Some(zksync_types::EIP_1559_TX_TYPE.into());
154            }
155        }
156        if tx.nonce.is_none() {
157            let nonce_key = self.storage_key_layout.get_nonce_key(&tx.from.unwrap());
158            tx.nonce = Some(h256_to_u256(self.storage.read_value_alt(&nonce_key).await?) + 1);
159        }
160
161        let mut tx_req = TransactionRequest::from(tx.clone());
162        tx_req.chain_id = Some(chain_id.as_u64());
163        // Needed to calculate hash. `v` is set to 0 as EIP1559 tx hash calculation uses boolean
164        // parity instead of raw `v` value (i.e. 27 becomes 0, 28 becomes 1).
165        tx_req.r = Some(U256::zero());
166        tx_req.s = Some(U256::zero());
167        tx_req.v = Some(U64::from(0));
168
169        let bytes = tx_req.get_signed_bytes(&PackedEthSignature::from_rsv(
170            &H256::zero(),
171            &H256::zero(),
172            0,
173        ))?;
174
175        let (mut tx_req, hash) = TransactionRequest::from_bytes(&bytes, chain_id)?;
176        tx_req.from = tx.from;
177        let mut l2_tx: L2Tx =
178            L2Tx::from_request(tx_req, MAX_TX_SIZE, self.system_contracts.allow_no_target())?;
179        l2_tx.set_input(bytes, hash);
180
181        if !self
182            .impersonation
183            .is_impersonating(&l2_tx.common_data.initiator_address)
184        {
185            let err = format!(
186                "Initiator address {:?} is not allowed to perform transactions",
187                l2_tx.common_data.initiator_address
188            );
189            tracing::error!("\n{err}");
190            return Err(TransparentError(err).into());
191        }
192
193        self.pool.add_tx(l2_tx.into());
194        Ok(hash)
195    }
196}
197
198impl InMemoryNode {
199    pub async fn get_balance_impl(
200        &self,
201        address: Address,
202        // TODO: Support
203        _block: Option<BlockIdVariant>,
204    ) -> anyhow::Result<U256> {
205        let balance_key = self
206            .storage_key_layout
207            .get_storage_key_for_base_token(&address);
208        match self.storage.read_value_alt(&balance_key).await {
209            Ok(balance) => Ok(h256_to_u256(balance)),
210            Err(error) => Err(anyhow::anyhow!("failed to read account balance: {error}")),
211        }
212    }
213
214    pub async fn get_block_impl(
215        &self,
216        block_id: api::BlockId,
217        full_transactions: bool,
218    ) -> anyhow::Result<Option<Block<TransactionVariant>>> {
219        let maybe_block = {
220            if let Some(block) = self.blockchain.get_block_by_id(block_id).await {
221                Some(block)
222            } else {
223                self.fork.get_block_by_id(block_id).await?
224            }
225        };
226
227        match maybe_block {
228            Some(mut block) => {
229                let block_hash = block.hash;
230                block.transactions = block
231                    .transactions
232                    .into_iter()
233                    .map(|transaction| match &transaction {
234                        TransactionVariant::Full(inner) => {
235                            if full_transactions {
236                                transaction
237                            } else {
238                                TransactionVariant::Hash(inner.hash)
239                            }
240                        }
241                        TransactionVariant::Hash(_) => {
242                            if full_transactions {
243                                panic!("unexpected non full transaction for block {}", block_hash)
244                            } else {
245                                transaction
246                            }
247                        }
248                    })
249                    .collect();
250
251                Ok(Some(block))
252            }
253            None => Ok(None),
254        }
255    }
256
257    pub async fn get_code_impl(
258        &self,
259        address: Address,
260        // TODO: Support
261        _block: Option<BlockIdVariant>,
262    ) -> anyhow::Result<Bytes> {
263        let code_key = get_code_key(&address);
264        match self.storage.read_value_alt(&code_key).await {
265            Ok(code_hash) => match self.storage.load_factory_dep_alt(code_hash).await {
266                Ok(raw_code) => {
267                    let code = raw_code.unwrap_or_default();
268                    Ok(Bytes::from(code))
269                }
270                Err(error) => Err(anyhow::anyhow!("failed to load factory dep: {error}")),
271            },
272            Err(error) => Err(anyhow::anyhow!("failed to read code storage: {error}")),
273        }
274    }
275
276    pub async fn get_transaction_count_impl(
277        &self,
278        address: Address,
279        // TODO: Support
280        _block: Option<BlockIdVariant>,
281    ) -> anyhow::Result<U256> {
282        let nonce_key = self.storage_key_layout.get_nonce_key(&address);
283        let code_key = get_code_key(&address);
284        let is_account_key = get_is_account_key(&address);
285
286        let full_nonce = self.storage.read_value_alt(&nonce_key).await?;
287        let (account_nonce, deployment_nonce) = decompose_full_nonce(h256_to_u256(full_nonce));
288        let code_hash = self.storage.read_value_alt(&code_key).await?;
289        let account_info = self.storage.read_value_alt(&is_account_key).await?;
290
291        if code_hash.is_zero() || !account_info.is_zero() {
292            // Return account nonce for EOA accounts
293            Ok(account_nonce)
294        } else {
295            // Return deployment nonce for contracts
296            Ok(deployment_nonce)
297        }
298    }
299
300    pub async fn get_transaction_receipt_impl(
301        &self,
302        hash: H256,
303    ) -> anyhow::Result<Option<api::TransactionReceipt>> {
304        // TODO: Call fork if not found
305        Ok(self.blockchain.get_tx_receipt(&hash).await)
306    }
307
308    pub async fn get_transaction_by_hash_impl(
309        &self,
310        hash: H256,
311    ) -> anyhow::Result<Option<api::Transaction>> {
312        // try retrieving transaction from memory, and if unavailable subsequently from the fork
313        match self.blockchain.get_tx_api(&hash).await? {
314            Some(tx) => Ok(Some(tx)),
315            None => self.fork.get_transaction_by_hash(hash).await,
316        }
317    }
318
319    pub async fn get_block_number_impl(&self) -> anyhow::Result<U64> {
320        Ok(U64::from(self.blockchain.current_block_number().await.0))
321    }
322
323    pub async fn estimate_gas_impl(
324        &self,
325        req: zksync_types::transaction_request::CallRequest,
326        // TODO: Support
327        _block: Option<BlockNumber>,
328    ) -> AnvilNodeResult<U256> {
329        let fee = self.inner.read().await.estimate_gas_impl(req).await?;
330        Ok(fee.gas_limit)
331    }
332
333    pub async fn gas_price_impl(&self) -> anyhow::Result<U256> {
334        let fair_l2_gas_price: u64 = self.inner.read().await.fee_input_provider.gas_price();
335        Ok(U256::from(fair_l2_gas_price))
336    }
337
338    pub async fn new_filter_impl(&self, filter: Filter) -> anyhow::Result<U256> {
339        let from_block = filter.from_block.unwrap_or(BlockNumber::Latest);
340        let to_block = filter.to_block.unwrap_or(BlockNumber::Latest);
341        let addresses = filter.address.unwrap_or_default().0;
342        let mut topics: [Option<HashSet<H256>>; 4] = Default::default();
343
344        if let Some(filter_topics) = filter.topics {
345            filter_topics
346                .into_iter()
347                .take(4)
348                .enumerate()
349                .for_each(|(i, maybe_topic_set)| {
350                    if let Some(topic_set) = maybe_topic_set {
351                        topics[i] = Some(topic_set.0.into_iter().collect());
352                    }
353                })
354        }
355        self.inner
356            .write()
357            .await
358            .filters
359            .write()
360            .await
361            .add_log_filter(from_block, to_block, addresses, topics)
362            .map_err(anyhow::Error::msg)
363    }
364
365    pub async fn new_block_filter_impl(&self) -> anyhow::Result<U256> {
366        self.inner
367            .write()
368            .await
369            .filters
370            .write()
371            .await
372            .add_block_filter()
373            .map_err(anyhow::Error::msg)
374    }
375
376    pub async fn new_pending_transaction_filter_impl(&self) -> anyhow::Result<U256> {
377        self.inner
378            .write()
379            .await
380            .filters
381            .write()
382            .await
383            .add_pending_transaction_filter()
384            .map_err(anyhow::Error::msg)
385    }
386
387    pub async fn uninstall_filter_impl(&self, id: U256) -> anyhow::Result<bool> {
388        Ok(self
389            .inner
390            .write()
391            .await
392            .filters
393            .write()
394            .await
395            .remove_filter(id))
396    }
397
398    pub async fn get_logs_impl(
399        &self,
400        filter: Filter,
401    ) -> anyhow::Result<Vec<zksync_types::api::Log>> {
402        let from_block = filter.from_block.unwrap_or(BlockNumber::Earliest);
403        let to_block = filter.to_block.unwrap_or(BlockNumber::Latest);
404        let addresses = filter.address.unwrap_or_default().0;
405        let mut topics: [Option<HashSet<H256>>; 4] = Default::default();
406
407        if let Some(filter_topics) = filter.topics {
408            filter_topics
409                .into_iter()
410                .take(4)
411                .enumerate()
412                .for_each(|(i, maybe_topic_set)| {
413                    if let Some(topic_set) = maybe_topic_set {
414                        topics[i] = Some(topic_set.0.into_iter().collect());
415                    }
416                })
417        }
418
419        // TODO: LogFilter should really resolve `from_block` and `to_block` during init and not
420        //       on every `matches` call.
421        let log_filter = LogFilter::new(from_block, to_block, addresses, topics);
422        Ok(self.blockchain.get_filter_logs(&log_filter).await)
423    }
424
425    pub async fn get_filter_logs_impl(&self, id: U256) -> anyhow::Result<FilterChanges> {
426        let logs = match self.inner.read().await.filters.read().await.get_filter(id) {
427            Some(FilterType::Log(log_filter)) => self.blockchain.get_filter_logs(log_filter).await,
428            _ => {
429                anyhow::bail!("Failed to acquire read lock for filter logs.")
430            }
431        };
432
433        Ok(FilterChanges::Logs(logs))
434    }
435
436    pub async fn get_filter_changes_impl(&self, id: U256) -> anyhow::Result<FilterChanges> {
437        self.inner
438            .write()
439            .await
440            .filters
441            .write()
442            .await
443            .get_new_changes(id)
444            .map_err(anyhow::Error::msg)
445    }
446
447    pub async fn get_block_transaction_count_impl(
448        &self,
449        block_id: api::BlockId,
450    ) -> Result<Option<U256>, Web3Error> {
451        let count = match self.blockchain.get_block_tx_count_by_id(block_id).await {
452            Some(count) => Some(U256::from(count)),
453            None => {
454                self.fork
455                    .get_block_transaction_count_by_id(block_id)
456                    .await?
457            }
458        };
459
460        // TODO: Is this right? What is the purpose of having `Option` here then?
461        match count {
462            Some(count) => Ok(Some(count)),
463            None => Err(Web3Error::NoBlock),
464        }
465    }
466
467    pub async fn get_storage_impl(
468        &self,
469        address: Address,
470        idx: U256,
471        block: Option<api::BlockIdVariant>,
472    ) -> Result<H256, Web3Error> {
473        self.inner
474            .read()
475            .await
476            .get_storage_at_block(address, idx, block)
477            .await
478    }
479
480    pub async fn get_transaction_by_block_and_index_impl(
481        &self,
482        block_id: api::BlockId,
483        index: web3::Index,
484    ) -> anyhow::Result<Option<api::Transaction>> {
485        match self
486            .blockchain
487            .get_block_tx_by_id(block_id, index.as_usize())
488            .await
489        {
490            Some(tx) => Ok(Some(tx)),
491            None => {
492                self.fork
493                    .get_transaction_by_block_id_and_index(block_id, index)
494                    .await
495            }
496        }
497    }
498
499    pub fn protocol_version_impl(&self) -> String {
500        PROTOCOL_VERSION.to_string()
501    }
502
503    pub fn syncing_impl(&self) -> SyncState {
504        SyncState::NotSyncing
505    }
506
507    pub async fn accounts_impl(&self) -> anyhow::Result<Vec<H160>> {
508        Ok(self
509            .inner
510            .read()
511            .await
512            .rich_accounts
513            .clone()
514            .into_iter()
515            .collect())
516    }
517
518    pub async fn fee_history_impl(
519        &self,
520        block_count: u64,
521        // TODO: Support
522        _newest_block: BlockNumber,
523        reward_percentiles: Option<Vec<f32>>,
524    ) -> anyhow::Result<zksync_types::api::FeeHistory> {
525        let current_block = self.blockchain.current_block_number().await;
526
527        let block_count = (block_count as usize)
528            .min(1024)
529            // Can't be more than the total number of blocks
530            .clamp(1, current_block.0 as usize + 1);
531
532        let mut base_fee_per_gas =
533            vec![U256::from(self.inner.read().await.fee_input_provider.gas_price()); block_count];
534
535        let oldest_block = current_block + 1 - base_fee_per_gas.len() as u32;
536        // We do not store gas used ratio for blocks, returns array of zeroes as a placeholder.
537        let gas_used_ratio = vec![0.0; base_fee_per_gas.len()];
538        // Effective priority gas price is currently 0.
539        let reward = Some(vec![
540            vec![
541                U256::zero();
542                reward_percentiles.map_or(0, |v| v.len())
543            ];
544            base_fee_per_gas.len()
545        ]);
546
547        // `base_fee_per_gas` for next miniblock cannot be calculated, appending last fee as a placeholder.
548        base_fee_per_gas.push(*base_fee_per_gas.last().unwrap());
549
550        Ok(zksync_types::api::FeeHistory {
551            inner: FeeHistory {
552                oldest_block: web3::BlockNumber::Number(oldest_block.0.into()),
553                base_fee_per_gas,
554                gas_used_ratio,
555                reward,
556                base_fee_per_blob_gas: Default::default(),
557                blob_gas_used_ratio: Default::default(),
558            },
559            l2_pubdata_price: vec![],
560        })
561    }
562}
563
564#[cfg(test)]
565mod tests {
566    use super::*;
567    use crate::node::fork::{ForkClient, ForkConfig};
568    use crate::node::TransactionResult;
569    use crate::{
570        node::InMemoryNode,
571        testing::{
572            self, default_tx_debug_info, ForkBlockConfig, LogBuilder, MockServer,
573            TransactionResponseBuilder,
574        },
575    };
576    use anvil_zksync_config::constants::{
577        DEFAULT_ACCOUNT_BALANCE, DEFAULT_L2_GAS_PRICE, NON_FORK_FIRST_BLOCK_TIMESTAMP,
578    };
579    use maplit::hashmap;
580    use url::Url;
581    use zksync_multivm::utils::get_max_batch_gas_limit;
582    use zksync_types::block::L2BlockHasher;
583    use zksync_types::l2::TransactionType;
584    use zksync_types::vm::VmVersion;
585    use zksync_types::{
586        api,
587        api::{BlockHashObject, BlockNumber, BlockNumberObject, TransactionReceipt},
588        utils::deployed_address_create,
589        Bloom, K256PrivateKey, L2BlockNumber, StorageKey, EMPTY_UNCLES_HASH,
590    };
591    use zksync_types::{u256_to_h256, web3, AccountTreeId, Nonce};
592    use zksync_web3_decl::types::{SyncState, ValueOrArray};
593
594    async fn test_node(url: Url) -> InMemoryNode {
595        InMemoryNode::test(Some(
596            ForkClient::at_block_number(ForkConfig::unknown(url), None)
597                .await
598                .unwrap(),
599        ))
600    }
601
602    #[tokio::test]
603    async fn test_eth_syncing() {
604        let node = InMemoryNode::test(None);
605        let syncing = node.syncing_impl();
606        assert!(matches!(syncing, SyncState::NotSyncing));
607    }
608
609    #[tokio::test]
610    async fn test_get_fee_history_with_1_block() {
611        let node = InMemoryNode::test(None);
612
613        let fee_history = node
614            .fee_history_impl(1, BlockNumber::Latest, Some(vec![25.0, 50.0, 75.0]))
615            .await
616            .expect("fee_history failed")
617            .inner;
618
619        assert_eq!(
620            fee_history.oldest_block,
621            web3::BlockNumber::Number(U64::from(0))
622        );
623        assert_eq!(
624            fee_history.base_fee_per_gas,
625            vec![U256::from(DEFAULT_L2_GAS_PRICE); 2]
626        );
627        assert_eq!(fee_history.gas_used_ratio, vec![0.0]);
628        assert_eq!(fee_history.reward, Some(vec![vec![U256::from(0); 3]]));
629    }
630
631    #[tokio::test]
632    async fn test_get_fee_history_with_no_reward_percentiles() {
633        let node = InMemoryNode::test(None);
634
635        let fee_history = node
636            .fee_history_impl(1, BlockNumber::Latest, Some(vec![]))
637            .await
638            .expect("fee_history failed")
639            .inner;
640
641        assert_eq!(
642            fee_history.oldest_block,
643            web3::BlockNumber::Number(U64::from(0))
644        );
645        assert_eq!(
646            fee_history.base_fee_per_gas,
647            vec![U256::from(DEFAULT_L2_GAS_PRICE); 2]
648        );
649        assert_eq!(fee_history.gas_used_ratio, vec![0.0]);
650        assert_eq!(fee_history.reward, Some(vec![vec![]]));
651    }
652
653    #[tokio::test]
654    async fn test_get_fee_history_with_multiple_blocks() {
655        // Arrange
656        let node = InMemoryNode::test(None);
657        testing::apply_tx(&node).await;
658
659        // Act
660        let latest_block = node
661            .get_block_number_impl()
662            .await
663            .expect("Block number fetch failed");
664        let fee_history = node
665            .fee_history_impl(2, BlockNumber::Latest, Some(vec![25.0, 50.0, 75.0]))
666            .await
667            .expect("fee_history failed")
668            .inner;
669
670        // Assert
671        // We should receive 2 fees: from block 1 and 2.
672        assert_eq!(latest_block, U64::from(2));
673        assert_eq!(
674            fee_history.oldest_block,
675            web3::BlockNumber::Number(U64::from(1))
676        );
677        assert_eq!(
678            fee_history.base_fee_per_gas,
679            vec![U256::from(DEFAULT_L2_GAS_PRICE); 3]
680        );
681        assert_eq!(fee_history.gas_used_ratio, vec![0.0, 0.0]);
682        assert_eq!(fee_history.reward, Some(vec![vec![U256::from(0); 3]; 2]));
683    }
684
685    #[tokio::test]
686    async fn test_get_block_by_hash_returns_none_for_non_existing_block() {
687        let node = InMemoryNode::test(None);
688
689        let result = node
690            .get_block_impl(api::BlockId::Hash(H256::repeat_byte(0x01)), false)
691            .await
692            .expect("failed fetching block by hash");
693
694        assert!(result.is_none());
695    }
696
697    #[tokio::test]
698    async fn test_node_has_genesis_block() {
699        let node = InMemoryNode::test(None);
700
701        let block = node
702            .get_block_impl(api::BlockId::Number(BlockNumber::Latest), false)
703            .await
704            .expect("failed fetching block by number")
705            .expect("no block");
706
707        assert_eq!(0, block.number.as_u64());
708        assert_eq!(L2BlockHasher::legacy_hash(L2BlockNumber(0)), block.hash);
709    }
710
711    #[tokio::test]
712    async fn test_node_creates_genesis_block_with_hash_and_zero_parent_hash() {
713        let node = InMemoryNode::test(None);
714
715        let block = node
716            .get_block_impl(
717                api::BlockId::Hash(L2BlockHasher::legacy_hash(L2BlockNumber(0))),
718                false,
719            )
720            .await
721            .expect("failed fetching block by hash")
722            .expect("no block");
723
724        assert_eq!(block.parent_hash, H256::zero());
725    }
726
727    #[tokio::test]
728    async fn test_node_produces_blocks_with_parent_hash_links() {
729        let node = InMemoryNode::test(None);
730        testing::apply_tx(&node).await;
731
732        let genesis_block = node
733            .get_block_impl(api::BlockId::Number(BlockNumber::from(0)), false)
734            .await
735            .expect("failed fetching block by number")
736            .expect("no block");
737        let first_block = node
738            .get_block_impl(api::BlockId::Number(BlockNumber::from(1)), false)
739            .await
740            .expect("failed fetching block by number")
741            .expect("no block");
742        let second_block = node
743            .get_block_impl(api::BlockId::Number(BlockNumber::from(2)), false)
744            .await
745            .expect("failed fetching block by number")
746            .expect("no block");
747
748        assert_eq!(genesis_block.hash, first_block.parent_hash);
749        assert_eq!(first_block.hash, second_block.parent_hash);
750    }
751
752    #[tokio::test]
753    async fn test_get_block_by_hash_for_produced_block() {
754        let node = InMemoryNode::test(None);
755        let (expected_block_hash, _, tx) = testing::apply_tx(&node).await;
756        let genesis_block = node
757            .get_block_impl(api::BlockId::Number(BlockNumber::from(0)), false)
758            .await
759            .expect("failed fetching block by number")
760            .expect("no block");
761
762        let actual_block = node
763            .get_block_impl(api::BlockId::Hash(expected_block_hash), false)
764            .await
765            .expect("failed fetching block by hash")
766            .expect("no block");
767
768        let expected_block: Block<TransactionVariant> = Block {
769            hash: expected_block_hash,
770            parent_hash: genesis_block.hash,
771            uncles_hash: EMPTY_UNCLES_HASH,
772            author: Default::default(),
773            state_root: Default::default(),
774            transactions_root: Default::default(),
775            receipts_root: Default::default(),
776            number: U64::from(1),
777            l1_batch_number: Some(U64::from(1)),
778            gas_used: actual_block.gas_used, // Checked separately, see below
779            gas_limit: U256::from(get_max_batch_gas_limit(VmVersion::latest())),
780            base_fee_per_gas: actual_block.base_fee_per_gas, // Checked separately, see below
781            extra_data: Default::default(),
782            logs_bloom: actual_block.logs_bloom, // Checked separately, see below
783            timestamp: U256::from(NON_FORK_FIRST_BLOCK_TIMESTAMP + 1),
784            l1_batch_timestamp: Some(U256::from(NON_FORK_FIRST_BLOCK_TIMESTAMP + 1)),
785            difficulty: Default::default(),
786            total_difficulty: Default::default(),
787            seal_fields: vec![],
788            uncles: vec![],
789            transactions: vec![TransactionVariant::Hash(tx.hash())],
790            size: Default::default(),
791            mix_hash: Default::default(),
792            nonce: Default::default(),
793        };
794
795        assert_eq!(expected_block, actual_block);
796
797        // It is hard to predict the values below without repeating the exact logic used to calculate
798        // them. We are resorting to some basic sanity checks instead.
799        assert!(actual_block.gas_used > U256::zero());
800        assert!(actual_block.base_fee_per_gas > U256::zero());
801        assert_ne!(actual_block.logs_bloom, Bloom::zero());
802    }
803
804    #[tokio::test]
805    async fn test_node_block_mapping_is_correctly_populated_when_using_fork_source() {
806        let input_block_number = 8;
807        let input_block_hash = H256::repeat_byte(0x01);
808        let mock_server = MockServer::run_with_config(ForkBlockConfig {
809            number: input_block_number,
810            hash: input_block_hash,
811            transaction_count: 0,
812        });
813
814        let node = test_node(mock_server.url()).await;
815        assert!(
816            node.blockchain
817                .get_block_by_hash(&input_block_hash)
818                .await
819                .is_some(),
820            "block wasn't cached"
821        );
822    }
823
824    #[tokio::test]
825    async fn test_get_block_by_hash_uses_fork_source() {
826        let input_block_hash = H256::repeat_byte(0x01);
827
828        let mock_server = MockServer::run_with_config(ForkBlockConfig {
829            number: 10,
830            hash: H256::repeat_byte(0xab),
831            transaction_count: 0,
832        });
833        let mock_block_number = 8;
834        let block_response = testing::BlockResponseBuilder::new()
835            .set_hash(input_block_hash)
836            .set_number(mock_block_number)
837            .build_result();
838        mock_server.expect(
839            "eth_getBlockByHash",
840            Some(serde_json::json!([format!("{input_block_hash:#x}"), true])),
841            block_response,
842        );
843        let node = test_node(mock_server.url()).await;
844
845        let actual_block = node
846            .get_block_impl(api::BlockId::Hash(input_block_hash), false)
847            .await
848            .expect("failed fetching block by hash")
849            .expect("no block");
850
851        assert_eq!(input_block_hash, actual_block.hash);
852        assert_eq!(U64::from(mock_block_number), actual_block.number);
853        assert_eq!(Some(U64::from(6)), actual_block.l1_batch_number);
854    }
855
856    #[tokio::test]
857    async fn test_get_block_by_number_returns_none_for_non_existing_block() {
858        let node = InMemoryNode::test(None);
859
860        let result = node
861            .get_block_impl(
862                api::BlockId::Number(BlockNumber::Number(U64::from(42))),
863                false,
864            )
865            .await
866            .expect("failed fetching block by number");
867
868        assert!(result.is_none());
869    }
870
871    #[tokio::test]
872    async fn test_get_block_by_number_for_produced_block() {
873        let node = InMemoryNode::test(None);
874        let (expected_block_hash, _, tx) = testing::apply_tx(&node).await;
875        let expected_block_number = 1;
876        let genesis_block = node
877            .get_block_impl(api::BlockId::Number(BlockNumber::from(0)), false)
878            .await
879            .expect("failed fetching block by number")
880            .expect("no block");
881
882        let actual_block = node
883            .get_block_impl(
884                api::BlockId::Number(BlockNumber::Number(U64::from(expected_block_number))),
885                false,
886            )
887            .await
888            .expect("failed fetching block by number")
889            .expect("no block");
890
891        let expected_block: Block<TransactionVariant> = Block {
892            hash: expected_block_hash,
893            parent_hash: genesis_block.hash,
894            uncles_hash: EMPTY_UNCLES_HASH,
895            author: Default::default(),
896            state_root: Default::default(),
897            transactions_root: Default::default(),
898            receipts_root: Default::default(),
899            number: U64::from(expected_block_number),
900            l1_batch_number: Some(U64::from(1)),
901            gas_used: actual_block.gas_used, // Checked separately, see below
902            gas_limit: U256::from(get_max_batch_gas_limit(VmVersion::latest())),
903            base_fee_per_gas: actual_block.base_fee_per_gas, // Checked separately, see below
904            extra_data: Default::default(),
905            logs_bloom: actual_block.logs_bloom, // Checked separately, see below
906            timestamp: U256::from(NON_FORK_FIRST_BLOCK_TIMESTAMP + 1),
907            l1_batch_timestamp: Some(U256::from(NON_FORK_FIRST_BLOCK_TIMESTAMP + 1)),
908            difficulty: Default::default(),
909            total_difficulty: Default::default(),
910            seal_fields: vec![],
911            uncles: vec![],
912            transactions: vec![TransactionVariant::Hash(tx.hash())],
913            size: Default::default(),
914            mix_hash: Default::default(),
915            nonce: Default::default(),
916        };
917
918        assert_eq!(expected_block, actual_block);
919
920        // It is hard to predict the values below without repeating the exact logic used to calculate
921        // them. We are resorting to some basic sanity checks instead.
922        assert!(actual_block.gas_used > U256::zero());
923        assert!(actual_block.base_fee_per_gas > U256::zero());
924        assert_ne!(actual_block.logs_bloom, Bloom::zero());
925    }
926
927    #[tokio::test]
928    async fn test_get_block_by_number_for_produced_block_full_txs() {
929        let node = InMemoryNode::test(None);
930        let (block_hash, _, tx) = testing::apply_tx(&node).await;
931        let expected_block_number = 1;
932
933        let mut actual_block = node
934            .get_block_impl(
935                api::BlockId::Number(BlockNumber::Number(U64::from(expected_block_number))),
936                true,
937            )
938            .await
939            .expect("failed fetching block by number")
940            .expect("no block");
941
942        assert_eq!(actual_block.transactions.len(), 1);
943        let actual_tx = match actual_block.transactions.remove(0) {
944            TransactionVariant::Full(tx) => tx,
945            TransactionVariant::Hash(_) => unreachable!(),
946        };
947        let expected_tx = api::Transaction {
948            hash: tx.hash(),
949            nonce: U256::from(0),
950            block_hash: Some(block_hash),
951            block_number: Some(U64::from(expected_block_number)),
952            transaction_index: Some(U64::from(0)),
953            from: Some(tx.initiator_account()),
954            to: tx.recipient_account(),
955            value: U256::from(1),
956            gas_price: Some(tx.common_data.fee.max_fee_per_gas),
957            gas: tx.common_data.fee.gas_limit,
958            input: Default::default(),
959            v: actual_tx.v,               // Checked separately, see below
960            r: actual_tx.r,               // Checked separately, see below
961            s: actual_tx.s,               // Checked separately, see below
962            y_parity: actual_tx.y_parity, // Checked separately, see below
963            raw: None,
964            transaction_type: Some(U64::from(TransactionType::EIP712Transaction as u32)),
965            access_list: None,
966            max_fee_per_gas: Some(tx.common_data.fee.max_fee_per_gas),
967            max_priority_fee_per_gas: Some(tx.common_data.fee.max_priority_fee_per_gas),
968            chain_id: U256::from(260),
969            l1_batch_number: Some(U64::from(1)),
970            l1_batch_tx_index: Some(U64::from(0)),
971        };
972        assert_eq!(expected_tx, actual_tx);
973
974        // TODO: Verify that the TX is signed properly (use alloy to abstract from zksync-core code?)
975    }
976
977    #[tokio::test]
978    async fn test_get_block_by_number_uses_fork_source_if_missing_number() {
979        let mock_server = MockServer::run_with_config(ForkBlockConfig {
980            number: 10,
981            hash: H256::repeat_byte(0xab),
982            transaction_count: 0,
983        });
984        let mock_block_number = 8;
985        let block_response = testing::BlockResponseBuilder::new()
986            .set_number(mock_block_number)
987            .build_result();
988        mock_server.expect(
989            "eth_getBlockByNumber",
990            Some(serde_json::json!(["0x8", true])),
991            block_response,
992        );
993        let node = test_node(mock_server.url()).await;
994
995        let actual_block = node
996            .get_block_impl(
997                api::BlockId::Number(BlockNumber::Number(U64::from(8))),
998                false,
999            )
1000            .await
1001            .expect("failed fetching block by hash")
1002            .expect("no block");
1003        assert_eq!(U64::from(mock_block_number), actual_block.number);
1004    }
1005
1006    #[tokio::test]
1007    async fn test_get_block_by_number_for_latest_block_produced_locally() {
1008        let node = InMemoryNode::test(None);
1009        testing::apply_tx(&node).await;
1010
1011        // The latest block, will be the 'virtual' one with 0 transactions (block 2).
1012        let virtual_block = node
1013            .get_block_impl(api::BlockId::Number(BlockNumber::Latest), true)
1014            .await
1015            .expect("failed fetching block by hash")
1016            .expect("no block");
1017
1018        assert_eq!(U64::from(2), virtual_block.number);
1019        assert_eq!(0, virtual_block.transactions.len());
1020
1021        let actual_block = node
1022            .get_block_impl(
1023                api::BlockId::Number(BlockNumber::Number(U64::from(1))),
1024                true,
1025            )
1026            .await
1027            .expect("failed fetching block by hash")
1028            .expect("no block");
1029
1030        assert_eq!(U64::from(1), actual_block.number);
1031        assert_eq!(1, actual_block.transactions.len());
1032    }
1033
1034    #[tokio::test]
1035    async fn test_get_block_by_number_uses_locally_available_block_for_latest_block() {
1036        let input_block_number = 10;
1037        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1038            number: input_block_number,
1039            hash: H256::repeat_byte(0x01),
1040            transaction_count: 0,
1041        });
1042
1043        let node = test_node(mock_server.url()).await;
1044
1045        let actual_block = node
1046            .get_block_impl(api::BlockId::Number(BlockNumber::Latest), false)
1047            .await
1048            .expect("failed fetching block by hash")
1049            .expect("no block");
1050        assert_eq!(U64::from(input_block_number), actual_block.number);
1051    }
1052
1053    #[tokio::test]
1054    async fn test_get_block_by_number_uses_fork_source_for_earliest_block() {
1055        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1056            number: 10,
1057            hash: H256::repeat_byte(0xab),
1058            transaction_count: 0,
1059        });
1060        let input_block_number = 1;
1061        mock_server.expect(
1062            "eth_getBlockByNumber",
1063            Some(serde_json::json!(["earliest", true])),
1064            testing::BlockResponseBuilder::new()
1065                .set_number(input_block_number)
1066                .build_result(),
1067        );
1068        let node = test_node(mock_server.url()).await;
1069
1070        let actual_block = node
1071            .get_block_impl(api::BlockId::Number(BlockNumber::Earliest), false)
1072            .await
1073            .expect("failed fetching block by hash")
1074            .expect("no block");
1075        assert_eq!(U64::from(input_block_number), actual_block.number);
1076    }
1077
1078    #[tokio::test]
1079    async fn test_get_block_by_number_uses_locally_available_for_latest_alike_blocks() {
1080        for block_number in [
1081            BlockNumber::Pending,
1082            BlockNumber::Committed,
1083            BlockNumber::Finalized,
1084        ] {
1085            let input_block_number = 10;
1086            let mock_server = MockServer::run_with_config(ForkBlockConfig {
1087                number: input_block_number,
1088                hash: H256::repeat_byte(0xab),
1089                transaction_count: 0,
1090            });
1091            let node = test_node(mock_server.url()).await;
1092
1093            let actual_block = node
1094                .get_block_impl(api::BlockId::Number(block_number), false)
1095                .await
1096                .expect("failed fetching block by hash")
1097                .expect("no block");
1098            assert_eq!(
1099                U64::from(input_block_number),
1100                actual_block.number,
1101                "case {}",
1102                block_number,
1103            );
1104        }
1105    }
1106
1107    #[tokio::test]
1108    async fn test_get_block_transaction_count_by_hash_for_produced_block() {
1109        let node = InMemoryNode::test(None);
1110
1111        let (expected_block_hash, _, _) = testing::apply_tx(&node).await;
1112        let actual_transaction_count = node
1113            .get_block_transaction_count_impl(api::BlockId::Hash(expected_block_hash))
1114            .await
1115            .expect("failed fetching block by hash")
1116            .expect("no result");
1117
1118        assert_eq!(U256::from(1), actual_transaction_count);
1119    }
1120
1121    #[tokio::test]
1122    async fn test_get_block_transaction_count_by_hash_uses_fork_source() {
1123        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1124            number: 10,
1125            hash: H256::repeat_byte(0xab),
1126            transaction_count: 0,
1127        });
1128        let input_block_hash = H256::repeat_byte(0x01);
1129        let input_transaction_count = 1;
1130        mock_server.expect(
1131            "eth_getBlockTransactionCountByHash",
1132            Some(serde_json::json!([format!("{:#x}", input_block_hash)])),
1133            serde_json::json!(format!("{:#x}", input_transaction_count)),
1134        );
1135        let node = test_node(mock_server.url()).await;
1136
1137        let actual_transaction_count = node
1138            .get_block_transaction_count_impl(api::BlockId::Hash(input_block_hash))
1139            .await
1140            .expect("failed fetching block by hash")
1141            .expect("no result");
1142
1143        assert_eq!(
1144            U256::from(input_transaction_count),
1145            actual_transaction_count
1146        );
1147    }
1148
1149    #[tokio::test]
1150    async fn test_get_block_transaction_count_by_number_for_produced_block() {
1151        let node = InMemoryNode::test(None);
1152
1153        testing::apply_tx(&node).await;
1154        let actual_transaction_count = node
1155            .get_block_transaction_count_impl(api::BlockId::Number(api::BlockNumber::Number(
1156                U64::from(1),
1157            )))
1158            .await
1159            .expect("failed fetching block by hash")
1160            .expect("no result");
1161
1162        assert_eq!(U256::from(1), actual_transaction_count);
1163    }
1164
1165    #[tokio::test]
1166    async fn test_get_block_transaction_count_by_number_uses_fork_source() {
1167        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1168            number: 10,
1169            hash: H256::repeat_byte(0xab),
1170            transaction_count: 0,
1171        });
1172        let input_block_number = 1;
1173        let input_transaction_count = 1;
1174        mock_server.expect(
1175            "eth_getBlockTransactionCountByNumber",
1176            Some(serde_json::json!([format!("{:#x}", input_block_number)])),
1177            serde_json::json!(format!("{:#x}", input_transaction_count)),
1178        );
1179
1180        let node = test_node(mock_server.url()).await;
1181
1182        let actual_transaction_count = node
1183            .get_block_transaction_count_impl(api::BlockId::Number(BlockNumber::Number(U64::from(
1184                1,
1185            ))))
1186            .await
1187            .expect("failed fetching block by hash")
1188            .expect("no result");
1189
1190        assert_eq!(
1191            U256::from(input_transaction_count),
1192            actual_transaction_count
1193        );
1194    }
1195
1196    #[tokio::test]
1197    async fn test_get_block_transaction_count_by_number_earliest_uses_fork_source() {
1198        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1199            number: 10,
1200            hash: H256::repeat_byte(0xab),
1201            transaction_count: 0,
1202        });
1203        let input_transaction_count = 1;
1204        mock_server.expect(
1205            "eth_getBlockTransactionCountByNumber",
1206            Some(serde_json::json!(["earliest"])),
1207            serde_json::json!(format!("{:#x}", input_transaction_count)),
1208        );
1209
1210        let node = test_node(mock_server.url()).await;
1211
1212        let actual_transaction_count = node
1213            .get_block_transaction_count_impl(api::BlockId::Number(BlockNumber::Earliest))
1214            .await
1215            .expect("failed fetching block by hash")
1216            .expect("no result");
1217
1218        assert_eq!(
1219            U256::from(input_transaction_count),
1220            actual_transaction_count
1221        );
1222    }
1223
1224    #[tokio::test]
1225    async fn test_get_block_transaction_count_by_number_latest_alike_uses_fork_source() {
1226        for block_number in [
1227            BlockNumber::Latest,
1228            BlockNumber::Pending,
1229            BlockNumber::Committed,
1230            BlockNumber::Finalized,
1231        ] {
1232            let input_transaction_count = 1;
1233            let mock_server = MockServer::run_with_config(ForkBlockConfig {
1234                number: 10,
1235                transaction_count: input_transaction_count,
1236                hash: H256::repeat_byte(0xab),
1237            });
1238
1239            let node = test_node(mock_server.url()).await;
1240
1241            let actual_transaction_count = node
1242                .get_block_transaction_count_impl(api::BlockId::Number(block_number))
1243                .await
1244                .expect("failed fetching block by hash")
1245                .expect("no result");
1246
1247            assert_eq!(
1248                U256::from(input_transaction_count),
1249                actual_transaction_count,
1250                "case {}",
1251                block_number,
1252            );
1253        }
1254    }
1255
1256    #[tokio::test]
1257    async fn test_get_transaction_receipt_uses_produced_block_hash() {
1258        let node = InMemoryNode::test(None);
1259        let (expected_block_hash, _, tx) = testing::apply_tx(&node).await;
1260
1261        let actual_tx_receipt = node
1262            .get_transaction_receipt_impl(tx.hash())
1263            .await
1264            .expect("failed fetching transaction receipt by hash")
1265            .expect("no transaction receipt");
1266
1267        assert_eq!(expected_block_hash, actual_tx_receipt.block_hash);
1268    }
1269
1270    #[tokio::test]
1271    async fn test_new_block_filter_returns_filter_id() {
1272        let node = InMemoryNode::test(None);
1273
1274        let actual_filter_id = node
1275            .new_block_filter_impl()
1276            .await
1277            .expect("failed creating filter");
1278
1279        assert_eq!(U256::from(1), actual_filter_id);
1280    }
1281
1282    #[tokio::test]
1283    async fn test_new_filter_returns_filter_id() {
1284        let node = InMemoryNode::test(None);
1285
1286        let actual_filter_id = node
1287            .new_filter_impl(Filter::default())
1288            .await
1289            .expect("failed creating filter");
1290
1291        assert_eq!(U256::from(1), actual_filter_id);
1292    }
1293
1294    #[tokio::test]
1295    async fn test_new_pending_transaction_filter_returns_filter_id() {
1296        let node = InMemoryNode::test(None);
1297
1298        let actual_filter_id = node
1299            .new_pending_transaction_filter_impl()
1300            .await
1301            .expect("failed creating filter");
1302
1303        assert_eq!(U256::from(1), actual_filter_id);
1304    }
1305
1306    #[tokio::test]
1307    async fn test_uninstall_filter_returns_true_if_filter_exists() {
1308        let node = InMemoryNode::test(None);
1309        let filter_id = node
1310            .new_block_filter_impl()
1311            .await
1312            .expect("failed creating filter");
1313
1314        let actual_result = node
1315            .uninstall_filter_impl(filter_id)
1316            .await
1317            .expect("failed creating filter");
1318
1319        assert!(actual_result);
1320    }
1321
1322    #[tokio::test]
1323    async fn test_uninstall_filter_returns_false_if_filter_does_not_exist() {
1324        let node = InMemoryNode::test(None);
1325
1326        let actual_result = node
1327            .uninstall_filter_impl(U256::from(100))
1328            .await
1329            .expect("failed creating filter");
1330
1331        assert!(!actual_result);
1332    }
1333
1334    #[tokio::test]
1335    async fn test_get_filter_changes_returns_block_hash_updates_only_once() {
1336        let node = InMemoryNode::test(None);
1337        let filter_id = node
1338            .new_block_filter_impl()
1339            .await
1340            .expect("failed creating filter");
1341        let (block_hash, _, _) = testing::apply_tx(&node).await;
1342
1343        match node
1344            .get_filter_changes_impl(filter_id)
1345            .await
1346            .expect("failed getting filter changes")
1347        {
1348            FilterChanges::Hashes(result) => {
1349                // Get the block hash and the virtual block hash.
1350                assert_eq!(2, result.len());
1351                assert_eq!(block_hash, result[0]);
1352            }
1353            changes => panic!("unexpected filter changes: {:?}", changes),
1354        }
1355
1356        match node
1357            .get_filter_changes_impl(filter_id)
1358            .await
1359            .expect("failed getting filter changes")
1360        {
1361            FilterChanges::Empty(_) => (),
1362            changes => panic!("expected no changes in the second call, got {:?}", changes),
1363        }
1364    }
1365
1366    #[tokio::test]
1367    async fn test_get_filter_changes_returns_log_updates_only_once() {
1368        let node = InMemoryNode::test(None);
1369        let filter_id = node
1370            .new_filter_impl(Filter {
1371                from_block: None,
1372                to_block: None,
1373                address: None,
1374                topics: None,
1375                block_hash: None,
1376            })
1377            .await
1378            .expect("failed creating filter");
1379        testing::apply_tx(&node).await;
1380
1381        match node
1382            .get_filter_changes_impl(filter_id)
1383            .await
1384            .expect("failed getting filter changes")
1385        {
1386            FilterChanges::Logs(result) => assert_eq!(4, result.len()),
1387            changes => panic!("unexpected filter changes: {:?}", changes),
1388        }
1389
1390        match node
1391            .get_filter_changes_impl(filter_id)
1392            .await
1393            .expect("failed getting filter changes")
1394        {
1395            FilterChanges::Empty(_) => (),
1396            changes => panic!("expected no changes in the second call, got {:?}", changes),
1397        }
1398    }
1399
1400    #[tokio::test]
1401    async fn test_get_filter_changes_returns_pending_transaction_updates_only_once() {
1402        let node = InMemoryNode::test(None);
1403        let filter_id = node
1404            .new_pending_transaction_filter_impl()
1405            .await
1406            .expect("failed creating filter");
1407        let (_, _, tx) = testing::apply_tx(&node).await;
1408
1409        match node
1410            .get_filter_changes_impl(filter_id)
1411            .await
1412            .expect("failed getting filter changes")
1413        {
1414            FilterChanges::Hashes(result) => assert_eq!(vec![tx.hash()], result),
1415            changes => panic!("unexpected filter changes: {:?}", changes),
1416        }
1417
1418        match node
1419            .get_filter_changes_impl(filter_id)
1420            .await
1421            .expect("failed getting filter changes")
1422        {
1423            FilterChanges::Empty(_) => (),
1424            changes => panic!("expected no changes in the second call, got {:?}", changes),
1425        }
1426    }
1427
1428    #[tokio::test]
1429    async fn test_produced_block_archives_previous_blocks() {
1430        let node = InMemoryNode::test(None);
1431
1432        let input_storage_key = StorageKey::new(
1433            AccountTreeId::new(H160::repeat_byte(0x1)),
1434            u256_to_h256(U256::zero()),
1435        );
1436        let input_storage_value = H256::repeat_byte(0xcd);
1437        node.inner
1438            .write()
1439            .await
1440            .fork_storage
1441            .set_value(input_storage_key, input_storage_value);
1442        let initial_miniblock = node.blockchain.current_block_number().await;
1443
1444        testing::apply_tx(&node).await;
1445        let current_miniblock = node.blockchain.current_block_number().await;
1446
1447        for miniblock in initial_miniblock.0..current_miniblock.0 {
1448            let hash = node
1449                .blockchain
1450                .get_block_hash_by_number(L2BlockNumber(miniblock))
1451                .await
1452                .unwrap();
1453            let previous_state = node.inner.read().await.get_previous_state(hash).unwrap();
1454            let actual_cached_value = previous_state.get(&input_storage_key).copied();
1455
1456            assert_eq!(
1457                Some(input_storage_value),
1458                actual_cached_value,
1459                "unexpected cached state value for block {}",
1460                miniblock
1461            );
1462        }
1463    }
1464
1465    #[tokio::test]
1466    async fn test_get_storage_fetches_zero_value_for_non_existent_key() {
1467        let node = InMemoryNode::test(None);
1468
1469        let value = node
1470            .get_storage_impl(H160::repeat_byte(0xf1), U256::from(1024), None)
1471            .await
1472            .expect("failed retrieving storage");
1473        assert_eq!(H256::zero(), value);
1474    }
1475
1476    #[tokio::test]
1477    async fn test_get_storage_uses_fork_to_get_value_for_historical_block() {
1478        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1479            number: 10,
1480            transaction_count: 0,
1481            hash: H256::repeat_byte(0xab),
1482        });
1483        let input_address = H160::repeat_byte(0x1);
1484        let input_storage_value = H256::repeat_byte(0xcd);
1485        mock_server.expect(
1486            "eth_getStorageAt",
1487            Some(serde_json::json!([
1488                format!("{:#x}", input_address),
1489                "0x0",
1490                { "blockNumber": "0x2" },
1491            ])),
1492            serde_json::json!(format!("{:#x}", input_storage_value)),
1493        );
1494
1495        let node = test_node(mock_server.url()).await;
1496
1497        let actual_value = node
1498            .get_storage_impl(
1499                input_address,
1500                U256::zero(),
1501                Some(zksync_types::api::BlockIdVariant::BlockNumberObject(
1502                    BlockNumberObject {
1503                        block_number: BlockNumber::Number(U64::from(2)),
1504                    },
1505                )),
1506            )
1507            .await
1508            .expect("failed retrieving storage");
1509        assert_eq!(input_storage_value, actual_value);
1510    }
1511
1512    #[tokio::test]
1513    async fn test_get_storage_uses_archived_storage_to_get_value_for_missing_key() {
1514        let input_address = H160::repeat_byte(0x1);
1515        let input_storage_key = StorageKey::new(
1516            AccountTreeId::new(input_address),
1517            u256_to_h256(U256::zero()),
1518        );
1519        let input_storage_value = H256::repeat_byte(0xcd);
1520
1521        let node = InMemoryNode::test(None);
1522        {
1523            let mut writer = node.inner.write().await;
1524            let historical_block = Block::<TransactionVariant> {
1525                hash: H256::repeat_byte(0x2),
1526                number: U64::from(2),
1527                ..Default::default()
1528            };
1529            writer
1530                .insert_block_hash(L2BlockNumber(2), historical_block.hash)
1531                .await;
1532
1533            writer.insert_previous_state(
1534                historical_block.hash,
1535                hashmap! {
1536                    input_storage_key => input_storage_value,
1537                },
1538            );
1539            writer
1540                .insert_block(historical_block.hash, historical_block)
1541                .await;
1542        }
1543
1544        let actual_value = node
1545            .get_storage_impl(
1546                input_address,
1547                U256::zero(),
1548                Some(zksync_types::api::BlockIdVariant::BlockNumberObject(
1549                    BlockNumberObject {
1550                        block_number: BlockNumber::Number(U64::from(2)),
1551                    },
1552                )),
1553            )
1554            .await
1555            .expect("failed retrieving storage");
1556        assert_eq!(input_storage_value, actual_value);
1557    }
1558
1559    // FIXME: Multi-threaded flavor is needed because of the `block_on` mess inside `ForkStorage`.
1560    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
1561    async fn test_get_storage_uses_fork_to_get_value_for_latest_block_for_missing_key() {
1562        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1563            number: 10,
1564            transaction_count: 0,
1565            hash: H256::repeat_byte(0xab),
1566        });
1567        let input_address = H160::repeat_byte(0x1);
1568        let input_storage_value = H256::repeat_byte(0xcd);
1569        mock_server.expect(
1570            "eth_getStorageAt",
1571            Some(serde_json::json!([
1572                format!("{:#x}", input_address),
1573                "0x0",
1574                "0xa",
1575            ])),
1576            serde_json::json!(format!("{:#x}", input_storage_value)),
1577        );
1578
1579        let node = test_node(mock_server.url()).await;
1580        {
1581            let mut writer = node.inner.write().await;
1582            let historical_block = Block::<TransactionVariant> {
1583                hash: H256::repeat_byte(0x2),
1584                number: U64::from(2),
1585                ..Default::default()
1586            };
1587            writer
1588                .insert_block_hash(L2BlockNumber(2), historical_block.hash)
1589                .await;
1590            writer.insert_previous_state(historical_block.hash, Default::default());
1591            writer
1592                .insert_block(historical_block.hash, historical_block)
1593                .await;
1594        };
1595
1596        let actual_value = node
1597            .get_storage_impl(
1598                input_address,
1599                U256::zero(),
1600                Some(zksync_types::api::BlockIdVariant::BlockNumberObject(
1601                    BlockNumberObject {
1602                        block_number: BlockNumber::Number(U64::from(2)),
1603                    },
1604                )),
1605            )
1606            .await
1607            .expect("failed retrieving storage");
1608        assert_eq!(input_storage_value, actual_value);
1609    }
1610
1611    #[tokio::test]
1612    async fn test_get_storage_fetches_state_for_deployed_smart_contract_in_current_block() {
1613        let node = InMemoryNode::test(None);
1614
1615        let private_key = K256PrivateKey::from_bytes(H256::repeat_byte(0xef)).unwrap();
1616        let from_account = private_key.address();
1617        node.set_rich_account(from_account, U256::from(DEFAULT_ACCOUNT_BALANCE))
1618            .await;
1619
1620        let deployed_address = deployed_address_create(from_account, U256::zero());
1621
1622        testing::deploy_contract(
1623            &node,
1624            &private_key,
1625            hex::decode(testing::STORAGE_CONTRACT_BYTECODE).unwrap(),
1626            None,
1627            Nonce(0),
1628        )
1629        .await;
1630
1631        let number1 = node
1632            .get_storage_impl(deployed_address, U256::from(0), None)
1633            .await
1634            .expect("failed retrieving storage at slot 0");
1635        assert_eq!(U256::from(1024), h256_to_u256(number1));
1636
1637        let number2 = node
1638            .get_storage_impl(deployed_address, U256::from(1), None)
1639            .await
1640            .expect("failed retrieving storage at slot 1");
1641        assert_eq!(U256::MAX, h256_to_u256(number2));
1642    }
1643
1644    #[tokio::test]
1645    async fn test_get_storage_fetches_state_for_deployed_smart_contract_in_old_block() {
1646        let node = InMemoryNode::test(None);
1647
1648        let private_key = K256PrivateKey::from_bytes(H256::repeat_byte(0xef)).unwrap();
1649        let from_account = private_key.address();
1650        node.set_rich_account(from_account, U256::from(DEFAULT_ACCOUNT_BALANCE))
1651            .await;
1652
1653        let deployed_address = deployed_address_create(from_account, U256::zero());
1654
1655        let initial_block_hash = testing::deploy_contract(
1656            &node,
1657            &private_key,
1658            hex::decode(testing::STORAGE_CONTRACT_BYTECODE).unwrap(),
1659            None,
1660            Nonce(0),
1661        )
1662        .await;
1663
1664        // simulate a tx modifying the storage
1665        testing::apply_tx(&node).await;
1666        let key = StorageKey::new(
1667            AccountTreeId::new(deployed_address),
1668            u256_to_h256(U256::from(0)),
1669        );
1670        node.inner
1671            .write()
1672            .await
1673            .fork_storage
1674            .inner
1675            .write()
1676            .unwrap()
1677            .raw_storage
1678            .state
1679            .insert(key, u256_to_h256(U256::from(512)));
1680
1681        let number1_current = node
1682            .get_storage_impl(deployed_address, U256::from(0), None)
1683            .await
1684            .expect("failed retrieving storage at slot 0");
1685        assert_eq!(U256::from(512), h256_to_u256(number1_current));
1686
1687        let number1_old = node
1688            .get_storage_impl(
1689                deployed_address,
1690                U256::from(0),
1691                Some(api::BlockIdVariant::BlockHashObject(BlockHashObject {
1692                    block_hash: initial_block_hash,
1693                })),
1694            )
1695            .await
1696            .expect("failed retrieving storage at slot 0");
1697        assert_eq!(U256::from(1024), h256_to_u256(number1_old));
1698    }
1699
1700    #[tokio::test]
1701    async fn test_get_filter_logs_returns_matching_logs_for_valid_id() {
1702        let node = InMemoryNode::test(None);
1703
1704        // populate tx receipts with 2 tx each having logs
1705        {
1706            let mut writer = node.inner.write().await;
1707            writer
1708                .insert_tx_result(
1709                    H256::repeat_byte(0x1),
1710                    TransactionResult {
1711                        info: testing::default_tx_execution_info(),
1712                        new_bytecodes: vec![],
1713                        receipt: TransactionReceipt {
1714                            logs: vec![LogBuilder::new()
1715                                .set_address(H160::repeat_byte(0xa1))
1716                                .build()],
1717                            ..Default::default()
1718                        },
1719                        debug: default_tx_debug_info(),
1720                    },
1721                )
1722                .await;
1723            writer
1724                .insert_tx_result(
1725                    H256::repeat_byte(0x2),
1726                    TransactionResult {
1727                        info: testing::default_tx_execution_info(),
1728                        new_bytecodes: vec![],
1729                        receipt: TransactionReceipt {
1730                            logs: vec![
1731                                LogBuilder::new()
1732                                    .set_address(H160::repeat_byte(0xa1))
1733                                    .build(),
1734                                LogBuilder::new()
1735                                    .set_address(H160::repeat_byte(0xa2))
1736                                    .build(),
1737                            ],
1738                            ..Default::default()
1739                        },
1740                        debug: default_tx_debug_info(),
1741                    },
1742                )
1743                .await;
1744        }
1745
1746        let filter_id = node
1747            .new_filter_impl(Filter {
1748                address: Some(ValueOrArray(vec![H160::repeat_byte(0xa1)])),
1749                ..Default::default()
1750            })
1751            .await
1752            .expect("failed creating filter");
1753
1754        match node
1755            .get_filter_logs_impl(filter_id)
1756            .await
1757            .expect("failed getting filter changes")
1758        {
1759            FilterChanges::Logs(result) => assert_eq!(2, result.len()),
1760            changes => panic!("unexpected filter changes: {:?}", changes),
1761        }
1762    }
1763
1764    #[tokio::test]
1765    async fn test_get_filter_logs_returns_error_for_invalid_id() {
1766        let node = InMemoryNode::test(None);
1767
1768        // populate tx receipts with 2 tx each having logs
1769        {
1770            let mut writer = node.inner.write().await;
1771            writer
1772                .insert_tx_result(
1773                    H256::repeat_byte(0x1),
1774                    TransactionResult {
1775                        info: testing::default_tx_execution_info(),
1776                        new_bytecodes: vec![],
1777                        receipt: TransactionReceipt {
1778                            logs: vec![LogBuilder::new()
1779                                .set_address(H160::repeat_byte(0xa1))
1780                                .build()],
1781                            ..Default::default()
1782                        },
1783                        debug: default_tx_debug_info(),
1784                    },
1785                )
1786                .await;
1787        }
1788
1789        let invalid_filter_id = U256::from(100);
1790        let result = node.get_filter_logs_impl(invalid_filter_id).await;
1791
1792        assert!(result.is_err(), "expected an error for invalid filter id");
1793    }
1794
1795    #[tokio::test]
1796    async fn test_get_logs_returns_matching_logs() {
1797        let node = InMemoryNode::test(None);
1798
1799        // populate tx receipts with 2 tx each having logs
1800        {
1801            let mut writer = node.inner.write().await;
1802            writer
1803                .insert_tx_result(
1804                    H256::repeat_byte(0x1),
1805                    TransactionResult {
1806                        info: testing::default_tx_execution_info(),
1807                        new_bytecodes: vec![],
1808                        receipt: TransactionReceipt {
1809                            logs: vec![LogBuilder::new()
1810                                .set_address(H160::repeat_byte(0xa1))
1811                                .build()],
1812                            ..Default::default()
1813                        },
1814                        debug: testing::default_tx_debug_info(),
1815                    },
1816                )
1817                .await;
1818            writer
1819                .insert_tx_result(
1820                    H256::repeat_byte(0x2),
1821                    TransactionResult {
1822                        info: testing::default_tx_execution_info(),
1823                        new_bytecodes: vec![],
1824                        receipt: TransactionReceipt {
1825                            logs: vec![
1826                                LogBuilder::new()
1827                                    .set_address(H160::repeat_byte(0xa1))
1828                                    .build(),
1829                                LogBuilder::new()
1830                                    .set_address(H160::repeat_byte(0xa2))
1831                                    .build(),
1832                            ],
1833                            ..Default::default()
1834                        },
1835                        debug: testing::default_tx_debug_info(),
1836                    },
1837                )
1838                .await;
1839        }
1840
1841        let result = node
1842            .get_logs_impl(Filter {
1843                address: Some(ValueOrArray(vec![H160::repeat_byte(0xa2)])),
1844                ..Default::default()
1845            })
1846            .await
1847            .expect("failed getting filter changes");
1848        assert_eq!(1, result.len());
1849
1850        let result = node
1851            .get_logs_impl(Filter {
1852                address: Some(ValueOrArray(vec![H160::repeat_byte(0xa1)])),
1853                ..Default::default()
1854            })
1855            .await
1856            .expect("failed getting filter changes");
1857        assert_eq!(2, result.len());
1858
1859        let result = node
1860            .get_logs_impl(Filter {
1861                address: Some(ValueOrArray(vec![H160::repeat_byte(0x11)])),
1862                ..Default::default()
1863            })
1864            .await
1865            .expect("failed getting filter changes");
1866        assert_eq!(0, result.len());
1867    }
1868
1869    #[tokio::test]
1870    async fn test_accounts_impl() {
1871        let node = InMemoryNode::test(None);
1872
1873        let private_key = H256::repeat_byte(0x01);
1874        let from_account = K256PrivateKey::from_bytes(private_key).unwrap().address();
1875        node.set_rich_account(from_account, U256::from(DEFAULT_ACCOUNT_BALANCE))
1876            .await;
1877
1878        let account_result = node.accounts_impl().await;
1879        let expected_accounts: Vec<H160> = vec![from_account];
1880
1881        match account_result {
1882            Ok(accounts) => {
1883                assert_eq!(expected_accounts, accounts);
1884            }
1885            Err(e) => {
1886                panic!("Failed to fetch accounts: {:?}", e);
1887            }
1888        }
1889    }
1890
1891    #[tokio::test]
1892    async fn test_get_transaction_by_block_hash_and_index_returns_none_for_invalid_block_hash() {
1893        let node = InMemoryNode::test(None);
1894        let (input_block_hash, _, _) = testing::apply_tx(&node).await;
1895        let invalid_block_hash = H256::repeat_byte(0xab);
1896        assert_ne!(input_block_hash, invalid_block_hash);
1897
1898        let result = node
1899            .get_transaction_by_block_and_index_impl(
1900                api::BlockId::Hash(invalid_block_hash),
1901                U64::from(0),
1902            )
1903            .await
1904            .expect("failed fetching transaction");
1905
1906        assert!(result.is_none());
1907    }
1908
1909    #[tokio::test]
1910    async fn test_get_transaction_by_block_hash_and_index_returns_none_for_invalid_index() {
1911        let node = InMemoryNode::test(None);
1912        let (input_block_hash, _, _) = testing::apply_tx(&node).await;
1913
1914        let result = node
1915            .get_transaction_by_block_and_index_impl(
1916                api::BlockId::Hash(input_block_hash),
1917                U64::from(10),
1918            )
1919            .await
1920            .expect("failed fetching transaction");
1921
1922        assert!(result.is_none());
1923    }
1924
1925    #[tokio::test]
1926    async fn test_get_transaction_by_block_hash_and_index_returns_transaction_for_valid_input() {
1927        let node = InMemoryNode::test(None);
1928        let (input_block_hash, _, tx) = testing::apply_tx(&node).await;
1929
1930        let actual_tx = node
1931            .get_transaction_by_block_and_index_impl(
1932                api::BlockId::Hash(input_block_hash),
1933                U64::from(0),
1934            )
1935            .await
1936            .expect("failed fetching transaction")
1937            .expect("no transaction");
1938
1939        assert_eq!(tx.hash(), actual_tx.hash);
1940    }
1941
1942    #[tokio::test]
1943    async fn test_get_transaction_by_block_hash_and_index_fetches_from_fork_if_block_missing() {
1944        let mock_server = MockServer::run_with_config(ForkBlockConfig {
1945            number: 10,
1946            transaction_count: 0,
1947            hash: H256::repeat_byte(0xab),
1948        });
1949        let input_block_hash = H256::repeat_byte(0x01);
1950        let input_tx_hash = H256::repeat_byte(0x02);
1951        mock_server.expect(
1952            "eth_getTransactionByBlockHashAndIndex",
1953            Some(serde_json::json!([
1954                format!("{:#x}", input_block_hash),
1955                "0x1"
1956            ])),
1957            TransactionResponseBuilder::new()
1958                .set_hash(input_tx_hash)
1959                .set_block_hash(input_block_hash)
1960                .set_block_number(U64::from(100))
1961                .build_result(),
1962        );
1963
1964        let node = test_node(mock_server.url()).await;
1965
1966        let actual_tx = node
1967            .get_transaction_by_block_and_index_impl(
1968                api::BlockId::Hash(input_block_hash),
1969                U64::from(1),
1970            )
1971            .await
1972            .expect("failed fetching transaction")
1973            .expect("no transaction");
1974
1975        assert_eq!(input_tx_hash, actual_tx.hash);
1976        assert_eq!(Some(U64::from(100)), actual_tx.block_number);
1977    }
1978
1979    #[tokio::test]
1980    async fn test_get_transaction_by_block_number_and_index_returns_none_for_invalid_block_number()
1981    {
1982        let node = InMemoryNode::test(None);
1983        let (input_block_hash, _, _) = testing::apply_tx(&node).await;
1984        let invalid_block_hash = H256::repeat_byte(0xab);
1985        assert_ne!(input_block_hash, invalid_block_hash);
1986
1987        let result = node
1988            .get_transaction_by_block_and_index_impl(
1989                api::BlockId::Number(BlockNumber::Number(U64::from(100))),
1990                U64::from(0),
1991            )
1992            .await
1993            .expect("failed fetching transaction");
1994
1995        assert!(result.is_none());
1996    }
1997
1998    #[tokio::test]
1999    async fn test_get_transaction_by_block_number_and_index_returns_none_for_invalid_index() {
2000        let node = InMemoryNode::test(None);
2001        testing::apply_tx(&node).await;
2002
2003        let result = node
2004            .get_transaction_by_block_and_index_impl(
2005                api::BlockId::Number(BlockNumber::Latest),
2006                U64::from(10),
2007            )
2008            .await
2009            .expect("failed fetching transaction");
2010
2011        assert!(result.is_none());
2012    }
2013
2014    #[tokio::test]
2015    async fn test_get_transaction_by_block_number_and_index_returns_transaction_for_valid_input() {
2016        let node = InMemoryNode::test(None);
2017        let (_, input_block_number, tx) = testing::apply_tx(&node).await;
2018
2019        let actual_tx = node
2020            .get_transaction_by_block_and_index_impl(
2021                api::BlockId::Number(BlockNumber::Number(U64::from(input_block_number.0))),
2022                U64::from(0),
2023            )
2024            .await
2025            .expect("failed fetching transaction")
2026            .expect("no transaction");
2027
2028        assert_eq!(tx.hash(), actual_tx.hash);
2029    }
2030
2031    #[tokio::test]
2032    async fn test_get_transaction_by_block_number_and_index_fetches_from_fork_if_block_missing() {
2033        let mock_server = MockServer::run_with_config(ForkBlockConfig {
2034            number: 10,
2035            transaction_count: 0,
2036            hash: H256::repeat_byte(0xab),
2037        });
2038        let input_block_hash = H256::repeat_byte(0x01);
2039        let input_block_number = U64::from(100);
2040        let input_tx_hash = H256::repeat_byte(0x02);
2041        mock_server.expect(
2042            "eth_getTransactionByBlockNumberAndIndex",
2043            Some(serde_json::json!([
2044                format!("{:#x}", input_block_number),
2045                "0x1"
2046            ])),
2047            TransactionResponseBuilder::new()
2048                .set_hash(input_tx_hash)
2049                .set_block_hash(input_block_hash)
2050                .set_block_number(input_block_number)
2051                .build_result(),
2052        );
2053
2054        let node = test_node(mock_server.url()).await;
2055
2056        let actual_tx = node
2057            .get_transaction_by_block_and_index_impl(
2058                api::BlockId::Number(BlockNumber::Number(input_block_number)),
2059                U64::from(1),
2060            )
2061            .await
2062            .expect("failed fetching transaction")
2063            .expect("no transaction");
2064
2065        assert_eq!(input_tx_hash, actual_tx.hash);
2066        assert_eq!(Some(input_block_number), actual_tx.block_number);
2067    }
2068
2069    #[tokio::test]
2070    async fn test_protocol_version_returns_currently_supported_version() {
2071        let node = InMemoryNode::test(None);
2072
2073        let expected_version = String::from(PROTOCOL_VERSION);
2074        let actual_version = node.protocol_version_impl();
2075
2076        assert_eq!(expected_version, actual_version);
2077    }
2078}