Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions crates/rpc/eth/block.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -85,6 +85,22 @@ pub enum BlockTag {
Pending,
}

pub(crate) fn resolve_block_number(
identifier: &BlockIdentifier,
storage: &Store,
) -> Result<Option<BlockNumber>, 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<Vec<Value>>) -> Option<GetBlockByNumberRequest> {
let params = params.as_ref()?;
Expand Down Expand Up @@ -210,9 +226,9 @@ pub fn get_block_by_number(
storage: Store,
) -> Result<Value, RpcErr> {
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);
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -495,6 +511,16 @@ pub fn create_access_list(
serde_json::to_value(result).map_err(|_| RpcErr::Internal)
}

pub fn block_number(storage: Store) -> Result<Value, RpcErr> {
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 {
Expand Down
1 change: 1 addition & 0 deletions crates/rpc/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ pub fn map_requests(req: &RpcRequest, storage: Store) -> Result<Value, RpcErr> {
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 =
Expand Down
34 changes: 34 additions & 0 deletions crates/storage/engines/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,38 @@ pub trait StoreEngine: Debug + Send {

/// Obtain the current chain id
fn get_chain_id(&self) -> Result<Option<U256>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, StoreError>;
}
56 changes: 56 additions & 0 deletions crates/storage/engines/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ pub struct Store {
#[derive(Default)]
struct ChainData {
chain_id: Option<U256>,
earliest_block_number: Option<BlockNumber>,
finalized_block_number: Option<BlockNumber>,
safe_block_number: Option<BlockNumber>,
latest_block_number: Option<BlockNumber>,
pending_block_number: Option<BlockNumber>,
}

impl Store {
Expand Down Expand Up @@ -177,6 +182,57 @@ impl StoreEngine for Store {
fn get_chain_id(&self) -> Result<Option<U256>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, 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<Option<BlockNumber>, StoreError> {
Ok(self.chain_data.pending_block_number)
}
}

impl Debug for Store {
Expand Down
91 changes: 91 additions & 0 deletions crates/storage/engines/libmdbx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,92 @@ impl StoreEngine for Store {
.map_err(|_| StoreError::DecodeError),
}
}

fn update_earliest_block_number(
&mut self,
block_number: BlockNumber,
) -> Result<(), StoreError> {
self.write::<ChainData>(
ChainDataIndex::EarliestBlockNumber,
block_number.encode_to_vec(),
)
}

fn get_earliest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
match self.read::<ChainData>(ChainDataIndex::EarliestBlockNumber)? {
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> {
self.write::<ChainData>(
ChainDataIndex::FinalizedBlockNumber,
block_number.encode_to_vec(),
)
}

fn get_finalized_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
match self.read::<ChainData>(ChainDataIndex::FinalizedBlockNumber)? {
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> {
self.write::<ChainData>(
ChainDataIndex::SafeBlockNumber,
block_number.encode_to_vec(),
)
}

fn get_safe_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
match self.read::<ChainData>(ChainDataIndex::SafeBlockNumber)? {
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> {
self.write::<ChainData>(
ChainDataIndex::LatestBlockNumber,
block_number.encode_to_vec(),
)
}

fn get_latest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
match self.read::<ChainData>(ChainDataIndex::LatestBlockNumber)? {
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> {
self.write::<ChainData>(
ChainDataIndex::PendingBlockNumber,
block_number.encode_to_vec(),
)
}

fn get_pending_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
match self.read::<ChainData>(ChainDataIndex::PendingBlockNumber)? {
None => Ok(None),
Some(ref rlp) => RLPDecode::decode(rlp)
.map(Some)
.map_err(|_| StoreError::DecodeError),
}
}
}

impl Debug for Store {
Expand Down Expand Up @@ -317,6 +403,11 @@ impl From<AccountStorageValueBytes> 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 {
Expand Down
Loading