diff --git a/lighthouse/state/block.rs b/lighthouse/state/block/block.rs similarity index 100% rename from lighthouse/state/block.rs rename to lighthouse/state/block/block.rs diff --git a/lighthouse/state/block/mod.rs b/lighthouse/state/block/mod.rs new file mode 100644 index 000000000..20467eca7 --- /dev/null +++ b/lighthouse/state/block/mod.rs @@ -0,0 +1,11 @@ +extern crate blake2_rfc; + +use super::ssz; +use super::utils; +use super::attestation_record; + +mod block; +mod ssz_block; + +pub use self::block::Block; +pub use self::ssz_block::SszBlock; diff --git a/lighthouse/state/block/ssz_block.rs b/lighthouse/state/block/ssz_block.rs new file mode 100644 index 000000000..d9ad3945f --- /dev/null +++ b/lighthouse/state/block/ssz_block.rs @@ -0,0 +1,90 @@ +use super::ssz::decode::{ + decode_length, + Decodable, +}; +use super::utils::hash::canonical_hash; + +pub enum BlockValidatorError { + SszInvalid, + BadPowHash, + SlotTooLow, + SlotTooHigh, +} + +const LENGTH_BYTES: usize = 4; +const MIN_SSZ_BLOCK_LENGTH: usize = { + 32 + // parent_hash + 8 + // slot_number + 32 + // randao_reveal + LENGTH_BYTES + // attestations (assuming zero) + 32 + // pow_chain_ref + 32 + // active_state_root + 32 // crystallized_state_root +}; +const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + 2^24; + + +pub struct SszBlock<'a> { + ssz: &'a [u8], + attestation_len: usize, +} + +impl<'a> SszBlock<'a> { + pub fn from_vec(vec: &'a Vec) + -> Result + { + if vec.len() < MIN_SSZ_BLOCK_LENGTH { + return Err(BlockValidatorError::SszInvalid); + } + if vec.len() > MAX_SSZ_BLOCK_LENGTH { + return Err(BlockValidatorError::SszInvalid); + } + let attestation_len = decode_length(&vec[72..76], LENGTH_BYTES) + .map_err(|_| BlockValidatorError::SszInvalid)?; + // Is the length adequate now we know now many attestation + // records exist? + if vec.len() < (76 + attestation_len + 96) { + return Err(BlockValidatorError::SszInvalid); + } + Ok(Self{ + ssz: &vec[..], + attestation_len + }) + } + + pub fn block_hash(&self) -> Vec { + canonical_hash(self.ssz) + } + + pub fn parent_hash(&self) -> &[u8] { + &self.ssz[0..32] + } + + pub fn slot_number(&self) -> u64 { + u64::ssz_decode(&self.ssz[32..40]).unwrap() + } + + pub fn randao_reveal(&self) -> &[u8] { + &self.ssz[40..72] + } + + pub fn attestations(&self) -> &[u8] { + let start = 72 + LENGTH_BYTES; + &self.ssz[start..(start + self.attestation_len)] + } + + pub fn pow_chain_ref(&self) -> &[u8] { + let len = self.ssz.len(); + &self.ssz[(len - 96)..(len - 64)] + } + + pub fn act_state_root(&self) -> &[u8] { + let len = self.ssz.len(); + &self.ssz[(len - 64)..(len - 32)] + } + + pub fn cry_state_root(&self) -> &[u8] { + let len = self.ssz.len(); + &self.ssz[(len - 32)..(len)] + } +}