mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 19:02:42 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user