From 5bcc0e4b2cd90d1e3afdd8c2e629e898f297c7ac Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 14:41:56 -0300 Subject: [PATCH 01/10] Add ChainData table to libmdx impl --- crates/storage/libmdbx.rs | 47 ++++++++++++++++++++++++++++++++++++++- crates/storage/storage.rs | 10 ++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/crates/storage/libmdbx.rs b/crates/storage/libmdbx.rs index 1ea4c18c0fd..7e0d8e26821 100644 --- a/crates/storage/libmdbx.rs +++ b/crates/storage/libmdbx.rs @@ -6,10 +6,12 @@ use crate::rlp::{ }; use anyhow::Result; use bytes::Bytes; +use ethereum_rust_core::rlp::decode::RLPDecode; +use ethereum_rust_core::rlp::encode::RLPEncode; use ethereum_rust_core::types::{ AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, Index, Receipt, }; -use ethereum_types::{Address, H256}; +use ethereum_types::{Address, H256, U256}; use libmdbx::orm::{Decodable, Encodable}; use libmdbx::{ dupsort, @@ -269,6 +271,30 @@ impl StoreEngine for Store { .map_err(StoreError::LibmdbxError)?; txn.commit().map_err(StoreError::LibmdbxError) } + + fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::(ChainDataIndex::ChainId, chain_id.encode_to_vec()) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_chain_id(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::ChainId) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => U256::decode(rlp) + .map(|ci| Some(ci)) + .map_err(|_| StoreError::DecodeError), + } + } } impl Debug for Store { @@ -314,6 +340,11 @@ table!( ( TransactionLocations ) TransactionHashRLP => (BlockNumber, Index) ); +table!( + /// Stores chain data, each value is unique and stored as its rlp encoding + ( ChainData ) ChainDataIndex => Vec +); + // Storage values are stored as bytes instead of using their rlp encoding // As they are stored in a dupsort table, they need to have a fixed size, and encoding them doesn't preserve their size pub struct AccountStorageKeyBytes(pub [u8; 32]); @@ -365,6 +396,20 @@ impl From for H256 { } } +// Represents the key for each unique value of the chain data +enum ChainDataIndex { + ChainId = 0, + LatestBlockNumber = 1, +} + +impl Encodable for ChainDataIndex { + type Encoded = [u8; 4]; + + fn encode(self) -> Self::Encoded { + (self as u32).encode() + } +} + /// Initializes a new database with the provided path. If the path is `None`, the database /// will be temporary. pub fn init_db(path: Option>) -> Database { diff --git a/crates/storage/storage.rs b/crates/storage/storage.rs index 17025004d98..95573e69775 100644 --- a/crates/storage/storage.rs +++ b/crates/storage/storage.rs @@ -18,7 +18,7 @@ use ethereum_rust_core::types::{ Account, AccountInfo, Block, BlockBody, BlockHash, BlockHeader, BlockNumber, Genesis, Index, Receipt, Transaction, }; -use ethereum_types::{Address, H256}; +use ethereum_types::{Address, H256, U256}; use std::fmt::Debug; use std::sync::{Arc, Mutex}; use tracing::info; @@ -186,6 +186,12 @@ pub trait StoreEngine: Debug + Send { self.remove_account_info(address)?; self.remove_account_storage(address) } + + /// Updates the value of the chain id + fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError>; + + /// Obtain the current chain id + fn get_chain_id(&self) -> Result, StoreError>; } #[derive(Debug, Clone)] @@ -427,6 +433,8 @@ impl Store { for (address, account) in genesis.alloc.into_iter() { self.add_account(address, account.into())?; } + + // Store chain info Ok(()) } From c145e8fdf5663dec92ea4b1e8d6784deb93cb0ec Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:02:12 -0300 Subject: [PATCH 02/10] Store chain id when storing genesis --- crates/storage/engines/libmdbx.rs | 1 + crates/storage/storage.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 9b3abfd8ceb..78343959190 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -414,6 +414,7 @@ pub fn init_db(path: Option>) -> Database { table_info!(AccountCodes), table_info!(Receipts), table_info!(TransactionLocations), + table_info!(ChainData), ] .into_iter() .collect(); diff --git a/crates/storage/storage.rs b/crates/storage/storage.rs index 0165ab54e97..a9b76edbb31 100644 --- a/crates/storage/storage.rs +++ b/crates/storage/storage.rs @@ -247,7 +247,7 @@ impl Store { } // Store chain info - Ok(()) + self.update_chain_id(genesis.config.chain_id) } pub fn get_transaction_by_hash( @@ -290,6 +290,14 @@ impl Store { pub fn remove_account(&self, address: Address) -> Result<(), StoreError> { self.engine.lock().unwrap().remove_account(address) } + + pub fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { + self.engine.lock().unwrap().update_chain_id(chain_id) + } + + pub fn get_chain_id(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_chain_id() + } } #[cfg(test)] From 361f8460234383f2dd81d9c4e4edebf6288c4139 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:08:19 -0300 Subject: [PATCH 03/10] Complete impl --- crates/storage/engines/in_memory.rs | 17 ++++++++++++++++- crates/storage/engines/libmdbx.rs | 3 +-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/storage/engines/in_memory.rs b/crates/storage/engines/in_memory.rs index 1c3552fc8dd..18f2e5d56a0 100644 --- a/crates/storage/engines/in_memory.rs +++ b/crates/storage/engines/in_memory.rs @@ -3,13 +3,14 @@ use bytes::Bytes; use ethereum_rust_core::types::{ AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, Index, Receipt, }; -use ethereum_types::{Address, H256}; +use ethereum_types::{Address, H256, U256}; use std::{collections::HashMap, fmt::Debug}; use super::api::StoreEngine; #[derive(Default)] pub struct Store { + chain_data: ChainData, account_infos: HashMap, block_numbers: HashMap, bodies: HashMap, @@ -22,6 +23,11 @@ pub struct Store { receipts: HashMap>, } +#[derive(Default)] +struct ChainData { + chain_id: Option, +} + impl Store { pub fn new() -> Result { Ok(Self::default()) @@ -162,6 +168,15 @@ impl StoreEngine for Store { self.account_storages.remove(&address); Ok(()) } + + fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { + self.chain_data.chain_id.replace(chain_id); + Ok(()) + } + + fn get_chain_id(&self) -> Result, StoreError> { + Ok(self.chain_data.chain_id) + } } impl Debug for Store { diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 78343959190..153a06c23ba 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -389,9 +389,8 @@ impl From for H256 { } // Represents the key for each unique value of the chain data -enum ChainDataIndex { +pub enum ChainDataIndex { ChainId = 0, - LatestBlockNumber = 1, } impl Encodable for ChainDataIndex { From 53615a1bd51c907422feb641dba015b414f93d1d Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:11:16 -0300 Subject: [PATCH 04/10] Add test --- crates/storage/storage.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/storage/storage.rs b/crates/storage/storage.rs index a9b76edbb31..d9a889ded2d 100644 --- a/crates/storage/storage.rs +++ b/crates/storage/storage.rs @@ -291,7 +291,7 @@ impl Store { self.engine.lock().unwrap().remove_account(address) } - pub fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { + pub fn update_chain_id(&self, chain_id: U256) -> Result<(), StoreError> { self.engine.lock().unwrap().update_chain_id(chain_id) } @@ -340,6 +340,7 @@ mod tests { test_store_account_code(store.clone()); test_store_account_storage(store.clone()); test_remove_account_storage(store.clone()); + test_store_chain_data(store.clone()); } fn test_store_account(store: Store) { @@ -576,4 +577,14 @@ mod tests { assert!(stored_value_beta_a.is_some()); assert!(stored_value_beta_b.is_some()); } + + fn test_store_chain_data(store: Store) { + let chain_id = U256::from_dec_str("46").unwrap(); + + store.update_chain_id(chain_id).unwrap(); + + let stored_chain_id = store.get_chain_id().unwrap().unwrap(); + + assert_eq!(chain_id, stored_chain_id); + } } From ccafc91efd983a054c8bc43fcc2c14ff29e130bf Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:14:38 -0300 Subject: [PATCH 05/10] doc --- crates/storage/engines/libmdbx.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 153a06c23ba..72b6aee6d50 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -334,6 +334,7 @@ table!( table!( /// Stores chain data, each value is unique and stored as its rlp encoding + /// See [ChainDataIndex] for available chain values ( ChainData ) ChainDataIndex => Vec ); @@ -388,7 +389,8 @@ impl From for H256 { } } -// Represents the key for each unique value of the chain data +/// Represents the key for each unique value of the chain data stored in the db +// (TODO: Remove this comment once full) Will store chain-specific data such as chain id and latest finalized/pending/safe block number pub enum ChainDataIndex { ChainId = 0, } From 0d06de5e885d959ca5d5c9f19c7b618b7fe8a8ac Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:45:19 -0300 Subject: [PATCH 06/10] Impl eth_chainId endpoint --- crates/rpc/eth/client.rs | 14 ++++++++++++-- crates/rpc/rpc.rs | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/rpc/eth/client.rs b/crates/rpc/eth/client.rs index 2e09a3efce4..05154664a2f 100644 --- a/crates/rpc/eth/client.rs +++ b/crates/rpc/eth/client.rs @@ -1,9 +1,19 @@ +use ethereum_rust_storage::Store; use serde_json::Value; +use tracing::info; use crate::utils::RpcErr; -pub fn chain_id() -> Result { - Ok(Value::String("0xaa36a7".to_string())) +pub fn chain_id(storage: Store) -> Result { + info!("Requested chain id"); + match storage.get_chain_id() { + Ok(Some(chain_id)) => { + serde_json::to_value(format!("{:#x}", chain_id)).map_err(|_| RpcErr::Internal) + } + // Treat missing value as internal error as we should have a chain id + // loaded in the db from loading the genesis file + _ => Err(RpcErr::Internal), + } } pub fn syncing() -> Result { diff --git a/crates/rpc/rpc.rs b/crates/rpc/rpc.rs index 7809207e4c4..2b1738eb84a 100644 --- a/crates/rpc/rpc.rs +++ b/crates/rpc/rpc.rs @@ -84,7 +84,7 @@ pub fn map_requests(req: &RpcRequest, storage: Store) -> Result { .and_then(|v| serde_json::from_value(v.clone()).map_err(|_| RpcErr::BadParams))?; engine::exchange_capabilities(&capabilities) } - "eth_chainId" => client::chain_id(), + "eth_chainId" => client::chain_id(storage), "eth_syncing" => client::syncing(), "eth_getBlockByNumber" => { let request = GetBlockByNumberRequest::parse(&req.params).ok_or(RpcErr::BadParams)?; From 142da5c5c86d4fd0eaac23bee67ccf31aa6d4601 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 15:53:37 -0300 Subject: [PATCH 07/10] Clippy --- crates/storage/engines/libmdbx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 72b6aee6d50..33e93eb5951 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -283,7 +283,7 @@ impl StoreEngine for Store { { None => Ok(None), Some(ref rlp) => U256::decode(rlp) - .map(|ci| Some(ci)) + .map(Some) .map_err(|_| StoreError::DecodeError), } } From 90a483dd47b593b035d7dd01e87d1222fb73a599 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 17:27:16 -0300 Subject: [PATCH 08/10] Fetch block numbers from db --- crates/storage/engines/api.rs | 34 +++++++ crates/storage/engines/in_memory.rs | 56 +++++++++++ crates/storage/engines/libmdbx.rs | 146 ++++++++++++++++++++++++++++ crates/storage/storage.rs | 89 +++++++++++++++++ 4 files changed, 325 insertions(+) diff --git a/crates/storage/engines/api.rs b/crates/storage/engines/api.rs index 6ad3e0858de..7d97affd399 100644 --- a/crates/storage/engines/api.rs +++ b/crates/storage/engines/api.rs @@ -166,4 +166,38 @@ pub trait StoreEngine: Debug + Send { /// Obtain the current chain id fn get_chain_id(&self) -> Result, StoreError>; + + // Update earliest block number + fn update_earliest_block_number(&mut self, block_number: BlockNumber) + -> Result<(), StoreError>; + + // Obtain earliest block number + fn get_earliest_block_number(&self) -> Result, StoreError>; + + // Update finalized block number + fn update_finalized_block_number( + &mut self, + block_number: BlockNumber, + ) -> Result<(), StoreError>; + + // Obtain finalized block number + fn get_finalized_block_number(&self) -> Result, StoreError>; + + // Update safe block number + fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>; + + // Obtain safe block number + fn get_safe_block_number(&self) -> Result, StoreError>; + + // Update latest block number + fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>; + + // Obtain latest block number + fn get_latest_block_number(&self) -> Result, StoreError>; + + // Update pending block number + fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>; + + // Obtain pending block number + fn get_pending_block_number(&self) -> Result, StoreError>; } diff --git a/crates/storage/engines/in_memory.rs b/crates/storage/engines/in_memory.rs index 18f2e5d56a0..48d5aa51852 100644 --- a/crates/storage/engines/in_memory.rs +++ b/crates/storage/engines/in_memory.rs @@ -26,6 +26,11 @@ pub struct Store { #[derive(Default)] struct ChainData { chain_id: Option, + earliest_block_number: Option, + finalized_block_number: Option, + safe_block_number: Option, + latest_block_number: Option, + pending_block_number: Option, } impl Store { @@ -177,6 +182,57 @@ impl StoreEngine for Store { fn get_chain_id(&self) -> Result, StoreError> { Ok(self.chain_data.chain_id) } + + fn update_earliest_block_number( + &mut self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + self.chain_data.earliest_block_number.replace(block_number); + Ok(()) + } + + fn get_earliest_block_number(&self) -> Result, StoreError> { + Ok(self.chain_data.earliest_block_number) + } + + fn update_finalized_block_number( + &mut self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + self.chain_data.finalized_block_number.replace(block_number); + Ok(()) + } + + fn get_finalized_block_number(&self) -> Result, StoreError> { + Ok(self.chain_data.finalized_block_number) + } + + fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + self.chain_data.safe_block_number.replace(block_number); + Ok(()) + } + + fn get_safe_block_number(&self) -> Result, StoreError> { + Ok(self.chain_data.safe_block_number) + } + + fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + self.chain_data.latest_block_number.replace(block_number); + Ok(()) + } + + fn get_latest_block_number(&self) -> Result, StoreError> { + Ok(self.chain_data.latest_block_number) + } + + fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + self.chain_data.pending_block_number.replace(block_number); + Ok(()) + } + + fn get_pending_block_number(&self) -> Result, StoreError> { + Ok(self.chain_data.pending_block_number) + } } impl Debug for Store { diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 33e93eb5951..909e2293c0e 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -287,6 +287,147 @@ impl StoreEngine for Store { .map_err(|_| StoreError::DecodeError), } } + + fn update_earliest_block_number( + &mut self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::( + ChainDataIndex::EarliestBlockNumber, + block_number.encode_to_vec(), + ) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_earliest_block_number(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::EarliestBlockNumber) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } + + fn update_finalized_block_number( + &mut self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::( + ChainDataIndex::FinalizedBlockNumber, + block_number.encode_to_vec(), + ) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_finalized_block_number(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::FinalizedBlockNumber) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } + + fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::( + ChainDataIndex::SafeBlockNumber, + block_number.encode_to_vec(), + ) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_safe_block_number(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::SafeBlockNumber) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } + + fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::( + ChainDataIndex::LatestBlockNumber, + block_number.encode_to_vec(), + ) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_latest_block_number(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::LatestBlockNumber) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } + + fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> { + // Overwrites previous value if present + let txn = self + .db + .begin_readwrite() + .map_err(StoreError::LibmdbxError)?; + txn.upsert::( + ChainDataIndex::PendingBlockNumber, + block_number.encode_to_vec(), + ) + .map_err(StoreError::LibmdbxError)?; + txn.commit().map_err(StoreError::LibmdbxError) + } + + fn get_pending_block_number(&self) -> Result, StoreError> { + let txn = self.db.begin_read().map_err(StoreError::LibmdbxError)?; + match txn + .get::(ChainDataIndex::PendingBlockNumber) + .map_err(StoreError::LibmdbxError)? + { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } } impl Debug for Store { @@ -393,6 +534,11 @@ impl From for H256 { // (TODO: Remove this comment once full) Will store chain-specific data such as chain id and latest finalized/pending/safe block number pub enum ChainDataIndex { ChainId = 0, + EarliestBlockNumber = 1, + FinalizedBlockNumber = 2, + SafeBlockNumber = 3, + LatestBlockNumber = 4, + PendingBlockNumber = 5, } impl Encodable for ChainDataIndex { diff --git a/crates/storage/storage.rs b/crates/storage/storage.rs index c943124a1d4..f51e611699a 100644 --- a/crates/storage/storage.rs +++ b/crates/storage/storage.rs @@ -305,6 +305,67 @@ impl Store { pub fn get_chain_id(&self) -> Result, StoreError> { self.engine.lock().unwrap().get_chain_id() } + + pub fn update_earliest_block_number( + &self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + self.engine + .lock() + .unwrap() + .update_earliest_block_number(block_number) + } + + pub fn get_earliest_block_number(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_earliest_block_number() + } + + pub fn update_finalized_block_number( + &self, + block_number: BlockNumber, + ) -> Result<(), StoreError> { + self.engine + .lock() + .unwrap() + .update_finalized_block_number(block_number) + } + + pub fn get_finalized_block_number(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_finalized_block_number() + } + + pub fn update_safe_block_number(&self, block_number: BlockNumber) -> Result<(), StoreError> { + self.engine + .lock() + .unwrap() + .update_safe_block_number(block_number) + } + + pub fn get_safe_block_number(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_safe_block_number() + } + + pub fn update_latest_block_number(&self, block_number: BlockNumber) -> Result<(), StoreError> { + self.engine + .lock() + .unwrap() + .update_latest_block_number(block_number) + } + + pub fn get_latest_block_number(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_latest_block_number() + } + + pub fn update_pending_block_number(&self, block_number: BlockNumber) -> Result<(), StoreError> { + self.engine + .lock() + .unwrap() + .update_pending_block_number(block_number) + } + + pub fn get_pending_block_number(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_pending_block_number() + } } #[cfg(test)] @@ -602,11 +663,39 @@ mod tests { fn test_store_chain_data(store: Store) { let chain_id = U256::from_dec_str("46").unwrap(); + let earliest_block_number = 0; + let finalized_block_number = 7; + let safe_block_number = 6; + let latest_block_number = 8; + let pending_block_number = 9; store.update_chain_id(chain_id).unwrap(); + store + .update_earliest_block_number(earliest_block_number) + .unwrap(); + store + .update_finalized_block_number(finalized_block_number) + .unwrap(); + store.update_safe_block_number(safe_block_number).unwrap(); + store + .update_latest_block_number(latest_block_number) + .unwrap(); + store + .update_pending_block_number(pending_block_number) + .unwrap(); let stored_chain_id = store.get_chain_id().unwrap().unwrap(); + let stored_earliest_block_number = store.get_earliest_block_number().unwrap().unwrap(); + let stored_finalized_block_number = store.get_finalized_block_number().unwrap().unwrap(); + let stored_safe_block_number = store.get_safe_block_number().unwrap().unwrap(); + let stored_latest_block_number = store.get_latest_block_number().unwrap().unwrap(); + let stored_pending_block_number = store.get_pending_block_number().unwrap().unwrap(); assert_eq!(chain_id, stored_chain_id); + assert_eq!(earliest_block_number, stored_earliest_block_number); + assert_eq!(finalized_block_number, stored_finalized_block_number); + assert_eq!(safe_block_number, stored_safe_block_number); + assert_eq!(latest_block_number, stored_latest_block_number); + assert_eq!(pending_block_number, stored_pending_block_number); } } From edd842d8c5d15b4118fd5762c6b42070e2491a82 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 1 Aug 2024 17:44:11 -0300 Subject: [PATCH 09/10] Resolve block number --- crates/rpc/eth/block.rs | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/crates/rpc/eth/block.rs b/crates/rpc/eth/block.rs index cbf61efb21d..81f2bbed407 100644 --- a/crates/rpc/eth/block.rs +++ b/crates/rpc/eth/block.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use ethereum_rust_evm::{evm_state, ExecutionResult, SpecId}; -use ethereum_rust_storage::Store; +use ethereum_rust_storage::{error::StoreError, Store}; use serde::{Deserialize, Serialize}; use serde_json::Value; use tracing::info; @@ -85,6 +85,22 @@ pub enum BlockTag { Pending, } +pub(crate) fn resolve_block_number( + identifier: &BlockIdentifier, + storage: &Store, +) -> Result, StoreError> { + match identifier { + BlockIdentifier::Number(num) => Ok(Some(*num)), + BlockIdentifier::Tag(tag) => match tag { + BlockTag::Earliest => storage.get_earliest_block_number(), + BlockTag::Finalized => storage.get_finalized_block_number(), + BlockTag::Safe => storage.get_safe_block_number(), + BlockTag::Latest => storage.get_latest_block_number(), + BlockTag::Pending => storage.get_pending_block_number(), + }, + } +} + impl GetBlockByNumberRequest { pub fn parse(params: &Option>) -> Option { let params = params.as_ref()?; @@ -210,9 +226,9 @@ pub fn get_block_by_number( storage: Store, ) -> Result { info!("Requested block with number: {}", request.block); - let block_number = match request.block { - BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"), - BlockIdentifier::Number(block_number) => block_number, + let block_number = match resolve_block_number(&request.block, &storage) { + Ok(Some(block_number)) => block_number, + _ => return Ok(Value::Null), }; let header = storage.get_block_header(block_number); let body = storage.get_block_body(block_number); @@ -257,9 +273,9 @@ pub fn get_block_transaction_count_by_number( "Requested transaction count for block with number: {}", request.block ); - let block_number = match request.block { - BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"), - BlockIdentifier::Number(block_number) => block_number, + let block_number = match resolve_block_number(&request.block, &storage) { + Ok(Some(block_number)) => block_number, + _ => return Ok(Value::Null), }; let block_body = match storage.get_block_body(block_number) { Ok(Some(block_body)) => block_body, @@ -279,9 +295,9 @@ pub fn get_transaction_by_block_number_and_index( "Requested transaction at index: {} of block with number: {}", request.transaction_index, request.block, ); - let block_number = match request.block { - BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"), - BlockIdentifier::Number(block_number) => block_number, + let block_number = match resolve_block_number(&request.block, &storage) { + Ok(Some(block_number)) => block_number, + _ => return Ok(Value::Null), }; let block_body = match storage.get_block_body(block_number) { Ok(Some(block_body)) => block_body, @@ -330,9 +346,9 @@ pub fn get_block_receipts( "Requested receipts for block with number: {}", request.block ); - let block_number = match request.block { - BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"), - BlockIdentifier::Number(block_number) => block_number, + let block_number = match resolve_block_number(&request.block, &storage) { + Ok(Some(block_number)) => block_number, + _ => return Ok(Value::Null), }; let header = storage.get_block_header(block_number); let body = storage.get_block_body(block_number); From 20c29d69851b76f0ec6adcb4d2897fe9fd2caf1e Mon Sep 17 00:00:00 2001 From: fmoletta <99273364+fmoletta@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:57:49 -0300 Subject: [PATCH 10/10] feat: add rpc endpoint `eth_blockNumber` (#218) Based on #217, please merge it first **Motivation** Support rpc endpoint `eth_blockNumber` **Description** Add rpc endpoint `eth_blockNumber` Closes #34 --- crates/rpc/eth/block.rs | 10 ++++++++++ crates/rpc/rpc.rs | 1 + 2 files changed, 11 insertions(+) diff --git a/crates/rpc/eth/block.rs b/crates/rpc/eth/block.rs index 81f2bbed407..2e24b671fc8 100644 --- a/crates/rpc/eth/block.rs +++ b/crates/rpc/eth/block.rs @@ -511,6 +511,16 @@ pub fn create_access_list( serde_json::to_value(result).map_err(|_| RpcErr::Internal) } +pub fn block_number(storage: Store) -> Result { + info!("Requested latest block number"); + match storage.get_latest_block_number() { + Ok(Some(block_number)) => { + serde_json::to_value(format!("{:#x}", block_number)).map_err(|_| RpcErr::Internal) + } + _ => Err(RpcErr::Internal), + } +} + impl Display for BlockIdentifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/crates/rpc/rpc.rs b/crates/rpc/rpc.rs index 2b1738eb84a..9de1591c8b6 100644 --- a/crates/rpc/rpc.rs +++ b/crates/rpc/rpc.rs @@ -139,6 +139,7 @@ pub fn map_requests(req: &RpcRequest, storage: Store) -> Result { let request = CreateAccessListRequest::parse(&req.params).ok_or(RpcErr::BadParams)?; block::create_access_list(&request, storage) } + "eth_blockNumber" => block::block_number(storage), "engine_forkchoiceUpdatedV3" => engine::forkchoice_updated_v3(), "engine_newPayloadV3" => { let request =