mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 19:51:47 +00:00
Add gossip conditions from spec v0.12.3 (#1667)
## Issue Addressed NA ## Proposed Changes There are four new conditions introduced in v0.12.3: 1. _[REJECT]_ The attestation's epoch matches its target -- i.e. `attestation.data.target.epoch == compute_epoch_at_slot(attestation.data.slot)` 1. _[REJECT]_ The attestation's target block is an ancestor of the block named in the LMD vote -- i.e. `get_ancestor(store, attestation.data.beacon_block_root, compute_start_slot_at_epoch(attestation.data.target.epoch)) == attestation.data.target.root` 1. _[REJECT]_ The committee index is within the expected range -- i.e. `data.index < get_committee_count_per_slot(state, data.target.epoch)`. 1. _[REJECT]_ The number of aggregation bits matches the committee size -- i.e. `len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot, data.index))`. This PR implements new logic to suit (1) and (2). Tests are added for (3) and (4), although they were already implicitly enforced. ## Additional Info - There's a bit of edge-case with target root verification that I raised here: https://github.com/ethereum/eth2.0-specs/pull/2001#issuecomment-699246659 - I've had to add an `--ignore` to `cargo audit` to get CI to pass. See https://github.com/sigp/lighthouse/issues/1669
This commit is contained in:
@@ -11,13 +11,15 @@ use beacon_chain::{
|
||||
BeaconChain, BeaconChainTypes,
|
||||
};
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use state_processing::per_slot_processing;
|
||||
use state_processing::{
|
||||
per_block_processing::errors::AttestationValidationError, per_slot_processing,
|
||||
};
|
||||
use store::config::StoreConfig;
|
||||
use tree_hash::TreeHash;
|
||||
use types::{
|
||||
test_utils::generate_deterministic_keypair, AggregateSignature, Attestation, EthSpec, Hash256,
|
||||
Keypair, MainnetEthSpec, SecretKey, SelectionProof, SignedAggregateAndProof, SignedBeaconBlock,
|
||||
SubnetId, Unsigned,
|
||||
test_utils::generate_deterministic_keypair, AggregateSignature, Attestation, BeaconStateError,
|
||||
BitList, EthSpec, Hash256, Keypair, MainnetEthSpec, SecretKey, SelectionProof,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SubnetId, Unsigned,
|
||||
};
|
||||
|
||||
pub type E = MainnetEthSpec;
|
||||
@@ -582,6 +584,31 @@ fn unaggregated_gossip_verification() {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* The following test ensures:
|
||||
*
|
||||
* Spec v0.12.3
|
||||
*
|
||||
* The committee index is within the expected range -- i.e. `data.index <
|
||||
* get_committee_count_per_slot(state, data.target.epoch)`.
|
||||
*/
|
||||
assert_invalid!(
|
||||
"attestation with invalid committee index",
|
||||
{
|
||||
let mut a = valid_attestation.clone();
|
||||
a.data.index = harness
|
||||
.chain
|
||||
.head()
|
||||
.unwrap()
|
||||
.beacon_state
|
||||
.get_committee_count_at_slot(a.data.slot)
|
||||
.unwrap();
|
||||
a
|
||||
},
|
||||
subnet_id,
|
||||
AttnError::NoCommitteeForSlotAndIndex { .. }
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures:
|
||||
*
|
||||
@@ -642,6 +669,7 @@ fn unaggregated_gossip_verification() {
|
||||
{
|
||||
let mut a = valid_attestation.clone();
|
||||
a.data.slot = early_slot;
|
||||
a.data.target.epoch = early_slot.epoch(E::slots_per_epoch());
|
||||
a
|
||||
},
|
||||
subnet_id,
|
||||
@@ -654,6 +682,27 @@ fn unaggregated_gossip_verification() {
|
||||
if attestation_slot == early_slot && earliest_permissible_slot == current_slot - E::slots_per_epoch() - 1
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures:
|
||||
*
|
||||
* Spec v0.12.3
|
||||
*
|
||||
* The attestation's epoch matches its target -- i.e. `attestation.data.target.epoch ==
|
||||
* compute_epoch_at_slot(attestation.data.slot)`
|
||||
*
|
||||
*/
|
||||
|
||||
assert_invalid!(
|
||||
"attestation with invalid target epoch",
|
||||
{
|
||||
let mut a = valid_attestation.clone();
|
||||
a.data.target.epoch += 1;
|
||||
a
|
||||
},
|
||||
subnet_id,
|
||||
AttnError::InvalidTargetEpoch { .. }
|
||||
);
|
||||
|
||||
/*
|
||||
* The following two tests ensure:
|
||||
*
|
||||
@@ -694,6 +743,32 @@ fn unaggregated_gossip_verification() {
|
||||
AttnError::NotExactlyOneAggregationBitSet(2)
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures:
|
||||
*
|
||||
* Spec v0.12.3
|
||||
*
|
||||
* The number of aggregation bits matches the committee size -- i.e.
|
||||
* `len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot,
|
||||
* data.index))`.
|
||||
*/
|
||||
assert_invalid!(
|
||||
"attestation with invalid bitfield",
|
||||
{
|
||||
let mut a = valid_attestation.clone();
|
||||
let bits = a.aggregation_bits.iter().collect::<Vec<_>>();
|
||||
a.aggregation_bits = BitList::with_capacity(bits.len() + 1).unwrap();
|
||||
for (i, bit) in bits.into_iter().enumerate() {
|
||||
a.aggregation_bits.set(i, bit).unwrap();
|
||||
}
|
||||
a
|
||||
},
|
||||
subnet_id,
|
||||
AttnError::Invalid(AttestationValidationError::BeaconStateError(
|
||||
BeaconStateError::InvalidBitfield
|
||||
))
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures that:
|
||||
*
|
||||
@@ -717,6 +792,26 @@ fn unaggregated_gossip_verification() {
|
||||
if beacon_block_root == unknown_root
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures that:
|
||||
*
|
||||
* Spec v0.12.3
|
||||
*
|
||||
* The attestation's target block is an ancestor of the block named in the LMD vote
|
||||
*/
|
||||
|
||||
let unknown_root = Hash256::from_low_u64_le(424242);
|
||||
assert_invalid!(
|
||||
"attestation with invalid target root",
|
||||
{
|
||||
let mut a = valid_attestation.clone();
|
||||
a.data.target.root = unknown_root;
|
||||
a
|
||||
},
|
||||
subnet_id,
|
||||
AttnError::InvalidTargetRoot { .. }
|
||||
);
|
||||
|
||||
/*
|
||||
* The following test ensures that:
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user