2019-12-06 07:52:11 +00:00
|
|
|
use crate::chunked_iter::ChunkedVectorIter;
|
|
|
|
use crate::chunked_vector::BlockRoots;
|
2020-06-09 23:55:44 +00:00
|
|
|
use crate::errors::{Error, Result};
|
2020-06-02 00:41:42 +00:00
|
|
|
use crate::iter::BlockRootsIterator;
|
2020-05-31 22:13:49 +00:00
|
|
|
use crate::{HotColdDB, Store};
|
2020-06-09 23:55:44 +00:00
|
|
|
use itertools::process_results;
|
2019-12-06 07:52:11 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
use types::{BeaconState, ChainSpec, EthSpec, Hash256, Slot};
|
|
|
|
|
|
|
|
/// Forwards block roots iterator that makes use of the `block_roots` table in the freezer DB.
|
|
|
|
pub struct FrozenForwardsBlockRootsIterator<E: EthSpec> {
|
|
|
|
inner: ChunkedVectorIter<BlockRoots, E>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Forwards block roots iterator that reverses a backwards iterator (only good for short ranges).
|
|
|
|
pub struct SimpleForwardsBlockRootsIterator {
|
|
|
|
// Values from the backwards iterator (in slot descending order)
|
|
|
|
values: Vec<(Hash256, Slot)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Fusion of the above two approaches to forwards iteration. Fast and efficient.
|
|
|
|
pub enum HybridForwardsBlockRootsIterator<E: EthSpec> {
|
|
|
|
PreFinalization {
|
2020-01-21 07:38:56 +00:00
|
|
|
iter: Box<FrozenForwardsBlockRootsIterator<E>>,
|
2019-12-06 07:52:11 +00:00
|
|
|
/// Data required by the `PostFinalization` iterator when we get to it.
|
2020-01-21 07:38:56 +00:00
|
|
|
continuation_data: Box<Option<(BeaconState<E>, Hash256)>>,
|
2019-12-06 07:52:11 +00:00
|
|
|
},
|
|
|
|
PostFinalization {
|
|
|
|
iter: SimpleForwardsBlockRootsIterator,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: EthSpec> FrozenForwardsBlockRootsIterator<E> {
|
|
|
|
pub fn new(
|
2020-05-31 22:13:49 +00:00
|
|
|
store: Arc<HotColdDB<E>>,
|
2019-12-06 07:52:11 +00:00
|
|
|
start_slot: Slot,
|
|
|
|
last_restore_point_slot: Slot,
|
|
|
|
spec: &ChainSpec,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
inner: ChunkedVectorIter::new(
|
|
|
|
store,
|
|
|
|
start_slot.as_usize(),
|
|
|
|
last_restore_point_slot,
|
|
|
|
spec,
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: EthSpec> Iterator for FrozenForwardsBlockRootsIterator<E> {
|
|
|
|
type Item = (Hash256, Slot);
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.inner
|
|
|
|
.next()
|
|
|
|
.map(|(slot, block_hash)| (block_hash, Slot::from(slot)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SimpleForwardsBlockRootsIterator {
|
|
|
|
pub fn new<S: Store<E>, E: EthSpec>(
|
|
|
|
store: Arc<S>,
|
|
|
|
start_slot: Slot,
|
|
|
|
end_state: BeaconState<E>,
|
|
|
|
end_block_root: Hash256,
|
2020-06-09 23:55:44 +00:00
|
|
|
) -> Result<Self> {
|
2019-12-06 07:52:11 +00:00
|
|
|
// Iterate backwards from the end state, stopping at the start slot.
|
2020-06-09 23:55:44 +00:00
|
|
|
let values = process_results(
|
|
|
|
std::iter::once(Ok((end_block_root, end_state.slot)))
|
|
|
|
.chain(BlockRootsIterator::owned(store, end_state)),
|
|
|
|
|iter| {
|
|
|
|
iter.take_while(|(_, slot)| *slot >= start_slot)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
},
|
|
|
|
)?;
|
|
|
|
Ok(Self { values: values })
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for SimpleForwardsBlockRootsIterator {
|
2020-06-09 23:55:44 +00:00
|
|
|
type Item = Result<(Hash256, Slot)>;
|
2019-12-06 07:52:11 +00:00
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
// Pop from the end of the vector to get the block roots in slot-ascending order.
|
2020-06-09 23:55:44 +00:00
|
|
|
Ok(self.values.pop()).transpose()
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: EthSpec> HybridForwardsBlockRootsIterator<E> {
|
|
|
|
pub fn new(
|
2020-05-31 22:13:49 +00:00
|
|
|
store: Arc<HotColdDB<E>>,
|
2019-12-06 07:52:11 +00:00
|
|
|
start_slot: Slot,
|
|
|
|
end_state: BeaconState<E>,
|
|
|
|
end_block_root: Hash256,
|
|
|
|
spec: &ChainSpec,
|
2020-06-09 23:55:44 +00:00
|
|
|
) -> Result<Self> {
|
2019-12-06 07:52:11 +00:00
|
|
|
use HybridForwardsBlockRootsIterator::*;
|
|
|
|
|
|
|
|
let latest_restore_point_slot = store.get_latest_restore_point_slot();
|
|
|
|
|
2020-06-09 23:55:44 +00:00
|
|
|
let result = if start_slot < latest_restore_point_slot {
|
2019-12-06 07:52:11 +00:00
|
|
|
PreFinalization {
|
2020-01-21 07:38:56 +00:00
|
|
|
iter: Box::new(FrozenForwardsBlockRootsIterator::new(
|
2019-12-06 07:52:11 +00:00
|
|
|
store,
|
|
|
|
start_slot,
|
|
|
|
latest_restore_point_slot,
|
|
|
|
spec,
|
2020-01-21 07:38:56 +00:00
|
|
|
)),
|
|
|
|
continuation_data: Box::new(Some((end_state, end_block_root))),
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PostFinalization {
|
|
|
|
iter: SimpleForwardsBlockRootsIterator::new(
|
|
|
|
store,
|
|
|
|
start_slot,
|
|
|
|
end_state,
|
|
|
|
end_block_root,
|
2020-06-09 23:55:44 +00:00
|
|
|
)?,
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
2020-06-09 23:55:44 +00:00
|
|
|
};
|
2019-12-06 07:52:11 +00:00
|
|
|
|
2020-06-09 23:55:44 +00:00
|
|
|
Ok(result)
|
|
|
|
}
|
2019-12-06 07:52:11 +00:00
|
|
|
|
2020-06-09 23:55:44 +00:00
|
|
|
fn do_next(&mut self) -> Result<Option<(Hash256, Slot)>> {
|
2019-12-06 07:52:11 +00:00
|
|
|
use HybridForwardsBlockRootsIterator::*;
|
|
|
|
|
|
|
|
match self {
|
|
|
|
PreFinalization {
|
|
|
|
iter,
|
|
|
|
continuation_data,
|
|
|
|
} => {
|
|
|
|
match iter.next() {
|
2020-06-09 23:55:44 +00:00
|
|
|
Some(x) => Ok(Some(x)),
|
2019-12-06 07:52:11 +00:00
|
|
|
// Once the pre-finalization iterator is consumed, transition
|
|
|
|
// to a post-finalization iterator beginning from the last slot
|
|
|
|
// of the pre iterator.
|
|
|
|
None => {
|
|
|
|
let (end_state, end_block_root) =
|
2020-06-09 23:55:44 +00:00
|
|
|
continuation_data.take().ok_or(Error::NoContinuationData)?;
|
2019-12-06 07:52:11 +00:00
|
|
|
|
|
|
|
*self = PostFinalization {
|
|
|
|
iter: SimpleForwardsBlockRootsIterator::new(
|
|
|
|
iter.inner.store.clone(),
|
|
|
|
Slot::from(iter.inner.end_vindex),
|
|
|
|
end_state,
|
|
|
|
end_block_root,
|
2020-06-09 23:55:44 +00:00
|
|
|
)?,
|
2019-12-06 07:52:11 +00:00
|
|
|
};
|
2020-06-09 23:55:44 +00:00
|
|
|
self.do_next()
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-09 23:55:44 +00:00
|
|
|
PostFinalization { iter } => iter.next().transpose(),
|
2019-12-06 07:52:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-09 23:55:44 +00:00
|
|
|
|
|
|
|
impl<E: EthSpec> Iterator for HybridForwardsBlockRootsIterator<E> {
|
|
|
|
type Item = Result<(Hash256, Slot)>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.do_next().transpose()
|
|
|
|
}
|
|
|
|
}
|