diff --git a/lighthouse/state/block/block.rs b/lighthouse/state/block/block.rs index 115cbcd0e..3fe9a668e 100644 --- a/lighthouse/state/block/block.rs +++ b/lighthouse/state/block/block.rs @@ -1,15 +1,12 @@ use super::utils::types::Hash256; -use super::attestation_record::{ - AttestationRecord, - MIN_SSZ_ATTESTION_RECORD_LENGTH, -}; +use super::attestation_record::AttestationRecord; use super::ssz::{ Encodable, SszStream }; pub const MIN_SSZ_BLOCK_LENGTH: usize = { 4 + 32 + // parent_hash - 8 + // slot_number + 8 + // slot_number 4 + 32 + // randao_reveal - 4 + MIN_SSZ_ATTESTION_RECORD_LENGTH + // attestations (minimum one) + 4 + // attestations (assuming zero) 4 + 32 + // pow_chain_ref 4 + 32 + // active_state_root 4 + 32 // crystallized_state_root @@ -71,8 +68,7 @@ mod tests { #[test] pub fn test_block_min_ssz_length() { - let mut b = Block::zero(); - b.attestations = vec![AttestationRecord::zero()]; + let b = Block::zero(); let mut ssz_stream = SszStream::new(); ssz_stream.append(&b); diff --git a/lighthouse/state/block/ssz_block.rs b/lighthouse/state/block/ssz_block.rs index 1e4d20bb1..dc2a60a1a 100644 --- a/lighthouse/state/block/ssz_block.rs +++ b/lighthouse/state/block/ssz_block.rs @@ -7,6 +7,7 @@ use super::block::{ MIN_SSZ_BLOCK_LENGTH, MAX_SSZ_BLOCK_LENGTH, }; +use super::attestation_record::MIN_SSZ_ATTESTION_RECORD_LENGTH; #[derive(Debug, PartialEq)] pub enum BlockValidatorError { @@ -32,34 +33,41 @@ impl<'a> SszBlock<'a> { pub fn from_slice(vec: &'a [u8]) -> Result { - let ssz = &vec[..]; - let len = vec.len(); + let untrimmed_ssz = &vec[..]; /* - * Ensure the SSZ is long enough to be a block. + * Ensure the SSZ is long enough to be a block with + * one attestation record (not necessarily a valid + * attestation record). */ - if len < MIN_SSZ_BLOCK_LENGTH { + if vec.len() < MIN_SSZ_BLOCK_LENGTH + MIN_SSZ_ATTESTION_RECORD_LENGTH { return Err(BlockValidatorError::TooShort); } /* * Ensure the SSZ slice isn't longer than is possible for a block. */ - if len > MAX_SSZ_BLOCK_LENGTH { + if vec.len() > MAX_SSZ_BLOCK_LENGTH { return Err(BlockValidatorError::TooLong); } /* - * Determine how many bytes are used to store attestation records - * and ensure that length is enough to store at least one attestation - * record. + * Determine how many bytes are used to store attestation records. */ - let attestation_len = decode_length(ssz, 80, LENGTH_BYTES) + let attestation_len = decode_length(untrimmed_ssz, 80, LENGTH_BYTES) .map_err(|_| BlockValidatorError::TooShort)?; - if len < (76 + attestation_len + 96) { + /* + * The block only has one variable field, `attestations`, therefore + * the size of the block must be the minimum size, plus the length + * of the attestations. + */ + let block_ssz_len = { + MIN_SSZ_BLOCK_LENGTH + attestation_len + }; + if vec.len() < block_ssz_len { return Err(BlockValidatorError::TooShort); } Ok(Self{ - ssz, + ssz: &untrimmed_ssz[0..block_ssz_len], attestation_len, - len, + len: block_ssz_len, }) } @@ -156,6 +164,19 @@ mod tests { ); } + #[test] + fn test_ssz_block_single_attestation_record_one_byte_long() { + let mut b = Block::zero(); + b.attestations = vec![AttestationRecord::zero()]; + let mut ssz = get_block_ssz(&b); + let original_len = ssz.len(); + ssz.push(42); + + let ssz_block = SszBlock::from_slice(&ssz[..]).unwrap(); + + assert_eq!(ssz_block.len, original_len); + } + #[test] fn test_ssz_block_single_attestation_record() { let mut b = Block::zero();