Skip to content

Commit 62cba55

Browse files
committed
feat: support getting blocks by epoch+slot
1 parent f895149 commit 62cba55

File tree

3 files changed

+77
-14
lines changed

3 files changed

+77
-14
lines changed

modules/chain_store/src/chain_store.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,36 @@ impl ChainStore {
8383
query: &BlocksStateQuery,
8484
) -> Result<BlocksStateQueryResponse> {
8585
match query {
86-
BlocksStateQuery::GetLatestBlock => {
87-
match store.get_latest_block()? {
88-
Some(block) => {
89-
let info = Self::to_block_info(block, store, true)?;
90-
Ok(BlocksStateQueryResponse::LatestBlock(info))
91-
}
92-
None => Ok(BlocksStateQueryResponse::NotFound)
86+
BlocksStateQuery::GetLatestBlock => match store.get_latest_block()? {
87+
Some(block) => {
88+
let info = Self::to_block_info(block, store, true)?;
89+
Ok(BlocksStateQueryResponse::LatestBlock(info))
9390
}
94-
}
91+
None => Ok(BlocksStateQueryResponse::NotFound),
92+
},
9593
BlocksStateQuery::GetBlockInfo { block_key } => {
96-
match store.get_block_by_hash(&block_key)? {
94+
match store.get_block_by_hash(block_key)? {
9795
Some(block) => {
9896
let info = Self::to_block_info(block, store, false)?;
9997
Ok(BlocksStateQueryResponse::BlockInfo(info))
10098
}
101-
None => Ok(BlocksStateQueryResponse::NotFound)
99+
None => Ok(BlocksStateQueryResponse::NotFound),
102100
}
103101
}
104-
BlocksStateQuery::GetBlockBySlot { slot } => {
105-
match store.get_block_by_slot(*slot)? {
102+
BlocksStateQuery::GetBlockBySlot { slot } => match store.get_block_by_slot(*slot)? {
103+
Some(block) => {
104+
let info = Self::to_block_info(block, store, false)?;
105+
Ok(BlocksStateQueryResponse::BlockBySlot(info))
106+
}
107+
None => Ok(BlocksStateQueryResponse::NotFound),
108+
},
109+
BlocksStateQuery::GetBlockByEpochSlot { epoch, slot } => {
110+
match store.get_block_by_epoch_slot(*epoch, *slot)? {
106111
Some(block) => {
107112
let info = Self::to_block_info(block, store, false)?;
108-
Ok(BlocksStateQueryResponse::BlockBySlot(info))
113+
Ok(BlocksStateQueryResponse::BlockByEpochSlot(info))
109114
}
110-
None => Ok(BlocksStateQueryResponse::NotFound)
115+
None => Ok(BlocksStateQueryResponse::NotFound),
111116
}
112117
}
113118
other => bail!("{other:?} not yet supported"),

modules/chain_store/src/stores/fjall.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const DEFAULT_DATABASE_PATH: &str = "fjall-blocks";
1717
const BLOCKS_PARTITION: &str = "blocks";
1818
const BLOCK_HASHES_BY_SLOT_PARTITION: &str = "block-hashes-by-slot";
1919
const BLOCK_HASHES_BY_NUMBER_PARTITION: &str = "block-hashes-by-number";
20+
const BLOCK_HASHES_BY_EPOCH_SLOT_PARTITION: &str = "block-hashes-by-epoch-slot";
2021
const TXS_PARTITION: &str = "txs";
2122

2223
impl FjallStore {
@@ -74,6 +75,10 @@ impl super::Store for FjallStore {
7475
self.blocks.get_by_number(number)
7576
}
7677

78+
fn get_block_by_epoch_slot(&self, epoch: u64, epoch_slot: u64) -> Result<Option<Block>> {
79+
self.blocks.get_by_epoch_slot(epoch, epoch_slot)
80+
}
81+
7782
fn get_latest_block(&self) -> Result<Option<Block>> {
7883
self.blocks.get_latest()
7984
}
@@ -83,6 +88,7 @@ struct FjallBlockStore {
8388
blocks: Partition,
8489
block_hashes_by_slot: Partition,
8590
block_hashes_by_number: Partition,
91+
block_hashes_by_epoch_slot: Partition,
8692
}
8793

8894
impl FjallBlockStore {
@@ -97,10 +103,15 @@ impl FjallBlockStore {
97103
BLOCK_HASHES_BY_NUMBER_PARTITION,
98104
fjall::PartitionCreateOptions::default(),
99105
)?;
106+
let block_hashes_by_epoch_slot = keyspace.open_partition(
107+
BLOCK_HASHES_BY_EPOCH_SLOT_PARTITION,
108+
fjall::PartitionCreateOptions::default(),
109+
)?;
100110
Ok(Self {
101111
blocks,
102112
block_hashes_by_slot,
103113
block_hashes_by_number,
114+
block_hashes_by_epoch_slot,
104115
})
105116
}
106117

@@ -121,6 +132,11 @@ impl FjallBlockStore {
121132
info.number.to_be_bytes(),
122133
&info.hash,
123134
);
135+
batch.insert(
136+
&self.block_hashes_by_epoch_slot,
137+
epoch_slot_key(info.epoch, info.epoch_slot),
138+
&info.hash,
139+
);
124140
}
125141

126142
fn get_by_hash(&self, hash: &[u8]) -> Result<Option<Block>> {
@@ -144,6 +160,14 @@ impl FjallBlockStore {
144160
self.get_by_hash(&hash)
145161
}
146162

163+
fn get_by_epoch_slot(&self, epoch: u64, epoch_slot: u64) -> Result<Option<Block>> {
164+
let Some(hash) = self.block_hashes_by_epoch_slot.get(epoch_slot_key(epoch, epoch_slot))?
165+
else {
166+
return Ok(None);
167+
};
168+
self.get_by_hash(&hash)
169+
}
170+
147171
fn get_latest(&self) -> Result<Option<Block>> {
148172
let Some((_, hash)) = self.block_hashes_by_slot.last_key_value()? else {
149173
return Ok(None);
@@ -152,6 +176,13 @@ impl FjallBlockStore {
152176
}
153177
}
154178

179+
fn epoch_slot_key(epoch: u64, epoch_slot: u64) -> [u8; 16] {
180+
let mut key = [0; 16];
181+
key[..8].copy_from_slice(epoch.to_be_bytes().as_slice());
182+
key[8..].copy_from_slice(epoch_slot.to_be_bytes().as_slice());
183+
key
184+
}
185+
155186
struct FjallTXStore {
156187
txs: Partition,
157188
}
@@ -276,6 +307,32 @@ mod tests {
276307
assert_eq!(block, new_block.unwrap());
277308
}
278309

310+
#[test]
311+
fn should_get_block_by_number() {
312+
let state = init_state();
313+
let bytes = test_block_bytes();
314+
let info = test_block_info(&bytes);
315+
let block = build_block(&info, &bytes);
316+
317+
state.store.insert_block(&info, &bytes).unwrap();
318+
319+
let new_block = state.store.get_block_by_number(info.number).unwrap();
320+
assert_eq!(block, new_block.unwrap());
321+
}
322+
323+
#[test]
324+
fn should_get_block_by_epoch_slot() {
325+
let state = init_state();
326+
let bytes = test_block_bytes();
327+
let info = test_block_info(&bytes);
328+
let block = build_block(&info, &bytes);
329+
330+
state.store.insert_block(&info, &bytes).unwrap();
331+
332+
let new_block = state.store.get_block_by_epoch_slot(info.epoch, info.epoch_slot).unwrap();
333+
assert_eq!(block, new_block.unwrap());
334+
}
335+
279336
#[test]
280337
fn should_get_latest_block() {
281338
let state = init_state();

modules/chain_store/src/stores/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub trait Store: Send + Sync {
99
fn get_block_by_hash(&self, hash: &[u8]) -> Result<Option<Block>>;
1010
fn get_block_by_slot(&self, slot: u64) -> Result<Option<Block>>;
1111
fn get_block_by_number(&self, number: u64) -> Result<Option<Block>>;
12+
fn get_block_by_epoch_slot(&self, epoch: u64, epoch_slot: u64) -> Result<Option<Block>>;
1213
fn get_latest_block(&self) -> Result<Option<Block>>;
1314
}
1415

0 commit comments

Comments
 (0)