diff --git a/crates/rpc/engine/mod.rs b/crates/rpc/engine/mod.rs index f5aca8d7804..ab1a152d599 100644 --- a/crates/rpc/engine/mod.rs +++ b/crates/rpc/engine/mod.rs @@ -2,6 +2,7 @@ use ethereum_rust_core::{ types::{ExecutionPayloadV3, PayloadStatus, PayloadValidationStatus}, H256, }; +use ethereum_rust_storage::Store; use serde_json::{json, Value}; use tracing::info; @@ -15,6 +16,20 @@ pub struct NewPayloadV3Request { pub parent_beacon_block_root: H256, } +impl NewPayloadV3Request { + pub fn parse(params: &Option>) -> Option { + let params = params.as_ref()?; + if params.len() != 3 { + return None; + } + Some(NewPayloadV3Request { + payload: serde_json::from_value(params[0].clone()).ok()?, + expected_blob_versioned_hashes: serde_json::from_value(params[1].clone()).ok()?, + parent_beacon_block_root: serde_json::from_value(params[2].clone()).ok()?, + }) + } +} + pub fn exchange_capabilities(capabilities: &ExchangeCapabilitiesRequest) -> Result { Ok(json!(capabilities)) } @@ -30,7 +45,10 @@ pub fn forkchoice_updated_v3() -> Result { })) } -pub fn new_payload_v3(request: NewPayloadV3Request) -> Result { +pub fn new_payload_v3( + request: NewPayloadV3Request, + storage: Store, +) -> Result { let block_hash = request.payload.block_hash; info!("Received new payload with block hash: {}", block_hash); @@ -50,10 +68,11 @@ pub fn new_payload_v3(request: NewPayloadV3Request) -> Result we should fetch this from genesis? - if block_header.timestamp <= cancun_time { - return Err(RpcErr::UnsuportedFork); + match storage.get_cancun_time().map_err(|_| RpcErr::Internal)? { + Some(cancun_time) if block_header.timestamp > cancun_time => {} + _ => return Err(RpcErr::UnsuportedFork), } + // Check that block_hash is valid let actual_block_hash = block_header.compute_block_hash(); if block_hash != actual_block_hash { diff --git a/crates/rpc/rpc.rs b/crates/rpc/rpc.rs index 9de1591c8b6..82e02b13a60 100644 --- a/crates/rpc/rpc.rs +++ b/crates/rpc/rpc.rs @@ -142,9 +142,8 @@ pub fn map_requests(req: &RpcRequest, storage: Store) -> Result { "eth_blockNumber" => block::block_number(storage), "engine_forkchoiceUpdatedV3" => engine::forkchoice_updated_v3(), "engine_newPayloadV3" => { - let request = - parse_new_payload_v3_request(req.params.as_ref().ok_or(RpcErr::BadParams)?)?; - Ok(serde_json::to_value(engine::new_payload_v3(request)?).unwrap()) + let request = NewPayloadV3Request::parse(&req.params).ok_or(RpcErr::BadParams)?; + Ok(serde_json::to_value(engine::new_payload_v3(request, storage)?).unwrap()) } "admin_nodeInfo" => admin::node_info(), _ => Err(RpcErr::MethodNotFound), @@ -180,22 +179,6 @@ where } } -fn parse_new_payload_v3_request(params: &[Value]) -> Result { - if params.len() != 3 { - return Err(RpcErr::BadParams); - } - let payload = serde_json::from_value(params[0].clone()).map_err(|_| RpcErr::BadParams)?; - let expected_blob_versioned_hashes = - serde_json::from_value(params[1].clone()).map_err(|_| RpcErr::BadParams)?; - let parent_beacon_block_root = - serde_json::from_value(params[2].clone()).map_err(|_| RpcErr::BadParams)?; - Ok(NewPayloadV3Request { - payload, - expected_blob_versioned_hashes, - parent_beacon_block_root, - }) -} - #[cfg(test)] mod tests { use ethereum_rust_core::{ diff --git a/crates/storage/engines/api.rs b/crates/storage/engines/api.rs index eed2ee9ec40..3dd584adc95 100644 --- a/crates/storage/engines/api.rs +++ b/crates/storage/engines/api.rs @@ -4,8 +4,8 @@ use bytes::Bytes; use ethereum_types::{Address, H256, U256}; use ethereum_rust_core::types::{ - Account, AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, Index, Receipt, - Transaction, + Account, AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig, Index, + Receipt, Transaction, }; use crate::error::StoreError; @@ -169,12 +169,17 @@ pub trait StoreEngine: Debug + Send { } Ok(()) } - /// Updates the value of the chain id - fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError>; + + /// Stores the chain configuration values, should only be called once after reading the genesis file + /// Ignores previously stored values if present + fn set_chain_config(&mut self, chain_config: &ChainConfig) -> Result<(), StoreError>; /// Obtain the current chain id fn get_chain_id(&self) -> Result, StoreError>; + /// Obtain the timestamp at which the cancun fork was activated + fn get_cancun_time(&self) -> Result, StoreError>; + // Update earliest block number fn update_earliest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>; diff --git a/crates/storage/engines/in_memory.rs b/crates/storage/engines/in_memory.rs index 48d5aa51852..2ab4c9b6dbc 100644 --- a/crates/storage/engines/in_memory.rs +++ b/crates/storage/engines/in_memory.rs @@ -1,7 +1,7 @@ use crate::error::StoreError; use bytes::Bytes; use ethereum_rust_core::types::{ - AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, Index, Receipt, + AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig, Index, Receipt, }; use ethereum_types::{Address, H256, U256}; use std::{collections::HashMap, fmt::Debug}; @@ -31,6 +31,7 @@ struct ChainData { safe_block_number: Option, latest_block_number: Option, pending_block_number: Option, + cancun_time: Option, } impl Store { @@ -174,8 +175,11 @@ impl StoreEngine for Store { Ok(()) } - fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { - self.chain_data.chain_id.replace(chain_id); + fn set_chain_config(&mut self, chain_config: &ChainConfig) -> Result<(), StoreError> { + // Store cancun timestamp + self.chain_data.cancun_time = chain_config.cancun_time; + // Store chain id + self.chain_data.chain_id.replace(chain_config.chain_id); Ok(()) } @@ -183,6 +187,10 @@ impl StoreEngine for Store { Ok(self.chain_data.chain_id) } + fn get_cancun_time(&self) -> Result, StoreError> { + Ok(self.chain_data.cancun_time) + } + fn update_earliest_block_number( &mut self, block_number: BlockNumber, diff --git a/crates/storage/engines/libmdbx.rs b/crates/storage/engines/libmdbx.rs index 91b53cbfa5b..fcfc2ed9089 100644 --- a/crates/storage/engines/libmdbx.rs +++ b/crates/storage/engines/libmdbx.rs @@ -9,7 +9,7 @@ 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, + AccountInfo, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig, Index, Receipt, }; use ethereum_types::{Address, H256, U256}; use libmdbx::orm::{Decodable, Encodable}; @@ -199,8 +199,16 @@ impl StoreEngine for Store { self.remove::(address.into()) } - fn update_chain_id(&mut self, chain_id: U256) -> Result<(), StoreError> { - self.write::(ChainDataIndex::ChainId, chain_id.encode_to_vec()) + fn set_chain_config(&mut self, chain_config: &ChainConfig) -> Result<(), StoreError> { + // Store cancun timestamp + if let Some(cancun_time) = chain_config.cancun_time { + self.write::(ChainDataIndex::CancunTime, cancun_time.encode_to_vec())?; + }; + // Store chain id + self.write::( + ChainDataIndex::ChainId, + chain_config.chain_id.encode_to_vec(), + ) } fn get_chain_id(&self) -> Result, StoreError> { @@ -212,6 +220,15 @@ impl StoreEngine for Store { } } + fn get_cancun_time(&self) -> Result, StoreError> { + match self.read::(ChainDataIndex::CancunTime)? { + None => Ok(None), + Some(ref rlp) => RLPDecode::decode(rlp) + .map(Some) + .map_err(|_| StoreError::DecodeError), + } + } + fn update_earliest_block_number( &mut self, block_number: BlockNumber, @@ -408,6 +425,7 @@ pub enum ChainDataIndex { SafeBlockNumber = 3, LatestBlockNumber = 4, PendingBlockNumber = 5, + CancunTime = 6, } impl Encodable for ChainDataIndex { diff --git a/crates/storage/storage.rs b/crates/storage/storage.rs index f51e611699a..1babe80f559 100644 --- a/crates/storage/storage.rs +++ b/crates/storage/storage.rs @@ -6,8 +6,8 @@ use self::error::StoreError; use bytes::Bytes; use engines::api::StoreEngine; use ethereum_rust_core::types::{ - Account, AccountInfo, Block, BlockBody, BlockHash, BlockHeader, BlockNumber, Genesis, Index, - Receipt, Transaction, + Account, AccountInfo, Block, BlockBody, BlockHash, BlockHeader, BlockNumber, ChainConfig, + Genesis, Index, Receipt, Transaction, }; use ethereum_types::{Address, H256, U256}; use std::fmt::Debug; @@ -246,8 +246,8 @@ impl Store { self.add_account(address, account.into())?; } - // Store chain info - self.update_chain_id(genesis.config.chain_id) + // Set chain config + self.set_chain_config(&genesis.config) } pub fn get_transaction_by_hash( @@ -298,14 +298,18 @@ impl Store { .increment_balance(address, amount) } - pub fn update_chain_id(&self, chain_id: U256) -> Result<(), StoreError> { - self.engine.lock().unwrap().update_chain_id(chain_id) + pub fn set_chain_config(&self, chain_config: &ChainConfig) -> Result<(), StoreError> { + self.engine.lock().unwrap().set_chain_config(chain_config) } pub fn get_chain_id(&self) -> Result, StoreError> { self.engine.lock().unwrap().get_chain_id() } + pub fn get_cancun_time(&self) -> Result, StoreError> { + self.engine.lock().unwrap().get_cancun_time() + } + pub fn update_earliest_block_number( &self, block_number: BlockNumber, @@ -409,7 +413,8 @@ mod tests { test_store_account_storage(store.clone()); test_remove_account_storage(store.clone()); test_increment_balance(store.clone()); - test_store_chain_data(store.clone()); + test_store_chain_config(store.clone()); + test_store_block_tags(store.clone()); } fn test_store_account(store: Store) { @@ -661,15 +666,30 @@ mod tests { assert_eq!(stored_account_info.balance, 75.into()); } - fn test_store_chain_data(store: Store) { + fn test_store_chain_config(store: Store) { let chain_id = U256::from_dec_str("46").unwrap(); + let cancun_time = 12; + let chain_config = ChainConfig { + chain_id, + cancun_time: Some(cancun_time), + ..Default::default() + }; + + store.set_chain_config(&chain_config).unwrap(); + + let stored_chain_id = store.get_chain_id().unwrap().unwrap(); + let stored_cancun_time = store.get_cancun_time().unwrap().unwrap(); + + assert_eq!(chain_id, stored_chain_id); + assert_eq!(cancun_time, stored_cancun_time); + } + fn test_store_block_tags(store: Store) { 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(); @@ -684,14 +704,12 @@ mod tests { .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);