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 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::*;

View File

@ -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::*;

View File

@ -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,

View File

@ -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,

View File

@ -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)]

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 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)]

View File

@ -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),

View File

@ -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::*;

View File

@ -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>,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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)]

View File

@ -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,
}
}
}

View File

@ -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)
}
}

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 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::*;

View File

@ -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();