Update to spec v0.9.1 (#597)

* Update to spec v0.9.0

* Update to v0.9.1

* Bump spec tags for v0.9.1

* Formatting, fix CI failures

* Resolve accidental KeyPair merge conflict

* Document new BeaconState functions

* Fix incorrect cache drops in `advance_caches`

* Update fork choice for v0.9.1

* Clean up some FIXMEs

* Fix a few docs/logs
This commit is contained in:
Michael Sproul
2019-11-21 11:47:30 +11:00
committed by GitHub
parent b7a0feb725
commit 24e941d175
105 changed files with 1211 additions and 2940 deletions

View File

@@ -3,19 +3,13 @@ use types::*;
/// Returns validator indices which participated in the attestation, sorted by increasing index.
///
/// Spec v0.8.1
/// Spec v0.9.1
pub fn get_attesting_indices<T: EthSpec>(
state: &BeaconState<T>,
attestation_data: &AttestationData,
bitlist: &BitList<T::MaxValidatorsPerCommittee>,
) -> Result<BTreeSet<usize>, BeaconStateError> {
let target_relative_epoch =
RelativeEpoch::from_epoch(state.current_epoch(), attestation_data.target.epoch)?;
let committee = state.get_crosslink_committee_for_shard(
attestation_data.crosslink.shard,
target_relative_epoch,
)?;
let committee = state.get_beacon_committee(attestation_data.slot, attestation_data.index)?;
if bitlist.len() != committee.committee.len() {
return Err(BeaconStateError::InvalidBitfield);

View File

@@ -1,41 +0,0 @@
use tree_hash::TreeHash;
use types::*;
/// Return the compact committee root at `relative_epoch`.
///
/// Spec v0.8.3
pub fn get_compact_committees_root<T: EthSpec>(
state: &BeaconState<T>,
relative_epoch: RelativeEpoch,
spec: &ChainSpec,
) -> Result<Hash256, BeaconStateError> {
let mut committees =
FixedVector::<_, T::ShardCount>::from_elem(CompactCommittee::<T>::default());
let start_shard = state.get_epoch_start_shard(relative_epoch)?;
for committee_number in 0..state.get_committee_count(relative_epoch)? {
let shard = (start_shard + committee_number) % T::ShardCount::to_u64();
for &index in state
.get_crosslink_committee_for_shard(shard, relative_epoch)?
.committee
{
let validator = state
.validators
.get(index)
.ok_or(BeaconStateError::UnknownValidator)?;
committees[shard as usize]
.pubkeys
.push(validator.pubkey.clone())?;
let compact_balance = validator.effective_balance / spec.effective_balance_increment;
// `index` (top 6 bytes) + `slashed` (16th bit) + `compact_balance` (bottom 15 bits)
let compact_validator: u64 =
((index as u64) << 16) + (u64::from(validator.slashed) << 15) + compact_balance;
committees[shard as usize]
.compact_validators
.push(compact_validator)?;
}
}
Ok(Hash256::from_slice(&committees.tree_hash_root()))
}

View File

@@ -6,139 +6,19 @@ type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
/// Convert `attestation` to (almost) indexed-verifiable form.
///
/// Spec v0.8.0
/// Spec v0.9.1
pub fn get_indexed_attestation<T: EthSpec>(
state: &BeaconState<T>,
attestation: &Attestation<T>,
) -> Result<IndexedAttestation<T>> {
// Note: we rely on both calls to `get_attesting_indices` to check the bitfield lengths
// against the committee length
let attesting_indices =
get_attesting_indices(state, &attestation.data, &attestation.aggregation_bits)?;
let custody_bit_1_indices =
get_attesting_indices(state, &attestation.data, &attestation.custody_bits)?;
verify!(
custody_bit_1_indices.is_subset(&attesting_indices),
Invalid::CustodyBitfieldNotSubset
);
let custody_bit_0_indices = &attesting_indices - &custody_bit_1_indices;
Ok(IndexedAttestation {
custody_bit_0_indices: VariableList::new(
custody_bit_0_indices
.into_iter()
.map(|x| x as u64)
.collect(),
)?,
custody_bit_1_indices: VariableList::new(
custody_bit_1_indices
.into_iter()
.map(|x| x as u64)
.collect(),
attesting_indices: VariableList::new(
attesting_indices.into_iter().map(|x| x as u64).collect(),
)?,
data: attestation.data.clone(),
signature: attestation.signature.clone(),
})
}
#[cfg(test)]
mod test {
use super::*;
use itertools::{Either, Itertools};
use types::test_utils::*;
#[test]
fn custody_bitfield_indexing() {
let validator_count = 128;
let spec = MinimalEthSpec::default_spec();
let state_builder =
TestingBeaconStateBuilder::<MinimalEthSpec>::from_default_keypairs_file_if_exists(
validator_count,
&spec,
);
let (mut state, keypairs) = state_builder.build();
state.build_all_caches(&spec).unwrap();
state.slot += 1;
let shard = 0;
let cc = state
.get_crosslink_committee_for_shard(shard, RelativeEpoch::Current)
.unwrap();
// Make a third of the validators sign with custody bit 0, a third with custody bit 1
// and a third not sign at all.
assert!(
cc.committee.len() >= 4,
"need at least 4 validators per committee for this test to work"
);
let (mut bit_0_indices, mut bit_1_indices): (Vec<_>, Vec<_>) = cc
.committee
.iter()
.enumerate()
.filter(|(i, _)| i % 3 != 0)
.partition_map(|(i, index)| {
if i % 3 == 1 {
Either::Left(*index)
} else {
Either::Right(*index)
}
});
assert!(!bit_0_indices.is_empty());
assert!(!bit_1_indices.is_empty());
let bit_0_keys = bit_0_indices
.iter()
.map(|validator_index| &keypairs[*validator_index].sk)
.collect::<Vec<_>>();
let bit_1_keys = bit_1_indices
.iter()
.map(|validator_index| &keypairs[*validator_index].sk)
.collect::<Vec<_>>();
let mut attestation_builder = TestingAttestationBuilder::new(
&AttestationTestTask::Valid,
&state,
&cc.committee,
cc.slot,
shard,
&spec,
);
attestation_builder
.sign(
&AttestationTestTask::Valid,
&bit_0_indices,
&bit_0_keys,
&state.fork,
&spec,
false,
)
.sign(
&AttestationTestTask::Valid,
&bit_1_indices,
&bit_1_keys,
&state.fork,
&spec,
true,
);
let attestation = attestation_builder.build();
let indexed_attestation = get_indexed_attestation(&state, &attestation).unwrap();
bit_0_indices.sort();
bit_1_indices.sort();
assert!(indexed_attestation
.custody_bit_0_indices
.iter()
.copied()
.eq(bit_0_indices.iter().map(|idx| *idx as u64)));
assert!(indexed_attestation
.custody_bit_1_indices
.iter()
.copied()
.eq(bit_1_indices.iter().map(|idx| *idx as u64)));
}
}

View File

@@ -3,7 +3,7 @@ use types::{BeaconStateError as Error, *};
/// Initiate the exit of the validator of the given `index`.
///
/// Spec v0.8.1
/// Spec v0.9.1
pub fn initiate_validator_exit<T: EthSpec>(
state: &mut BeaconState<T>,
index: usize,

View File

@@ -1,11 +1,9 @@
mod get_attesting_indices;
mod get_compact_committees_root;
mod get_indexed_attestation;
mod initiate_validator_exit;
mod slash_validator;
pub use get_attesting_indices::get_attesting_indices;
pub use get_compact_committees_root::get_compact_committees_root;
pub use get_indexed_attestation::get_indexed_attestation;
pub use initiate_validator_exit::initiate_validator_exit;
pub use slash_validator::slash_validator;

View File

@@ -4,7 +4,7 @@ use types::{BeaconStateError as Error, *};
/// Slash the validator with index ``index``.
///
/// Spec v0.8.0
/// Spec v0.9.1
pub fn slash_validator<T: EthSpec>(
state: &mut BeaconState<T>,
slashed_index: usize,
@@ -35,8 +35,7 @@ pub fn slash_validator<T: EthSpec>(
);
// Apply proposer and whistleblower rewards
let proposer_index =
state.get_beacon_proposer_index(state.slot, RelativeEpoch::Current, spec)?;
let proposer_index = state.get_beacon_proposer_index(state.slot, spec)?;
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
let whistleblower_reward = validator_effective_balance / spec.whistleblower_reward_quotient;
let proposer_reward = whistleblower_reward / spec.proposer_reward_quotient;