Add skip slot support to BeaconChain fns

This commit is contained in:
Paul Hauner 2019-03-24 12:49:59 +11:00
parent a57a7c2394
commit 3eae7b3fc5
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
2 changed files with 97 additions and 31 deletions

View File

@ -142,7 +142,38 @@ where
}) })
} }
/// Returns beacon block roots for `count` slots, starting from `start_slot`. /// Returns the beacon block body for each beacon block root in `roots`.
///
/// Fails if any root in `roots` does not have a corresponding block.
pub fn get_block_bodies(&self, roots: &[Hash256]) -> Result<Vec<BeaconBlockBody>, Error> {
let bodies: Result<Vec<BeaconBlockBody>, _> = roots
.iter()
.map(|root| match self.get_block(root)? {
Some(block) => Ok(block.body),
None => Err(Error::DBInconsistent("Missing block".into())),
})
.collect();
Ok(bodies?)
}
/// Returns the beacon block header for each beacon block root in `roots`.
///
/// Fails if any root in `roots` does not have a corresponding block.
pub fn get_block_headers(&self, roots: &[Hash256]) -> Result<Vec<BeaconBlockHeader>, Error> {
let headers: Result<Vec<BeaconBlockHeader>, _> = roots
.iter()
.map(|root| match self.get_block(root)? {
Some(block) => Ok(block.block_header()),
None => Err(Error::DBInconsistent("Missing block".into())),
})
.collect();
Ok(headers?)
}
/// Returns `count `beacon block roots, starting from `start_slot` with an
/// interval of `skip` slots between each root.
/// ///
/// ## Errors: /// ## Errors:
/// ///
@ -152,40 +183,45 @@ where
/// - Other: BeaconState` is inconsistent. /// - Other: BeaconState` is inconsistent.
pub fn get_block_roots( pub fn get_block_roots(
&self, &self,
start_slot: Slot, earliest_slot: Slot,
count: Slot, count: usize,
) -> Result<Vec<Hash256>, BeaconStateError> { skip: usize,
) -> Result<Vec<Hash256>, Error> {
let spec = &self.spec; let spec = &self.spec;
let step_by = Slot::from(skip + 1);
let mut roots: Vec<Hash256> = vec![]; let mut roots: Vec<Hash256> = vec![];
// The state for reading block roots. Will be updated with an older state if slots go too
// far back in history.
let mut state = self.state.read().clone(); let mut state = self.state.read().clone();
let mut slot = start_slot + count - 1;
// The final slot in this series, will be reduced by `skip` each loop iteration.
let mut slot = earliest_slot + Slot::from(count * (skip + 1)) - 1;
// If the highest slot requested is that of the current state insert the root of the
// head block, unless the head block's slot is not matching.
if slot == state.slot && self.head().beacon_block.slot == slot {
roots.push(self.head().beacon_block_root);
slot -= step_by;
} else if slot >= state.slot {
return Err(BeaconStateError::SlotOutOfBounds.into());
}
loop { loop {
// If the highest slot requested is that of the current state insert the root of the
// head block, unless the head block's slot is not matching.
if slot == state.slot && self.head().beacon_block.slot == slot {
roots.push(self.head().beacon_block_root);
slot -= 1;
continue;
} else if slot >= state.slot {
return Err(BeaconStateError::SlotOutOfBounds);
}
// If the slot is within the range of the current state's block roots, append the root // If the slot is within the range of the current state's block roots, append the root
// to the output vec. // to the output vec.
// //
// If we get `SlotOutOfBounds` error, load the oldest known state to the present state // If we get `SlotOutOfBounds` error, load the oldest available historic
// from the DB. // state from the DB.
match state.get_block_root(slot, spec) { match state.get_block_root(slot, spec) {
Ok(root) => { Ok(root) => {
roots.push(*root); if slot < earliest_slot {
if slot == start_slot {
break; break;
} else { } else {
slot -= 1; roots.push(*root);
slot -= step_by;
} }
} }
Err(BeaconStateError::SlotOutOfBounds) => { Err(BeaconStateError::SlotOutOfBounds) => {
@ -201,18 +237,19 @@ where
_ => break, _ => break,
} }
} }
Err(e) => return Err(e), Err(e) => return Err(e.into()),
}; };
} }
if (slot == start_slot) && (roots.len() == count.as_usize()) { // Return the results if they pass a sanity check.
if (slot <= earliest_slot) && (roots.len() == count) {
// Reverse the ordering of the roots. We extracted them in reverse order to make it // Reverse the ordering of the roots. We extracted them in reverse order to make it
// simpler to lookup historic states. // simpler to lookup historic states.
// //
// This is a potential optimisation target. // This is a potential optimisation target.
Ok(roots.iter().rev().cloned().collect()) Ok(roots.iter().rev().cloned().collect())
} else { } else {
Err(BeaconStateError::SlotOutOfBounds) Err(BeaconStateError::SlotOutOfBounds.into())
} }
} }

View File

@ -8,7 +8,7 @@ use beacon_chain::{
CheckPoint, CheckPoint,
}; };
use eth2_libp2p::HelloMessage; use eth2_libp2p::HelloMessage;
use types::{BeaconBlock, BeaconStateError, Epoch, Hash256, Slot}; use types::{BeaconBlock, BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};
pub use beacon_chain::{BeaconChainError, BlockProcessingOutcome}; pub use beacon_chain::{BeaconChainError, BlockProcessingOutcome};
@ -40,8 +40,19 @@ pub trait BeaconChain: Send + Sync {
fn get_block_roots( fn get_block_roots(
&self, &self,
start_slot: Slot, start_slot: Slot,
count: Slot, count: usize,
) -> Result<Vec<Hash256>, BeaconStateError>; skip: usize,
) -> Result<Vec<Hash256>, BeaconChainError>;
fn get_block_headers(
&self,
start_slot: Slot,
count: usize,
skip: usize,
) -> Result<Vec<BeaconBlockHeader>, BeaconChainError>;
fn get_block_bodies(&self, roots: &[Hash256])
-> Result<Vec<BeaconBlockBody>, BeaconChainError>;
fn is_new_block_root(&self, beacon_block_root: &Hash256) -> Result<bool, BeaconChainError>; fn is_new_block_root(&self, beacon_block_root: &Hash256) -> Result<bool, BeaconChainError>;
} }
@ -111,9 +122,27 @@ where
fn get_block_roots( fn get_block_roots(
&self, &self,
start_slot: Slot, start_slot: Slot,
count: Slot, count: usize,
) -> Result<Vec<Hash256>, BeaconStateError> { skip: usize,
self.get_block_roots(start_slot, count) ) -> Result<Vec<Hash256>, BeaconChainError> {
self.get_block_roots(start_slot, count, skip)
}
fn get_block_headers(
&self,
start_slot: Slot,
count: usize,
skip: usize,
) -> Result<Vec<BeaconBlockHeader>, BeaconChainError> {
let roots = self.get_block_roots(start_slot, count, skip)?;
self.get_block_headers(&roots)
}
fn get_block_bodies(
&self,
roots: &[Hash256],
) -> Result<Vec<BeaconBlockBody>, BeaconChainError> {
self.get_block_bodies(roots)
} }
fn is_new_block_root(&self, beacon_block_root: &Hash256) -> Result<bool, BeaconChainError> { fn is_new_block_root(&self, beacon_block_root: &Hash256) -> Result<bool, BeaconChainError> {