Fix issues with building on genesis block

This commit is contained in:
Paul Hauner
2019-03-18 16:53:59 +11:00
parent 191761f356
commit edeace9e75
5 changed files with 202 additions and 74 deletions

View File

@@ -63,16 +63,32 @@ impl BeaconBlock {
Hash256::from_slice(&self.hash_tree_root()[..])
}
/// Returns a full `BeaconBlockHeader` of this block.
///
/// Note: This method is used instead of an `Into` impl to avoid a `Clone` of an entire block
/// when you want to have the block _and_ the header.
///
/// Note: performs a full tree-hash of `self.body`.
///
/// Spec v0.5.0
pub fn into_header(&self) -> BeaconBlockHeader {
BeaconBlockHeader {
slot: self.slot,
previous_block_root: self.previous_block_root,
state_root: self.state_root,
block_body_root: Hash256::from_slice(&self.body.hash_tree_root()[..]),
signature: self.signature.clone(),
}
}
/// Returns a "temporary" header, where the `state_root` is `spec.zero_hash`.
///
/// Spec v0.5.0
pub fn into_temporary_header(&self, spec: &ChainSpec) -> BeaconBlockHeader {
BeaconBlockHeader {
slot: self.slot,
previous_block_root: self.previous_block_root,
state_root: spec.zero_hash,
block_body_root: Hash256::from_slice(&self.hash_tree_root()),
signature: self.signature.clone(),
signature: spec.empty_signature.clone(),
..self.into_header()
}
}
}

View File

@@ -30,6 +30,15 @@ pub struct BeaconBlockHeader {
pub signature: Signature,
}
impl BeaconBlockHeader {
/// Returns the `hash_tree_root` of the header.
///
/// Spec v0.5.0
pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..])
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -35,6 +35,7 @@ pub enum Error {
InsufficientAttestations,
InsufficientCommittees,
InsufficientSlashedBalances,
InsufficientStateRoots,
NoCommitteeForShard,
EpochCacheUninitialized(RelativeEpoch),
PubkeyCacheInconsistent,
@@ -425,6 +426,22 @@ impl BeaconState {
.ok_or_else(|| Error::NoCommitteeForShard)?)
}
/// Safely obtains the index for latest block roots, given some `slot`.
///
/// Spec v0.5.0
fn get_latest_block_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root;
if i >= self.latest_block_roots.len() {
Err(Error::InsufficientStateRoots)
} else {
Ok(i)
}
} else {
Err(BeaconStateError::SlotOutOfBounds)
}
}
/// Return the block root at a recent `slot`.
///
/// Spec v0.5.0
@@ -433,13 +450,21 @@ impl BeaconState {
slot: Slot,
spec: &ChainSpec,
) -> Result<&Hash256, BeaconStateError> {
if (self.slot <= slot + spec.slots_per_historical_root as u64) && (slot < self.slot) {
self.latest_block_roots
.get(slot.as_usize() % spec.slots_per_historical_root)
.ok_or_else(|| Error::InsufficientBlockRoots)
} else {
Err(Error::EpochOutOfBounds)
}
let i = self.get_latest_block_roots_index(slot, spec)?;
Ok(&self.latest_block_roots[i])
}
/// Sets the block root for some given slot.
///
/// Spec v0.5.0
pub fn set_block_root(
&mut self,
slot: Slot,
block_root: Hash256,
spec: &ChainSpec,
) -> Result<(), BeaconStateError> {
let i = self.get_latest_block_roots_index(slot, spec)?;
Ok(self.latest_block_roots[i] = block_root)
}
/// XOR-assigns the existing `epoch` randao mix with the hash of the `signature`.
@@ -506,6 +531,43 @@ impl BeaconState {
}
}
/// Safely obtains the index for latest state roots, given some `slot`.
///
/// Spec v0.5.0
fn get_latest_state_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root;
if i >= self.latest_state_roots.len() {
Err(Error::InsufficientStateRoots)
} else {
Ok(i)
}
} else {
Err(BeaconStateError::SlotOutOfBounds)
}
}
/// Gets the state root for some slot.
///
/// Spec v0.5.0
pub fn get_state_root(&mut self, slot: Slot, spec: &ChainSpec) -> Result<&Hash256, Error> {
let i = self.get_latest_state_roots_index(slot, spec)?;
Ok(&self.latest_state_roots[i])
}
/// Sets the latest state root for slot.
///
/// Spec v0.5.0
pub fn set_state_root(
&mut self,
slot: Slot,
state_root: Hash256,
spec: &ChainSpec,
) -> Result<(), Error> {
let i = self.get_latest_state_roots_index(slot, spec)?;
Ok(self.latest_state_roots[i] = state_root)
}
/// Generate a seed for the given `epoch`.
///
/// Spec v0.4.0