diff --git a/eth2/types/src/attestation.rs b/eth2/types/src/attestation.rs index d1511763d..0a4493ae6 100644 --- a/eth2/types/src/attestation.rs +++ b/eth2/types/src/attestation.rs @@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// Details an attestation that can be slashable. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, Clone, @@ -28,7 +28,7 @@ pub struct Attestation { pub data: AttestationData, pub custody_bitfield: Bitfield, #[signed_root(skip_hashing)] - pub aggregate_signature: AggregateSignature, + pub signature: AggregateSignature, } impl Attestation { @@ -49,8 +49,7 @@ impl Attestation { self.aggregation_bitfield .union_inplace(&other.aggregation_bitfield); self.custody_bitfield.union_inplace(&other.custody_bitfield); - self.aggregate_signature - .add_aggregate(&other.aggregate_signature); + self.signature.add_aggregate(&other.signature); } } diff --git a/eth2/types/src/attestation_data.rs b/eth2/types/src/attestation_data.rs index c963d6001..63b94fd70 100644 --- a/eth2/types/src/attestation_data.rs +++ b/eth2/types/src/attestation_data.rs @@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// The data upon which an attestation is based. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, Clone, @@ -37,7 +37,7 @@ pub struct AttestationData { // Crosslink Vote pub shard: u64, - pub previous_crosslink: Crosslink, + pub previous_crosslink_root: Crosslink, pub crosslink_data_root: Hash256, } diff --git a/eth2/types/src/attester_slashing.rs b/eth2/types/src/attester_slashing.rs index d4848b01c..1c9897cc1 100644 --- a/eth2/types/src/attester_slashing.rs +++ b/eth2/types/src/attester_slashing.rs @@ -1,4 +1,4 @@ -use crate::{test_utils::TestRandom, SlashableAttestation}; +use crate::{test_utils::TestRandom, IndexedAttestation}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; @@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Two conflicting attestations. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, PartialEq, @@ -21,8 +21,8 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; TestRandom, )] pub struct AttesterSlashing { - pub slashable_attestation_1: SlashableAttestation, - pub slashable_attestation_2: SlashableAttestation, + pub attestation_1: IndexedAttestation, + pub attestation_2: IndexedAttestation, } #[cfg(test)] diff --git a/eth2/types/src/beacon_block.rs b/eth2/types/src/beacon_block.rs index d198d16fc..1265a4864 100644 --- a/eth2/types/src/beacon_block.rs +++ b/eth2/types/src/beacon_block.rs @@ -47,6 +47,7 @@ impl BeaconBlock { eth1_data: Eth1Data { deposit_root: spec.zero_hash, block_hash: spec.zero_hash, + deposit_count: 0, }, proposer_slashings: vec![], attester_slashings: vec![], diff --git a/eth2/types/src/beacon_state.rs b/eth2/types/src/beacon_state.rs index e9b052f99..cb37c8448 100644 --- a/eth2/types/src/beacon_state.rs +++ b/eth2/types/src/beacon_state.rs @@ -69,17 +69,11 @@ pub struct BeaconState { // Validator registry pub validator_registry: Vec, - pub validator_balances: Vec, - pub validator_registry_update_epoch: Epoch, + pub balances: Vec, // Randomness and committees pub latest_randao_mixes: TreeHashVector, - 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, + pub latest_start_shard: u64, // Finality pub previous_epoch_attestations: Vec, @@ -93,7 +87,8 @@ pub struct BeaconState { pub finalized_root: Hash256, // Recent state - pub latest_crosslinks: TreeHashVector, + pub current_crosslinks: TreeHashVector, + pub previous_crosslinks: TreeHashVector, pub latest_block_roots: TreeHashVector, latest_state_roots: TreeHashVector, latest_active_index_roots: TreeHashVector, @@ -103,7 +98,7 @@ pub struct BeaconState { // Ethereum 1.0 chain data pub latest_eth1_data: Eth1Data, - pub eth1_data_votes: Vec, + pub eth1_data_votes: Vec, pub deposit_index: u64, // Caching (not in the spec) @@ -143,6 +138,7 @@ impl BeaconState { pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState { let initial_crosslink = Crosslink { epoch: spec.genesis_epoch, + previous_crosslink_root: spec.zero_hash, crosslink_data_root: spec.zero_hash, }; @@ -154,18 +150,12 @@ impl BeaconState { // Validator registry validator_registry: vec![], // Set later in the function. - validator_balances: vec![], // Set later in the function. - validator_registry_update_epoch: spec.genesis_epoch, + balances: vec![], // Set later in the function. // Randomness and committees latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize] .into(), - 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, + latest_start_shard: 0, // FIXME(sproul) // Finality previous_epoch_attestations: vec![], @@ -179,7 +169,8 @@ impl BeaconState { finalized_root: spec.zero_hash, // Recent state - latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(), + current_crosslinks: vec![initial_crosslink.clone(); spec.shard_count as usize].into(), + previous_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(), latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(), latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(), latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length] @@ -630,7 +621,7 @@ impl BeaconState { spec: &ChainSpec, ) -> Result { let balance = self - .validator_balances + .balances .get(validator_index) .ok_or_else(|| Error::UnknownValidator)?; Ok(std::cmp::min(*balance, spec.max_deposit_amount)) @@ -647,7 +638,8 @@ impl BeaconState { /// /// Spec v0.5.1 pub fn initiate_validator_exit(&mut self, validator_index: usize) { - self.validator_registry[validator_index].initiated_exit = true; + // FIXME(sproul) + // self.validator_registry[validator_index].initiated_exit = true; } /// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an diff --git a/eth2/types/src/beacon_state/epoch_cache.rs b/eth2/types/src/beacon_state/epoch_cache.rs index 1a63e9eb9..9230c5af2 100644 --- a/eth2/types/src/beacon_state/epoch_cache.rs +++ b/eth2/types/src/beacon_state/epoch_cache.rs @@ -207,8 +207,9 @@ impl EpochCrosslinkCommitteesBuilder { ) -> Self { Self { epoch: state.previous_epoch(spec), - shuffling_start_shard: state.previous_shuffling_start_shard, - shuffling_seed: state.previous_shuffling_seed, + // FIXME(sproul) + shuffling_start_shard: 0, + shuffling_seed: spec.zero_hash, committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()), active_validator_indices, } @@ -222,8 +223,9 @@ impl EpochCrosslinkCommitteesBuilder { ) -> Self { Self { epoch: state.current_epoch(spec), - shuffling_start_shard: state.current_shuffling_start_shard, - shuffling_seed: state.current_shuffling_seed, + // FIXME(sproul) + shuffling_start_shard: 0, + shuffling_seed: spec.zero_hash, committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()), active_validator_indices, } @@ -243,8 +245,9 @@ impl EpochCrosslinkCommitteesBuilder { let next_epoch = state.next_epoch(spec); let committees_per_epoch = spec.get_epoch_committee_count(active_validator_indices.len()); - let epochs_since_last_registry_update = - current_epoch - state.validator_registry_update_epoch; + // FIXME(sproul) + // current_epoch - state.validator_registry_update_epoch; + let epochs_since_last_registry_update = 0u64; let (seed, shuffling_start_shard) = if registry_change { let next_seed = state @@ -252,7 +255,9 @@ impl EpochCrosslinkCommitteesBuilder { .map_err(|_| Error::UnableToGenerateSeed)?; ( next_seed, - (state.current_shuffling_start_shard + committees_per_epoch) % spec.shard_count, + 0, + // FIXME(sproul) + // (state.current_shuffling_start_shard + committees_per_epoch) % spec.shard_count, ) } else if (epochs_since_last_registry_update > 1) & epochs_since_last_registry_update.is_power_of_two() @@ -260,11 +265,13 @@ impl EpochCrosslinkCommitteesBuilder { let next_seed = state .generate_seed(next_epoch, spec) .map_err(|_| Error::UnableToGenerateSeed)?; - (next_seed, state.current_shuffling_start_shard) + ( + next_seed, 0, /* FIXME(sproul) state.current_shuffling_start_shard*/ + ) } else { ( - state.current_shuffling_seed, - state.current_shuffling_start_shard, + spec.zero_hash, // state.current_shuffling_seed, + 0 // state.current_shuffling_start_shard, ) }; diff --git a/eth2/types/src/crosslink.rs b/eth2/types/src/crosslink.rs index 448f5ea30..e6d353452 100644 --- a/eth2/types/src/crosslink.rs +++ b/eth2/types/src/crosslink.rs @@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Specifies the block hash for a shard at an epoch. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, Clone, @@ -25,6 +25,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; )] pub struct Crosslink { pub epoch: Epoch, + pub previous_crosslink_root: Hash256, pub crosslink_data_root: Hash256, } diff --git a/eth2/types/src/deposit.rs b/eth2/types/src/deposit.rs index e8d2f5a4b..88dc5f427 100644 --- a/eth2/types/src/deposit.rs +++ b/eth2/types/src/deposit.rs @@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// A deposit to potentially become a beacon chain validator. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, PartialEq, @@ -24,7 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; pub struct Deposit { pub proof: TreeHashVector, pub index: u64, - pub deposit_data: DepositData, + pub data: DepositData, } #[cfg(test)] diff --git a/eth2/types/src/deposit_data.rs b/eth2/types/src/deposit_data.rs index 38c44d1a7..930836c70 100644 --- a/eth2/types/src/deposit_data.rs +++ b/eth2/types/src/deposit_data.rs @@ -1,14 +1,16 @@ -use super::DepositInput; use crate::test_utils::TestRandom; +use crate::*; +use bls::{PublicKey, Signature}; use rand::RngCore; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; -use tree_hash_derive::{CachedTreeHash, TreeHash}; +use tree_hash::{SignedRoot, TreeHash}; +use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; -/// Data generated by the deposit contract. +/// The data supplied by the user to the deposit contract. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, PartialEq, @@ -17,14 +19,45 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; Deserialize, Encode, Decode, + SignedRoot, TreeHash, CachedTreeHash, TestRandom, )] pub struct DepositData { + pub pubkey: PublicKey, + pub withdrawal_credentials: Hash256, pub amount: u64, - pub timestamp: u64, - pub deposit_input: DepositInput, + #[signed_root(skip_hashing)] + pub signature: Signature, +} + +impl DepositData { + /// Generate the signature for a given DepositData details. + /// + /// Spec v0.5.1 + pub fn create_signature( + &self, + secret_key: &SecretKey, + epoch: Epoch, + fork: &Fork, + spec: &ChainSpec, + ) -> Signature { + let msg = self.signed_root(); + let domain = spec.get_domain(epoch, Domain::Deposit, fork); + + Signature::new(msg.as_slice(), domain, secret_key) + } + + /// Verify that proof-of-possession is valid. + /// + /// Spec v0.5.1 + pub fn validate_signature(&self, epoch: Epoch, fork: &Fork, spec: &ChainSpec) -> bool { + let msg = self.signed_root(); + let domain = spec.get_domain(epoch, Domain::Deposit, fork); + + self.signature.verify(&msg, domain, &self.pubkey) + } } #[cfg(test)] @@ -33,4 +66,22 @@ mod tests { ssz_tests!(DepositData); cached_tree_hash_tests!(DepositData); + + #[test] + fn can_create_and_validate() { + let spec = ChainSpec::foundation(); + let fork = Fork::genesis(&spec); + let keypair = Keypair::random(); + let epoch = Epoch::new(0); + + let mut deposit_input = DepositData { + pubkey: keypair.pk.clone(), + withdrawal_credentials: Hash256::zero(), + signature: Signature::empty_signature(), + }; + + deposit_input.signature = deposit_input.create_signature(&keypair.sk, epoch, &fork, &spec); + + assert!(deposit_input.validate_signature(epoch, &fork, &spec)); + } } diff --git a/eth2/types/src/deposit_input.rs b/eth2/types/src/deposit_input.rs deleted file mode 100644 index af1049a20..000000000 --- a/eth2/types/src/deposit_input.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::test_utils::TestRandom; -use crate::*; -use bls::{PublicKey, Signature}; -use rand::RngCore; -use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use test_random_derive::TestRandom; -use tree_hash::{SignedRoot, TreeHash}; -use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; - -/// The data supplied by the user to the deposit contract. -/// -/// Spec v0.5.1 -#[derive( - Debug, - PartialEq, - Clone, - Serialize, - Deserialize, - Encode, - Decode, - SignedRoot, - TreeHash, - CachedTreeHash, - TestRandom, -)] -pub struct DepositInput { - pub pubkey: PublicKey, - pub withdrawal_credentials: Hash256, - #[signed_root(skip_hashing)] - pub proof_of_possession: Signature, -} - -impl DepositInput { - /// Generate the 'proof_of_posession' signature for a given DepositInput details. - /// - /// Spec v0.5.1 - pub fn create_proof_of_possession( - &self, - secret_key: &SecretKey, - epoch: Epoch, - fork: &Fork, - spec: &ChainSpec, - ) -> Signature { - let msg = self.signed_root(); - let domain = spec.get_domain(epoch, Domain::Deposit, fork); - - Signature::new(msg.as_slice(), domain, secret_key) - } - - /// Verify that proof-of-possession is valid. - /// - /// Spec v0.5.1 - pub fn validate_proof_of_possession( - &self, - epoch: Epoch, - fork: &Fork, - spec: &ChainSpec, - ) -> bool { - let msg = self.signed_root(); - let domain = spec.get_domain(epoch, Domain::Deposit, fork); - - self.proof_of_possession.verify(&msg, domain, &self.pubkey) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - ssz_tests!(DepositInput); - cached_tree_hash_tests!(DepositInput); - - #[test] - fn can_create_and_validate() { - let spec = ChainSpec::foundation(); - let fork = Fork::genesis(&spec); - let keypair = Keypair::random(); - let epoch = Epoch::new(0); - - let mut deposit_input = DepositInput { - pubkey: keypair.pk.clone(), - withdrawal_credentials: Hash256::zero(), - proof_of_possession: Signature::empty_signature(), - }; - - deposit_input.proof_of_possession = - deposit_input.create_proof_of_possession(&keypair.sk, epoch, &fork, &spec); - - assert!(deposit_input.validate_proof_of_possession(epoch, &fork, &spec)); - } -} diff --git a/eth2/types/src/eth1_data.rs b/eth2/types/src/eth1_data.rs index 3c0c3af02..6fc07e882 100644 --- a/eth2/types/src/eth1_data.rs +++ b/eth2/types/src/eth1_data.rs @@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Contains data obtained from the Eth1 chain. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, PartialEq, @@ -24,6 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; )] pub struct Eth1Data { pub deposit_root: Hash256, + pub deposit_count: u64, pub block_hash: Hash256, } diff --git a/eth2/types/src/eth1_data_vote.rs b/eth2/types/src/eth1_data_vote.rs deleted file mode 100644 index 00818ebf4..000000000 --- a/eth2/types/src/eth1_data_vote.rs +++ /dev/null @@ -1,36 +0,0 @@ -use super::Eth1Data; -use crate::test_utils::TestRandom; -use rand::RngCore; -use serde_derive::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use test_random_derive::TestRandom; -use tree_hash_derive::{CachedTreeHash, TreeHash}; - -/// A summation of votes for some `Eth1Data`. -/// -/// Spec v0.5.1 -#[derive( - Debug, - PartialEq, - Clone, - Default, - Serialize, - Deserialize, - Encode, - Decode, - TreeHash, - CachedTreeHash, - TestRandom, -)] -pub struct Eth1DataVote { - pub eth1_data: Eth1Data, - pub vote_count: u64, -} - -#[cfg(test)] -mod tests { - use super::*; - - ssz_tests!(Eth1DataVote); - cached_tree_hash_tests!(Eth1DataVote); -} diff --git a/eth2/types/src/slashable_attestation.rs b/eth2/types/src/indexed_attestation.rs similarity index 56% rename from eth2/types/src/slashable_attestation.rs rename to eth2/types/src/indexed_attestation.rs index fb838e0c4..5b56f34df 100644 --- a/eth2/types/src/slashable_attestation.rs +++ b/eth2/types/src/indexed_attestation.rs @@ -10,7 +10,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; /// /// To be included in an `AttesterSlashing`. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, PartialEq, @@ -24,27 +24,28 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash}; TestRandom, SignedRoot, )] -pub struct SlashableAttestation { +pub struct IndexedAttestation { /// Lists validator registry indices, not committee indices. - pub validator_indices: Vec, + pub custody_bit_0_indices: Vec, + pub custody_bit_1_indices: Vec, pub data: AttestationData, pub custody_bitfield: Bitfield, #[signed_root(skip_hashing)] - pub aggregate_signature: AggregateSignature, + pub signature: AggregateSignature, } -impl SlashableAttestation { +impl IndexedAttestation { /// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target. /// /// Spec v0.5.1 - pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { + pub fn is_double_vote(&self, other: &IndexedAttestation, spec: &ChainSpec) -> bool { self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch) } /// Check if ``attestation_data_1`` surrounds ``attestation_data_2``. /// /// Spec v0.5.1 - pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { + pub fn is_surround_vote(&self, other: &IndexedAttestation, spec: &ChainSpec) -> bool { let source_epoch_1 = self.data.source_epoch; let source_epoch_2 = other.data.source_epoch; let target_epoch_1 = self.data.slot.epoch(spec.slots_per_epoch); @@ -64,11 +65,11 @@ mod tests { #[test] pub fn test_is_double_vote_true() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(1, 1, &spec); - let slashable_vote_second = create_slashable_attestation(1, 1, &spec); + let indexed_vote_first = create_indexed_attestation(1, 1, &spec); + let indexed_vote_second = create_indexed_attestation(1, 1, &spec); assert_eq!( - slashable_vote_first.is_double_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_double_vote(&indexed_vote_second, &spec), true ) } @@ -76,11 +77,11 @@ mod tests { #[test] pub fn test_is_double_vote_false() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(1, 1, &spec); - let slashable_vote_second = create_slashable_attestation(2, 1, &spec); + let indexed_vote_first = create_indexed_attestation(1, 1, &spec); + let indexed_vote_second = create_indexed_attestation(2, 1, &spec); assert_eq!( - slashable_vote_first.is_double_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_double_vote(&indexed_vote_second, &spec), false ); } @@ -88,11 +89,11 @@ mod tests { #[test] pub fn test_is_surround_vote_true() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(2, 1, &spec); - let slashable_vote_second = create_slashable_attestation(1, 2, &spec); + let indexed_vote_first = create_indexed_attestation(2, 1, &spec); + let indexed_vote_second = create_indexed_attestation(1, 2, &spec); assert_eq!( - slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec), true ); } @@ -100,11 +101,11 @@ mod tests { #[test] pub fn test_is_surround_vote_true_realistic() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(4, 1, &spec); - let slashable_vote_second = create_slashable_attestation(3, 2, &spec); + let indexed_vote_first = create_indexed_attestation(4, 1, &spec); + let indexed_vote_second = create_indexed_attestation(3, 2, &spec); assert_eq!( - slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec), true ); } @@ -112,11 +113,11 @@ mod tests { #[test] pub fn test_is_surround_vote_false_source_epoch_fails() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(2, 2, &spec); - let slashable_vote_second = create_slashable_attestation(1, 1, &spec); + let indexed_vote_first = create_indexed_attestation(2, 2, &spec); + let indexed_vote_second = create_indexed_attestation(1, 1, &spec); assert_eq!( - slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec), false ); } @@ -124,28 +125,28 @@ mod tests { #[test] pub fn test_is_surround_vote_false_target_epoch_fails() { let spec = ChainSpec::foundation(); - let slashable_vote_first = create_slashable_attestation(1, 1, &spec); - let slashable_vote_second = create_slashable_attestation(2, 2, &spec); + let indexed_vote_first = create_indexed_attestation(1, 1, &spec); + let indexed_vote_second = create_indexed_attestation(2, 2, &spec); assert_eq!( - slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), + indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec), false ); } - ssz_tests!(SlashableAttestation); - cached_tree_hash_tests!(SlashableAttestation); + ssz_tests!(IndexedAttestation); + cached_tree_hash_tests!(IndexedAttestation); - fn create_slashable_attestation( + fn create_indexed_attestation( slot_factor: u64, source_epoch: u64, spec: &ChainSpec, - ) -> SlashableAttestation { + ) -> IndexedAttestation { let mut rng = XorShiftRng::from_seed([42; 16]); - let mut slashable_vote = SlashableAttestation::random_for_test(&mut rng); + let mut indexed_vote = IndexedAttestation::random_for_test(&mut rng); - slashable_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch); - slashable_vote.data.source_epoch = Epoch::new(source_epoch); - slashable_vote + indexed_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch); + indexed_vote.data.source_epoch = Epoch::new(source_epoch); + indexed_vote } } diff --git a/eth2/types/src/lib.rs b/eth2/types/src/lib.rs index 070ed6745..82e5b69ce 100644 --- a/eth2/types/src/lib.rs +++ b/eth2/types/src/lib.rs @@ -17,15 +17,13 @@ pub mod crosslink; pub mod crosslink_committee; pub mod deposit; pub mod deposit_data; -pub mod deposit_input; pub mod eth1_data; -pub mod eth1_data_vote; pub mod fork; pub mod free_attestation; pub mod historical_batch; +pub mod indexed_attestation; pub mod pending_attestation; pub mod proposer_slashing; -pub mod slashable_attestation; pub mod transfer; pub mod tree_hash_vector; pub mod voluntary_exit; @@ -53,16 +51,14 @@ pub use crate::crosslink::Crosslink; pub use crate::crosslink_committee::CrosslinkCommittee; pub use crate::deposit::Deposit; 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::fork::Fork; pub use crate::free_attestation::FreeAttestation; pub use crate::historical_batch::HistoricalBatch; +pub use crate::indexed_attestation::IndexedAttestation; pub use crate::pending_attestation::PendingAttestation; pub use crate::proposer_slashing::ProposerSlashing; pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch}; -pub use crate::slashable_attestation::SlashableAttestation; pub use crate::slot_epoch::{Epoch, Slot}; pub use crate::slot_height::SlotHeight; pub use crate::transfer::Transfer; diff --git a/eth2/types/src/pending_attestation.rs b/eth2/types/src/pending_attestation.rs index b71351f9a..e2ad23716 100644 --- a/eth2/types/src/pending_attestation.rs +++ b/eth2/types/src/pending_attestation.rs @@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// An attestation that has been included in the state but not yet fully processed. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, Clone, @@ -24,18 +24,22 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; pub struct PendingAttestation { pub aggregation_bitfield: Bitfield, pub data: AttestationData, - pub custody_bitfield: Bitfield, pub inclusion_slot: Slot, + pub proposer_index: u64, } impl PendingAttestation { - /// Create a `PendingAttestation` from an `Attestation`, at the given `inclusion_slot`. - pub fn from_attestation(attestation: &Attestation, inclusion_slot: Slot) -> Self { + /// Create a `PendingAttestation` from an `Attestation`. + pub fn from_attestation( + attestation: &Attestation, + inclusion_slot: Slot, + proposer_index: u64, + ) -> Self { PendingAttestation { data: attestation.data.clone(), aggregation_bitfield: attestation.aggregation_bitfield.clone(), - custody_bitfield: attestation.custody_bitfield.clone(), inclusion_slot, + proposer_index, } } } diff --git a/eth2/types/src/test_utils/testing_attestation_builder.rs b/eth2/types/src/test_utils/testing_attestation_builder.rs index 162facc8e..b41bf6f8d 100644 --- a/eth2/types/src/test_utils/testing_attestation_builder.rs +++ b/eth2/types/src/test_utils/testing_attestation_builder.rs @@ -33,7 +33,7 @@ impl TestingAttestationBuilder { aggregation_bitfield, data: data_builder.build(), custody_bitfield, - aggregate_signature: AggregateSignature::new(), + signature: AggregateSignature::new(), }; Self { @@ -83,7 +83,7 @@ impl TestingAttestationBuilder { ); let signature = Signature::new(&message, domain, secret_keys[key_index]); - self.attestation.aggregate_signature.add(&signature) + self.attestation.signature.add(&signature) } } diff --git a/eth2/types/src/test_utils/testing_attestation_data_builder.rs b/eth2/types/src/test_utils/testing_attestation_data_builder.rs index a270e3859..146485fc0 100644 --- a/eth2/types/src/test_utils/testing_attestation_data_builder.rs +++ b/eth2/types/src/test_utils/testing_attestation_data_builder.rs @@ -49,8 +49,9 @@ impl TestingAttestationDataBuilder { // Crosslink vote shard, - previous_crosslink: Crosslink { + previous_crosslink_root: Crosslink { epoch: slot.epoch(spec.slots_per_epoch), + previous_crosslink_root: spec.zero_hash, crosslink_data_root: spec.zero_hash, }, crosslink_data_root: spec.zero_hash, diff --git a/eth2/types/src/test_utils/testing_attester_slashing_builder.rs b/eth2/types/src/test_utils/testing_attester_slashing_builder.rs index dc01f7fb0..bd5aea2a4 100644 --- a/eth2/types/src/test_utils/testing_attester_slashing_builder.rs +++ b/eth2/types/src/test_utils/testing_attester_slashing_builder.rs @@ -34,8 +34,9 @@ impl TestingAttesterSlashingBuilder { source_root: hash_1, target_root: hash_1, shard, - previous_crosslink: Crosslink { + previous_crosslink_root: Crosslink { epoch, + previous_crosslink_root: hash_1, crosslink_data_root: hash_1, }, crosslink_data_root: hash_1, @@ -46,21 +47,23 @@ impl TestingAttesterSlashingBuilder { ..data_1.clone() }; - let mut slashable_attestation_1 = SlashableAttestation { - validator_indices: validator_indices.to_vec(), + let mut attestation_1 = IndexedAttestation { + custody_bit_0_indices: validator_indices.to_vec(), + custody_bit_1_indices: vec![], data: data_1, custody_bitfield: Bitfield::new(), - aggregate_signature: AggregateSignature::new(), + signature: AggregateSignature::new(), }; - let mut slashable_attestation_2 = SlashableAttestation { - validator_indices: validator_indices.to_vec(), + let mut attestation_2 = IndexedAttestation { + custody_bit_0_indices: validator_indices.to_vec(), + custody_bit_1_indices: vec![], data: data_2, custody_bitfield: Bitfield::new(), - aggregate_signature: AggregateSignature::new(), + signature: AggregateSignature::new(), }; - let add_signatures = |attestation: &mut SlashableAttestation| { + let add_signatures = |attestation: &mut IndexedAttestation| { // All validators sign with a `false` custody bit. let attestation_data_and_custody_bit = AttestationDataAndCustodyBit { data: attestation.data.clone(), @@ -71,16 +74,16 @@ impl TestingAttesterSlashingBuilder { for (i, validator_index) in validator_indices.iter().enumerate() { attestation.custody_bitfield.set(i, false); let signature = signer(*validator_index, &message[..], epoch, Domain::Attestation); - attestation.aggregate_signature.add(&signature); + attestation.signature.add(&signature); } }; - add_signatures(&mut slashable_attestation_1); - add_signatures(&mut slashable_attestation_2); + add_signatures(&mut attestation_1); + add_signatures(&mut attestation_2); AttesterSlashing { - slashable_attestation_1, - slashable_attestation_2, + attestation_1, + attestation_2, } } } diff --git a/eth2/types/src/test_utils/testing_beacon_state_builder.rs b/eth2/types/src/test_utils/testing_beacon_state_builder.rs index 9bdd9e149..7987a256f 100644 --- a/eth2/types/src/test_utils/testing_beacon_state_builder.rs +++ b/eth2/types/src/test_utils/testing_beacon_state_builder.rs @@ -95,6 +95,7 @@ impl TestingBeaconStateBuilder { /// Creates the builder from an existing set of keypairs. pub fn from_keypairs(keypairs: Vec, spec: &ChainSpec) -> Self { let validator_count = keypairs.len(); + let starting_balance = 32_000_000_000; debug!( "Building {} Validator objects from keypairs...", @@ -112,11 +113,12 @@ impl TestingBeaconStateBuilder { pubkey: keypair.pk.clone(), withdrawal_credentials, // All validators start active. + activation_eligibility_epoch: spec.genesis_epoch, activation_epoch: spec.genesis_epoch, exit_epoch: spec.far_future_epoch, withdrawable_epoch: spec.far_future_epoch, - initiated_exit: false, slashed: false, + effective_balance: starting_balance, } }) .collect(); @@ -137,16 +139,17 @@ impl TestingBeaconStateBuilder { genesis_time, Eth1Data { deposit_root: Hash256::zero(), + deposit_count: 0, block_hash: Hash256::zero(), }, spec, ); - let balances = vec![32_000_000_000; validator_count]; + let balances = vec![starting_balance; validator_count]; debug!("Importing {} existing validators...", validator_count); state.validator_registry = validators; - state.validator_balances = balances; + state.balances = balances; debug!("BeaconState initialized."); @@ -192,18 +195,13 @@ impl TestingBeaconStateBuilder { state.slot = slot; - state.previous_shuffling_epoch = epoch - 1; - state.current_shuffling_epoch = epoch; - - state.previous_shuffling_seed = Hash256::from_low_u64_le(0); - state.current_shuffling_seed = Hash256::from_low_u64_le(1); + // FIXME(sproul): update latest_start_shard? state.previous_justified_epoch = epoch - 3; state.current_justified_epoch = epoch - 2; state.justification_bitfield = u64::max_value(); state.finalized_epoch = epoch - 3; - state.validator_registry_update_epoch = epoch - 3; } /// Creates a full set of attestations for the `BeaconState`. Each attestation has full diff --git a/eth2/types/src/test_utils/testing_deposit_builder.rs b/eth2/types/src/test_utils/testing_deposit_builder.rs index 080ed5cfb..dcb6a56ef 100644 --- a/eth2/types/src/test_utils/testing_deposit_builder.rs +++ b/eth2/types/src/test_utils/testing_deposit_builder.rs @@ -14,14 +14,11 @@ impl TestingDepositBuilder { let deposit = Deposit { proof: vec![].into(), index: 0, - deposit_data: DepositData { + data: DepositData { + pubkey, + withdrawal_credentials: Hash256::zero(), amount, - timestamp: 1, - deposit_input: DepositInput { - pubkey, - withdrawal_credentials: Hash256::zero(), - proof_of_possession: Signature::empty_signature(), - }, + signature: Signature::empty_signature(), }, }; @@ -43,17 +40,13 @@ impl TestingDepositBuilder { &get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..], ); - self.deposit.deposit_data.deposit_input.pubkey = keypair.pk.clone(); - self.deposit - .deposit_data - .deposit_input - .withdrawal_credentials = withdrawal_credentials; + self.deposit.data.pubkey = keypair.pk.clone(); + self.deposit.data.withdrawal_credentials = withdrawal_credentials; - self.deposit.deposit_data.deposit_input.proof_of_possession = self - .deposit - .deposit_data - .deposit_input - .create_proof_of_possession(&keypair.sk, epoch, fork, spec); + self.deposit.data.signature = + self.deposit + .data + .create_signature(&keypair.sk, epoch, fork, spec); } /// Builds the deposit, consuming the builder. diff --git a/eth2/types/src/test_utils/testing_pending_attestation_builder.rs b/eth2/types/src/test_utils/testing_pending_attestation_builder.rs index 655b3d1e8..831cda0f8 100644 --- a/eth2/types/src/test_utils/testing_pending_attestation_builder.rs +++ b/eth2/types/src/test_utils/testing_pending_attestation_builder.rs @@ -22,8 +22,9 @@ impl TestingPendingAttestationBuilder { let pending_attestation = PendingAttestation { aggregation_bitfield: Bitfield::new(), data: data_builder.build(), - custody_bitfield: Bitfield::new(), inclusion_slot: slot + spec.min_attestation_inclusion_delay, + // FIXME(sproul) + proposer_index: 0, }; Self { @@ -37,15 +38,12 @@ impl TestingPendingAttestationBuilder { /// `signers` is true. pub fn add_committee_participation(&mut self, signers: Vec) { let mut aggregation_bitfield = Bitfield::new(); - let mut custody_bitfield = Bitfield::new(); for (i, signed) in signers.iter().enumerate() { aggregation_bitfield.set(i, *signed); - custody_bitfield.set(i, false); // Fixed to `false` for phase 0. } self.pending_attestation.aggregation_bitfield = aggregation_bitfield; - self.pending_attestation.custody_bitfield = custody_bitfield; } /// Returns the `PendingAttestation`, consuming the builder. diff --git a/eth2/types/src/validator.rs b/eth2/types/src/validator.rs index a20eb6426..5b369427c 100644 --- a/eth2/types/src/validator.rs +++ b/eth2/types/src/validator.rs @@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; /// Information about a `BeaconChain` validator. /// -/// Spec v0.5.1 +/// Spec v0.6.0 #[derive( Debug, Clone, @@ -23,11 +23,12 @@ use tree_hash_derive::{CachedTreeHash, TreeHash}; pub struct Validator { pub pubkey: PublicKey, pub withdrawal_credentials: Hash256, + pub activation_eligibility_epoch: Epoch, pub activation_epoch: Epoch, pub exit_epoch: Epoch, pub withdrawable_epoch: Epoch, - pub initiated_exit: bool, pub slashed: bool, + pub effective_balance: u64, } impl Validator { @@ -53,11 +54,12 @@ impl Default for Validator { Self { pubkey: PublicKey::default(), withdrawal_credentials: Hash256::default(), + activation_eligibility_epoch: Epoch::from(std::u64::MAX), activation_epoch: Epoch::from(std::u64::MAX), exit_epoch: Epoch::from(std::u64::MAX), withdrawable_epoch: Epoch::from(std::u64::MAX), - initiated_exit: false, slashed: false, + effective_balance: std::u64::MAX, } } }