Implement ssz Enc/Decode for BeaconState + more

This commit is contained in:
Paul Hauner 2018-12-28 19:46:33 +11:00
parent e4e729d309
commit 39f2171053
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
12 changed files with 574 additions and 59 deletions

View File

@ -6,6 +6,9 @@ use super::shard_committee::ShardCommittee;
use super::shard_reassignment_record::ShardReassignmentRecord; use super::shard_reassignment_record::ShardReassignmentRecord;
use super::validator_record::ValidatorRecord; use super::validator_record::ValidatorRecord;
use super::Hash256; use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
use ssz::{Decodable, DecodeError, Encodable, SszStream};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct BeaconState { pub struct BeaconState {
@ -51,3 +54,114 @@ impl BeaconState {
Hash256::zero() Hash256::zero()
} }
} }
impl Encodable for BeaconState {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slot);
s.append(&self.genesis_time);
s.append(&self.fork_data);
s.append(&self.validator_registry);
s.append(&self.validator_registry_latest_change_slot);
s.append(&self.validator_registry_exit_count);
s.append(&self.validator_registry_delta_chain_tip);
s.append(&self.randao_mix);
s.append(&self.next_seed);
s.append(&self.shard_committees_at_slots);
s.append(&self.persistent_committees);
s.append(&self.persistent_committee_reassignments);
s.append(&self.previous_justified_slot);
s.append(&self.justified_slot);
s.append(&self.justification_bitfield);
s.append(&self.finalized_slot);
s.append(&self.latest_crosslinks);
s.append(&self.latest_block_roots);
s.append(&self.latest_penalized_exit_balances);
s.append(&self.latest_attestations);
s.append(&self.processed_pow_receipt_root);
s.append(&self.candidate_pow_receipt_roots);
}
}
impl Decodable for BeaconState {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (slot, i) = <_>::ssz_decode(bytes, i)?;
let (genesis_time, i) = <_>::ssz_decode(bytes, i)?;
let (fork_data, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_latest_change_slot, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_exit_count, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_delta_chain_tip, i) = <_>::ssz_decode(bytes, i)?;
let (randao_mix, i) = <_>::ssz_decode(bytes, i)?;
let (next_seed, i) = <_>::ssz_decode(bytes, i)?;
let (shard_committees_at_slots, i) = <_>::ssz_decode(bytes, i)?;
let (persistent_committees, i) = <_>::ssz_decode(bytes, i)?;
let (persistent_committee_reassignments, i) = <_>::ssz_decode(bytes, i)?;
let (previous_justified_slot, i) = <_>::ssz_decode(bytes, i)?;
let (justified_slot, i) = <_>::ssz_decode(bytes, i)?;
let (justification_bitfield, i) = <_>::ssz_decode(bytes, i)?;
let (finalized_slot, i) = <_>::ssz_decode(bytes, i)?;
let (latest_crosslinks, i) = <_>::ssz_decode(bytes, i)?;
let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?;
let (latest_penalized_exit_balances, i) = <_>::ssz_decode(bytes, i)?;
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
let (processed_pow_receipt_root, i) = <_>::ssz_decode(bytes, i)?;
let (candidate_pow_receipt_roots, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
slot,
genesis_time,
fork_data,
validator_registry,
validator_registry_latest_change_slot,
validator_registry_exit_count,
validator_registry_delta_chain_tip,
randao_mix,
next_seed,
shard_committees_at_slots,
persistent_committees,
persistent_committee_reassignments,
previous_justified_slot,
justified_slot,
justification_bitfield,
finalized_slot,
latest_crosslinks,
latest_block_roots,
latest_penalized_exit_balances,
latest_attestations,
processed_pow_receipt_root,
candidate_pow_receipt_roots,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for BeaconState {
fn random_for_test(rng: &mut T) -> Self {
Self {
slot: <_>::random_for_test(rng),
genesis_time: <_>::random_for_test(rng),
fork_data: <_>::random_for_test(rng),
validator_registry: <_>::random_for_test(rng),
validator_registry_latest_change_slot: <_>::random_for_test(rng),
validator_registry_exit_count: <_>::random_for_test(rng),
validator_registry_delta_chain_tip: <_>::random_for_test(rng),
randao_mix: <_>::random_for_test(rng),
next_seed: <_>::random_for_test(rng),
shard_committees_at_slots: <_>::random_for_test(rng),
persistent_committees: <_>::random_for_test(rng),
persistent_committee_reassignments: <_>::random_for_test(rng),
previous_justified_slot: <_>::random_for_test(rng),
justified_slot: <_>::random_for_test(rng),
justification_bitfield: <_>::random_for_test(rng),
finalized_slot: <_>::random_for_test(rng),
latest_crosslinks: <_>::random_for_test(rng),
latest_block_roots: <_>::random_for_test(rng),
latest_penalized_exit_balances: <_>::random_for_test(rng),
latest_attestations: <_>::random_for_test(rng),
processed_pow_receipt_root: <_>::random_for_test(rng),
candidate_pow_receipt_roots: <_>::random_for_test(rng),
}
}
}

View File

@ -1,7 +1,60 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::Hash256; use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct CandidatePoWReceiptRootRecord { pub struct CandidatePoWReceiptRootRecord {
pub candidate_pow_receipt_root: Hash256, pub candidate_pow_receipt_root: Hash256,
pub votes: u64, pub votes: u64,
} }
impl Encodable for CandidatePoWReceiptRootRecord {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.candidate_pow_receipt_root);
s.append(&self.votes);
}
}
impl Decodable for CandidatePoWReceiptRootRecord {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (candidate_pow_receipt_root, i) = <_>::ssz_decode(bytes, i)?;
let (votes, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
candidate_pow_receipt_root,
votes,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for CandidatePoWReceiptRootRecord {
fn random_for_test(rng: &mut T) -> Self {
Self {
candidate_pow_receipt_root: <_>::random_for_test(rng),
votes: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = CandidatePoWReceiptRootRecord::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -1,4 +1,7 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::Hash256; use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct CrosslinkRecord { pub struct CrosslinkRecord {
@ -15,3 +18,53 @@ impl CrosslinkRecord {
} }
} }
} }
impl Encodable for CrosslinkRecord {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slot);
s.append(&self.shard_block_root);
}
}
impl Decodable for CrosslinkRecord {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (slot, i) = <_>::ssz_decode(bytes, i)?;
let (shard_block_root, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
slot,
shard_block_root,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for CrosslinkRecord {
fn random_for_test(rng: &mut T) -> Self {
Self {
slot: <_>::random_for_test(rng),
shard_block_root: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = CrosslinkRecord::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -1,4 +1,4 @@
use super::ssz::{decode_ssz_list, Decodable, DecodeError, Encodable, SszStream}; use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::Hash256; use super::Hash256;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use bls::{PublicKey, Signature}; use bls::{PublicKey, Signature};
@ -14,7 +14,7 @@ pub struct DepositInput {
impl Encodable for DepositInput { impl Encodable for DepositInput {
fn ssz_append(&self, s: &mut SszStream) { fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.pubkey.as_bytes()); s.append(&self.pubkey);
s.append(&self.withdrawal_credentials); s.append(&self.withdrawal_credentials);
s.append(&self.randao_commitment); s.append(&self.randao_commitment);
s.append(&self.proof_of_possession); s.append(&self.proof_of_possession);
@ -23,8 +23,7 @@ impl Encodable for DepositInput {
impl Decodable for DepositInput { impl Decodable for DepositInput {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> { fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (pubkey_bytes, i) = decode_ssz_list(bytes, i)?; let (pubkey, i) = <_>::ssz_decode(bytes, i)?;
let pubkey = PublicKey::from_bytes(&pubkey_bytes).map_err(|_| DecodeError::TooShort)?;
let (withdrawal_credentials, i) = <_>::ssz_decode(bytes, i)?; let (withdrawal_credentials, i) = <_>::ssz_decode(bytes, i)?;
let (randao_commitment, i) = <_>::ssz_decode(bytes, i)?; let (randao_commitment, i) = <_>::ssz_decode(bytes, i)?;
let (proof_of_possession, i) = <_>::ssz_decode(bytes, i)?; let (proof_of_possession, i) = <_>::ssz_decode(bytes, i)?;

View File

@ -1,6 +1,64 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct ForkData { pub struct ForkData {
pub pre_fork_version: u64, pub pre_fork_version: u64,
pub post_fork_version: u64, pub post_fork_version: u64,
pub fork_slot: u64, pub fork_slot: u64,
} }
impl Encodable for ForkData {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.pre_fork_version);
s.append(&self.post_fork_version);
s.append(&self.fork_slot);
}
}
impl Decodable for ForkData {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (pre_fork_version, i) = <_>::ssz_decode(bytes, i)?;
let (post_fork_version, i) = <_>::ssz_decode(bytes, i)?;
let (fork_slot, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
pre_fork_version,
post_fork_version,
fork_slot,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for ForkData {
fn random_for_test(rng: &mut T) -> Self {
Self {
pre_fork_version: <_>::random_for_test(rng),
post_fork_version: <_>::random_for_test(rng),
fork_slot: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = ForkData::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -1,4 +1,7 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use super::{AttestationData, Bitfield}; use super::{AttestationData, Bitfield};
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct PendingAttestationRecord { pub struct PendingAttestationRecord {
@ -7,3 +10,61 @@ pub struct PendingAttestationRecord {
pub custody_bitfield: Bitfield, pub custody_bitfield: Bitfield,
pub slot_included: u64, pub slot_included: u64,
} }
impl Encodable for PendingAttestationRecord {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.data);
s.append(&self.participation_bitfield);
s.append(&self.custody_bitfield);
s.append(&self.slot_included);
}
}
impl Decodable for PendingAttestationRecord {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (data, i) = <_>::ssz_decode(bytes, i)?;
let (participation_bitfield, i) = <_>::ssz_decode(bytes, i)?;
let (custody_bitfield, i) = <_>::ssz_decode(bytes, i)?;
let (slot_included, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
data,
participation_bitfield,
custody_bitfield,
slot_included,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for PendingAttestationRecord {
fn random_for_test(rng: &mut T) -> Self {
Self {
data: <_>::random_for_test(rng),
participation_bitfield: <_>::random_for_test(rng),
custody_bitfield: <_>::random_for_test(rng),
slot_included: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = PendingAttestationRecord::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -1,28 +1,53 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ShardCommittee { pub struct ShardCommittee {
pub shard: u16, pub shard: u64,
pub committee: Vec<usize>, pub committee: Vec<usize>,
} }
impl ShardCommittee { impl Encodable for ShardCommittee {
/// Returns a new instance where the `shard_id` is zero and the fn ssz_append(&self, s: &mut SszStream) {
/// committee is an empty vector. s.append(&self.shard);
pub fn zero() -> Self { s.append(&self.committee);
}
}
impl Decodable for ShardCommittee {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (shard, i) = <_>::ssz_decode(bytes, i)?;
let (committee, i) = <_>::ssz_decode(bytes, i)?;
Ok((Self { shard, committee }, i))
}
}
impl<T: RngCore> TestRandom<T> for ShardCommittee {
fn random_for_test(rng: &mut T) -> Self {
Self { Self {
shard: 0, shard: <_>::random_for_test(rng),
committee: vec![], committee: <_>::random_for_test(rng),
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::ssz::ssz_encode;
use super::*; use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test] #[test]
fn test_shard_and_committee_zero() { pub fn test_ssz_round_trip() {
let s = ShardCommittee::zero(); let mut rng = XorShiftRng::from_seed([42; 16]);
assert_eq!(s.shard, 0); let original = ShardCommittee::random_for_test(&mut rng);
assert_eq!(s.committee.len(), 0);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
} }
} }

View File

@ -1,6 +1,64 @@
use super::ssz::{Decodable, DecodeError, Encodable, SszStream};
use crate::test_utils::TestRandom;
use rand::RngCore;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct ShardReassignmentRecord { pub struct ShardReassignmentRecord {
pub validator_index: u64, pub validator_index: u64,
pub shard: u64, pub shard: u64,
pub slot: u64, pub slot: u64,
} }
impl Encodable for ShardReassignmentRecord {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.validator_index);
s.append(&self.shard);
s.append(&self.slot);
}
}
impl Decodable for ShardReassignmentRecord {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (validator_index, i) = <_>::ssz_decode(bytes, i)?;
let (shard, i) = <_>::ssz_decode(bytes, i)?;
let (slot, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
validator_index,
shard,
slot,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for ShardReassignmentRecord {
fn random_for_test(rng: &mut T) -> Self {
Self {
validator_index: <_>::random_for_test(rng),
shard: <_>::random_for_test(rng),
slot: <_>::random_for_test(rng),
}
}
}
#[cfg(test)]
mod tests {
use super::super::ssz::ssz_encode;
use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = ShardReassignmentRecord::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@ -0,0 +1,11 @@
use super::TestRandom;
use crate::Address;
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for Address {
fn random_for_test(rng: &mut T) -> Self {
let mut key_bytes = vec![0; 20];
rng.fill_bytes(&mut key_bytes);
Address::from(&key_bytes[..])
}
}

View File

@ -2,6 +2,7 @@ use rand::RngCore;
pub use rand::{prng::XorShiftRng, SeedableRng}; pub use rand::{prng::XorShiftRng, SeedableRng};
pub mod address;
pub mod aggregate_signature; pub mod aggregate_signature;
pub mod bitfield; pub mod bitfield;
pub mod hash256; pub mod hash256;
@ -27,6 +28,12 @@ impl<T: RngCore> TestRandom<T> for u32 {
} }
} }
impl<T: RngCore> TestRandom<T> for usize {
fn random_for_test(rng: &mut T) -> Self {
rng.next_u32() as usize
}
}
impl<T: RngCore, U> TestRandom<T> for Vec<U> impl<T: RngCore, U> TestRandom<T> for Vec<U>
where U: TestRandom<T> where U: TestRandom<T>
{ {

View File

@ -1,5 +1,8 @@
use super::bls::{Keypair, PublicKey}; use super::bls::PublicKey;
use super::{Address, Hash256}; use super::{Address, Hash256};
use crate::test_utils::TestRandom;
use rand::RngCore;
use ssz::{Decodable, DecodeError, Encodable, SszStream};
use std::convert; use std::convert;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -38,44 +41,131 @@ pub struct ValidatorRecord {
pub exit_slot: u64, pub exit_slot: u64,
} }
impl ValidatorRecord { impl Encodable for ValidatorStatus {
/// Generates a new instance where the keypair is generated using fn ssz_append(&self, s: &mut SszStream) {
/// `rand::thread_rng` entropy and all other fields are set to zero. let byte: u8 = match self {
/// ValidatorStatus::PendingActivation => 0,
/// Returns the new instance and new keypair. ValidatorStatus::Active => 1,
pub fn zero_with_thread_rand_keypair() -> (Self, Keypair) { ValidatorStatus::PendingExit => 2,
let keypair = Keypair::random(); ValidatorStatus::PendingWithdraw => 3,
let s = Self { ValidatorStatus::Withdrawn => 5,
pubkey: keypair.pk.clone(), ValidatorStatus::Penalized => 127,
withdrawal_shard: 0,
withdrawal_address: Address::zero(),
randao_commitment: Hash256::zero(),
randao_last_change: 0,
balance: 0,
status: From::from(0),
exit_slot: 0,
}; };
(s, keypair) s.append(&byte);
}
} }
pub fn status_is(&self, status: ValidatorStatus) -> bool { impl Decodable for ValidatorStatus {
self.status == status fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (byte, i) = u8::ssz_decode(bytes, i)?;
let status = match byte {
0 => ValidatorStatus::PendingActivation,
1 => ValidatorStatus::Active,
2 => ValidatorStatus::PendingExit,
3 => ValidatorStatus::PendingWithdraw,
5 => ValidatorStatus::Withdrawn,
127 => ValidatorStatus::Penalized,
_ => return Err(DecodeError::Invalid),
};
Ok((status, i))
}
}
impl<T: RngCore> TestRandom<T> for ValidatorStatus {
fn random_for_test(rng: &mut T) -> Self {
let options = vec![
ValidatorStatus::PendingActivation,
ValidatorStatus::Active,
ValidatorStatus::PendingExit,
ValidatorStatus::PendingWithdraw,
ValidatorStatus::Withdrawn,
ValidatorStatus::Penalized,
];
options[(rng.next_u32() as usize) % options.len()].clone()
}
}
impl Encodable for ValidatorRecord {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.pubkey);
s.append(&self.withdrawal_shard);
s.append(&self.withdrawal_address);
s.append(&self.randao_commitment);
s.append(&self.randao_last_change);
s.append(&self.balance);
s.append(&self.status);
s.append(&self.exit_slot);
}
}
impl Decodable for ValidatorRecord {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (pubkey, i) = <_>::ssz_decode(bytes, i)?;
let (withdrawal_shard, i) = <_>::ssz_decode(bytes, i)?;
let (withdrawal_address, i) = <_>::ssz_decode(bytes, i)?;
let (randao_commitment, i) = <_>::ssz_decode(bytes, i)?;
let (randao_last_change, i) = <_>::ssz_decode(bytes, i)?;
let (balance, i) = <_>::ssz_decode(bytes, i)?;
let (status, i) = <_>::ssz_decode(bytes, i)?;
let (exit_slot, i) = <_>::ssz_decode(bytes, i)?;
Ok((
Self {
pubkey,
withdrawal_shard,
withdrawal_address,
randao_commitment,
randao_last_change,
balance,
status,
exit_slot,
},
i,
))
}
}
impl<T: RngCore> TestRandom<T> for ValidatorRecord {
fn random_for_test(rng: &mut T) -> Self {
Self {
pubkey: <_>::random_for_test(rng),
withdrawal_shard: <_>::random_for_test(rng),
withdrawal_address: <_>::random_for_test(rng),
randao_commitment: <_>::random_for_test(rng),
randao_last_change: <_>::random_for_test(rng),
balance: <_>::random_for_test(rng),
status: <_>::random_for_test(rng),
exit_slot: <_>::random_for_test(rng),
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::ssz::ssz_encode;
use super::*; use super::*;
use crate::test_utils::TestRandom;
use rand::{prng::XorShiftRng, SeedableRng};
#[test] #[test]
fn test_validator_record_zero_rand_keypair() { pub fn test_ssz_round_trip() {
let (v, _kp) = ValidatorRecord::zero_with_thread_rand_keypair(); let mut rng = XorShiftRng::from_seed([42; 16]);
assert_eq!(v.withdrawal_shard, 0); let original = ValidatorRecord::random_for_test(&mut rng);
assert!(v.withdrawal_address.is_zero());
assert!(v.randao_commitment.is_zero()); let bytes = ssz_encode(&original);
assert_eq!(v.randao_last_change, 0); let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(v.balance, 0);
assert_eq!(v.status, From::from(0)); assert_eq!(original, decoded);
assert_eq!(v.exit_slot, 0); }
#[test]
pub fn test_validator_status_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = ValidatorStatus::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
} }
} }

View File

@ -1,5 +1,5 @@
use super::{Address, Hash256}; use super::{Address, Hash256};
use bls::{create_proof_of_possession, Keypair, PublicKey, Signature}; use bls::{PublicKey, Signature};
/// The information gathered from the PoW chain validator registration function. /// The information gathered from the PoW chain validator registration function.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -10,17 +10,3 @@ pub struct ValidatorRegistration {
pub randao_commitment: Hash256, pub randao_commitment: Hash256,
pub proof_of_possession: Signature, pub proof_of_possession: Signature,
} }
impl ValidatorRegistration {
pub fn random() -> Self {
let keypair = Keypair::random();
Self {
pubkey: keypair.pk.clone(),
withdrawal_shard: 0,
withdrawal_address: Address::random(),
randao_commitment: Hash256::random(),
proof_of_possession: create_proof_of_possession(&keypair),
}
}
}