Update "attestation" family of structs in types

Also adds/splits up some testing builders.
This commit is contained in:
Paul Hauner 2019-03-15 15:19:17 +11:00
parent 8050ed7a26
commit 20a439101e
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
9 changed files with 175 additions and 145 deletions

View File

@ -8,7 +8,7 @@ use test_random_derive::TestRandom;
/// The data upon which an attestation is based. /// The data upon which an attestation is based.
/// ///
/// Spec v0.4.0 /// Spec v0.5.0
#[derive( #[derive(
Debug, Debug,
Clone, Clone,
@ -24,14 +24,19 @@ use test_random_derive::TestRandom;
SignedRoot, SignedRoot,
)] )]
pub struct AttestationData { pub struct AttestationData {
// LMD GHOST vote
pub slot: Slot, pub slot: Slot,
pub shard: u64,
pub beacon_block_root: Hash256, pub beacon_block_root: Hash256,
pub epoch_boundary_root: Hash256,
// FFG Vote
pub source_epoch: Epoch,
pub source_root: Hash256,
pub target_root: Hash256,
// Crosslink Vote
pub shard: u64,
pub previous_crosslink: Crosslink,
pub crosslink_data_root: Hash256, pub crosslink_data_root: Hash256,
pub latest_crosslink: Crosslink,
pub justified_epoch: Epoch,
pub justified_block_root: Hash256,
} }
impl Eq for AttestationData {} impl Eq for AttestationData {}

View File

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

View File

@ -9,7 +9,7 @@ use test_random_derive::TestRandom;
/// ///
/// To be included in an `AttesterSlashing`. /// To be included in an `AttesterSlashing`.
/// ///
/// Spec v0.4.0 /// Spec v0.5.0
#[derive( #[derive(
Debug, Debug,
PartialEq, PartialEq,
@ -33,17 +33,17 @@ pub struct SlashableAttestation {
impl SlashableAttestation { impl SlashableAttestation {
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target. /// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
/// ///
/// Spec v0.4.0 /// Spec v0.5.0
pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
self.data.slot.epoch(spec.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.4.0 /// Spec v0.5.0
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool { pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
let source_epoch_1 = self.data.justified_epoch; let source_epoch_1 = self.data.source_epoch;
let source_epoch_2 = other.data.justified_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);
let target_epoch_2 = other.data.slot.epoch(spec.slots_per_epoch); let target_epoch_2 = other.data.slot.epoch(spec.slots_per_epoch);
@ -134,14 +134,14 @@ mod tests {
fn create_slashable_attestation( fn create_slashable_attestation(
slot_factor: u64, slot_factor: u64,
justified_epoch: u64, source_epoch: u64,
spec: &ChainSpec, spec: &ChainSpec,
) -> SlashableAttestation { ) -> SlashableAttestation {
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 slashable_vote = SlashableAttestation::random_for_test(&mut rng);
slashable_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch); slashable_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch);
slashable_vote.data.justified_epoch = Epoch::new(justified_epoch); slashable_vote.data.source_epoch = Epoch::new(source_epoch);
slashable_vote slashable_vote
} }
} }

View File

@ -4,10 +4,12 @@ mod generate_deterministic_keypairs;
mod keypairs_file; mod keypairs_file;
mod test_random; mod test_random;
mod testing_attestation_builder; mod testing_attestation_builder;
mod testing_attestation_data_builder;
mod testing_attester_slashing_builder; mod testing_attester_slashing_builder;
mod testing_beacon_block_builder; mod testing_beacon_block_builder;
mod testing_beacon_state_builder; mod testing_beacon_state_builder;
mod testing_deposit_builder; mod testing_deposit_builder;
mod testing_pending_attestation_builder;
mod testing_proposer_slashing_builder; mod testing_proposer_slashing_builder;
mod testing_transfer_builder; mod testing_transfer_builder;
mod testing_voluntary_exit_builder; mod testing_voluntary_exit_builder;
@ -17,10 +19,12 @@ pub use keypairs_file::KeypairsFile;
pub use rand::{prng::XorShiftRng, SeedableRng}; pub use rand::{prng::XorShiftRng, SeedableRng};
pub use test_random::TestRandom; pub use test_random::TestRandom;
pub use testing_attestation_builder::TestingAttestationBuilder; pub use testing_attestation_builder::TestingAttestationBuilder;
pub use testing_attestation_data_builder::TestingAttestationDataBuilder;
pub use testing_attester_slashing_builder::TestingAttesterSlashingBuilder; pub use testing_attester_slashing_builder::TestingAttesterSlashingBuilder;
pub use testing_beacon_block_builder::TestingBeaconBlockBuilder; pub use testing_beacon_block_builder::TestingBeaconBlockBuilder;
pub use testing_beacon_state_builder::{keypairs_path, TestingBeaconStateBuilder}; pub use testing_beacon_state_builder::{keypairs_path, TestingBeaconStateBuilder};
pub use testing_deposit_builder::TestingDepositBuilder; pub use testing_deposit_builder::TestingDepositBuilder;
pub use testing_pending_attestation_builder::TestingPendingAttestationBuilder;
pub use testing_proposer_slashing_builder::TestingProposerSlashingBuilder; pub use testing_proposer_slashing_builder::TestingProposerSlashingBuilder;
pub use testing_transfer_builder::TestingTransferBuilder; pub use testing_transfer_builder::TestingTransferBuilder;
pub use testing_voluntary_exit_builder::TestingVoluntaryExitBuilder; pub use testing_voluntary_exit_builder::TestingVoluntaryExitBuilder;

View File

@ -1,3 +1,4 @@
use crate::test_utils::TestingAttestationDataBuilder;
use crate::*; use crate::*;
use ssz::TreeHash; use ssz::TreeHash;
@ -18,31 +19,7 @@ impl TestingAttestationBuilder {
shard: u64, shard: u64,
spec: &ChainSpec, spec: &ChainSpec,
) -> Self { ) -> Self {
let current_epoch = state.current_epoch(spec); let data_builder = TestingAttestationDataBuilder::new(state, shard, slot, spec);
let previous_epoch = state.previous_epoch(spec);
let is_previous_epoch =
state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch);
let justified_epoch = if is_previous_epoch {
state.previous_justified_epoch
} else {
state.justified_epoch
};
let epoch_boundary_root = if is_previous_epoch {
*state
.get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
} else {
*state
.get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
};
let justified_block_root = *state
.get_block_root(justified_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap();
let mut aggregation_bitfield = Bitfield::new(); let mut aggregation_bitfield = Bitfield::new();
let mut custody_bitfield = Bitfield::new(); let mut custody_bitfield = Bitfield::new();
@ -54,16 +31,7 @@ impl TestingAttestationBuilder {
let attestation = Attestation { let attestation = Attestation {
aggregation_bitfield, aggregation_bitfield,
data: AttestationData { data: data_builder.build(),
slot,
shard,
beacon_block_root: *state.get_block_root(slot, spec).unwrap(),
epoch_boundary_root,
crosslink_data_root: Hash256::zero(),
latest_crosslink: state.latest_crosslinks[shard as usize].clone(),
justified_epoch,
justified_block_root,
},
custody_bitfield, custody_bitfield,
aggregate_signature: AggregateSignature::new(), aggregate_signature: AggregateSignature::new(),
}; };

View File

@ -0,0 +1,66 @@
use crate::*;
/// Builds an `AttestationData` to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingAttestationDataBuilder {
data: AttestationData,
}
impl TestingAttestationDataBuilder {
/// Configures a new `AttestationData` which attests to all of the same parameters as the
/// state.
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
let current_epoch = state.current_epoch(spec);
let previous_epoch = state.previous_epoch(spec);
let is_previous_epoch =
state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch);
let source_epoch = if is_previous_epoch {
state.previous_justified_epoch
} else {
state.justified_epoch
};
let target_root = if is_previous_epoch {
*state
.get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
} else {
*state
.get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
};
let source_root = *state
.get_block_root(source_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap();
let data = AttestationData {
// LMD GHOST vote
slot,
beacon_block_root: *state.get_block_root(slot, spec).unwrap(),
// FFG Vote
source_epoch,
source_root,
target_root,
// Crosslink vote
shard,
previous_crosslink: Crosslink {
epoch: slot.epoch(spec.slots_per_epoch),
crosslink_data_root: spec.zero_hash,
},
crosslink_data_root: spec.zero_hash,
};
Self { data }
}
/// Returns the `AttestationData`, consuming the builder.
pub fn build(self) -> AttestationData {
self.data
}
}

View File

@ -23,45 +23,39 @@ impl TestingAttesterSlashingBuilder {
{ {
let double_voted_slot = Slot::new(0); let double_voted_slot = Slot::new(0);
let shard = 0; let shard = 0;
let justified_epoch = Epoch::new(0);
let epoch = Epoch::new(0); let epoch = Epoch::new(0);
let hash_1 = Hash256::from_low_u64_le(1); let hash_1 = Hash256::from_low_u64_le(1);
let hash_2 = Hash256::from_low_u64_le(2); let hash_2 = Hash256::from_low_u64_le(2);
let data_1 = AttestationData {
slot: double_voted_slot,
beacon_block_root: hash_1,
source_epoch: epoch,
source_root: hash_1,
target_root: hash_1,
shard,
previous_crosslink: Crosslink {
epoch,
crosslink_data_root: hash_1,
},
crosslink_data_root: hash_1,
};
let data_2 = AttestationData {
beacon_block_root: hash_2,
..data_1.clone()
};
let mut slashable_attestation_1 = SlashableAttestation { let mut slashable_attestation_1 = SlashableAttestation {
validator_indices: validator_indices.to_vec(), validator_indices: validator_indices.to_vec(),
data: AttestationData { data: data_1,
slot: double_voted_slot,
shard,
beacon_block_root: hash_1,
epoch_boundary_root: hash_1,
crosslink_data_root: hash_1,
latest_crosslink: Crosslink {
epoch,
crosslink_data_root: hash_1,
},
justified_epoch,
justified_block_root: hash_1,
},
custody_bitfield: Bitfield::new(), custody_bitfield: Bitfield::new(),
aggregate_signature: AggregateSignature::new(), aggregate_signature: AggregateSignature::new(),
}; };
let mut slashable_attestation_2 = SlashableAttestation { let mut slashable_attestation_2 = SlashableAttestation {
validator_indices: validator_indices.to_vec(), validator_indices: validator_indices.to_vec(),
data: AttestationData { data: data_2,
slot: double_voted_slot,
shard,
beacon_block_root: hash_2,
epoch_boundary_root: hash_2,
crosslink_data_root: hash_2,
latest_crosslink: Crosslink {
epoch,
crosslink_data_root: hash_2,
},
justified_epoch,
justified_block_root: hash_2,
},
custody_bitfield: Bitfield::new(), custody_bitfield: Bitfield::new(),
aggregate_signature: AggregateSignature::new(), aggregate_signature: AggregateSignature::new(),
}; };

View File

@ -1,5 +1,6 @@
use super::{generate_deterministic_keypairs, KeypairsFile}; use super::{generate_deterministic_keypairs, KeypairsFile};
use crate::beacon_state::BeaconStateBuilder; use crate::beacon_state::BeaconStateBuilder;
use crate::test_utils::TestingPendingAttestationBuilder;
use crate::*; use crate::*;
use bls::get_withdrawal_credentials; use bls::get_withdrawal_credentials;
use dirs; use dirs;
@ -227,76 +228,13 @@ impl TestingBeaconStateBuilder {
.clone(); .clone();
for (committee, shard) in committees { for (committee, shard) in committees {
state let mut builder = TestingPendingAttestationBuilder::new(state, shard, slot, spec);
.latest_attestations // The entire committee should have signed the pending attestation.
.push(committee_to_pending_attestation( let signers = vec![true; committee.len()];
state, &committee, shard, slot, spec, builder.add_committee_participation(signers);
))
state.latest_attestations.push(builder.build())
} }
} }
} }
} }
/// Maps a committee to a `PendingAttestation`.
///
/// The committee will be signed by all validators in the committee.
fn committee_to_pending_attestation(
state: &BeaconState,
committee: &[usize],
shard: u64,
slot: Slot,
spec: &ChainSpec,
) -> PendingAttestation {
let current_epoch = state.current_epoch(spec);
let previous_epoch = state.previous_epoch(spec);
let mut aggregation_bitfield = Bitfield::new();
let mut custody_bitfield = Bitfield::new();
for (i, _) in committee.iter().enumerate() {
aggregation_bitfield.set(i, true);
custody_bitfield.set(i, true);
}
let is_previous_epoch =
state.slot.epoch(spec.slots_per_epoch) != slot.epoch(spec.slots_per_epoch);
let justified_epoch = if is_previous_epoch {
state.previous_justified_epoch
} else {
state.justified_epoch
};
let epoch_boundary_root = if is_previous_epoch {
*state
.get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
} else {
*state
.get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap()
};
let justified_block_root = *state
.get_block_root(justified_epoch.start_slot(spec.slots_per_epoch), spec)
.unwrap();
PendingAttestation {
aggregation_bitfield,
data: AttestationData {
slot,
shard,
beacon_block_root: *state.get_block_root(slot, spec).unwrap(),
epoch_boundary_root,
crosslink_data_root: Hash256::zero(),
latest_crosslink: Crosslink {
epoch: slot.epoch(spec.slots_per_epoch),
crosslink_data_root: Hash256::zero(),
},
justified_epoch,
justified_block_root,
},
custody_bitfield,
inclusion_slot: slot + spec.min_attestation_inclusion_delay,
}
}

View File

@ -0,0 +1,55 @@
use crate::test_utils::TestingAttestationDataBuilder;
use crate::*;
/// Builds an `AttesterSlashing` to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingPendingAttestationBuilder {
pending_attestation: PendingAttestation,
}
impl TestingPendingAttestationBuilder {
/// Create a new valid* `PendingAttestation` for the given parameters.
///
/// The `inclusion_slot` will be set to be the earliest possible slot the `Attestation` could
/// have been included (`slot + MIN_ATTESTATION_INCLUSION_DELAY`).
///
/// * The aggregation and custody bitfields will all be empty, they need to be set with
/// `Self::add_committee_participation`.
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
let data_builder = TestingAttestationDataBuilder::new(state, shard, slot, spec);
let pending_attestation = PendingAttestation {
aggregation_bitfield: Bitfield::new(),
data: data_builder.build(),
custody_bitfield: Bitfield::new(),
inclusion_slot: slot + spec.min_attestation_inclusion_delay,
};
Self {
pending_attestation,
}
}
/// Sets the committee participation in the `PendingAttestation`.
///
/// The `PendingAttestation` will appear to be signed by each committee member who's value in
/// `signers` is true.
pub fn add_committee_participation(&mut self, signers: Vec<bool>) {
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.
pub fn build(self) -> PendingAttestation {
self.pending_attestation
}
}