Skip to content

Commit 0c9170a

Browse files
authored
feat: store relevant block numbers by tag in db (#217)
**Motivation** Having a way to obtain lates/earliest/pending/etc block numbers <!-- Why does this pull request exist? What are its goals? --> **Description** * Add get and update methods for earliest, latest, finalized, safe & pending block number to `Store` & `StoreEngine` * Resolve block numbers from tag in rpc methods <!-- A clear and concise general description of the changes this PR introduces --> <!-- Link to issues: Resolves #111, Resolves #222 --> Closes None, but fixes many and enables others
1 parent d373053 commit 0c9170a

File tree

6 files changed

+310
-13
lines changed

6 files changed

+310
-13
lines changed

crates/rpc/eth/block.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::fmt::Display;
22

33
use ethereum_rust_evm::{evm_state, ExecutionResult, SpecId};
4-
use ethereum_rust_storage::Store;
4+
use ethereum_rust_storage::{error::StoreError, Store};
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
77
use tracing::info;
@@ -85,6 +85,22 @@ pub enum BlockTag {
8585
Pending,
8686
}
8787

88+
pub(crate) fn resolve_block_number(
89+
identifier: &BlockIdentifier,
90+
storage: &Store,
91+
) -> Result<Option<BlockNumber>, StoreError> {
92+
match identifier {
93+
BlockIdentifier::Number(num) => Ok(Some(*num)),
94+
BlockIdentifier::Tag(tag) => match tag {
95+
BlockTag::Earliest => storage.get_earliest_block_number(),
96+
BlockTag::Finalized => storage.get_finalized_block_number(),
97+
BlockTag::Safe => storage.get_safe_block_number(),
98+
BlockTag::Latest => storage.get_latest_block_number(),
99+
BlockTag::Pending => storage.get_pending_block_number(),
100+
},
101+
}
102+
}
103+
88104
impl GetBlockByNumberRequest {
89105
pub fn parse(params: &Option<Vec<Value>>) -> Option<GetBlockByNumberRequest> {
90106
let params = params.as_ref()?;
@@ -210,9 +226,9 @@ pub fn get_block_by_number(
210226
storage: Store,
211227
) -> Result<Value, RpcErr> {
212228
info!("Requested block with number: {}", request.block);
213-
let block_number = match request.block {
214-
BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"),
215-
BlockIdentifier::Number(block_number) => block_number,
229+
let block_number = match resolve_block_number(&request.block, &storage) {
230+
Ok(Some(block_number)) => block_number,
231+
_ => return Ok(Value::Null),
216232
};
217233
let header = storage.get_block_header(block_number);
218234
let body = storage.get_block_body(block_number);
@@ -257,9 +273,9 @@ pub fn get_block_transaction_count_by_number(
257273
"Requested transaction count for block with number: {}",
258274
request.block
259275
);
260-
let block_number = match request.block {
261-
BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"),
262-
BlockIdentifier::Number(block_number) => block_number,
276+
let block_number = match resolve_block_number(&request.block, &storage) {
277+
Ok(Some(block_number)) => block_number,
278+
_ => return Ok(Value::Null),
263279
};
264280
let block_body = match storage.get_block_body(block_number) {
265281
Ok(Some(block_body)) => block_body,
@@ -279,9 +295,9 @@ pub fn get_transaction_by_block_number_and_index(
279295
"Requested transaction at index: {} of block with number: {}",
280296
request.transaction_index, request.block,
281297
);
282-
let block_number = match request.block {
283-
BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"),
284-
BlockIdentifier::Number(block_number) => block_number,
298+
let block_number = match resolve_block_number(&request.block, &storage) {
299+
Ok(Some(block_number)) => block_number,
300+
_ => return Ok(Value::Null),
285301
};
286302
let block_body = match storage.get_block_body(block_number) {
287303
Ok(Some(block_body)) => block_body,
@@ -330,9 +346,9 @@ pub fn get_block_receipts(
330346
"Requested receipts for block with number: {}",
331347
request.block
332348
);
333-
let block_number = match request.block {
334-
BlockIdentifier::Tag(_) => unimplemented!("Obtain block number from tag"),
335-
BlockIdentifier::Number(block_number) => block_number,
349+
let block_number = match resolve_block_number(&request.block, &storage) {
350+
Ok(Some(block_number)) => block_number,
351+
_ => return Ok(Value::Null),
336352
};
337353
let header = storage.get_block_header(block_number);
338354
let body = storage.get_block_body(block_number);
@@ -495,6 +511,16 @@ pub fn create_access_list(
495511
serde_json::to_value(result).map_err(|_| RpcErr::Internal)
496512
}
497513

514+
pub fn block_number(storage: Store) -> Result<Value, RpcErr> {
515+
info!("Requested latest block number");
516+
match storage.get_latest_block_number() {
517+
Ok(Some(block_number)) => {
518+
serde_json::to_value(format!("{:#x}", block_number)).map_err(|_| RpcErr::Internal)
519+
}
520+
_ => Err(RpcErr::Internal),
521+
}
522+
}
523+
498524
impl Display for BlockIdentifier {
499525
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
500526
match self {

crates/rpc/rpc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub fn map_requests(req: &RpcRequest, storage: Store) -> Result<Value, RpcErr> {
139139
let request = CreateAccessListRequest::parse(&req.params).ok_or(RpcErr::BadParams)?;
140140
block::create_access_list(&request, storage)
141141
}
142+
"eth_blockNumber" => block::block_number(storage),
142143
"engine_forkchoiceUpdatedV3" => engine::forkchoice_updated_v3(),
143144
"engine_newPayloadV3" => {
144145
let request =

crates/storage/engines/api.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,38 @@ pub trait StoreEngine: Debug + Send {
174174

175175
/// Obtain the current chain id
176176
fn get_chain_id(&self) -> Result<Option<U256>, StoreError>;
177+
178+
// Update earliest block number
179+
fn update_earliest_block_number(&mut self, block_number: BlockNumber)
180+
-> Result<(), StoreError>;
181+
182+
// Obtain earliest block number
183+
fn get_earliest_block_number(&self) -> Result<Option<BlockNumber>, StoreError>;
184+
185+
// Update finalized block number
186+
fn update_finalized_block_number(
187+
&mut self,
188+
block_number: BlockNumber,
189+
) -> Result<(), StoreError>;
190+
191+
// Obtain finalized block number
192+
fn get_finalized_block_number(&self) -> Result<Option<BlockNumber>, StoreError>;
193+
194+
// Update safe block number
195+
fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>;
196+
197+
// Obtain safe block number
198+
fn get_safe_block_number(&self) -> Result<Option<BlockNumber>, StoreError>;
199+
200+
// Update latest block number
201+
fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>;
202+
203+
// Obtain latest block number
204+
fn get_latest_block_number(&self) -> Result<Option<BlockNumber>, StoreError>;
205+
206+
// Update pending block number
207+
fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError>;
208+
209+
// Obtain pending block number
210+
fn get_pending_block_number(&self) -> Result<Option<BlockNumber>, StoreError>;
177211
}

crates/storage/engines/in_memory.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ pub struct Store {
2626
#[derive(Default)]
2727
struct ChainData {
2828
chain_id: Option<U256>,
29+
earliest_block_number: Option<BlockNumber>,
30+
finalized_block_number: Option<BlockNumber>,
31+
safe_block_number: Option<BlockNumber>,
32+
latest_block_number: Option<BlockNumber>,
33+
pending_block_number: Option<BlockNumber>,
2934
}
3035

3136
impl Store {
@@ -177,6 +182,57 @@ impl StoreEngine for Store {
177182
fn get_chain_id(&self) -> Result<Option<U256>, StoreError> {
178183
Ok(self.chain_data.chain_id)
179184
}
185+
186+
fn update_earliest_block_number(
187+
&mut self,
188+
block_number: BlockNumber,
189+
) -> Result<(), StoreError> {
190+
self.chain_data.earliest_block_number.replace(block_number);
191+
Ok(())
192+
}
193+
194+
fn get_earliest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
195+
Ok(self.chain_data.earliest_block_number)
196+
}
197+
198+
fn update_finalized_block_number(
199+
&mut self,
200+
block_number: BlockNumber,
201+
) -> Result<(), StoreError> {
202+
self.chain_data.finalized_block_number.replace(block_number);
203+
Ok(())
204+
}
205+
206+
fn get_finalized_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
207+
Ok(self.chain_data.finalized_block_number)
208+
}
209+
210+
fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
211+
self.chain_data.safe_block_number.replace(block_number);
212+
Ok(())
213+
}
214+
215+
fn get_safe_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
216+
Ok(self.chain_data.safe_block_number)
217+
}
218+
219+
fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
220+
self.chain_data.latest_block_number.replace(block_number);
221+
Ok(())
222+
}
223+
224+
fn get_latest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
225+
Ok(self.chain_data.latest_block_number)
226+
}
227+
228+
fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
229+
self.chain_data.pending_block_number.replace(block_number);
230+
Ok(())
231+
}
232+
233+
fn get_pending_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
234+
Ok(self.chain_data.pending_block_number)
235+
}
180236
}
181237

182238
impl Debug for Store {

crates/storage/engines/libmdbx.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,92 @@ impl StoreEngine for Store {
211211
.map_err(|_| StoreError::DecodeError),
212212
}
213213
}
214+
215+
fn update_earliest_block_number(
216+
&mut self,
217+
block_number: BlockNumber,
218+
) -> Result<(), StoreError> {
219+
self.write::<ChainData>(
220+
ChainDataIndex::EarliestBlockNumber,
221+
block_number.encode_to_vec(),
222+
)
223+
}
224+
225+
fn get_earliest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
226+
match self.read::<ChainData>(ChainDataIndex::EarliestBlockNumber)? {
227+
None => Ok(None),
228+
Some(ref rlp) => RLPDecode::decode(rlp)
229+
.map(Some)
230+
.map_err(|_| StoreError::DecodeError),
231+
}
232+
}
233+
234+
fn update_finalized_block_number(
235+
&mut self,
236+
block_number: BlockNumber,
237+
) -> Result<(), StoreError> {
238+
self.write::<ChainData>(
239+
ChainDataIndex::FinalizedBlockNumber,
240+
block_number.encode_to_vec(),
241+
)
242+
}
243+
244+
fn get_finalized_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
245+
match self.read::<ChainData>(ChainDataIndex::FinalizedBlockNumber)? {
246+
None => Ok(None),
247+
Some(ref rlp) => RLPDecode::decode(rlp)
248+
.map(Some)
249+
.map_err(|_| StoreError::DecodeError),
250+
}
251+
}
252+
253+
fn update_safe_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
254+
self.write::<ChainData>(
255+
ChainDataIndex::SafeBlockNumber,
256+
block_number.encode_to_vec(),
257+
)
258+
}
259+
260+
fn get_safe_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
261+
match self.read::<ChainData>(ChainDataIndex::SafeBlockNumber)? {
262+
None => Ok(None),
263+
Some(ref rlp) => RLPDecode::decode(rlp)
264+
.map(Some)
265+
.map_err(|_| StoreError::DecodeError),
266+
}
267+
}
268+
269+
fn update_latest_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
270+
self.write::<ChainData>(
271+
ChainDataIndex::LatestBlockNumber,
272+
block_number.encode_to_vec(),
273+
)
274+
}
275+
276+
fn get_latest_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
277+
match self.read::<ChainData>(ChainDataIndex::LatestBlockNumber)? {
278+
None => Ok(None),
279+
Some(ref rlp) => RLPDecode::decode(rlp)
280+
.map(Some)
281+
.map_err(|_| StoreError::DecodeError),
282+
}
283+
}
284+
285+
fn update_pending_block_number(&mut self, block_number: BlockNumber) -> Result<(), StoreError> {
286+
self.write::<ChainData>(
287+
ChainDataIndex::PendingBlockNumber,
288+
block_number.encode_to_vec(),
289+
)
290+
}
291+
292+
fn get_pending_block_number(&self) -> Result<Option<BlockNumber>, StoreError> {
293+
match self.read::<ChainData>(ChainDataIndex::PendingBlockNumber)? {
294+
None => Ok(None),
295+
Some(ref rlp) => RLPDecode::decode(rlp)
296+
.map(Some)
297+
.map_err(|_| StoreError::DecodeError),
298+
}
299+
}
214300
}
215301

216302
impl Debug for Store {
@@ -317,6 +403,11 @@ impl From<AccountStorageValueBytes> for H256 {
317403
// (TODO: Remove this comment once full) Will store chain-specific data such as chain id and latest finalized/pending/safe block number
318404
pub enum ChainDataIndex {
319405
ChainId = 0,
406+
EarliestBlockNumber = 1,
407+
FinalizedBlockNumber = 2,
408+
SafeBlockNumber = 3,
409+
LatestBlockNumber = 4,
410+
PendingBlockNumber = 5,
320411
}
321412

322413
impl Encodable for ChainDataIndex {

0 commit comments

Comments
 (0)