Begin implementing new types

This commit is contained in:
Paul Hauner 2018-12-18 18:09:21 +11:00
parent be4c6701ac
commit 0260564c15
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
9 changed files with 314 additions and 128 deletions

View File

@ -1,142 +1,28 @@
use super::attestation::Attestation;
use super::special_record::SpecialRecord;
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::Hash256;
pub const MIN_SSZ_BLOCK_LENGTH: usize = {
8 + // slot
32 + // randao_reveal
32 + // pow_chain_reference
4 + // ancestor hashes (assuming empty)
32 + // active_state_root
32 + // crystallized_state_root
4 + // attestations (assuming empty)
4 // specials (assuming empty)
};
pub const MAX_SSZ_BLOCK_LENGTH: usize = MIN_SSZ_BLOCK_LENGTH + (1 << 24);
use super::{BeaconBlockBody, Hash256};
use bls::AggregateSignature;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct BeaconBlock {
pub slot: u64,
pub parent_root: Hash256,
pub state_root: Hash256,
pub randao_reveal: Hash256,
pub pow_chain_reference: Hash256,
pub ancestor_hashes: Vec<Hash256>,
pub active_state_root: Hash256,
pub crystallized_state_root: Hash256,
pub attestations: Vec<Attestation>,
pub specials: Vec<SpecialRecord>,
}
impl BeaconBlock {
pub fn zero() -> Self {
Self {
slot: 0,
randao_reveal: Hash256::zero(),
pow_chain_reference: Hash256::zero(),
ancestor_hashes: vec![],
active_state_root: Hash256::zero(),
crystallized_state_root: Hash256::zero(),
attestations: vec![],
specials: vec![],
}
}
/// Return a reference to `ancestor_hashes[0]`.
///
/// The first hash in `ancestor_hashes` is the parent of the block.
pub fn parent_hash(&self) -> Option<&Hash256> {
self.ancestor_hashes.get(0)
}
pub candidate_pow_receipt_root: Hash256,
pub signature: AggregateSignature,
pub body: BeaconBlockBody,
}
/*
impl Encodable for BeaconBlock {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slot);
s.append(&self.parent_root);
s.append(&self.state_root);
s.append(&self.randao_reveal);
s.append(&self.pow_chain_reference);
s.append_vec(&self.ancestor_hashes);
s.append(&self.active_state_root);
s.append(&self.crystallized_state_root);
s.append_vec(&self.attestations);
s.append_vec(&self.specials);
}
}
impl Decodable for BeaconBlock {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (slot, i) = u64::ssz_decode(bytes, i)?;
let (randao_reveal, i) = Hash256::ssz_decode(bytes, i)?;
let (pow_chain_reference, i) = Hash256::ssz_decode(bytes, i)?;
let (ancestor_hashes, i) = Decodable::ssz_decode(bytes, i)?;
let (active_state_root, i) = Hash256::ssz_decode(bytes, i)?;
let (crystallized_state_root, i) = Hash256::ssz_decode(bytes, i)?;
let (attestations, i) = Decodable::ssz_decode(bytes, i)?;
let (specials, i) = Decodable::ssz_decode(bytes, i)?;
let block = BeaconBlock {
slot,
randao_reveal,
pow_chain_reference,
ancestor_hashes,
active_state_root,
crystallized_state_root,
attestations,
specials,
};
Ok((block, i))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_block_zero() {
let b = BeaconBlock::zero();
assert_eq!(b.slot, 0);
assert!(b.randao_reveal.is_zero());
assert!(b.pow_chain_reference.is_zero());
assert_eq!(b.ancestor_hashes, vec![]);
assert!(b.active_state_root.is_zero());
assert!(b.crystallized_state_root.is_zero());
assert_eq!(b.attestations.len(), 0);
assert_eq!(b.specials.len(), 0);
}
#[test]
pub fn test_block_ssz_encode_decode() {
let mut b = BeaconBlock::zero();
b.ancestor_hashes = vec![Hash256::zero(); 32];
let mut ssz_stream = SszStream::new();
ssz_stream.append(&b);
let ssz = ssz_stream.drain();
let (b_decoded, _) = BeaconBlock::ssz_decode(&ssz, 0).unwrap();
assert_eq!(b, b_decoded);
}
#[test]
pub fn test_block_min_ssz_length() {
let b = BeaconBlock::zero();
let mut ssz_stream = SszStream::new();
ssz_stream.append(&b);
let ssz = ssz_stream.drain();
assert_eq!(ssz.len(), MIN_SSZ_BLOCK_LENGTH);
}
#[test]
pub fn test_block_parent_hash() {
let mut b = BeaconBlock::zero();
b.ancestor_hashes = vec![
Hash256::from("cats".as_bytes()),
Hash256::from("dogs".as_bytes()),
Hash256::from("birds".as_bytes()),
];
assert_eq!(b.parent_hash().unwrap(), &Hash256::from("cats".as_bytes()));
s.append(&self.candidate_pow_receipt_root);
s.append_vec(&self.signature.as_bytes());
s.append(&self.body);
}
}
*/

View File

@ -0,0 +1,23 @@
use super::ssz::{Encodable, SszStream};
use super::{Attestation, CasperSlashing, Deposit, Exit, ProposerSlashing};
#[derive(Debug, PartialEq, Clone, Default)]
pub struct BeaconBlockBody {
pub proposer_slashings: Vec<ProposerSlashing>,
pub casper_slashings: Vec<CasperSlashing>,
pub attestations: Vec<Attestation>,
pub deposits: Vec<Deposit>,
pub exits: Vec<Exit>,
}
/*
impl Encodable for BeaconBlockBody {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.proposer_slashings);
s.append(&self.casper_slashings);
s.append(&self.attestations);
s.append(&self.deposits);
s.append(&self.exits);
}
}
*/

View File

@ -0,0 +1,30 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::SlashableVoteData;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct CasperSlashing {
pub slashable_vote_data_1: SlashableVoteData,
pub slashable_vote_data_2: SlashableVoteData,
}
impl Encodable for CasperSlashing {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slashable_vote_data_1);
s.append(&self.slashable_vote_data_1);
}
}
impl Decodable for CasperSlashing {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (slashable_vote_data_1, i) = SlashableVoteData::ssz_decode(bytes, i)?;
let (slashable_vote_data_2, i) = SlashableVoteData::ssz_decode(bytes, i)?;
Ok((
CasperSlashing {
slashable_vote_data_1,
slashable_vote_data_2,
},
i,
))
}
}

View File

@ -0,0 +1,24 @@
use super::Hash256;
use bls::{AggregateSignature, PublicKey};
#[derive(Debug, PartialEq, Clone)]
pub struct Deposit {
pub merkle_branch: Vec<Hash256>,
pub merkle_tree_index: u64,
pub deposit_data: DepositData,
}
#[derive(Debug, PartialEq, Clone)]
pub struct DepositData {
pub deposit_input: DepositInput,
pub value: u64,
pub timestamp: u64,
}
#[derive(Debug, PartialEq, Clone)]
pub struct DepositInput {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
pub randao_commitment: Hash256,
pub proof_of_possession: AggregateSignature,
}

View File

@ -0,0 +1,8 @@
use bls::AggregateSignature;
#[derive(Debug, PartialEq, Clone)]
pub struct Exit {
pub slot: u64,
pub validator_index: u32,
pub signature: AggregateSignature,
}

View File

@ -7,16 +7,23 @@ pub mod active_state;
pub mod attestation_data;
pub mod attestation;
pub mod beacon_block;
pub mod beacon_block_body;
pub mod beacon_state;
pub mod candidate_pow_receipt_root_record;
pub mod casper_slashing;
pub mod chain_config;
pub mod crosslink_record;
pub mod crystallized_state;
pub mod deposit;
pub mod exit;
pub mod fork_data;
pub mod pending_attestation_record;
pub mod proposal_signed_data;
pub mod proposer_slashing;
pub mod shard_and_committee;
pub mod shard_reassignment_record;
pub mod special_record;
pub mod slashable_vote_data;
pub mod validator_record;
pub mod validator_registration;
@ -27,12 +34,19 @@ pub use active_state::ActiveState;
pub use attestation_data::AttestationData;
pub use attestation::Attestation;
pub use beacon_block::BeaconBlock;
pub use beacon_block_body::BeaconBlockBody;
pub use beacon_state::BeaconState;
pub use casper_slashing::CasperSlashing;
pub use chain_config::ChainConfig;
pub use crosslink_record::CrosslinkRecord;
pub use crystallized_state::CrystallizedState;
pub use deposit::{Deposit, DepositData, DepositInput};
pub use exit::Exit;
pub use fork_data::ForkData;
pub use pending_attestation_record::PendingAttestationRecord;
pub use proposal_signed_data::ProposalSignedData;
pub use proposer_slashing::ProposerSlashing;
pub use slashable_vote_data::SlashableVoteData;
pub use shard_and_committee::ShardAndCommittee;
pub use special_record::{SpecialRecord, SpecialRecordKind};
pub use validator_record::{ValidatorRecord, ValidatorStatus};

View File

@ -0,0 +1,54 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::Hash256;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct ProposalSignedData {
pub slot: u64,
pub shard: u64,
pub block_root: Hash256,
}
impl Encodable for ProposalSignedData {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slot);
s.append(&self.shard);
s.append(&self.block_root);
}
}
impl Decodable for ProposalSignedData {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (slot, i) = u64::ssz_decode(bytes, i)?;
let (shard, i) = u64::ssz_decode(bytes, i)?;
let (block_root, i) = Hash256::ssz_decode(bytes, i)?;
Ok((
ProposalSignedData {
slot,
shard,
block_root,
},
i,
))
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
#[test]
pub fn test_ssz_round_trip() {
let original = ProposalSignedData {
slot: 42,
shard: 120,
block_root: Hash256::from("cats".as_bytes()),
};
let bytes = ssz_encode(&original);
let (decoded, _) = ProposalSignedData::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -0,0 +1,77 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::ProposalSignedData;
use bls::Signature;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct ProposerSlashing {
pub proposer_index: u32,
pub proposal_data_1: ProposalSignedData,
pub proposal_signature_1: Signature,
pub proposal_data_2: ProposalSignedData,
pub proposal_signature_2: Signature,
}
impl Encodable for ProposerSlashing {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.proposer_index);
s.append(&self.proposal_data_1);
s.append(&self.proposal_signature_1);
s.append(&self.proposal_data_2);
s.append(&self.proposal_signature_2);
}
}
impl Decodable for ProposerSlashing {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (proposer_index, i) = u32::ssz_decode(bytes, i)?;
let (proposal_data_1, i) = ProposalSignedData::ssz_decode(bytes, i)?;
let (proposal_signature_1, i) = Signature::ssz_decode(bytes, i)?;
let (proposal_data_2, i) = ProposalSignedData::ssz_decode(bytes, i)?;
let (proposal_signature_2, i) = Signature::ssz_decode(bytes, i)?;
Ok((
ProposerSlashing {
proposer_index,
proposal_data_1,
proposal_signature_1,
proposal_data_2,
proposal_signature_2,
},
i,
))
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::super::Hash256;
use super::*;
use bls::{Keypair, Signature};
#[test]
pub fn test_ssz_round_trip() {
let keypair = Keypair::random();
let original = ProposerSlashing {
proposer_index: 42,
proposal_data_1: ProposalSignedData {
slot: 45,
shard: 110,
block_root: Hash256::from("cats".as_bytes()),
},
proposal_signature_1: Signature::new(&[42, 42], &keypair.sk),
proposal_data_2: ProposalSignedData {
slot: 1,
shard: 260,
block_root: Hash256::from("lol".as_bytes()),
},
proposal_signature_2: Signature::new(&[7, 8], &keypair.sk),
};
let bytes = ssz_encode(&original);
let (decoded, _) = ProposerSlashing::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -0,0 +1,70 @@
use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream};
use super::AttestationData;
use bls::AggregateSignature;
#[derive(Debug, PartialEq, Clone, Default)]
pub struct SlashableVoteData {
pub aggregate_signature_poc_0_indices: Vec<u32>,
pub aggregate_signature_poc_1_indices: Vec<u32>,
pub data: AttestationData,
pub aggregate_signature: AggregateSignature,
}
impl Encodable for SlashableVoteData {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.aggregate_signature_poc_0_indices);
s.append_vec(&self.aggregate_signature_poc_1_indices);
s.append(&self.data);
s.append(&self.aggregate_signature);
}
}
impl Decodable for SlashableVoteData {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (aggregate_signature_poc_0_indices, i) = decode_ssz_list(bytes, i)?;
let (aggregate_signature_poc_1_indices, i) = decode_ssz_list(bytes, i)?;
let (data, i) = AttestationData::ssz_decode(bytes, i)?;
let (aggregate_signature, i) = AggregateSignature::ssz_decode(bytes, i)?;
Ok((
SlashableVoteData {
aggregate_signature_poc_0_indices,
aggregate_signature_poc_1_indices,
data,
aggregate_signature,
},
i,
))
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::super::Hash256;
use super::*;
#[test]
pub fn test_ssz_round_trip() {
let original = SlashableVoteData {
aggregate_signature_poc_0_indices: vec![0, 1, 2],
aggregate_signature_poc_1_indices: vec![42, 42, 42],
data: AttestationData {
slot: 42,
shard: 16,
beacon_block_hash: Hash256::from("beacon".as_bytes()),
epoch_boundary_hash: Hash256::from("epoch".as_bytes()),
shard_block_hash: Hash256::from("shard".as_bytes()),
latest_crosslink_hash: Hash256::from("xlink".as_bytes()),
justified_slot: 8,
justified_block_hash: Hash256::from("justified".as_bytes()),
},
aggregate_signature: AggregateSignature::new(),
};
let bytes = ssz_encode(&original);
let (decoded, _) = SlashableVoteData::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}