diff --git a/src/fork.rs b/src/fork.rs index 6dc4ccb4..6eced8eb 100644 --- a/src/fork.rs +++ b/src/fork.rs @@ -100,61 +100,61 @@ impl ForkStorage { } } - fn read_value_internal(&self, key: &StorageKey) -> zksync_types::StorageValue { + pub fn read_value_internal( + &self, + key: &StorageKey, + ) -> eyre::Result { let mut mutator = self.inner.write().unwrap(); let local_storage = mutator.raw_storage.read_value(key); if let Some(fork) = &mutator.fork { if !H256::is_zero(&local_storage) { - return local_storage; + return Ok(local_storage); } if let Some(value) = mutator.value_read_cache.get(key) { - return *value; + return Ok(*value); } let l2_miniblock = fork.l2_miniblock; let key_ = *key; - let result = fork - .fork_source - .get_storage_at( - *key_.account().address(), - h256_to_u256(*key_.key()), - Some(BlockIdVariant::BlockNumber(BlockNumber::Number(U64::from( - l2_miniblock, - )))), - ) - .unwrap(); + let result = fork.fork_source.get_storage_at( + *key_.account().address(), + h256_to_u256(*key_.key()), + Some(BlockIdVariant::BlockNumber(BlockNumber::Number(U64::from( + l2_miniblock, + )))), + )?; mutator.value_read_cache.insert(*key, result); - result + Ok(result) } else { - local_storage + Ok(local_storage) } } - fn load_factory_dep_internal(&self, hash: H256) -> Option> { + pub fn load_factory_dep_internal(&self, hash: H256) -> eyre::Result>> { let mut mutator = self.inner.write().unwrap(); let local_storage = mutator.raw_storage.load_factory_dep(hash); if let Some(fork) = &mutator.fork { if local_storage.is_some() { - return local_storage; + return Ok(local_storage); } if let Some(value) = mutator.factory_dep_cache.get(&hash) { - return value.clone(); + return Ok(value.clone()); } - let result = fork.fork_source.get_bytecode_by_hash(hash).unwrap(); + let result = fork.fork_source.get_bytecode_by_hash(hash)?; mutator.factory_dep_cache.insert(hash, result.clone()); - result + Ok(result) } else { - local_storage + Ok(local_storage) } } /// Check if this is the first time when we're ever writing to this key. /// This has impact on amount of pubdata that we have to spend for the write. - fn is_write_initial_internal(&self, key: &StorageKey) -> bool { + pub fn is_write_initial_internal(&self, key: &StorageKey) -> eyre::Result { // Currently we don't have the zks API to return us the information on whether a given // key was written to before a given block. // This means, we have to depend on the following heuristic: we'll read the value of the slot. @@ -162,15 +162,15 @@ impl ForkStorage { // - but if the value = 0 - there is a chance, that slot was written to in the past - and later was reset. // but unfortunately we cannot detect that with the current zks api, so we'll attempt to do it // only on local storage. - let value = self.read_value_internal(key); + let value = self.read_value_internal(key)?; if value != H256::zero() { - return false; + return Ok(false); } // If value was 0, there is still a chance, that the slot was written to in the past - and only now set to 0. // We unfortunately don't have the API to check it on the fork, but we can at least try to check it on local storage. let mut mutator = self.inner.write().unwrap(); - mutator.raw_storage.is_write_initial(key) + Ok(mutator.raw_storage.is_write_initial(key)) } /// Retrieves the enumeration index for a given `key`. @@ -182,15 +182,15 @@ impl ForkStorage { impl ReadStorage for ForkStorage { fn is_write_initial(&mut self, key: &StorageKey) -> bool { - self.is_write_initial_internal(key) + self.is_write_initial_internal(key).unwrap() } fn load_factory_dep(&mut self, hash: H256) -> Option> { - self.load_factory_dep_internal(hash) + self.load_factory_dep_internal(hash).unwrap() } fn read_value(&mut self, key: &StorageKey) -> zksync_types::StorageValue { - self.read_value_internal(key) + self.read_value_internal(key).unwrap() } fn get_enumeration_index(&mut self, key: &StorageKey) -> Option { @@ -200,15 +200,15 @@ impl ReadStorage for ForkStorage { impl ReadStorage for &ForkStorage { fn read_value(&mut self, key: &StorageKey) -> zksync_types::StorageValue { - self.read_value_internal(key) + self.read_value_internal(key).unwrap() } fn is_write_initial(&mut self, key: &StorageKey) -> bool { - self.is_write_initial_internal(key) + self.is_write_initial_internal(key).unwrap() } fn load_factory_dep(&mut self, hash: H256) -> Option> { - self.load_factory_dep_internal(hash) + self.load_factory_dep_internal(hash).unwrap() } fn get_enumeration_index(&mut self, key: &StorageKey) -> Option { diff --git a/src/node/eth.rs b/src/node/eth.rs index aeb61750..3a0e3366 100644 --- a/src/node/eth.rs +++ b/src/node/eth.rs @@ -9,7 +9,6 @@ use zksync_basic_types::{ web3::{self, Bytes}, AccountTreeId, Address, H160, H256, U256, U64, }; -use zksync_state::ReadStorage; use zksync_types::{ api::{Block, BlockIdVariant, BlockNumber, TransactionVariant}, fee::Fee, @@ -30,7 +29,10 @@ use crate::{ fork::ForkSource, namespaces::{EthNamespaceT, EthTestNodeNamespaceT, RpcResult}, node::{InMemoryNode, TransactionResult, MAX_TX_SIZE, PROTOCOL_VERSION}, - utils::{self, h256_to_u64, into_jsrpc_error, not_implemented, IntoBoxedFuture}, + utils::{ + self, h256_to_u64, into_jsrpc_error, not_implemented, report_into_jsrpc_error, + IntoBoxedFuture, + }, }; impl EthNamespaceT @@ -137,9 +139,11 @@ impl EthNamespa ); match inner.write() { - Ok(mut inner_guard) => { - let balance = inner_guard.fork_storage.read_value(&balance_key); - Ok(h256_to_u256(balance)) + Ok(inner_guard) => { + match inner_guard.fork_storage.read_value_internal(&balance_key) { + Ok(balance) => Ok(h256_to_u256(balance)), + Err(error) => Err(report_into_jsrpc_error(error)), + } } Err(_) => { let error_message = "Error acquiring write lock for balance retrieval"; @@ -259,16 +263,18 @@ impl EthNamespa let code_key = get_code_key(&address); match inner.write() { - Ok(mut guard) => { - let code_hash = guard.fork_storage.read_value(&code_key); - - let code = guard - .fork_storage - .load_factory_dep(code_hash) - .unwrap_or_default(); - - Ok(Bytes::from(code)) - } + Ok(guard) => match guard.fork_storage.read_value_internal(&code_key) { + Ok(code_hash) => { + match guard.fork_storage.load_factory_dep_internal(code_hash) { + Ok(raw_code) => { + let code = raw_code.unwrap_or_default(); + Ok(Bytes::from(code)) + } + Err(error) => Err(report_into_jsrpc_error(error)), + } + } + Err(error) => Err(report_into_jsrpc_error(error)), + }, Err(_) => Err(into_jsrpc_error(Web3Error::InternalError( anyhow::Error::msg("Failed to acquire write lock for code retrieval"), ))), @@ -297,10 +303,10 @@ impl EthNamespa let nonce_key = get_nonce_key(&address); match inner.write() { - Ok(mut guard) => { - let result = guard.fork_storage.read_value(&nonce_key); - Ok(h256_to_u64(result).into()) - } + Ok(guard) => match guard.fork_storage.read_value_internal(&nonce_key) { + Ok(result) => Ok(h256_to_u64(result).into()), + Err(error) => Err(report_into_jsrpc_error(error)), + }, Err(_) => Err(into_jsrpc_error(Web3Error::InternalError( anyhow::Error::msg("Failed to acquire write lock for nonce retrieval"), ))), @@ -1020,7 +1026,7 @@ impl EthNamespa let inner = self.get_inner().clone(); Box::pin(async move { - let mut writer = match inner.write() { + let writer = match inner.write() { Ok(r) => r, Err(_) => { return Err(into_jsrpc_error(Web3Error::InternalError( @@ -1058,7 +1064,10 @@ impl EthNamespa .unwrap_or_else(|| Ok(U64::from(writer.current_miniblock)))?; if block_number.as_u64() == writer.current_miniblock { - Ok(H256(writer.fork_storage.read_value(&storage_key).0)) + match writer.fork_storage.read_value_internal(&storage_key) { + Ok(value) => Ok(H256(value.0)), + Err(error) => Err(report_into_jsrpc_error(error)), + } } else if writer.block_hashes.contains_key(&block_number.as_u64()) { let value = writer .block_hashes @@ -1069,7 +1078,10 @@ impl EthNamespa .unwrap_or_default(); if value.is_zero() { - Ok(H256(writer.fork_storage.read_value(&storage_key).0)) + match writer.fork_storage.read_value_internal(&storage_key) { + Ok(value) => Ok(H256(value.0)), + Err(error) => Err(report_into_jsrpc_error(error)), + } } else { Ok(value) } diff --git a/src/node/in_memory_ext.rs b/src/node/in_memory_ext.rs index 77c25e62..a20c3cab 100644 --- a/src/node/in_memory_ext.rs +++ b/src/node/in_memory_ext.rs @@ -1,6 +1,5 @@ use anyhow::anyhow; use zksync_basic_types::{Address, U256, U64}; -use zksync_state::ReadStorage; use zksync_types::{ get_code_key, get_nonce_key, utils::{decompose_full_nonce, nonces_to_full_nonce, storage_key_for_eth_balance}, @@ -210,7 +209,12 @@ impl InMemoryNo .map_err(|err| anyhow!("failed acquiring lock: {:?}", err)) .and_then(|mut writer| { let nonce_key = get_nonce_key(&address); - let full_nonce = writer.fork_storage.read_value(&nonce_key); + let full_nonce = match writer.fork_storage.read_value_internal(&nonce_key) { + Ok(full_nonce) => full_nonce, + Err(error) => { + return Err(anyhow!(error.to_string())); + } + }; let (mut account_nonce, mut deployment_nonce) = decompose_full_nonce(h256_to_u256(full_nonce)); if account_nonce >= nonce { diff --git a/src/node/zks.rs b/src/node/zks.rs index e21ed855..0fda2e81 100644 --- a/src/node/zks.rs +++ b/src/node/zks.rs @@ -4,7 +4,6 @@ use bigdecimal::BigDecimal; use colored::Colorize; use futures::FutureExt; use zksync_basic_types::{AccountTreeId, Address, L1BatchNumber, L2BlockNumber, H256, U256}; -use zksync_state::ReadStorage; use zksync_types::{ api::{ BlockDetails, BlockDetailsBase, BlockStatus, BridgeAddresses, Proof, ProtocolVersion, @@ -22,8 +21,8 @@ use crate::{ namespaces::{RpcResult, ZksNamespaceT}, node::{InMemoryNode, TransactionResult}, utils::{ - internal_error, into_jsrpc_error, not_implemented, utc_datetime_from_epoch_ms, - IntoBoxedFuture, + internal_error, into_jsrpc_error, not_implemented, report_into_jsrpc_error, + utc_datetime_from_epoch_ms, IntoBoxedFuture, }, }; @@ -295,7 +294,7 @@ impl ZksNamespa })?; let balances = { - let mut writer = inner.write().map_err(|_e| { + let writer = inner.write().map_err(|_e| { let error_message = "Failed to acquire lock. Please ensure the lock is not being held by another process or thread.".to_string(); into_jsrpc_error(Web3Error::InternalError(anyhow::Error::msg(error_message))) })?; @@ -305,7 +304,12 @@ impl ZksNamespa AccountTreeId::new(token.l2_address), &address, ); - let balance = writer.fork_storage.read_value(&balance_key); + let balance = match writer.fork_storage.read_value_internal(&balance_key) { + Ok(balance) => balance, + Err(error) => { + return Err(report_into_jsrpc_error(error)); + } + }; if !balance.is_zero() { balances.insert(token.l2_address, h256_to_u256(balance)); } @@ -513,24 +517,41 @@ impl ZksNamespa fn get_bytecode_by_hash(&self, hash: zksync_basic_types::H256) -> RpcResult>> { let inner = self.get_inner().clone(); Box::pin(async move { - let mut writer = inner.write().map_err(|_e| { + let writer = inner.write().map_err(|_e| { into_jsrpc_error(Web3Error::InternalError(anyhow::Error::msg( "Failed to acquire write lock for bytecode retrieval.", ))) })?; - let maybe_bytecode = writer.fork_storage.load_factory_dep(hash).or_else(|| { - writer - .fork_storage - .inner - .read() - .expect("failed reading fork storage") - .fork - .as_ref() - .and_then(|fork| fork.fork_source.get_bytecode_by_hash(hash).ok().flatten()) - }); - - Ok(maybe_bytecode) + let maybe_bytecode = match writer.fork_storage.load_factory_dep_internal(hash) { + Ok(maybe_bytecode) => maybe_bytecode, + Err(error) => { + return Err(report_into_jsrpc_error(error)); + } + }; + + if maybe_bytecode.is_some() { + return Ok(maybe_bytecode); + } + + let maybe_fork_details = &writer + .fork_storage + .inner + .read() + .expect("failed reading fork storage") + .fork; + if let Some(fork_details) = maybe_fork_details { + let maybe_bytecode = match fork_details.fork_source.get_bytecode_by_hash(hash) { + Ok(maybe_bytecode) => maybe_bytecode, + Err(error) => { + return Err(report_into_jsrpc_error(error)); + } + }; + + Ok(maybe_bytecode) + } else { + Ok(None) + } }) } diff --git a/src/utils.rs b/src/utils.rs index 669f85bc..872cc416 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -229,6 +229,12 @@ pub fn utc_datetime_from_epoch_ms(millis: u64) -> DateTime { DateTime::::from_timestamp(secs as i64, nanos as u32).expect("valid timestamp") } +pub fn report_into_jsrpc_error(error: eyre::Report) -> Error { + into_jsrpc_error(Web3Error::InternalError(anyhow::Error::msg( + error.to_string(), + ))) +} + pub fn into_jsrpc_error(err: Web3Error) -> Error { Error { code: match err {