Update all struct definitions
Does not compile
This commit is contained in:
parent
94122a7334
commit
9769ca4665
@ -1,12 +1,15 @@
|
||||
use super::{AggregatePublicKey, AggregateSignature, AttestationData, Bitfield, Hash256};
|
||||
use super::{AggregateSignature, AttestationData, Bitfield};
|
||||
use crate::test_utils::TestRandom;
|
||||
use rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
use ssz::TreeHash;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
|
||||
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 aggregation_bitfield: Bitfield,
|
||||
pub data: AttestationData,
|
||||
@ -14,29 +17,6 @@ pub struct Attestation {
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -1,31 +1,33 @@
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{AttestationDataAndCustodyBit, Crosslink, Epoch, Hash256, Slot};
|
||||
use crate::{Crosslink, Epoch, Hash256, Slot};
|
||||
use rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
use ssz::TreeHash;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
|
||||
use test_random_derive::TestRandom;
|
||||
|
||||
pub const SSZ_ATTESTION_DATA_LENGTH: usize = {
|
||||
8 + // slot
|
||||
8 + // shard
|
||||
32 + // beacon_block_hash
|
||||
32 + // epoch_boundary_root
|
||||
32 + // shard_block_hash
|
||||
32 + // latest_crosslink_hash
|
||||
8 + // justified_epoch
|
||||
32 // justified_block_root
|
||||
};
|
||||
|
||||
/// The data upon which an attestation is based.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[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 slot: Slot,
|
||||
pub shard: u64,
|
||||
pub beacon_block_root: Hash256,
|
||||
pub epoch_boundary_root: Hash256,
|
||||
pub shard_block_root: Hash256,
|
||||
pub crosslink_data_root: Hash256,
|
||||
pub latest_crosslink: Crosslink,
|
||||
pub justified_epoch: Epoch,
|
||||
pub justified_block_root: Hash256,
|
||||
@ -33,20 +35,6 @@ pub struct 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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -4,6 +4,9 @@ use rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
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)]
|
||||
pub struct AttestationDataAndCustodyBit {
|
||||
pub data: AttestationData,
|
||||
|
@ -8,6 +8,9 @@ mod builder;
|
||||
|
||||
pub use builder::AttesterSlashingBuilder;
|
||||
|
||||
/// Two conflicting attestations.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
pub struct AttesterSlashing {
|
||||
pub slashable_attestation_1: SlashableAttestation,
|
||||
|
@ -4,18 +4,21 @@ use bls::Signature;
|
||||
use rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
use ssz::TreeHash;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
|
||||
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 slot: Slot,
|
||||
pub parent_root: Hash256,
|
||||
pub state_root: Hash256,
|
||||
pub randao_reveal: Signature,
|
||||
pub eth1_data: Eth1Data,
|
||||
pub signature: Signature,
|
||||
pub body: BeaconBlockBody,
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
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)]
|
||||
|
@ -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 rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct BeaconBlockBody {
|
||||
pub proposer_slashings: Vec<ProposerSlashing>,
|
||||
pub attester_slashings: Vec<AttesterSlashing>,
|
||||
pub attestations: Vec<Attestation>,
|
||||
pub deposits: Vec<Deposit>,
|
||||
pub exits: Vec<Exit>,
|
||||
pub voluntary_exits: Vec<VolutaryExit>,
|
||||
pub transfers: Vec<Transfer>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use self::epoch_cache::EpochCache;
|
||||
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 honey_badger_split::SplitExt;
|
||||
use log::{debug, error, trace};
|
||||
@ -82,12 +82,12 @@ pub struct BeaconState {
|
||||
|
||||
// Randomness and committees
|
||||
pub latest_randao_mixes: Vec<Hash256>,
|
||||
pub previous_epoch_start_shard: u64,
|
||||
pub current_epoch_start_shard: u64,
|
||||
pub previous_calculation_epoch: Epoch,
|
||||
pub current_calculation_epoch: Epoch,
|
||||
pub previous_epoch_seed: Hash256,
|
||||
pub current_epoch_seed: Hash256,
|
||||
pub previous_shuffling_start_shard: u64,
|
||||
pub current_shuffling_start_shard: u64,
|
||||
pub previous_shuffling_epoch: Epoch,
|
||||
pub current_shuffling_epoch: Epoch,
|
||||
pub previous_shuffling_seed: Hash256,
|
||||
pub current_shuffling_seed: Hash256,
|
||||
|
||||
// Finality
|
||||
pub previous_justified_epoch: Epoch,
|
||||
@ -98,8 +98,8 @@ pub struct BeaconState {
|
||||
// Recent state
|
||||
pub latest_crosslinks: Vec<Crosslink>,
|
||||
pub latest_block_roots: Vec<Hash256>,
|
||||
pub latest_index_roots: Vec<Hash256>,
|
||||
pub latest_penalized_balances: Vec<u64>,
|
||||
pub latest_active_index_roots: Vec<Hash256>,
|
||||
pub latest_slashed_balances: Vec<u64>,
|
||||
pub latest_attestations: Vec<PendingAttestation>,
|
||||
pub batched_block_roots: Vec<Hash256>,
|
||||
|
||||
@ -107,7 +107,7 @@ pub struct BeaconState {
|
||||
pub latest_eth1_data: Eth1Data,
|
||||
pub eth1_data_votes: Vec<Eth1DataVote>,
|
||||
|
||||
// Caching
|
||||
// Caching (not in the spec)
|
||||
pub cache_index_offset: usize,
|
||||
pub caches: Vec<EpochCache>,
|
||||
}
|
||||
@ -148,12 +148,12 @@ impl BeaconState {
|
||||
* Randomness and committees
|
||||
*/
|
||||
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize],
|
||||
previous_epoch_start_shard: spec.genesis_start_shard,
|
||||
current_epoch_start_shard: spec.genesis_start_shard,
|
||||
previous_calculation_epoch: spec.genesis_epoch,
|
||||
current_calculation_epoch: spec.genesis_epoch,
|
||||
previous_epoch_seed: spec.zero_hash,
|
||||
current_epoch_seed: spec.zero_hash,
|
||||
previous_shuffling_start_shard: spec.genesis_start_shard,
|
||||
current_shuffling_start_shard: spec.genesis_start_shard,
|
||||
previous_shuffling_epoch: spec.genesis_epoch,
|
||||
current_shuffling_epoch: spec.genesis_epoch,
|
||||
previous_shuffling_seed: spec.zero_hash,
|
||||
current_shuffling_seed: spec.zero_hash,
|
||||
|
||||
/*
|
||||
* Finality
|
||||
@ -168,8 +168,11 @@ impl BeaconState {
|
||||
*/
|
||||
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_index_roots: vec![spec.zero_hash; spec.latest_index_roots_length as usize],
|
||||
latest_penalized_balances: vec![0; spec.latest_penalized_exit_length as usize],
|
||||
latest_active_index_roots: vec![
|
||||
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![],
|
||||
batched_block_roots: vec![],
|
||||
|
||||
@ -218,9 +221,10 @@ impl BeaconState {
|
||||
&genesis_state.validator_registry,
|
||||
spec.genesis_epoch,
|
||||
));
|
||||
genesis_state.latest_index_roots =
|
||||
vec![genesis_active_index_root; spec.latest_index_roots_length];
|
||||
genesis_state.current_epoch_seed = genesis_state.generate_seed(spec.genesis_epoch, spec)?;
|
||||
genesis_state.latest_active_index_roots =
|
||||
vec![genesis_active_index_root; spec.latest_active_index_roots_length];
|
||||
genesis_state.current_shuffling_seed =
|
||||
genesis_state.generate_seed(spec.genesis_epoch, spec)?;
|
||||
|
||||
Ok(genesis_state)
|
||||
}
|
||||
@ -440,7 +444,7 @@ impl BeaconState {
|
||||
/// Spec v0.2.0
|
||||
fn get_previous_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -449,7 +453,7 @@ impl BeaconState {
|
||||
/// Spec v0.2.0
|
||||
pub fn get_current_epoch_committee_count(&self, spec: &ChainSpec) -> u64 {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -468,13 +472,17 @@ impl BeaconState {
|
||||
pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Option<Hash256> {
|
||||
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)
|
||||
+ 1;
|
||||
let latest_index_root = current_epoch + spec.entry_exit_delay;
|
||||
|
||||
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 {
|
||||
None
|
||||
}
|
||||
@ -566,17 +574,17 @@ impl BeaconState {
|
||||
trace!("get_committee_params_at_slot: current_epoch");
|
||||
Ok((
|
||||
self.get_current_epoch_committee_count(spec),
|
||||
self.current_epoch_seed,
|
||||
self.current_calculation_epoch,
|
||||
self.current_epoch_start_shard,
|
||||
self.current_shuffling_seed,
|
||||
self.current_shuffling_epoch,
|
||||
self.current_shuffling_start_shard,
|
||||
))
|
||||
} else if epoch == previous_epoch {
|
||||
trace!("get_committee_params_at_slot: previous_epoch");
|
||||
Ok((
|
||||
self.get_previous_epoch_committee_count(spec),
|
||||
self.previous_epoch_seed,
|
||||
self.previous_calculation_epoch,
|
||||
self.previous_epoch_start_shard,
|
||||
self.previous_shuffling_seed,
|
||||
self.previous_shuffling_epoch,
|
||||
self.previous_shuffling_start_shard,
|
||||
))
|
||||
} else if epoch == 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)?;
|
||||
(
|
||||
next_seed,
|
||||
(self.current_epoch_start_shard + current_committees_per_epoch)
|
||||
(self.current_shuffling_start_shard + current_committees_per_epoch)
|
||||
% spec.shard_count,
|
||||
)
|
||||
} else if (epochs_since_last_registry_update > 1)
|
||||
& epochs_since_last_registry_update.is_power_of_two()
|
||||
{
|
||||
let next_seed = self.generate_seed(next_epoch, spec)?;
|
||||
(next_seed, self.current_epoch_start_shard)
|
||||
(next_seed, self.current_shuffling_start_shard)
|
||||
} else {
|
||||
(self.current_epoch_seed, self.current_epoch_start_shard)
|
||||
(
|
||||
self.current_shuffling_seed,
|
||||
self.current_shuffling_start_shard,
|
||||
)
|
||||
};
|
||||
Ok((
|
||||
self.get_next_epoch_committee_count(spec),
|
||||
@ -715,9 +726,9 @@ impl BeaconState {
|
||||
let epoch_index: usize =
|
||||
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];
|
||||
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 penalty = self.get_effective_balance(index, spec)
|
||||
* std::cmp::min(total_penalities * 3, total_balance)
|
||||
@ -983,7 +994,7 @@ impl BeaconState {
|
||||
self.exit_validator(validator_index, 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] +=
|
||||
self.get_effective_balance(validator_index, spec);
|
||||
|
||||
@ -1329,20 +1340,20 @@ impl Encodable for BeaconState {
|
||||
s.append(&self.validator_balances);
|
||||
s.append(&self.validator_registry_update_epoch);
|
||||
s.append(&self.latest_randao_mixes);
|
||||
s.append(&self.previous_epoch_start_shard);
|
||||
s.append(&self.current_epoch_start_shard);
|
||||
s.append(&self.previous_calculation_epoch);
|
||||
s.append(&self.current_calculation_epoch);
|
||||
s.append(&self.previous_epoch_seed);
|
||||
s.append(&self.current_epoch_seed);
|
||||
s.append(&self.previous_shuffling_start_shard);
|
||||
s.append(&self.current_shuffling_start_shard);
|
||||
s.append(&self.previous_shuffling_epoch);
|
||||
s.append(&self.current_shuffling_epoch);
|
||||
s.append(&self.previous_shuffling_seed);
|
||||
s.append(&self.current_shuffling_seed);
|
||||
s.append(&self.previous_justified_epoch);
|
||||
s.append(&self.justified_epoch);
|
||||
s.append(&self.justification_bitfield);
|
||||
s.append(&self.finalized_epoch);
|
||||
s.append(&self.latest_crosslinks);
|
||||
s.append(&self.latest_block_roots);
|
||||
s.append(&self.latest_index_roots);
|
||||
s.append(&self.latest_penalized_balances);
|
||||
s.append(&self.latest_active_index_roots);
|
||||
s.append(&self.latest_slashed_balances);
|
||||
s.append(&self.latest_attestations);
|
||||
s.append(&self.batched_block_roots);
|
||||
s.append(&self.latest_eth1_data);
|
||||
@ -1359,20 +1370,20 @@ impl Decodable for BeaconState {
|
||||
let (validator_balances, 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 (previous_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (current_epoch_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (previous_calculation_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (current_calculation_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (previous_epoch_seed, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (current_epoch_seed, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (previous_shuffling_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (current_shuffling_start_shard, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (previous_shuffling_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (current_shuffling_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (previous_shuffling_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 (justified_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (justification_bitfield, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (finalized_epoch, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (latest_crosslinks, 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_penalized_balances, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (latest_active_index_roots, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (latest_slashed_balances, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (latest_attestations, i) = <_>::ssz_decode(bytes, i)?;
|
||||
let (batched_block_roots, 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_registry_update_epoch,
|
||||
latest_randao_mixes,
|
||||
previous_epoch_start_shard,
|
||||
current_epoch_start_shard,
|
||||
previous_calculation_epoch,
|
||||
current_calculation_epoch,
|
||||
previous_epoch_seed,
|
||||
current_epoch_seed,
|
||||
previous_shuffling_start_shard,
|
||||
current_shuffling_start_shard,
|
||||
previous_shuffling_epoch,
|
||||
current_shuffling_epoch,
|
||||
previous_shuffling_seed,
|
||||
current_shuffling_seed,
|
||||
previous_justified_epoch,
|
||||
justified_epoch,
|
||||
justification_bitfield,
|
||||
finalized_epoch,
|
||||
latest_crosslinks,
|
||||
latest_block_roots,
|
||||
latest_index_roots,
|
||||
latest_penalized_balances,
|
||||
latest_active_index_roots,
|
||||
latest_slashed_balances,
|
||||
latest_attestations,
|
||||
batched_block_roots,
|
||||
latest_eth1_data,
|
||||
@ -1427,20 +1438,24 @@ impl TreeHash for BeaconState {
|
||||
.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(&mut self.current_epoch_start_shard.hash_tree_root_internal());
|
||||
result.append(&mut self.previous_calculation_epoch.hash_tree_root_internal());
|
||||
result.append(&mut self.current_calculation_epoch.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
|
||||
.previous_shuffling_start_shard
|
||||
.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.justified_epoch.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.latest_crosslinks.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_penalized_balances.hash_tree_root_internal());
|
||||
result.append(&mut self.latest_active_index_roots.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.batched_block_roots.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_registry_update_epoch: <_>::random_for_test(rng),
|
||||
latest_randao_mixes: <_>::random_for_test(rng),
|
||||
previous_epoch_start_shard: <_>::random_for_test(rng),
|
||||
current_epoch_start_shard: <_>::random_for_test(rng),
|
||||
previous_calculation_epoch: <_>::random_for_test(rng),
|
||||
current_calculation_epoch: <_>::random_for_test(rng),
|
||||
previous_epoch_seed: <_>::random_for_test(rng),
|
||||
current_epoch_seed: <_>::random_for_test(rng),
|
||||
previous_shuffling_start_shard: <_>::random_for_test(rng),
|
||||
current_shuffling_start_shard: <_>::random_for_test(rng),
|
||||
previous_shuffling_epoch: <_>::random_for_test(rng),
|
||||
current_shuffling_epoch: <_>::random_for_test(rng),
|
||||
previous_shuffling_seed: <_>::random_for_test(rng),
|
||||
current_shuffling_seed: <_>::random_for_test(rng),
|
||||
previous_justified_epoch: <_>::random_for_test(rng),
|
||||
justified_epoch: <_>::random_for_test(rng),
|
||||
justification_bitfield: <_>::random_for_test(rng),
|
||||
finalized_epoch: <_>::random_for_test(rng),
|
||||
latest_crosslinks: <_>::random_for_test(rng),
|
||||
latest_block_roots: <_>::random_for_test(rng),
|
||||
latest_index_roots: <_>::random_for_test(rng),
|
||||
latest_penalized_balances: <_>::random_for_test(rng),
|
||||
latest_active_index_roots: <_>::random_for_test(rng),
|
||||
latest_slashed_balances: <_>::random_for_test(rng),
|
||||
latest_attestations: <_>::random_for_test(rng),
|
||||
batched_block_roots: <_>::random_for_test(rng),
|
||||
latest_eth1_data: <_>::random_for_test(rng),
|
||||
|
@ -5,6 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
use test_random_derive::TestRandom;
|
||||
|
||||
/// Specifies the block hash for a shard at an epoch.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Default, Serialize, Hash, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
@ -13,16 +16,6 @@ pub struct Crosslink {
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -5,6 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct Deposit {
|
||||
pub branch: Vec<Hash256>,
|
||||
|
@ -5,6 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
use test_random_derive::TestRandom;
|
||||
|
||||
/// Data generated by the deposit contract.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
pub struct DepositData {
|
||||
pub amount: u64,
|
||||
|
@ -6,6 +6,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct DepositInput {
|
||||
pub pubkey: PublicKey,
|
||||
|
@ -5,7 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct Eth1Data {
|
||||
pub deposit_root: Hash256,
|
||||
|
@ -5,7 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct Eth1DataVote {
|
||||
pub eth1_data: Eth1Data,
|
||||
|
@ -4,6 +4,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct Fork {
|
||||
pub previous_version: u64,
|
||||
|
@ -15,7 +15,6 @@ pub mod deposit_data;
|
||||
pub mod deposit_input;
|
||||
pub mod eth1_data;
|
||||
pub mod eth1_data_vote;
|
||||
pub mod exit;
|
||||
pub mod fork;
|
||||
pub mod free_attestation;
|
||||
pub mod pending_attestation;
|
||||
@ -26,6 +25,8 @@ pub mod readers;
|
||||
pub mod shard_reassignment_record;
|
||||
pub mod slashable_attestation;
|
||||
pub mod slashable_vote_data;
|
||||
pub mod transfer;
|
||||
pub mod voluntary_exit;
|
||||
#[macro_use]
|
||||
pub mod slot_epoch_macros;
|
||||
pub mod slot_epoch;
|
||||
@ -54,7 +55,6 @@ pub use crate::deposit_data::DepositData;
|
||||
pub use crate::deposit_input::DepositInput;
|
||||
pub use crate::eth1_data::Eth1Data;
|
||||
pub use crate::eth1_data_vote::Eth1DataVote;
|
||||
pub use crate::exit::Exit;
|
||||
pub use crate::fork::Fork;
|
||||
pub use crate::free_attestation::FreeAttestation;
|
||||
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::slot_epoch::{Epoch, Slot};
|
||||
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::voluntary_exit::VolutaryExit;
|
||||
|
||||
pub type Hash256 = H256;
|
||||
pub type Address = H160;
|
||||
|
@ -5,6 +5,9 @@ use serde_derive::Serialize;
|
||||
use ssz_derive::{Decode, Encode, TreeHash};
|
||||
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)]
|
||||
pub struct PendingAttestation {
|
||||
pub aggregation_bitfield: Bitfield,
|
||||
|
@ -7,6 +7,9 @@ use ssz::TreeHash;
|
||||
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
|
||||
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)]
|
||||
pub struct Proposal {
|
||||
pub slot: Slot,
|
||||
|
@ -15,8 +15,8 @@ pub use builder::ProposerSlashingBuilder;
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
pub struct ProposerSlashing {
|
||||
pub proposer_index: u64,
|
||||
pub proposer_1: Proposal,
|
||||
pub proposer_2: Proposal,
|
||||
pub proposal_1: Proposal,
|
||||
pub proposal_2: Proposal,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::*;
|
||||
use ssz::TreeHash;
|
||||
use ssz::SignedRoot;
|
||||
|
||||
/// Builds a `ProposerSlashing`.
|
||||
pub struct ProposerSlashingBuilder();
|
||||
@ -22,27 +22,29 @@ impl ProposerSlashingBuilder {
|
||||
let slot = Slot::new(0);
|
||||
let shard = 0;
|
||||
|
||||
let proposal_data_1 = ProposalSignedData {
|
||||
let mut proposal_1 = Proposal {
|
||||
slot,
|
||||
shard,
|
||||
block_root: Hash256::from(&[1][..]),
|
||||
signature: Signature::empty_signature(),
|
||||
};
|
||||
|
||||
let proposal_data_2 = ProposalSignedData {
|
||||
let mut proposal_2 = Proposal {
|
||||
slot,
|
||||
shard,
|
||||
block_root: Hash256::from(&[2][..]),
|
||||
signature: Signature::empty_signature(),
|
||||
};
|
||||
|
||||
let proposal_signature_1 = {
|
||||
let message = proposal_data_1.hash_tree_root();
|
||||
proposal_1.signature = {
|
||||
let message = proposal_1.signed_root();
|
||||
let epoch = slot.epoch(spec.epoch_length);
|
||||
let domain = spec.domain_proposal;
|
||||
signer(proposer_index, &message[..], epoch, domain)
|
||||
};
|
||||
|
||||
let proposal_signature_2 = {
|
||||
let message = proposal_data_2.hash_tree_root();
|
||||
proposal_2.signature = {
|
||||
let message = proposal_2.signed_root();
|
||||
let epoch = slot.epoch(spec.epoch_length);
|
||||
let domain = spec.domain_proposal;
|
||||
signer(proposer_index, &message[..], epoch, domain)
|
||||
@ -50,10 +52,8 @@ impl ProposerSlashingBuilder {
|
||||
|
||||
ProposerSlashing {
|
||||
proposer_index,
|
||||
proposal_data_1,
|
||||
proposal_signature_1,
|
||||
proposal_data_2,
|
||||
proposal_signature_2,
|
||||
proposal_1,
|
||||
proposal_2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
|
||||
use rand::RngCore;
|
||||
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;
|
||||
|
||||
#[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 {
|
||||
/// Lists validator registry indices, not committee indices.
|
||||
pub validator_indices: Vec<u64>,
|
||||
pub data: AttestationData,
|
||||
pub custody_bitfield: Bitfield,
|
||||
@ -15,21 +22,21 @@ pub struct SlashableAttestation {
|
||||
impl SlashableAttestation {
|
||||
/// 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 {
|
||||
self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let source_epoch_1 = self.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_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)
|
||||
}
|
||||
}
|
||||
|
||||
|
51
eth2/types/src/transfer.rs
Normal file
51
eth2/types/src/transfer.rs
Normal 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
|
||||
}
|
||||
}
|
@ -2,55 +2,21 @@ use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
|
||||
use rand::RngCore;
|
||||
use serde_derive::Serialize;
|
||||
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;
|
||||
const STATUS_FLAG_WITHDRAWABLE: u8 = 2;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize)]
|
||||
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)]
|
||||
/// Information about a `BeaconChain` validator.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Encode, Decode, TestRandom)]
|
||||
pub struct Validator {
|
||||
pub pubkey: PublicKey,
|
||||
pub withdrawal_credentials: Hash256,
|
||||
pub activation_epoch: Epoch,
|
||||
pub exit_epoch: Epoch,
|
||||
pub withdrawal_epoch: Epoch,
|
||||
pub penalized_epoch: Epoch,
|
||||
pub status_flags: Option<StatusFlags>,
|
||||
pub initiated_exit: bool,
|
||||
pub slashed: bool,
|
||||
}
|
||||
|
||||
impl Validator {
|
||||
@ -64,9 +30,9 @@ impl Validator {
|
||||
self.exit_epoch <= epoch
|
||||
}
|
||||
|
||||
/// Returns `true` if the validator is considered penalized at some epoch.
|
||||
pub fn is_penalized_at(&self, epoch: Epoch) -> bool {
|
||||
self.penalized_epoch <= epoch
|
||||
/// Returns `true` if the validator is able to withdraw at some epoch.
|
||||
pub fn is_withdrawable_at(&self, epoch: Epoch) -> bool {
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -2,11 +2,15 @@ use crate::{test_utils::TestRandom, Epoch};
|
||||
use bls::Signature;
|
||||
use rand::RngCore;
|
||||
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;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
pub struct Exit {
|
||||
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
||||
///
|
||||
/// Spec v0.4.0
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Encode, Decode, TreeHash, TestRandom, SignedRoot)]
|
||||
pub struct VolutaryExit {
|
||||
pub epoch: Epoch,
|
||||
pub validator_index: u64,
|
||||
pub signature: Signature,
|
||||
@ -21,7 +25,7 @@ mod tests {
|
||||
#[test]
|
||||
pub fn test_ssz_round_trip() {
|
||||
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 (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();
|
||||
@ -32,7 +36,7 @@ mod tests {
|
||||
#[test]
|
||||
pub fn test_hash_tree_root_internal() {
|
||||
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();
|
||||
|
Loading…
Reference in New Issue
Block a user