Update all struct definitions

Does not compile
This commit is contained in:
Paul Hauner 2019-03-04 17:13:50 +11:00
parent 94122a7334
commit 9769ca4665
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
23 changed files with 261 additions and 315 deletions

View File

@ -1,12 +1,15 @@
use super::{AggregatePublicKey, AggregateSignature, AttestationData, Bitfield, Hash256}; use super::{AggregateSignature, AttestationData, Bitfield};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz::TreeHash; use ssz::TreeHash;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
#[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TreeHash, TestRandom)] /// Details an attestation that can be slashable.
///
/// Spec v0.4.0
#[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
pub struct Attestation { pub struct Attestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,
pub data: AttestationData, pub data: AttestationData,
@ -14,29 +17,6 @@ pub struct Attestation {
pub aggregate_signature: AggregateSignature, pub aggregate_signature: AggregateSignature,
} }
impl Attestation {
pub fn canonical_root(&self) -> Hash256 {
Hash256::from(&self.hash_tree_root()[..])
}
pub fn signable_message(&self, custody_bit: bool) -> Vec<u8> {
self.data.signable_message(custody_bit)
}
pub fn verify_signature(
&self,
group_public_key: &AggregatePublicKey,
custody_bit: bool,
domain: u64,
) -> bool {
self.aggregate_signature.verify(
&self.signable_message(custody_bit),
domain,
group_public_key,
)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -1,31 +1,33 @@
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::{AttestationDataAndCustodyBit, Crosslink, Epoch, Hash256, Slot}; use crate::{Crosslink, Epoch, Hash256, Slot};
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz::TreeHash; use ssz::TreeHash;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
pub const SSZ_ATTESTION_DATA_LENGTH: usize = { /// The data upon which an attestation is based.
8 + // slot ///
8 + // shard /// Spec v0.4.0
32 + // beacon_block_hash
32 + // epoch_boundary_root
32 + // shard_block_hash
32 + // latest_crosslink_hash
8 + // justified_epoch
32 // justified_block_root
};
#[derive( #[derive(
Debug, Clone, PartialEq, Default, Serialize, Hash, Encode, Decode, TreeHash, TestRandom, Debug,
Clone,
PartialEq,
Default,
Serialize,
Hash,
Encode,
Decode,
TreeHash,
TestRandom,
SignedRoot,
)] )]
pub struct AttestationData { pub struct AttestationData {
pub slot: Slot, pub slot: Slot,
pub shard: u64, pub shard: u64,
pub beacon_block_root: Hash256, pub beacon_block_root: Hash256,
pub epoch_boundary_root: Hash256, pub epoch_boundary_root: Hash256,
pub shard_block_root: Hash256, pub crosslink_data_root: Hash256,
pub latest_crosslink: Crosslink, pub latest_crosslink: Crosslink,
pub justified_epoch: Epoch, pub justified_epoch: Epoch,
pub justified_block_root: Hash256, pub justified_block_root: Hash256,
@ -33,20 +35,6 @@ pub struct AttestationData {
impl Eq for AttestationData {} impl Eq for AttestationData {}
impl AttestationData {
pub fn canonical_root(&self) -> Hash256 {
Hash256::from(&self.hash_tree_root()[..])
}
pub fn signable_message(&self, custody_bit: bool) -> Vec<u8> {
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
data: self.clone(),
custody_bit,
};
attestation_data_and_custody_bit.hash_tree_root()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -4,6 +4,9 @@ use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
/// Used for pairing an attestation with a proof-of-custody.
///
/// Spec v0.4.0
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)]
pub struct AttestationDataAndCustodyBit { pub struct AttestationDataAndCustodyBit {
pub data: AttestationData, pub data: AttestationData,

View File

@ -8,6 +8,9 @@ mod builder;
pub use builder::AttesterSlashingBuilder; pub use builder::AttesterSlashingBuilder;
/// Two conflicting attestations.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct AttesterSlashing { pub struct AttesterSlashing {
pub slashable_attestation_1: SlashableAttestation, pub slashable_attestation_1: SlashableAttestation,

View File

@ -4,18 +4,21 @@ use bls::Signature;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz::TreeHash; use ssz::TreeHash;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] /// A block of the `BeaconChain`.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
pub struct BeaconBlock { pub struct BeaconBlock {
pub slot: Slot, pub slot: Slot,
pub parent_root: Hash256, pub parent_root: Hash256,
pub state_root: Hash256, pub state_root: Hash256,
pub randao_reveal: Signature, pub randao_reveal: Signature,
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,
pub signature: Signature,
pub body: BeaconBlockBody, pub body: BeaconBlockBody,
pub signature: Signature,
} }
impl BeaconBlock { impl BeaconBlock {
@ -40,25 +43,6 @@ impl BeaconBlock {
}, },
} }
} }
pub fn canonical_root(&self) -> Hash256 {
Hash256::from(&self.hash_tree_root()[..])
}
pub fn proposal_root(&self, spec: &ChainSpec) -> Hash256 {
let block_without_signature_root = {
let mut block_without_signature = self.clone();
block_without_signature.signature = spec.empty_signature.clone();
block_without_signature.canonical_root()
};
let proposal = ProposalSignedData {
slot: self.slot,
shard: spec.beacon_chain_shard_number,
block_root: block_without_signature_root,
};
Hash256::from(&proposal.hash_tree_root()[..])
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,17 +1,21 @@
use super::{Attestation, AttesterSlashing, Deposit, Exit, ProposerSlashing}; use super::{Attestation, AttesterSlashing, Deposit, ProposerSlashing, Transfer, VolutaryExit};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// The body of a `BeaconChain` block, containing operations.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct BeaconBlockBody { pub struct BeaconBlockBody {
pub proposer_slashings: Vec<ProposerSlashing>, pub proposer_slashings: Vec<ProposerSlashing>,
pub attester_slashings: Vec<AttesterSlashing>, pub attester_slashings: Vec<AttesterSlashing>,
pub attestations: Vec<Attestation>, pub attestations: Vec<Attestation>,
pub deposits: Vec<Deposit>, pub deposits: Vec<Deposit>,
pub exits: Vec<Exit>, pub voluntary_exits: Vec<VolutaryExit>,
pub transfers: Vec<Transfer>,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,6 +1,6 @@
use self::epoch_cache::EpochCache; use self::epoch_cache::EpochCache;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::{validator::StatusFlags, validator_registry::get_active_validator_indices, *}; use crate::{validator_registry::get_active_validator_indices, *};
use bls::verify_proof_of_possession; use bls::verify_proof_of_possession;
use honey_badger_split::SplitExt; use honey_badger_split::SplitExt;
use log::{debug, error, trace}; use log::{debug, error, trace};
@ -82,12 +82,12 @@ pub struct BeaconState {
// Randomness and committees // Randomness and committees
pub latest_randao_mixes: Vec<Hash256>, pub latest_randao_mixes: Vec<Hash256>,
pub previous_epoch_start_shard: u64, pub previous_shuffling_start_shard: u64,
pub current_epoch_start_shard: u64, pub current_shuffling_start_shard: u64,
pub previous_calculation_epoch: Epoch, pub previous_shuffling_epoch: Epoch,
pub current_calculation_epoch: Epoch, pub current_shuffling_epoch: Epoch,
pub previous_epoch_seed: Hash256, pub previous_shuffling_seed: Hash256,
pub current_epoch_seed: Hash256, pub current_shuffling_seed: Hash256,
// Finality // Finality
pub previous_justified_epoch: Epoch, pub previous_justified_epoch: Epoch,
@ -98,8 +98,8 @@ pub struct BeaconState {
// Recent state // Recent state
pub latest_crosslinks: Vec<Crosslink>, pub latest_crosslinks: Vec<Crosslink>,
pub latest_block_roots: Vec<Hash256>, pub latest_block_roots: Vec<Hash256>,
pub latest_index_roots: Vec<Hash256>, pub latest_active_index_roots: Vec<Hash256>,
pub latest_penalized_balances: Vec<u64>, pub latest_slashed_balances: Vec<u64>,
pub latest_attestations: Vec<PendingAttestation>, pub latest_attestations: Vec<PendingAttestation>,
pub batched_block_roots: Vec<Hash256>, pub batched_block_roots: Vec<Hash256>,
@ -107,7 +107,7 @@ pub struct BeaconState {
pub latest_eth1_data: Eth1Data, pub latest_eth1_data: Eth1Data,
pub eth1_data_votes: Vec<Eth1DataVote>, pub eth1_data_votes: Vec<Eth1DataVote>,
// Caching // Caching (not in the spec)
pub cache_index_offset: usize, pub cache_index_offset: usize,
pub caches: Vec<EpochCache>, pub caches: Vec<EpochCache>,
} }
@ -148,12 +148,12 @@ impl BeaconState {
* Randomness and committees * Randomness and committees
*/ */
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize], latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize],
previous_epoch_start_shard: spec.genesis_start_shard, previous_shuffling_start_shard: spec.genesis_start_shard,
current_epoch_start_shard: spec.genesis_start_shard, current_shuffling_start_shard: spec.genesis_start_shard,
previous_calculation_epoch: spec.genesis_epoch, previous_shuffling_epoch: spec.genesis_epoch,
current_calculation_epoch: spec.genesis_epoch, current_shuffling_epoch: spec.genesis_epoch,
previous_epoch_seed: spec.zero_hash, previous_shuffling_seed: spec.zero_hash,
current_epoch_seed: spec.zero_hash, current_shuffling_seed: spec.zero_hash,
/* /*
* Finality * Finality
@ -168,8 +168,11 @@ impl BeaconState {
*/ */
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize], latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize],
latest_block_roots: vec![spec.zero_hash; spec.latest_block_roots_length as usize], latest_block_roots: vec![spec.zero_hash; spec.latest_block_roots_length as usize],
latest_index_roots: vec![spec.zero_hash; spec.latest_index_roots_length as usize], latest_active_index_roots: vec![
latest_penalized_balances: vec![0; spec.latest_penalized_exit_length as usize], spec.zero_hash;
spec.latest_active_index_roots_length as usize
],
latest_slashed_balances: vec![0; spec.latest_penalized_exit_length as usize],
latest_attestations: vec![], latest_attestations: vec![],
batched_block_roots: vec![], batched_block_roots: vec![],
@ -218,9 +221,10 @@ impl BeaconState {
&genesis_state.validator_registry, &genesis_state.validator_registry,
spec.genesis_epoch, spec.genesis_epoch,
)); ));
genesis_state.latest_index_roots = genesis_state.latest_active_index_roots =
vec![genesis_active_index_root; spec.latest_index_roots_length]; vec![genesis_active_index_root; spec.latest_active_index_roots_length];
genesis_state.current_epoch_seed = genesis_state.generate_seed(spec.genesis_epoch, spec)?; genesis_state.current_shuffling_seed =
genesis_state.generate_seed(spec.genesis_epoch, spec)?;
Ok(genesis_state) Ok(genesis_state)
} }
@ -440,7 +444,7 @@ impl BeaconState {
/// Spec v0.2.0 /// Spec v0.2.0
fn get_previous_epoch_committee_count(&self, spec: &ChainSpec) -> u64 { fn get_previous_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
let previous_active_validators = let previous_active_validators =
get_active_validator_indices(&self.validator_registry, self.previous_calculation_epoch); get_active_validator_indices(&self.validator_registry, self.previous_shuffling_epoch);
self.get_epoch_committee_count(previous_active_validators.len(), spec) self.get_epoch_committee_count(previous_active_validators.len(), spec)
} }
@ -449,7 +453,7 @@ impl BeaconState {
/// Spec v0.2.0 /// Spec v0.2.0
pub fn get_current_epoch_committee_count(&self, spec: &ChainSpec) -> u64 { pub fn get_current_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
let current_active_validators = let current_active_validators =
get_active_validator_indices(&self.validator_registry, self.current_calculation_epoch); get_active_validator_indices(&self.validator_registry, self.current_shuffling_epoch);
self.get_epoch_committee_count(current_active_validators.len(), spec) self.get_epoch_committee_count(current_active_validators.len(), spec)
} }
@ -468,13 +472,17 @@ impl BeaconState {
pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> { pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> {
let current_epoch = self.current_epoch(spec); let current_epoch = self.current_epoch(spec);
let earliest_index_root = current_epoch - Epoch::from(spec.latest_index_roots_length) let earliest_index_root = current_epoch
- Epoch::from(spec.latest_active_index_roots_length)
+ Epoch::from(spec.entry_exit_delay) + Epoch::from(spec.entry_exit_delay)
+ 1; + 1;
let latest_index_root = current_epoch + spec.entry_exit_delay; let latest_index_root = current_epoch + spec.entry_exit_delay;
if (epoch >= earliest_index_root) & (epoch <= latest_index_root) { if (epoch >= earliest_index_root) & (epoch <= latest_index_root) {
Some(self.latest_index_roots[epoch.as_usize() % spec.latest_index_roots_length]) Some(
self.latest_active_index_roots
[epoch.as_usize() % spec.latest_active_index_roots_length],
)
} else { } else {
None None
} }
@ -566,17 +574,17 @@ impl BeaconState {
trace!("get_committee_params_at_slot: current_epoch"); trace!("get_committee_params_at_slot: current_epoch");
Ok(( Ok((
self.get_current_epoch_committee_count(spec), self.get_current_epoch_committee_count(spec),
self.current_epoch_seed, self.current_shuffling_seed,
self.current_calculation_epoch, self.current_shuffling_epoch,
self.current_epoch_start_shard, self.current_shuffling_start_shard,
)) ))
} else if epoch == previous_epoch { } else if epoch == previous_epoch {
trace!("get_committee_params_at_slot: previous_epoch"); trace!("get_committee_params_at_slot: previous_epoch");
Ok(( Ok((
self.get_previous_epoch_committee_count(spec), self.get_previous_epoch_committee_count(spec),
self.previous_epoch_seed, self.previous_shuffling_seed,
self.previous_calculation_epoch, self.previous_shuffling_epoch,
self.previous_epoch_start_shard, self.previous_shuffling_start_shard,
)) ))
} else if epoch == next_epoch { } else if epoch == next_epoch {
trace!("get_committee_params_at_slot: next_epoch"); trace!("get_committee_params_at_slot: next_epoch");
@ -587,16 +595,19 @@ impl BeaconState {
let next_seed = self.generate_seed(next_epoch, spec)?; let next_seed = self.generate_seed(next_epoch, spec)?;
( (
next_seed, next_seed,
(self.current_epoch_start_shard + current_committees_per_epoch) (self.current_shuffling_start_shard + current_committees_per_epoch)
% spec.shard_count, % spec.shard_count,
) )
} else if (epochs_since_last_registry_update > 1) } else if (epochs_since_last_registry_update > 1)
& epochs_since_last_registry_update.is_power_of_two() & epochs_since_last_registry_update.is_power_of_two()
{ {
let next_seed = self.generate_seed(next_epoch, spec)?; let next_seed = self.generate_seed(next_epoch, spec)?;
(next_seed, self.current_epoch_start_shard) (next_seed, self.current_shuffling_start_shard)
} else { } else {
(self.current_epoch_seed, self.current_epoch_start_shard) (
self.current_shuffling_seed,
self.current_shuffling_start_shard,
)
}; };
Ok(( Ok((
self.get_next_epoch_committee_count(spec), self.get_next_epoch_committee_count(spec),
@ -715,9 +726,9 @@ impl BeaconState {
let epoch_index: usize = let epoch_index: usize =
current_epoch.as_usize() % spec.latest_penalized_exit_length; current_epoch.as_usize() % spec.latest_penalized_exit_length;
let total_at_start = self.latest_penalized_balances let total_at_start = self.latest_slashed_balances
[(epoch_index + 1) % spec.latest_penalized_exit_length]; [(epoch_index + 1) % spec.latest_penalized_exit_length];
let total_at_end = self.latest_penalized_balances[epoch_index]; let total_at_end = self.latest_slashed_balances[epoch_index];
let total_penalities = total_at_end.saturating_sub(total_at_start); let total_penalities = total_at_end.saturating_sub(total_at_start);
let penalty = self.get_effective_balance(index, spec) let penalty = self.get_effective_balance(index, spec)
* std::cmp::min(total_penalities * 3, total_balance) * std::cmp::min(total_penalities * 3, total_balance)
@ -983,7 +994,7 @@ impl BeaconState {
self.exit_validator(validator_index, spec); self.exit_validator(validator_index, spec);
let current_epoch = self.current_epoch(spec); let current_epoch = self.current_epoch(spec);
self.latest_penalized_balances self.latest_slashed_balances
[current_epoch.as_usize() % spec.latest_penalized_exit_length] += [current_epoch.as_usize() % spec.latest_penalized_exit_length] +=
self.get_effective_balance(validator_index, spec); self.get_effective_balance(validator_index, spec);
@ -1329,20 +1340,20 @@ impl Encodable for BeaconState {
s.append(&self.validator_balances); s.append(&self.validator_balances);
s.append(&self.validator_registry_update_epoch); s.append(&self.validator_registry_update_epoch);
s.append(&self.latest_randao_mixes); s.append(&self.latest_randao_mixes);
s.append(&self.previous_epoch_start_shard); s.append(&self.previous_shuffling_start_shard);
s.append(&self.current_epoch_start_shard); s.append(&self.current_shuffling_start_shard);
s.append(&self.previous_calculation_epoch); s.append(&self.previous_shuffling_epoch);
s.append(&self.current_calculation_epoch); s.append(&self.current_shuffling_epoch);
s.append(&self.previous_epoch_seed); s.append(&self.previous_shuffling_seed);
s.append(&self.current_epoch_seed); s.append(&self.current_shuffling_seed);
s.append(&self.previous_justified_epoch); s.append(&self.previous_justified_epoch);
s.append(&self.justified_epoch); s.append(&self.justified_epoch);
s.append(&self.justification_bitfield); s.append(&self.justification_bitfield);
s.append(&self.finalized_epoch); s.append(&self.finalized_epoch);
s.append(&self.latest_crosslinks); s.append(&self.latest_crosslinks);
s.append(&self.latest_block_roots); s.append(&self.latest_block_roots);
s.append(&self.latest_index_roots); s.append(&self.latest_active_index_roots);
s.append(&self.latest_penalized_balances); s.append(&self.latest_slashed_balances);
s.append(&self.latest_attestations); s.append(&self.latest_attestations);
s.append(&self.batched_block_roots); s.append(&self.batched_block_roots);
s.append(&self.latest_eth1_data); s.append(&self.latest_eth1_data);
@ -1359,20 +1370,20 @@ impl Decodable for BeaconState {
let (validator_balances, i) = <_>::ssz_decode(bytes, i)?; let (validator_balances, i) = <_>::ssz_decode(bytes, i)?;
let (validator_registry_update_epoch, i) = <_>::ssz_decode(bytes, i)?; let (validator_registry_update_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (latest_randao_mixes, i) = <_>::ssz_decode(bytes, i)?; let (latest_randao_mixes, i) = <_>::ssz_decode(bytes, i)?;
let (previous_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?; let (previous_shuffling_start_shard, i) = <_>::ssz_decode(bytes, i)?;
let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?; let (current_shuffling_start_shard, i) = <_>::ssz_decode(bytes, i)?;
let (previous_calculation_epoch, i) = <_>::ssz_decode(bytes, i)?; let (previous_shuffling_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (current_calculation_epoch, i) = <_>::ssz_decode(bytes, i)?; let (current_shuffling_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (previous_epoch_seed, i) = <_>::ssz_decode(bytes, i)?; let (previous_shuffling_seed, i) = <_>::ssz_decode(bytes, i)?;
let (current_epoch_seed, i) = <_>::ssz_decode(bytes, i)?; let (current_shuffling_seed, i) = <_>::ssz_decode(bytes, i)?;
let (previous_justified_epoch, i) = <_>::ssz_decode(bytes, i)?; let (previous_justified_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (justified_epoch, i) = <_>::ssz_decode(bytes, i)?; let (justified_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (justification_bitfield, i) = <_>::ssz_decode(bytes, i)?; let (justification_bitfield, i) = <_>::ssz_decode(bytes, i)?;
let (finalized_epoch, i) = <_>::ssz_decode(bytes, i)?; let (finalized_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (latest_crosslinks, i) = <_>::ssz_decode(bytes, i)?; let (latest_crosslinks, i) = <_>::ssz_decode(bytes, i)?;
let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?; let (latest_block_roots, i) = <_>::ssz_decode(bytes, i)?;
let (latest_index_roots, i) = <_>::ssz_decode(bytes, i)?; let (latest_active_index_roots, i) = <_>::ssz_decode(bytes, i)?;
let (latest_penalized_balances, i) = <_>::ssz_decode(bytes, i)?; let (latest_slashed_balances, i) = <_>::ssz_decode(bytes, i)?;
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?; let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
let (batched_block_roots, i) = <_>::ssz_decode(bytes, i)?; let (batched_block_roots, i) = <_>::ssz_decode(bytes, i)?;
let (latest_eth1_data, i) = <_>::ssz_decode(bytes, i)?; let (latest_eth1_data, i) = <_>::ssz_decode(bytes, i)?;
@ -1387,20 +1398,20 @@ impl Decodable for BeaconState {
validator_balances, validator_balances,
validator_registry_update_epoch, validator_registry_update_epoch,
latest_randao_mixes, latest_randao_mixes,
previous_epoch_start_shard, previous_shuffling_start_shard,
current_epoch_start_shard, current_shuffling_start_shard,
previous_calculation_epoch, previous_shuffling_epoch,
current_calculation_epoch, current_shuffling_epoch,
previous_epoch_seed, previous_shuffling_seed,
current_epoch_seed, current_shuffling_seed,
previous_justified_epoch, previous_justified_epoch,
justified_epoch, justified_epoch,
justification_bitfield, justification_bitfield,
finalized_epoch, finalized_epoch,
latest_crosslinks, latest_crosslinks,
latest_block_roots, latest_block_roots,
latest_index_roots, latest_active_index_roots,
latest_penalized_balances, latest_slashed_balances,
latest_attestations, latest_attestations,
batched_block_roots, batched_block_roots,
latest_eth1_data, latest_eth1_data,
@ -1427,20 +1438,24 @@ impl TreeHash for BeaconState {
.hash_tree_root_internal(), .hash_tree_root_internal(),
); );
result.append(&mut self.latest_randao_mixes.hash_tree_root_internal()); result.append(&mut self.latest_randao_mixes.hash_tree_root_internal());
result.append(&mut self.previous_epoch_start_shard.hash_tree_root_internal()); result.append(
result.append(&mut self.current_epoch_start_shard.hash_tree_root_internal()); &mut self
result.append(&mut self.previous_calculation_epoch.hash_tree_root_internal()); .previous_shuffling_start_shard
result.append(&mut self.current_calculation_epoch.hash_tree_root_internal()); .hash_tree_root_internal(),
result.append(&mut self.previous_epoch_seed.hash_tree_root_internal()); );
result.append(&mut self.current_epoch_seed.hash_tree_root_internal()); result.append(&mut self.current_shuffling_start_shard.hash_tree_root_internal());
result.append(&mut self.previous_shuffling_epoch.hash_tree_root_internal());
result.append(&mut self.current_shuffling_epoch.hash_tree_root_internal());
result.append(&mut self.previous_shuffling_seed.hash_tree_root_internal());
result.append(&mut self.current_shuffling_seed.hash_tree_root_internal());
result.append(&mut self.previous_justified_epoch.hash_tree_root_internal()); result.append(&mut self.previous_justified_epoch.hash_tree_root_internal());
result.append(&mut self.justified_epoch.hash_tree_root_internal()); result.append(&mut self.justified_epoch.hash_tree_root_internal());
result.append(&mut self.justification_bitfield.hash_tree_root_internal()); result.append(&mut self.justification_bitfield.hash_tree_root_internal());
result.append(&mut self.finalized_epoch.hash_tree_root_internal()); result.append(&mut self.finalized_epoch.hash_tree_root_internal());
result.append(&mut self.latest_crosslinks.hash_tree_root_internal()); result.append(&mut self.latest_crosslinks.hash_tree_root_internal());
result.append(&mut self.latest_block_roots.hash_tree_root_internal()); result.append(&mut self.latest_block_roots.hash_tree_root_internal());
result.append(&mut self.latest_index_roots.hash_tree_root_internal()); result.append(&mut self.latest_active_index_roots.hash_tree_root_internal());
result.append(&mut self.latest_penalized_balances.hash_tree_root_internal()); result.append(&mut self.latest_slashed_balances.hash_tree_root_internal());
result.append(&mut self.latest_attestations.hash_tree_root_internal()); result.append(&mut self.latest_attestations.hash_tree_root_internal());
result.append(&mut self.batched_block_roots.hash_tree_root_internal()); result.append(&mut self.batched_block_roots.hash_tree_root_internal());
result.append(&mut self.latest_eth1_data.hash_tree_root_internal()); result.append(&mut self.latest_eth1_data.hash_tree_root_internal());
@ -1459,20 +1474,20 @@ impl<T: RngCore> TestRandom<T> for BeaconState {
validator_balances: <_>::random_for_test(rng), validator_balances: <_>::random_for_test(rng),
validator_registry_update_epoch: <_>::random_for_test(rng), validator_registry_update_epoch: <_>::random_for_test(rng),
latest_randao_mixes: <_>::random_for_test(rng), latest_randao_mixes: <_>::random_for_test(rng),
previous_epoch_start_shard: <_>::random_for_test(rng), previous_shuffling_start_shard: <_>::random_for_test(rng),
current_epoch_start_shard: <_>::random_for_test(rng), current_shuffling_start_shard: <_>::random_for_test(rng),
previous_calculation_epoch: <_>::random_for_test(rng), previous_shuffling_epoch: <_>::random_for_test(rng),
current_calculation_epoch: <_>::random_for_test(rng), current_shuffling_epoch: <_>::random_for_test(rng),
previous_epoch_seed: <_>::random_for_test(rng), previous_shuffling_seed: <_>::random_for_test(rng),
current_epoch_seed: <_>::random_for_test(rng), current_shuffling_seed: <_>::random_for_test(rng),
previous_justified_epoch: <_>::random_for_test(rng), previous_justified_epoch: <_>::random_for_test(rng),
justified_epoch: <_>::random_for_test(rng), justified_epoch: <_>::random_for_test(rng),
justification_bitfield: <_>::random_for_test(rng), justification_bitfield: <_>::random_for_test(rng),
finalized_epoch: <_>::random_for_test(rng), finalized_epoch: <_>::random_for_test(rng),
latest_crosslinks: <_>::random_for_test(rng), latest_crosslinks: <_>::random_for_test(rng),
latest_block_roots: <_>::random_for_test(rng), latest_block_roots: <_>::random_for_test(rng),
latest_index_roots: <_>::random_for_test(rng), latest_active_index_roots: <_>::random_for_test(rng),
latest_penalized_balances: <_>::random_for_test(rng), latest_slashed_balances: <_>::random_for_test(rng),
latest_attestations: <_>::random_for_test(rng), latest_attestations: <_>::random_for_test(rng),
batched_block_roots: <_>::random_for_test(rng), batched_block_roots: <_>::random_for_test(rng),
latest_eth1_data: <_>::random_for_test(rng), latest_eth1_data: <_>::random_for_test(rng),

View File

@ -5,6 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// Specifies the block hash for a shard at an epoch.
///
/// Spec v0.4.0
#[derive( #[derive(
Debug, Clone, PartialEq, Default, Serialize, Hash, Encode, Decode, TreeHash, TestRandom, Debug, Clone, PartialEq, Default, Serialize, Hash, Encode, Decode, TreeHash, TestRandom,
)] )]
@ -13,16 +16,6 @@ pub struct Crosslink {
pub shard_block_root: Hash256, pub shard_block_root: Hash256,
} }
impl Crosslink {
/// Generates a new instance where `dynasty` and `hash` are both zero.
pub fn zero() -> Self {
Self {
epoch: Epoch::new(0),
shard_block_root: Hash256::zero(),
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -5,6 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// A deposit to potentially become a beacon chain validator.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct Deposit { pub struct Deposit {
pub branch: Vec<Hash256>, pub branch: Vec<Hash256>,

View File

@ -5,6 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// Data generated by the deposit contract.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct DepositData { pub struct DepositData {
pub amount: u64, pub amount: u64,

View File

@ -6,6 +6,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// The data supplied by the user to the deposit contract.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct DepositInput { pub struct DepositInput {
pub pubkey: PublicKey, pub pubkey: PublicKey,

View File

@ -5,7 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
// Note: this is refer to as DepositRootVote in specs /// Contains data obtained from the Eth1 chain.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct Eth1Data { pub struct Eth1Data {
pub deposit_root: Hash256, pub deposit_root: Hash256,

View File

@ -5,7 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
// Note: this is refer to as DepositRootVote in specs /// A summation of votes for some `Eth1Data`.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Default, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct Eth1DataVote { pub struct Eth1DataVote {
pub eth1_data: Eth1Data, pub eth1_data: Eth1Data,

View File

@ -4,6 +4,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
///
/// Spec v0.4.0
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct Fork { pub struct Fork {
pub previous_version: u64, pub previous_version: u64,

View File

@ -15,7 +15,6 @@ pub mod deposit_data;
pub mod deposit_input; pub mod deposit_input;
pub mod eth1_data; pub mod eth1_data;
pub mod eth1_data_vote; pub mod eth1_data_vote;
pub mod exit;
pub mod fork; pub mod fork;
pub mod free_attestation; pub mod free_attestation;
pub mod pending_attestation; pub mod pending_attestation;
@ -26,6 +25,8 @@ pub mod readers;
pub mod shard_reassignment_record; pub mod shard_reassignment_record;
pub mod slashable_attestation; pub mod slashable_attestation;
pub mod slashable_vote_data; pub mod slashable_vote_data;
pub mod transfer;
pub mod voluntary_exit;
#[macro_use] #[macro_use]
pub mod slot_epoch_macros; pub mod slot_epoch_macros;
pub mod slot_epoch; pub mod slot_epoch;
@ -54,7 +55,6 @@ pub use crate::deposit_data::DepositData;
pub use crate::deposit_input::DepositInput; pub use crate::deposit_input::DepositInput;
pub use crate::eth1_data::Eth1Data; pub use crate::eth1_data::Eth1Data;
pub use crate::eth1_data_vote::Eth1DataVote; pub use crate::eth1_data_vote::Eth1DataVote;
pub use crate::exit::Exit;
pub use crate::fork::Fork; pub use crate::fork::Fork;
pub use crate::free_attestation::FreeAttestation; pub use crate::free_attestation::FreeAttestation;
pub use crate::pending_attestation::PendingAttestation; pub use crate::pending_attestation::PendingAttestation;
@ -65,8 +65,10 @@ pub use crate::slashable_attestation::SlashableAttestation;
pub use crate::slashable_vote_data::SlashableVoteData; pub use crate::slashable_vote_data::SlashableVoteData;
pub use crate::slot_epoch::{Epoch, Slot}; pub use crate::slot_epoch::{Epoch, Slot};
pub use crate::slot_height::SlotHeight; pub use crate::slot_height::SlotHeight;
pub use crate::validator::{StatusFlags as ValidatorStatusFlags, Validator}; pub use crate::transfer::Transfer;
pub use crate::validator::Validator;
pub use crate::validator_registry_delta_block::ValidatorRegistryDeltaBlock; pub use crate::validator_registry_delta_block::ValidatorRegistryDeltaBlock;
pub use crate::voluntary_exit::VolutaryExit;
pub type Hash256 = H256; pub type Hash256 = H256;
pub type Address = H160; pub type Address = H160;

View File

@ -5,6 +5,9 @@ use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// An attestation that has been included in the state but not yet fully processed.
///
/// Spec v0.4.0
#[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct PendingAttestation { pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,

View File

@ -7,6 +7,9 @@ use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash}; use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
/// A proposal for some shard or beacon block.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
pub struct Proposal { pub struct Proposal {
pub slot: Slot, pub slot: Slot,

View File

@ -15,8 +15,8 @@ pub use builder::ProposerSlashingBuilder;
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] #[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct ProposerSlashing { pub struct ProposerSlashing {
pub proposer_index: u64, pub proposer_index: u64,
pub proposer_1: Proposal, pub proposal_1: Proposal,
pub proposer_2: Proposal, pub proposal_2: Proposal,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,5 +1,5 @@
use crate::*; use crate::*;
use ssz::TreeHash; use ssz::SignedRoot;
/// Builds a `ProposerSlashing`. /// Builds a `ProposerSlashing`.
pub struct ProposerSlashingBuilder(); pub struct ProposerSlashingBuilder();
@ -22,27 +22,29 @@ impl ProposerSlashingBuilder {
let slot = Slot::new(0); let slot = Slot::new(0);
let shard = 0; let shard = 0;
let proposal_data_1 = ProposalSignedData { let mut proposal_1 = Proposal {
slot, slot,
shard, shard,
block_root: Hash256::from(&[1][..]), block_root: Hash256::from(&[1][..]),
signature: Signature::empty_signature(),
}; };
let proposal_data_2 = ProposalSignedData { let mut proposal_2 = Proposal {
slot, slot,
shard, shard,
block_root: Hash256::from(&[2][..]), block_root: Hash256::from(&[2][..]),
signature: Signature::empty_signature(),
}; };
let proposal_signature_1 = { proposal_1.signature = {
let message = proposal_data_1.hash_tree_root(); let message = proposal_1.signed_root();
let epoch = slot.epoch(spec.epoch_length); let epoch = slot.epoch(spec.epoch_length);
let domain = spec.domain_proposal; let domain = spec.domain_proposal;
signer(proposer_index, &message[..], epoch, domain) signer(proposer_index, &message[..], epoch, domain)
}; };
let proposal_signature_2 = { proposal_2.signature = {
let message = proposal_data_2.hash_tree_root(); let message = proposal_2.signed_root();
let epoch = slot.epoch(spec.epoch_length); let epoch = slot.epoch(spec.epoch_length);
let domain = spec.domain_proposal; let domain = spec.domain_proposal;
signer(proposer_index, &message[..], epoch, domain) signer(proposer_index, &message[..], epoch, domain)
@ -50,10 +52,8 @@ impl ProposerSlashingBuilder {
ProposerSlashing { ProposerSlashing {
proposer_index, proposer_index,
proposal_data_1, proposal_1,
proposal_signature_1, proposal_2,
proposal_data_2,
proposal_signature_2,
} }
} }
} }

View File

@ -1,11 +1,18 @@
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec}; use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] /// Details an attestation that can be slashable.
///
/// To be included in an `AttesterSlashing`.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
pub struct SlashableAttestation { pub struct SlashableAttestation {
/// Lists validator registry indices, not committee indices.
pub validator_indices: Vec<u64>, pub validator_indices: Vec<u64>,
pub data: AttestationData, pub data: AttestationData,
pub custody_bitfield: Bitfield, pub custody_bitfield: Bitfield,
@ -15,21 +22,21 @@ pub struct SlashableAttestation {
impl SlashableAttestation { impl SlashableAttestation {
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target. /// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
/// ///
/// Spec v0.3.0 /// Spec v0.4.0
pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length) self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length)
} }
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``. /// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
/// ///
/// Spec v0.3.0 /// Spec v0.4.0
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
let source_epoch_1 = self.data.justified_epoch; let source_epoch_1 = self.data.justified_epoch;
let source_epoch_2 = other.data.justified_epoch; let source_epoch_2 = other.data.justified_epoch;
let target_epoch_1 = self.data.slot.epoch(spec.epoch_length); let target_epoch_1 = self.data.slot.epoch(spec.epoch_length);
let target_epoch_2 = other.data.slot.epoch(spec.epoch_length); let target_epoch_2 = other.data.slot.epoch(spec.epoch_length);
(source_epoch_1 < source_epoch_2) && (target_epoch_2 < target_epoch_1) (source_epoch_1 < source_epoch_2) & (target_epoch_2 < target_epoch_1)
} }
} }

View File

@ -0,0 +1,51 @@
use super::Slot;
use crate::test_utils::TestRandom;
use bls::{PublicKey, Signature};
use rand::RngCore;
use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom;
/// The data submitted to the deposit contract.
///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
pub struct Transfer {
pub from: u64,
pub to: u64,
pub amount: u64,
pub fee: u64,
pub slot: Slot,
pub pubkey: PublicKey,
pub signature: Signature,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use ssz::{ssz_encode, Decodable, TreeHash};
#[test]
pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = Transfer::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
#[test]
pub fn test_hash_tree_root_internal() {
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = Transfer::random_for_test(&mut rng);
let result = original.hash_tree_root_internal();
assert_eq!(result.len(), 32);
// TODO: Add further tests
// https://github.com/sigp/lighthouse/issues/170
}
}

View File

@ -2,55 +2,21 @@ use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash}; use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom;
const STATUS_FLAG_INITIATED_EXIT: u8 = 1; /// Information about a `BeaconChain` validator.
const STATUS_FLAG_WITHDRAWABLE: u8 = 2; ///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Copy, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TestRandom)]
pub enum StatusFlags {
InitiatedExit,
Withdrawable,
}
struct StatusFlagsDecodeError;
impl From<StatusFlagsDecodeError> for DecodeError {
fn from(_: StatusFlagsDecodeError) -> DecodeError {
DecodeError::Invalid
}
}
/// Handles the serialization logic for the `status_flags` field of the `Validator`.
fn status_flag_to_byte(flag: Option<StatusFlags>) -> u8 {
if let Some(flag) = flag {
match flag {
StatusFlags::InitiatedExit => STATUS_FLAG_INITIATED_EXIT,
StatusFlags::Withdrawable => STATUS_FLAG_WITHDRAWABLE,
}
} else {
0
}
}
/// Handles the deserialization logic for the `status_flags` field of the `Validator`.
fn status_flag_from_byte(flag: u8) -> Result<Option<StatusFlags>, StatusFlagsDecodeError> {
match flag {
0 => Ok(None),
1 => Ok(Some(StatusFlags::InitiatedExit)),
2 => Ok(Some(StatusFlags::Withdrawable)),
_ => Err(StatusFlagsDecodeError),
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Validator { pub struct Validator {
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256, pub withdrawal_credentials: Hash256,
pub activation_epoch: Epoch, pub activation_epoch: Epoch,
pub exit_epoch: Epoch, pub exit_epoch: Epoch,
pub withdrawal_epoch: Epoch, pub withdrawal_epoch: Epoch,
pub penalized_epoch: Epoch, pub initiated_exit: bool,
pub status_flags: Option<StatusFlags>, pub slashed: bool,
} }
impl Validator { impl Validator {
@ -64,9 +30,9 @@ impl Validator {
self.exit_epoch <= epoch self.exit_epoch <= epoch
} }
/// Returns `true` if the validator is considered penalized at some epoch. /// Returns `true` if the validator is able to withdraw at some epoch.
pub fn is_penalized_at(&self, epoch: Epoch) -> bool { pub fn is_withdrawable_at(&self, epoch: Epoch) -> bool {
self.penalized_epoch <= epoch self.withdrawal_epoch <= epoch
} }
} }
@ -85,82 +51,6 @@ impl Default for Validator {
} }
} }
impl<T: RngCore> TestRandom<T> for StatusFlags {
fn random_for_test(rng: &mut T) -> Self {
let options = vec![StatusFlags::InitiatedExit, StatusFlags::Withdrawable];
options[(rng.next_u32() as usize) % options.len()]
}
}
impl Encodable for Validator {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.pubkey);
s.append(&self.withdrawal_credentials);
s.append(&self.activation_epoch);
s.append(&self.exit_epoch);
s.append(&self.withdrawal_epoch);
s.append(&self.penalized_epoch);
s.append(&status_flag_to_byte(self.status_flags));
}
}
impl Decodable for Validator {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (pubkey, i) = <_>::ssz_decode(bytes, i)?;
let (withdrawal_credentials, i) = <_>::ssz_decode(bytes, i)?;
let (activation_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (exit_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (withdrawal_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (penalized_epoch, i) = <_>::ssz_decode(bytes, i)?;
let (status_flags_byte, i): (u8, usize) = <_>::ssz_decode(bytes, i)?;
let status_flags = status_flag_from_byte(status_flags_byte)?;
Ok((
Self {
pubkey,
withdrawal_credentials,
activation_epoch,
exit_epoch,
withdrawal_epoch,
penalized_epoch,
status_flags,
},
i,
))
}
}
impl TreeHash for Validator {
fn hash_tree_root_internal(&self) -> Vec<u8> {
let mut result: Vec<u8> = vec![];
result.append(&mut self.pubkey.hash_tree_root_internal());
result.append(&mut self.withdrawal_credentials.hash_tree_root_internal());
result.append(&mut self.activation_epoch.hash_tree_root_internal());
result.append(&mut self.exit_epoch.hash_tree_root_internal());
result.append(&mut self.withdrawal_epoch.hash_tree_root_internal());
result.append(&mut self.penalized_epoch.hash_tree_root_internal());
result.append(
&mut u64::from(status_flag_to_byte(self.status_flags)).hash_tree_root_internal(),
);
hash(&result)
}
}
impl<T: RngCore> TestRandom<T> for Validator {
fn random_for_test(rng: &mut T) -> Self {
Self {
pubkey: <_>::random_for_test(rng),
withdrawal_credentials: <_>::random_for_test(rng),
activation_epoch: <_>::random_for_test(rng),
exit_epoch: <_>::random_for_test(rng),
withdrawal_epoch: <_>::random_for_test(rng),
penalized_epoch: <_>::random_for_test(rng),
status_flags: Some(<_>::random_for_test(rng)),
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -2,11 +2,15 @@ use crate::{test_utils::TestRandom, Epoch};
use bls::Signature; use bls::Signature;
use rand::RngCore; use rand::RngCore;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash}; use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)] /// An exit voluntarily submitted a validator who wishes to withdraw.
pub struct Exit { ///
/// Spec v0.4.0
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
pub struct VolutaryExit {
pub epoch: Epoch, pub epoch: Epoch,
pub validator_index: u64, pub validator_index: u64,
pub signature: Signature, pub signature: Signature,
@ -21,7 +25,7 @@ mod tests {
#[test] #[test]
pub fn test_ssz_round_trip() { pub fn test_ssz_round_trip() {
let mut rng = XorShiftRng::from_seed([42; 16]); let mut rng = XorShiftRng::from_seed([42; 16]);
let original = Exit::random_for_test(&mut rng); let original = VolutaryExit::random_for_test(&mut rng);
let bytes = ssz_encode(&original); let bytes = ssz_encode(&original);
let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap(); let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
@ -32,7 +36,7 @@ mod tests {
#[test] #[test]
pub fn test_hash_tree_root_internal() { pub fn test_hash_tree_root_internal() {
let mut rng = XorShiftRng::from_seed([42; 16]); let mut rng = XorShiftRng::from_seed([42; 16]);
let original = Exit::random_for_test(&mut rng); let original = VolutaryExit::random_for_test(&mut rng);
let result = original.hash_tree_root_internal(); let result = original.hash_tree_root_internal();