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 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 if tx.gas.is_none() {
139 tx.gas = Some(U256::from(MAX_L1_TRANSACTION_GAS_LIMIT));
140 }
141
142 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 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 _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 _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 _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 Ok(account_nonce)
294 } else {
295 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 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 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 _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 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 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 _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 .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 let gas_used_ratio = vec![0.0; base_fee_per_gas.len()];
538 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.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 let node = InMemoryNode::test(None);
657 testing::apply_tx(&node).await;
658
659 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_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, gas_limit: U256::from(get_max_batch_gas_limit(VmVersion::latest())),
780 base_fee_per_gas: actual_block.base_fee_per_gas, extra_data: Default::default(),
782 logs_bloom: actual_block.logs_bloom, 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 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, gas_limit: U256::from(get_max_batch_gas_limit(VmVersion::latest())),
903 base_fee_per_gas: actual_block.base_fee_per_gas, extra_data: Default::default(),
905 logs_bloom: actual_block.logs_bloom, 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 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, r: actual_tx.r, s: actual_tx.s, y_parity: actual_tx.y_parity, 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 }
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 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 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 #[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 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 {
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 {
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 {
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}