Add block iter to beacon chain
This commit is contained in:
parent
8ab1d28c9f
commit
df366f99dc
@ -2,6 +2,7 @@ use crate::checkpoint::CheckPoint;
|
|||||||
use crate::errors::{BeaconChainError as Error, BlockProductionError};
|
use crate::errors::{BeaconChainError as Error, BlockProductionError};
|
||||||
use crate::metrics::Metrics;
|
use crate::metrics::Metrics;
|
||||||
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
||||||
|
use crate::iter::BlockRootsIterator;
|
||||||
use fork_choice::{ForkChoice, ForkChoiceError};
|
use fork_choice::{ForkChoice, ForkChoiceError};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use operation_pool::DepositInsertStatus;
|
use operation_pool::DepositInsertStatus;
|
||||||
@ -226,6 +227,17 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Ok(headers?)
|
Ok(headers?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate in reverse through all block roots starting from the current state, through to
|
||||||
|
/// genesis.
|
||||||
|
///
|
||||||
|
/// Returns `None` for roots prior to genesis or when there is an error reading from `Store`.
|
||||||
|
///
|
||||||
|
/// Contains duplicate roots when skip slots are encountered.
|
||||||
|
pub fn iter_block_roots(&self) -> BlockRootsIterator<T::EthSpec, T::Store> {
|
||||||
|
BlockRootsIterator::from_state(self.store.clone(), self.state.read().clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Returns `count `beacon block roots, starting from `start_slot` with an
|
/// Returns `count `beacon block roots, starting from `start_slot` with an
|
||||||
/// interval of `skip` slots between each root.
|
/// interval of `skip` slots between each root.
|
||||||
///
|
///
|
||||||
@ -305,6 +317,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
Err(BeaconStateError::SlotOutOfBounds.into())
|
Err(BeaconStateError::SlotOutOfBounds.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Returns the block at the given root, if any.
|
/// Returns the block at the given root, if any.
|
||||||
///
|
///
|
||||||
|
106
beacon_node/beacon_chain/src/iter.rs
Normal file
106
beacon_node/beacon_chain/src/iter.rs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use store::Store;
|
||||||
|
use types::{BeaconState, BeaconStateError, EthSpec, Hash256, Slot};
|
||||||
|
|
||||||
|
/// Iterates backwards through block roots.
|
||||||
|
///
|
||||||
|
/// Uses the `latest_block_roots` field of `BeaconState` to as the source of block roots and will
|
||||||
|
/// perform a lookup on the `Store` for a prior `BeaconState` if `latest_block_roots` has been
|
||||||
|
/// exhausted.
|
||||||
|
///
|
||||||
|
/// Returns `None` for roots prior to genesis or when there is an error reading from `Store`.
|
||||||
|
pub struct BlockRootsIterator<T: EthSpec, U> {
|
||||||
|
store: Arc<U>,
|
||||||
|
beacon_state: BeaconState<T>,
|
||||||
|
slot: Slot,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: EthSpec, U: Store> BlockRootsIterator<T, U> {
|
||||||
|
/// Create a new iterator over all block roots in the given `beacon_state` and prior states.
|
||||||
|
pub fn from_state(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
slot: beacon_state.slot,
|
||||||
|
beacon_state,
|
||||||
|
store,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: EthSpec, U: Store> Iterator for BlockRootsIterator<T, U> {
|
||||||
|
type Item = Hash256;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.slot == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let slot = self.slot - 1;
|
||||||
|
|
||||||
|
match self.beacon_state.get_block_root(slot) {
|
||||||
|
Ok(root) => Some(*root),
|
||||||
|
Err(BeaconStateError::SlotOutOfBounds) => {
|
||||||
|
// Read a `BeaconState` from the store that has access to prior historical root.
|
||||||
|
self.beacon_state = {
|
||||||
|
// Read the earliest historic state in the current slot.
|
||||||
|
let earliest_historic_slot =
|
||||||
|
self.beacon_state.slot - Slot::from(T::slots_per_historical_root());
|
||||||
|
|
||||||
|
// Load the earlier state from disk.
|
||||||
|
let new_state_root = self
|
||||||
|
.beacon_state
|
||||||
|
.get_state_root(earliest_historic_slot)
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
let state_option = self.store.get(&new_state_root).ok()?;
|
||||||
|
state_option?
|
||||||
|
};
|
||||||
|
|
||||||
|
self.beacon_state.get_block_root(slot).ok().cloned()
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use store::MemoryStore;
|
||||||
|
use types::{test_utils::TestingBeaconStateBuilder, FoundationEthSpec, Keypair};
|
||||||
|
|
||||||
|
fn get_state<T: EthSpec>() -> BeaconState<T> {
|
||||||
|
let builder =
|
||||||
|
TestingBeaconStateBuilder::from_single_keypair(0, &Keypair::random(), &T::spec());
|
||||||
|
let (state, _keypairs) = builder.build();
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn root_iter() {
|
||||||
|
let store = Arc::new(MemoryStore::open());
|
||||||
|
|
||||||
|
let mut state_a: BeaconState<FoundationEthSpec> = get_state();
|
||||||
|
let mut state_b: BeaconState<FoundationEthSpec> = get_state();
|
||||||
|
|
||||||
|
let mut hashes = (0..).into_iter().map(|i| Hash256::from(i));
|
||||||
|
|
||||||
|
for root in &mut state_a.latest_block_roots[..] {
|
||||||
|
*root = hashes.next().unwrap()
|
||||||
|
}
|
||||||
|
for root in &mut state_b.latest_block_roots[..] {
|
||||||
|
*root = hashes.next().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
let state_a_root = hashes.next().unwrap();
|
||||||
|
state_b.latest_state_roots[0] = state_a_root;
|
||||||
|
store.put(&state_a_root, &state_a).unwrap();
|
||||||
|
|
||||||
|
let iter = BlockRootsIterator::from_state(store.clone(), state_b.clone());
|
||||||
|
let mut collected: Vec<Hash256> = iter.collect();
|
||||||
|
collected.reverse();
|
||||||
|
|
||||||
|
for (i, item) in collected.iter().enumerate() {
|
||||||
|
assert_eq!(*item, Hash256::from(i as u64));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
mod beacon_chain;
|
mod beacon_chain;
|
||||||
mod checkpoint;
|
mod checkpoint;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
pub mod iter;
|
||||||
mod metrics;
|
mod metrics;
|
||||||
mod persisted_beacon_chain;
|
mod persisted_beacon_chain;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user