Implement basics for ssz_block
This commit is contained in:
parent
3dea40abe0
commit
61fddb2660
@ -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,
|
||||||
|
@ -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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user