Update to spec v0.9.0

This commit is contained in:
Michael Sproul
2019-11-11 15:00:10 +11:00
parent 613fdbeda6
commit aaa5f2042f
93 changed files with 651 additions and 2203 deletions

View File

@@ -35,16 +35,14 @@ impl<'a, T: EthSpec> MaxCover for AttMaxCover<'a, T> {
/// Sneaky: we keep all the attestations together in one bucket, even though
/// their aggregation bitfields refer to different committees. In order to avoid
/// confusing committees when updating covering sets, we update only those attestations
/// whose shard and epoch match the attestation being included in the solution, by the logic
/// that a shard and epoch uniquely identify a committee.
/// whose slot and index match the attestation being included in the solution, by the logic
/// that a slot and index uniquely identify a committee.
fn update_covering_set(
&mut self,
best_att: &Attestation<T>,
covered_validators: &BitList<T::MaxValidatorsPerCommittee>,
) {
if self.att.data.crosslink.shard == best_att.data.crosslink.shard
&& self.att.data.target.epoch == best_att.data.target.epoch
{
if self.att.data.slot == best_att.data.slot && self.att.data.index == best_att.data.index {
self.fresh_validators.difference_inplace(covered_validators);
}
}
@@ -80,11 +78,12 @@ pub fn earliest_attestation_validators<T: EthSpec>(
state_attestations
.iter()
// In a single epoch, an attester should only be attesting for one shard.
// In a single epoch, an attester should only be attesting for one slot and index.
// TODO: we avoid including slashable attestations in the state here,
// but maybe we should do something else with them (like construct slashings).
.filter(|existing_attestation| {
existing_attestation.data.crosslink.shard == attestation.data.crosslink.shard
existing_attestation.data.slot == attestation.data.slot
&& existing_attestation.data.index == attestation.data.index
})
.for_each(|existing_attestation| {
// Remove the validators who have signed the existing attestation (they are not new)

View File

@@ -29,7 +29,7 @@ impl AttestationId {
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Vec<u8> {
int_to_bytes8(spec.get_domain(epoch, Domain::Attestation, &state.fork))
int_to_bytes8(spec.get_domain(epoch, Domain::BeaconAttester, &state.fork))
}
pub fn domain_bytes_match(&self, domain_bytes: &[u8]) -> bool {

View File

@@ -7,24 +7,22 @@ pub use persistence::PersistedOperationPool;
use attestation::{earliest_attestation_validators, AttMaxCover};
use attestation_id::AttestationId;
use itertools::Itertools;
use max_cover::maximum_cover;
use parking_lot::RwLock;
use state_processing::per_block_processing::errors::{
AttestationValidationError, AttesterSlashingValidationError, DepositValidationError,
ExitValidationError, ProposerSlashingValidationError, TransferValidationError,
ExitValidationError, ProposerSlashingValidationError,
};
use state_processing::per_block_processing::{
get_slashable_indices_modular, verify_attestation_for_block_inclusion,
verify_attester_slashing, verify_exit, verify_exit_time_independent_only,
verify_proposer_slashing, verify_transfer, verify_transfer_time_independent_only,
VerifySignatures,
verify_proposer_slashing, VerifySignatures,
};
use std::collections::{btree_map::Entry, hash_map, BTreeMap, HashMap, HashSet};
use std::marker::PhantomData;
use types::{
typenum::Unsigned, Attestation, AttesterSlashing, BeaconState, ChainSpec, Deposit, EthSpec,
ProposerSlashing, Transfer, Validator, VoluntaryExit,
ProposerSlashing, Validator, VoluntaryExit,
};
#[derive(Default, Debug)]
@@ -43,8 +41,6 @@ pub struct OperationPool<T: EthSpec + Default> {
proposer_slashings: RwLock<HashMap<u64, ProposerSlashing>>,
/// Map from exiting validator to their exit data.
voluntary_exits: RwLock<HashMap<u64, VoluntaryExit>>,
/// Set of transfers.
transfers: RwLock<HashSet<Transfer>>,
_phantom: PhantomData<T>,
}
@@ -375,44 +371,6 @@ impl<T: EthSpec> OperationPool<T> {
);
}
/// Insert a transfer into the pool, checking it for validity in the process.
pub fn insert_transfer(
&self,
transfer: Transfer,
state: &BeaconState<T>,
spec: &ChainSpec,
) -> Result<(), TransferValidationError> {
// The signature of the transfer isn't hashed, but because we check
// it before we insert into the HashSet, we can't end up with duplicate
// transactions.
verify_transfer_time_independent_only(state, &transfer, VerifySignatures::True, spec)?;
self.transfers.write().insert(transfer);
Ok(())
}
/// Get a list of transfers for inclusion in a block.
// TODO: improve the economic optimality of this function by accounting for
// dependencies between transfers in the same block e.g. A pays B, B pays C
pub fn get_transfers(&self, state: &BeaconState<T>, spec: &ChainSpec) -> Vec<Transfer> {
self.transfers
.read()
.iter()
.filter(|transfer| {
verify_transfer(state, transfer, VerifySignatures::False, spec).is_ok()
})
.sorted_by_key(|transfer| std::cmp::Reverse(transfer.fee))
.take(T::MaxTransfers::to_usize())
.cloned()
.collect()
}
/// Prune the set of transfers by removing all those whose slot has already passed.
pub fn prune_transfers(&self, finalized_state: &BeaconState<T>) {
self.transfers
.write()
.retain(|transfer| transfer.slot > finalized_state.slot)
}
/// Prune all types of transactions given the latest finalized state.
pub fn prune_all(&self, finalized_state: &BeaconState<T>, spec: &ChainSpec) {
self.prune_attestations(finalized_state);
@@ -420,7 +378,6 @@ impl<T: EthSpec> OperationPool<T> {
self.prune_proposer_slashings(finalized_state);
self.prune_attester_slashings(finalized_state, spec);
self.prune_voluntary_exits(finalized_state);
self.prune_transfers(finalized_state);
}
}
@@ -467,7 +424,6 @@ impl<T: EthSpec + Default> PartialEq for OperationPool<T> {
&& *self.attester_slashings.read() == *other.attester_slashings.read()
&& *self.proposer_slashings.read() == *other.proposer_slashings.read()
&& *self.voluntary_exits.read() == *other.voluntary_exits.read()
&& *self.transfers.read() == *other.transfers.read()
}
}
@@ -611,7 +567,7 @@ mod tests {
/// Signed by all validators in `committee[signing_range]` and `committee[extra_signer]`.
fn signed_attestation<R: std::slice::SliceIndex<[usize], Output = [usize]>, E: EthSpec>(
committee: &[usize],
shard: u64,
index: u64,
keypairs: &[Keypair],
signing_range: R,
slot: Slot,
@@ -619,7 +575,7 @@ mod tests {
spec: &ChainSpec,
extra_signer: Option<usize>,
) -> Attestation<E> {
let mut builder = TestingAttestationBuilder::new(state, committee, slot, shard, spec);
let mut builder = TestingAttestationBuilder::new(state, committee, slot, index);
let signers = &committee[signing_range];
let committee_keys = signers.iter().map(|&i| &keypairs[i].sk).collect::<Vec<_>>();
builder.sign(signers, &committee_keys, &state.fork, spec, false);
@@ -662,16 +618,16 @@ mod tests {
attestation_test_state::<MainnetEthSpec>(1);
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot)
.get_beacon_committees_at_slot(slot)
.unwrap()
.into_iter()
.map(CrosslinkCommittee::into_owned)
.map(BeaconCommittee::into_owned)
.collect::<Vec<_>>();
for cc in committees {
for bc in committees {
let att1 = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
..2,
slot,
@@ -680,8 +636,8 @@ mod tests {
None,
);
let att2 = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
..,
slot,
@@ -705,7 +661,7 @@ mod tests {
.unwrap();
assert_eq!(
cc.committee.len() - 2,
bc.committee.len() - 2,
earliest_attestation_validators(&att2, state).num_set_bits()
);
}
@@ -721,10 +677,10 @@ mod tests {
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot)
.get_beacon_committees_at_slot(slot)
.unwrap()
.into_iter()
.map(CrosslinkCommittee::into_owned)
.map(BeaconCommittee::into_owned)
.collect::<Vec<_>>();
assert_eq!(
@@ -733,12 +689,12 @@ mod tests {
"we expect just one committee with this many validators"
);
for cc in &committees {
for bc in &committees {
let step_size = 2;
for i in (0..cc.committee.len()).step_by(step_size) {
for i in (0..bc.committee.len()).step_by(step_size) {
let att = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
i..i + step_size,
slot,
@@ -790,16 +746,16 @@ mod tests {
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot)
.get_beacon_committees_at_slot(slot)
.unwrap()
.into_iter()
.map(CrosslinkCommittee::into_owned)
.map(BeaconCommittee::into_owned)
.collect::<Vec<_>>();
for cc in &committees {
for bc in &committees {
let att = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
..,
slot,
@@ -827,20 +783,20 @@ mod tests {
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot)
.get_beacon_committees_at_slot(slot)
.unwrap()
.into_iter()
.map(CrosslinkCommittee::into_owned)
.map(BeaconCommittee::into_owned)
.collect::<Vec<_>>();
let step_size = 2;
for cc in &committees {
for bc in &committees {
// Create attestations that overlap on `step_size` validators, like:
// {0,1,2,3}, {2,3,4,5}, {4,5,6,7}, ...
for i in (0..cc.committee.len() - step_size).step_by(step_size) {
for i in (0..bc.committee.len() - step_size).step_by(step_size) {
let att = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
i..i + 2 * step_size,
slot,
@@ -875,20 +831,20 @@ mod tests {
let slot = state.slot - 1;
let committees = state
.get_crosslink_committees_at_slot(slot)
.get_beacon_committees_at_slot(slot)
.unwrap()
.into_iter()
.map(CrosslinkCommittee::into_owned)
.map(BeaconCommittee::into_owned)
.collect::<Vec<_>>();
let max_attestations = <MainnetEthSpec as EthSpec>::MaxAttestations::to_usize();
let target_committee_size = spec.target_committee_size as usize;
let insert_attestations = |cc: &OwnedCrosslinkCommittee, step_size| {
let insert_attestations = |bc: &OwnedBeaconCommittee, step_size| {
for i in (0..target_committee_size).step_by(step_size) {
let att = signed_attestation(
&cc.committee,
cc.shard,
&bc.committee,
bc.index,
keypairs,
i..i + step_size,
slot,

View File

@@ -21,8 +21,6 @@ pub struct PersistedOperationPool<T: EthSpec> {
proposer_slashings: Vec<ProposerSlashing>,
/// Voluntary exits.
voluntary_exits: Vec<VoluntaryExit>,
/// Transfers.
transfers: Vec<Transfer>,
}
impl<T: EthSpec> PersistedOperationPool<T> {
@@ -63,15 +61,12 @@ impl<T: EthSpec> PersistedOperationPool<T> {
.map(|(_, exit)| exit.clone())
.collect();
let transfers = operation_pool.transfers.read().iter().cloned().collect();
Self {
attestations,
deposits,
attester_slashings,
proposer_slashings,
voluntary_exits,
transfers,
}
}
@@ -102,7 +97,6 @@ impl<T: EthSpec> PersistedOperationPool<T> {
.map(|exit| (exit.validator_index, exit))
.collect(),
);
let transfers = RwLock::new(self.transfers.into_iter().collect());
OperationPool {
attestations,
@@ -110,7 +104,6 @@ impl<T: EthSpec> PersistedOperationPool<T> {
attester_slashings,
proposer_slashings,
voluntary_exits,
transfers,
_phantom: Default::default(),
}
}