Implement basics for ssz_block

This commit is contained in:
Paul Hauner 2018-09-19 16:15:05 +10:00
parent 3dea40abe0
commit 61fddb2660
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
2 changed files with 88 additions and 19 deletions

View File

@ -2,6 +2,16 @@ use super::utils::types::{ Hash256, Bitfield };
use super::utils::bls::{ AggregateSignature }; use super::utils::bls::{ AggregateSignature };
use super::ssz::{ Encodable, SszStream }; use super::ssz::{ Encodable, SszStream };
pub const MIN_SSZ_ATTESTION_RECORD_LENGTH: usize = {
8 + // slot
2 + // shard_id
4 + // oblique_parent_hashes (empty list)
32 + // shard_block_hash
5 + // attester_bitfield (assuming 1 byte of bitfield)
8 + // justified_slot
32 + // justified_block_hash
2 * 32 // aggregate sig (two 256 bit points)
};
pub struct AttestationRecord { pub struct AttestationRecord {
pub slot: u64, pub slot: u64,

View File

@ -3,9 +3,13 @@ use super::ssz::decode::{
Decodable, Decodable,
}; };
use super::utils::hash::canonical_hash; use super::utils::hash::canonical_hash;
use super::attestation_record::MIN_SSZ_ATTESTION_RECORD_LENGTH;
#[derive(Debug, PartialEq)]
pub enum BlockValidatorError { pub enum BlockValidatorError {
SszInvalid, TooShort,
TooLong,
NoAttestationRecords,
BadPowHash, BadPowHash,
SlotTooLow, SlotTooLow,
SlotTooHigh, SlotTooHigh,
@ -21,36 +25,56 @@ const MIN_SSZ_BLOCK_LENGTH: usize = {
32 + // active_state_root 32 + // active_state_root
32 // crystallized_state_root 32 // crystallized_state_root
}; };
const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + 2^24; const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + (1 << 24);
/// Allows for reading of block values directly from serialized /// Allows for reading of block values directly from serialized
/// ssz bytes. /// ssz bytes.
#[derive(Debug, PartialEq)]
pub struct SszBlock<'a> { pub struct SszBlock<'a> {
ssz: &'a [u8], ssz: &'a [u8],
attestation_len: usize, attestation_len: usize,
pub len: usize,
} }
impl<'a> SszBlock<'a> { impl<'a> SszBlock<'a> {
pub fn from_vec(vec: &'a Vec<u8>) pub fn from_slice(vec: &'a [u8])
-> Result<Self, BlockValidatorError> -> Result<Self, BlockValidatorError>
{ {
let ssz = &vec[..]; let ssz = &vec[..];
if vec.len() < MIN_SSZ_BLOCK_LENGTH { let len = vec.len();
return Err(BlockValidatorError::SszInvalid); /*
* Ensure the SSZ is long enough to be a block.
*/
if len < MIN_SSZ_BLOCK_LENGTH {
return Err(BlockValidatorError::TooShort);
} }
if vec.len() > MAX_SSZ_BLOCK_LENGTH { /*
return Err(BlockValidatorError::SszInvalid); * Ensure the SSZ slice isn't longer than is possible for a block.
*/
if 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.
*/
let attestation_len = decode_length(ssz, 72, LENGTH_BYTES) let attestation_len = decode_length(ssz, 72, LENGTH_BYTES)
.map_err(|_| BlockValidatorError::SszInvalid)?; .map_err(|_| BlockValidatorError::TooShort)?;
// Is the length adequate now we know now many attestation if attestation_len < MIN_SSZ_ATTESTION_RECORD_LENGTH {
// records exist? return Err(BlockValidatorError::NoAttestationRecords)
if vec.len() < (76 + attestation_len + 96) { }
return Err(BlockValidatorError::SszInvalid); /*
* Ensure that the SSZ is long enough, now we know the
* length of the attestation records field.
*/
if len < (76 + attestation_len + 96) {
return Err(BlockValidatorError::TooShort);
} }
Ok(Self{ Ok(Self{
ssz, ssz,
attestation_len attestation_len,
len,
}) })
} }
@ -76,17 +100,52 @@ impl<'a> SszBlock<'a> {
} }
pub fn pow_chain_ref(&self) -> &[u8] { pub fn pow_chain_ref(&self) -> &[u8] {
let len = self.ssz.len(); &self.ssz[(self.len - 96)..(self.len - 64)]
&self.ssz[(len - 96)..(len - 64)]
} }
pub fn act_state_root(&self) -> &[u8] { pub fn act_state_root(&self) -> &[u8] {
let len = self.ssz.len(); &self.ssz[(self.len - 64)..(self.len - 32)]
&self.ssz[(len - 64)..(len - 32)]
} }
pub fn cry_state_root(&self) -> &[u8] { pub fn cry_state_root(&self) -> &[u8] {
let len = self.ssz.len(); &self.ssz[(self.len - 32)..(self.len)]
&self.ssz[(len - 32)..(len)] }
}
#[cfg(test)]
mod tests {
use super::*;
use super::super::block::Block;
use super::super::attestation_record::AttestationRecord;
use super::super::ssz::SszStream;
fn get_block_ssz(b: &Block) -> Vec<u8> {
let mut ssz_stream = SszStream::new();
ssz_stream.append(b);
ssz_stream.drain()
}
#[test]
fn test_ssz_block_zero_attestation_records() {
let mut b = Block::zero();
b.attestations = vec![];
let ssz = get_block_ssz(&b);
assert_eq!(
SszBlock::from_slice(&ssz[..]),
Err(BlockValidatorError::NoAttestationRecords)
);
}
#[test]
fn test_ssz_block_single_attestation_record() {
let mut b = Block::zero();
b.attestations = vec![AttestationRecord::zero()];
let ssz = get_block_ssz(&b);
assert_eq!(
SszBlock::from_slice(&ssz[..]),
Err(BlockValidatorError::NoAttestationRecords)
);
} }
} }