spec v0.6.0: update types

This commit is contained in:
Michael Sproul 2019-04-29 14:54:52 +10:00
parent 7dda85e87e
commit 1ad0024045
No known key found for this signature in database
GPG Key ID: 77B1309D2E54E914
22 changed files with 192 additions and 272 deletions

View File

@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable. /// Details an attestation that can be slashable.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -28,7 +28,7 @@ pub struct Attestation {
pub data: AttestationData, pub data: AttestationData,
pub custody_bitfield: Bitfield, pub custody_bitfield: Bitfield,
#[signed_root(skip_hashing)] #[signed_root(skip_hashing)]
pub aggregate_signature: AggregateSignature, pub signature: AggregateSignature,
} }
impl Attestation { impl Attestation {
@ -49,8 +49,7 @@ impl Attestation {
self.aggregation_bitfield self.aggregation_bitfield
.union_inplace(&other.aggregation_bitfield); .union_inplace(&other.aggregation_bitfield);
self.custody_bitfield.union_inplace(&other.custody_bitfield); self.custody_bitfield.union_inplace(&other.custody_bitfield);
self.aggregate_signature self.signature.add_aggregate(&other.signature);
.add_aggregate(&other.aggregate_signature);
} }
} }

View File

@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data upon which an attestation is based. /// The data upon which an attestation is based.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -37,7 +37,7 @@ pub struct AttestationData {
// Crosslink Vote // Crosslink Vote
pub shard: u64, pub shard: u64,
pub previous_crosslink: Crosslink, pub previous_crosslink_root: Crosslink,
pub crosslink_data_root: Hash256, pub crosslink_data_root: Hash256,
} }

View File

@ -1,4 +1,4 @@
use crate::{test_utils::TestRandom, SlashableAttestation}; use crate::{test_utils::TestRandom, IndexedAttestation};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting attestations. /// Two conflicting attestations.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -21,8 +21,8 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
TestRandom, TestRandom,
)] )]
pub struct AttesterSlashing { pub struct AttesterSlashing {
pub slashable_attestation_1: SlashableAttestation, pub attestation_1: IndexedAttestation,
pub slashable_attestation_2: SlashableAttestation, pub attestation_2: IndexedAttestation,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -47,6 +47,7 @@ impl BeaconBlock {
eth1_data: Eth1Data { eth1_data: Eth1Data {
deposit_root: spec.zero_hash, deposit_root: spec.zero_hash,
block_hash: spec.zero_hash, block_hash: spec.zero_hash,
deposit_count: 0,
}, },
proposer_slashings: vec![], proposer_slashings: vec![],
attester_slashings: vec![], attester_slashings: vec![],

View File

@ -69,17 +69,11 @@ pub struct BeaconState {
// Validator registry // Validator registry
pub validator_registry: Vec<Validator>, pub validator_registry: Vec<Validator>,
pub validator_balances: Vec<u64>, pub balances: Vec<u64>,
pub validator_registry_update_epoch: Epoch,
// Randomness and committees // Randomness and committees
pub latest_randao_mixes: TreeHashVector<Hash256>, pub latest_randao_mixes: TreeHashVector<Hash256>,
pub previous_shuffling_start_shard: u64, pub latest_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 // Finality
pub previous_epoch_attestations: Vec<PendingAttestation>, pub previous_epoch_attestations: Vec<PendingAttestation>,
@ -93,7 +87,8 @@ pub struct BeaconState {
pub finalized_root: Hash256, pub finalized_root: Hash256,
// Recent state // Recent state
pub latest_crosslinks: TreeHashVector<Crosslink>, pub current_crosslinks: TreeHashVector<Crosslink>,
pub previous_crosslinks: TreeHashVector<Crosslink>,
pub latest_block_roots: TreeHashVector<Hash256>, pub latest_block_roots: TreeHashVector<Hash256>,
latest_state_roots: TreeHashVector<Hash256>, latest_state_roots: TreeHashVector<Hash256>,
latest_active_index_roots: TreeHashVector<Hash256>, latest_active_index_roots: TreeHashVector<Hash256>,
@ -103,7 +98,7 @@ pub struct BeaconState {
// Ethereum 1.0 chain data // Ethereum 1.0 chain data
pub latest_eth1_data: Eth1Data, pub latest_eth1_data: Eth1Data,
pub eth1_data_votes: Vec<Eth1DataVote>, pub eth1_data_votes: Vec<Eth1Data>,
pub deposit_index: u64, pub deposit_index: u64,
// Caching (not in the spec) // Caching (not in the spec)
@ -143,6 +138,7 @@ impl BeaconState {
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState { pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
let initial_crosslink = Crosslink { let initial_crosslink = Crosslink {
epoch: spec.genesis_epoch, epoch: spec.genesis_epoch,
previous_crosslink_root: spec.zero_hash,
crosslink_data_root: spec.zero_hash, crosslink_data_root: spec.zero_hash,
}; };
@ -154,18 +150,12 @@ impl BeaconState {
// Validator registry // Validator registry
validator_registry: vec![], // Set later in the function. validator_registry: vec![], // Set later in the function.
validator_balances: vec![], // Set later in the function. balances: vec![], // Set later in the function.
validator_registry_update_epoch: spec.genesis_epoch,
// Randomness and committees // Randomness and committees
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize] latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize]
.into(), .into(),
previous_shuffling_start_shard: spec.genesis_start_shard, latest_start_shard: 0, // FIXME(sproul)
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 // Finality
previous_epoch_attestations: vec![], previous_epoch_attestations: vec![],
@ -179,7 +169,8 @@ impl BeaconState {
finalized_root: spec.zero_hash, finalized_root: spec.zero_hash,
// Recent state // 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_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_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] latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length]
@ -630,7 +621,7 @@ impl BeaconState {
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
let balance = self let balance = self
.validator_balances .balances
.get(validator_index) .get(validator_index)
.ok_or_else(|| Error::UnknownValidator)?; .ok_or_else(|| Error::UnknownValidator)?;
Ok(std::cmp::min(*balance, spec.max_deposit_amount)) Ok(std::cmp::min(*balance, spec.max_deposit_amount))
@ -647,7 +638,8 @@ impl BeaconState {
/// ///
/// Spec v0.5.1 /// Spec v0.5.1
pub fn initiate_validator_exit(&mut self, validator_index: usize) { 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 /// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an

View File

@ -207,8 +207,9 @@ impl EpochCrosslinkCommitteesBuilder {
) -> Self { ) -> Self {
Self { Self {
epoch: state.previous_epoch(spec), epoch: state.previous_epoch(spec),
shuffling_start_shard: state.previous_shuffling_start_shard, // FIXME(sproul)
shuffling_seed: state.previous_shuffling_seed, shuffling_start_shard: 0,
shuffling_seed: spec.zero_hash,
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()), committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
active_validator_indices, active_validator_indices,
} }
@ -222,8 +223,9 @@ impl EpochCrosslinkCommitteesBuilder {
) -> Self { ) -> Self {
Self { Self {
epoch: state.current_epoch(spec), epoch: state.current_epoch(spec),
shuffling_start_shard: state.current_shuffling_start_shard, // FIXME(sproul)
shuffling_seed: state.current_shuffling_seed, shuffling_start_shard: 0,
shuffling_seed: spec.zero_hash,
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()), committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
active_validator_indices, active_validator_indices,
} }
@ -243,8 +245,9 @@ impl EpochCrosslinkCommitteesBuilder {
let next_epoch = state.next_epoch(spec); let next_epoch = state.next_epoch(spec);
let committees_per_epoch = spec.get_epoch_committee_count(active_validator_indices.len()); let committees_per_epoch = spec.get_epoch_committee_count(active_validator_indices.len());
let epochs_since_last_registry_update = // FIXME(sproul)
current_epoch - state.validator_registry_update_epoch; // current_epoch - state.validator_registry_update_epoch;
let epochs_since_last_registry_update = 0u64;
let (seed, shuffling_start_shard) = if registry_change { let (seed, shuffling_start_shard) = if registry_change {
let next_seed = state let next_seed = state
@ -252,7 +255,9 @@ impl EpochCrosslinkCommitteesBuilder {
.map_err(|_| Error::UnableToGenerateSeed)?; .map_err(|_| Error::UnableToGenerateSeed)?;
( (
next_seed, 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) } else if (epochs_since_last_registry_update > 1)
& epochs_since_last_registry_update.is_power_of_two() & epochs_since_last_registry_update.is_power_of_two()
@ -260,11 +265,13 @@ impl EpochCrosslinkCommitteesBuilder {
let next_seed = state let next_seed = state
.generate_seed(next_epoch, spec) .generate_seed(next_epoch, spec)
.map_err(|_| Error::UnableToGenerateSeed)?; .map_err(|_| Error::UnableToGenerateSeed)?;
(next_seed, state.current_shuffling_start_shard) (
next_seed, 0, /* FIXME(sproul) state.current_shuffling_start_shard*/
)
} else { } else {
( (
state.current_shuffling_seed, spec.zero_hash, // state.current_shuffling_seed,
state.current_shuffling_start_shard, 0 // state.current_shuffling_start_shard,
) )
}; };

View File

@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies the block hash for a shard at an epoch. /// Specifies the block hash for a shard at an epoch.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -25,6 +25,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
)] )]
pub struct Crosslink { pub struct Crosslink {
pub epoch: Epoch, pub epoch: Epoch,
pub previous_crosslink_root: Hash256,
pub crosslink_data_root: Hash256, pub crosslink_data_root: Hash256,
} }

View File

@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A deposit to potentially become a beacon chain validator. /// A deposit to potentially become a beacon chain validator.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -24,7 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
pub struct Deposit { pub struct Deposit {
pub proof: TreeHashVector<Hash256>, pub proof: TreeHashVector<Hash256>,
pub index: u64, pub index: u64,
pub deposit_data: DepositData, pub data: DepositData,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,14 +1,16 @@
use super::DepositInput;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::*;
use bls::{PublicKey, Signature};
use rand::RngCore; use rand::RngCore;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom; 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( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -17,14 +19,45 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
Deserialize, Deserialize,
Encode, Encode,
Decode, Decode,
SignedRoot,
TreeHash, TreeHash,
CachedTreeHash, CachedTreeHash,
TestRandom, TestRandom,
)] )]
pub struct DepositData { pub struct DepositData {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
pub amount: u64, pub amount: u64,
pub timestamp: u64, #[signed_root(skip_hashing)]
pub deposit_input: DepositInput, 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)] #[cfg(test)]
@ -33,4 +66,22 @@ mod tests {
ssz_tests!(DepositData); ssz_tests!(DepositData);
cached_tree_hash_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));
}
} }

View File

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

View File

@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Contains data obtained from the Eth1 chain. /// Contains data obtained from the Eth1 chain.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -24,6 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
)] )]
pub struct Eth1Data { pub struct Eth1Data {
pub deposit_root: Hash256, pub deposit_root: Hash256,
pub deposit_count: u64,
pub block_hash: Hash256, pub block_hash: Hash256,
} }

View File

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

View File

@ -10,7 +10,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// ///
/// To be included in an `AttesterSlashing`. /// To be included in an `AttesterSlashing`.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -24,27 +24,28 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
TestRandom, TestRandom,
SignedRoot, SignedRoot,
)] )]
pub struct SlashableAttestation { pub struct IndexedAttestation {
/// Lists validator registry indices, not committee indices. /// Lists validator registry indices, not committee indices.
pub validator_indices: Vec<u64>, pub custody_bit_0_indices: Vec<u64>,
pub custody_bit_1_indices: Vec<u64>,
pub data: AttestationData, pub data: AttestationData,
pub custody_bitfield: Bitfield, pub custody_bitfield: Bitfield,
#[signed_root(skip_hashing)] #[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. /// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
/// ///
/// Spec v0.5.1 /// 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) 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``. /// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
/// ///
/// Spec v0.5.1 /// 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_1 = self.data.source_epoch;
let source_epoch_2 = other.data.source_epoch; let source_epoch_2 = other.data.source_epoch;
let target_epoch_1 = self.data.slot.epoch(spec.slots_per_epoch); let target_epoch_1 = self.data.slot.epoch(spec.slots_per_epoch);
@ -64,11 +65,11 @@ mod tests {
#[test] #[test]
pub fn test_is_double_vote_true() { pub fn test_is_double_vote_true() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(1, 1, &spec); let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
let slashable_vote_second = create_slashable_attestation(1, 1, &spec); let indexed_vote_second = create_indexed_attestation(1, 1, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec), indexed_vote_first.is_double_vote(&indexed_vote_second, &spec),
true true
) )
} }
@ -76,11 +77,11 @@ mod tests {
#[test] #[test]
pub fn test_is_double_vote_false() { pub fn test_is_double_vote_false() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(1, 1, &spec); let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
let slashable_vote_second = create_slashable_attestation(2, 1, &spec); let indexed_vote_second = create_indexed_attestation(2, 1, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec), indexed_vote_first.is_double_vote(&indexed_vote_second, &spec),
false false
); );
} }
@ -88,11 +89,11 @@ mod tests {
#[test] #[test]
pub fn test_is_surround_vote_true() { pub fn test_is_surround_vote_true() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(2, 1, &spec); let indexed_vote_first = create_indexed_attestation(2, 1, &spec);
let slashable_vote_second = create_slashable_attestation(1, 2, &spec); let indexed_vote_second = create_indexed_attestation(1, 2, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
true true
); );
} }
@ -100,11 +101,11 @@ mod tests {
#[test] #[test]
pub fn test_is_surround_vote_true_realistic() { pub fn test_is_surround_vote_true_realistic() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(4, 1, &spec); let indexed_vote_first = create_indexed_attestation(4, 1, &spec);
let slashable_vote_second = create_slashable_attestation(3, 2, &spec); let indexed_vote_second = create_indexed_attestation(3, 2, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
true true
); );
} }
@ -112,11 +113,11 @@ mod tests {
#[test] #[test]
pub fn test_is_surround_vote_false_source_epoch_fails() { pub fn test_is_surround_vote_false_source_epoch_fails() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(2, 2, &spec); let indexed_vote_first = create_indexed_attestation(2, 2, &spec);
let slashable_vote_second = create_slashable_attestation(1, 1, &spec); let indexed_vote_second = create_indexed_attestation(1, 1, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
false false
); );
} }
@ -124,28 +125,28 @@ mod tests {
#[test] #[test]
pub fn test_is_surround_vote_false_target_epoch_fails() { pub fn test_is_surround_vote_false_target_epoch_fails() {
let spec = ChainSpec::foundation(); let spec = ChainSpec::foundation();
let slashable_vote_first = create_slashable_attestation(1, 1, &spec); let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
let slashable_vote_second = create_slashable_attestation(2, 2, &spec); let indexed_vote_second = create_indexed_attestation(2, 2, &spec);
assert_eq!( assert_eq!(
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec), indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
false false
); );
} }
ssz_tests!(SlashableAttestation); ssz_tests!(IndexedAttestation);
cached_tree_hash_tests!(SlashableAttestation); cached_tree_hash_tests!(IndexedAttestation);
fn create_slashable_attestation( fn create_indexed_attestation(
slot_factor: u64, slot_factor: u64,
source_epoch: u64, source_epoch: u64,
spec: &ChainSpec, spec: &ChainSpec,
) -> SlashableAttestation { ) -> IndexedAttestation {
let mut rng = XorShiftRng::from_seed([42; 16]); 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); indexed_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch);
slashable_vote.data.source_epoch = Epoch::new(source_epoch); indexed_vote.data.source_epoch = Epoch::new(source_epoch);
slashable_vote indexed_vote
} }
} }

View File

@ -17,15 +17,13 @@ pub mod crosslink;
pub mod crosslink_committee; pub mod crosslink_committee;
pub mod deposit; pub mod deposit;
pub mod deposit_data; pub mod deposit_data;
pub mod deposit_input;
pub mod eth1_data; pub mod eth1_data;
pub mod eth1_data_vote;
pub mod fork; pub mod fork;
pub mod free_attestation; pub mod free_attestation;
pub mod historical_batch; pub mod historical_batch;
pub mod indexed_attestation;
pub mod pending_attestation; pub mod pending_attestation;
pub mod proposer_slashing; pub mod proposer_slashing;
pub mod slashable_attestation;
pub mod transfer; pub mod transfer;
pub mod tree_hash_vector; pub mod tree_hash_vector;
pub mod voluntary_exit; pub mod voluntary_exit;
@ -53,16 +51,14 @@ pub use crate::crosslink::Crosslink;
pub use crate::crosslink_committee::CrosslinkCommittee; pub use crate::crosslink_committee::CrosslinkCommittee;
pub use crate::deposit::Deposit; pub use crate::deposit::Deposit;
pub use crate::deposit_data::DepositData; pub use crate::deposit_data::DepositData;
pub use crate::deposit_input::DepositInput;
pub use crate::eth1_data::Eth1Data; pub use crate::eth1_data::Eth1Data;
pub use crate::eth1_data_vote::Eth1DataVote;
pub use crate::fork::Fork; pub use crate::fork::Fork;
pub use crate::free_attestation::FreeAttestation; pub use crate::free_attestation::FreeAttestation;
pub use crate::historical_batch::HistoricalBatch; pub use crate::historical_batch::HistoricalBatch;
pub use crate::indexed_attestation::IndexedAttestation;
pub use crate::pending_attestation::PendingAttestation; pub use crate::pending_attestation::PendingAttestation;
pub use crate::proposer_slashing::ProposerSlashing; pub use crate::proposer_slashing::ProposerSlashing;
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch}; 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_epoch::{Epoch, Slot};
pub use crate::slot_height::SlotHeight; pub use crate::slot_height::SlotHeight;
pub use crate::transfer::Transfer; pub use crate::transfer::Transfer;

View File

@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// An attestation that has been included in the state but not yet fully processed. /// An attestation that has been included in the state but not yet fully processed.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -24,18 +24,22 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
pub struct PendingAttestation { pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield, pub aggregation_bitfield: Bitfield,
pub data: AttestationData, pub data: AttestationData,
pub custody_bitfield: Bitfield,
pub inclusion_slot: Slot, pub inclusion_slot: Slot,
pub proposer_index: u64,
} }
impl PendingAttestation { impl PendingAttestation {
/// Create a `PendingAttestation` from an `Attestation`, at the given `inclusion_slot`. /// Create a `PendingAttestation` from an `Attestation`.
pub fn from_attestation(attestation: &Attestation, inclusion_slot: Slot) -> Self { pub fn from_attestation(
attestation: &Attestation,
inclusion_slot: Slot,
proposer_index: u64,
) -> Self {
PendingAttestation { PendingAttestation {
data: attestation.data.clone(), data: attestation.data.clone(),
aggregation_bitfield: attestation.aggregation_bitfield.clone(), aggregation_bitfield: attestation.aggregation_bitfield.clone(),
custody_bitfield: attestation.custody_bitfield.clone(),
inclusion_slot, inclusion_slot,
proposer_index,
} }
} }
} }

View File

@ -33,7 +33,7 @@ impl TestingAttestationBuilder {
aggregation_bitfield, aggregation_bitfield,
data: data_builder.build(), data: data_builder.build(),
custody_bitfield, custody_bitfield,
aggregate_signature: AggregateSignature::new(), signature: AggregateSignature::new(),
}; };
Self { Self {
@ -83,7 +83,7 @@ impl TestingAttestationBuilder {
); );
let signature = Signature::new(&message, domain, secret_keys[key_index]); let signature = Signature::new(&message, domain, secret_keys[key_index]);
self.attestation.aggregate_signature.add(&signature) self.attestation.signature.add(&signature)
} }
} }

View File

@ -49,8 +49,9 @@ impl TestingAttestationDataBuilder {
// Crosslink vote // Crosslink vote
shard, shard,
previous_crosslink: Crosslink { previous_crosslink_root: Crosslink {
epoch: slot.epoch(spec.slots_per_epoch), 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,
}, },
crosslink_data_root: spec.zero_hash, crosslink_data_root: spec.zero_hash,

View File

@ -34,8 +34,9 @@ impl TestingAttesterSlashingBuilder {
source_root: hash_1, source_root: hash_1,
target_root: hash_1, target_root: hash_1,
shard, shard,
previous_crosslink: Crosslink { previous_crosslink_root: Crosslink {
epoch, epoch,
previous_crosslink_root: hash_1,
crosslink_data_root: hash_1, crosslink_data_root: hash_1,
}, },
crosslink_data_root: hash_1, crosslink_data_root: hash_1,
@ -46,21 +47,23 @@ impl TestingAttesterSlashingBuilder {
..data_1.clone() ..data_1.clone()
}; };
let mut slashable_attestation_1 = SlashableAttestation { let mut attestation_1 = IndexedAttestation {
validator_indices: validator_indices.to_vec(), custody_bit_0_indices: validator_indices.to_vec(),
custody_bit_1_indices: vec![],
data: data_1, data: data_1,
custody_bitfield: Bitfield::new(), custody_bitfield: Bitfield::new(),
aggregate_signature: AggregateSignature::new(), signature: AggregateSignature::new(),
}; };
let mut slashable_attestation_2 = SlashableAttestation { let mut attestation_2 = IndexedAttestation {
validator_indices: validator_indices.to_vec(), custody_bit_0_indices: validator_indices.to_vec(),
custody_bit_1_indices: vec![],
data: data_2, data: data_2,
custody_bitfield: Bitfield::new(), 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. // All validators sign with a `false` custody bit.
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit { let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
data: attestation.data.clone(), data: attestation.data.clone(),
@ -71,16 +74,16 @@ impl TestingAttesterSlashingBuilder {
for (i, validator_index) in validator_indices.iter().enumerate() { for (i, validator_index) in validator_indices.iter().enumerate() {
attestation.custody_bitfield.set(i, false); attestation.custody_bitfield.set(i, false);
let signature = signer(*validator_index, &message[..], epoch, Domain::Attestation); 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 attestation_1);
add_signatures(&mut slashable_attestation_2); add_signatures(&mut attestation_2);
AttesterSlashing { AttesterSlashing {
slashable_attestation_1, attestation_1,
slashable_attestation_2, attestation_2,
} }
} }
} }

View File

@ -95,6 +95,7 @@ impl TestingBeaconStateBuilder {
/// Creates the builder from an existing set of keypairs. /// Creates the builder from an existing set of keypairs.
pub fn from_keypairs(keypairs: Vec<Keypair>, spec: &ChainSpec) -> Self { pub fn from_keypairs(keypairs: Vec<Keypair>, spec: &ChainSpec) -> Self {
let validator_count = keypairs.len(); let validator_count = keypairs.len();
let starting_balance = 32_000_000_000;
debug!( debug!(
"Building {} Validator objects from keypairs...", "Building {} Validator objects from keypairs...",
@ -112,11 +113,12 @@ impl TestingBeaconStateBuilder {
pubkey: keypair.pk.clone(), pubkey: keypair.pk.clone(),
withdrawal_credentials, withdrawal_credentials,
// All validators start active. // All validators start active.
activation_eligibility_epoch: spec.genesis_epoch,
activation_epoch: spec.genesis_epoch, activation_epoch: spec.genesis_epoch,
exit_epoch: spec.far_future_epoch, exit_epoch: spec.far_future_epoch,
withdrawable_epoch: spec.far_future_epoch, withdrawable_epoch: spec.far_future_epoch,
initiated_exit: false,
slashed: false, slashed: false,
effective_balance: starting_balance,
} }
}) })
.collect(); .collect();
@ -137,16 +139,17 @@ impl TestingBeaconStateBuilder {
genesis_time, genesis_time,
Eth1Data { Eth1Data {
deposit_root: Hash256::zero(), deposit_root: Hash256::zero(),
deposit_count: 0,
block_hash: Hash256::zero(), block_hash: Hash256::zero(),
}, },
spec, spec,
); );
let balances = vec![32_000_000_000; validator_count]; let balances = vec![starting_balance; validator_count];
debug!("Importing {} existing validators...", validator_count); debug!("Importing {} existing validators...", validator_count);
state.validator_registry = validators; state.validator_registry = validators;
state.validator_balances = balances; state.balances = balances;
debug!("BeaconState initialized."); debug!("BeaconState initialized.");
@ -192,18 +195,13 @@ impl TestingBeaconStateBuilder {
state.slot = slot; state.slot = slot;
state.previous_shuffling_epoch = epoch - 1; // FIXME(sproul): update latest_start_shard?
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);
state.previous_justified_epoch = epoch - 3; state.previous_justified_epoch = epoch - 3;
state.current_justified_epoch = epoch - 2; state.current_justified_epoch = epoch - 2;
state.justification_bitfield = u64::max_value(); state.justification_bitfield = u64::max_value();
state.finalized_epoch = epoch - 3; 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 /// Creates a full set of attestations for the `BeaconState`. Each attestation has full

View File

@ -14,14 +14,11 @@ impl TestingDepositBuilder {
let deposit = Deposit { let deposit = Deposit {
proof: vec![].into(), proof: vec![].into(),
index: 0, index: 0,
deposit_data: DepositData { data: DepositData {
amount,
timestamp: 1,
deposit_input: DepositInput {
pubkey, pubkey,
withdrawal_credentials: Hash256::zero(), withdrawal_credentials: Hash256::zero(),
proof_of_possession: Signature::empty_signature(), amount,
}, signature: Signature::empty_signature(),
}, },
}; };
@ -43,17 +40,13 @@ impl TestingDepositBuilder {
&get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..], &get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..],
); );
self.deposit.deposit_data.deposit_input.pubkey = keypair.pk.clone(); self.deposit.data.pubkey = keypair.pk.clone();
self.deposit self.deposit.data.withdrawal_credentials = withdrawal_credentials;
.deposit_data
.deposit_input
.withdrawal_credentials = withdrawal_credentials;
self.deposit.deposit_data.deposit_input.proof_of_possession = self self.deposit.data.signature =
.deposit self.deposit
.deposit_data .data
.deposit_input .create_signature(&keypair.sk, epoch, fork, spec);
.create_proof_of_possession(&keypair.sk, epoch, fork, spec);
} }
/// Builds the deposit, consuming the builder. /// Builds the deposit, consuming the builder.

View File

@ -22,8 +22,9 @@ impl TestingPendingAttestationBuilder {
let pending_attestation = PendingAttestation { let pending_attestation = PendingAttestation {
aggregation_bitfield: Bitfield::new(), aggregation_bitfield: Bitfield::new(),
data: data_builder.build(), data: data_builder.build(),
custody_bitfield: Bitfield::new(),
inclusion_slot: slot + spec.min_attestation_inclusion_delay, inclusion_slot: slot + spec.min_attestation_inclusion_delay,
// FIXME(sproul)
proposer_index: 0,
}; };
Self { Self {
@ -37,15 +38,12 @@ impl TestingPendingAttestationBuilder {
/// `signers` is true. /// `signers` is true.
pub fn add_committee_participation(&mut self, signers: Vec<bool>) { pub fn add_committee_participation(&mut self, signers: Vec<bool>) {
let mut aggregation_bitfield = Bitfield::new(); let mut aggregation_bitfield = Bitfield::new();
let mut custody_bitfield = Bitfield::new();
for (i, signed) in signers.iter().enumerate() { for (i, signed) in signers.iter().enumerate() {
aggregation_bitfield.set(i, *signed); 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.aggregation_bitfield = aggregation_bitfield;
self.pending_attestation.custody_bitfield = custody_bitfield;
} }
/// Returns the `PendingAttestation`, consuming the builder. /// Returns the `PendingAttestation`, consuming the builder.

View File

@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Information about a `BeaconChain` validator. /// Information about a `BeaconChain` validator.
/// ///
/// Spec v0.5.1 /// Spec v0.6.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -23,11 +23,12 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
pub struct Validator { pub struct Validator {
pub pubkey: PublicKey, pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256, pub withdrawal_credentials: Hash256,
pub activation_eligibility_epoch: Epoch,
pub activation_epoch: Epoch, pub activation_epoch: Epoch,
pub exit_epoch: Epoch, pub exit_epoch: Epoch,
pub withdrawable_epoch: Epoch, pub withdrawable_epoch: Epoch,
pub initiated_exit: bool,
pub slashed: bool, pub slashed: bool,
pub effective_balance: u64,
} }
impl Validator { impl Validator {
@ -53,11 +54,12 @@ impl Default for Validator {
Self { Self {
pubkey: PublicKey::default(), pubkey: PublicKey::default(),
withdrawal_credentials: Hash256::default(), withdrawal_credentials: Hash256::default(),
activation_eligibility_epoch: Epoch::from(std::u64::MAX),
activation_epoch: Epoch::from(std::u64::MAX), activation_epoch: Epoch::from(std::u64::MAX),
exit_epoch: Epoch::from(std::u64::MAX), exit_epoch: Epoch::from(std::u64::MAX),
withdrawable_epoch: Epoch::from(std::u64::MAX), withdrawable_epoch: Epoch::from(std::u64::MAX),
initiated_exit: false,
slashed: false, slashed: false,
effective_balance: std::u64::MAX,
} }
} }
} }