Fix bug in attestation verification
We were ensuring that a validator was present on the aggregation bitfield before adding their signature to the agg pub
This commit is contained in:
parent
62ab782ee2
commit
6250c81bb9
@ -147,6 +147,8 @@ pub enum AttestationInvalid {
|
|||||||
///
|
///
|
||||||
/// (attestation_data_shard, attestation_data_slot)
|
/// (attestation_data_shard, attestation_data_slot)
|
||||||
NoCommitteeForShard(u64, Slot),
|
NoCommitteeForShard(u64, Slot),
|
||||||
|
/// The validator index was unknown.
|
||||||
|
UnknownValidator(u64),
|
||||||
/// The attestation signature verification failed.
|
/// The attestation signature verification failed.
|
||||||
BadSignature,
|
BadSignature,
|
||||||
/// The shard block root was not set to zero. This is a phase 0 requirement.
|
/// The shard block root was not set to zero. This is a phase 0 requirement.
|
||||||
|
@ -159,18 +159,16 @@ fn validate_attestation_signature_optional(
|
|||||||
|
|
||||||
if verify_signature {
|
if verify_signature {
|
||||||
let attestation_epoch = attestation.data.slot.epoch(spec.slots_per_epoch);
|
let attestation_epoch = attestation.data.slot.epoch(spec.slots_per_epoch);
|
||||||
verify!(
|
|
||||||
verify_attestation_signature(
|
verify_attestation_signature(
|
||||||
state,
|
state,
|
||||||
committee,
|
committee,
|
||||||
attestation_epoch,
|
attestation_epoch,
|
||||||
|
&attestation.aggregation_bitfield,
|
||||||
&attestation.custody_bitfield,
|
&attestation.custody_bitfield,
|
||||||
&attestation.data,
|
&attestation.data,
|
||||||
&attestation.aggregate_signature,
|
&attestation.aggregate_signature,
|
||||||
spec
|
spec,
|
||||||
),
|
)?;
|
||||||
Invalid::BadSignature
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.crosslink_data_root == ZERO_HASH`.
|
// [TO BE REMOVED IN PHASE 1] Verify that `attestation.data.crosslink_data_root == ZERO_HASH`.
|
||||||
@ -195,19 +193,33 @@ fn verify_attestation_signature(
|
|||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
committee: &[usize],
|
committee: &[usize],
|
||||||
attestation_epoch: Epoch,
|
attestation_epoch: Epoch,
|
||||||
|
aggregation_bitfield: &Bitfield,
|
||||||
custody_bitfield: &Bitfield,
|
custody_bitfield: &Bitfield,
|
||||||
attestation_data: &AttestationData,
|
attestation_data: &AttestationData,
|
||||||
aggregate_signature: &AggregateSignature,
|
aggregate_signature: &AggregateSignature,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> bool {
|
) -> Result<(), Error> {
|
||||||
let mut aggregate_pubs = vec![AggregatePublicKey::new(); 2];
|
let mut aggregate_pubs = vec![AggregatePublicKey::new(); 2];
|
||||||
let mut message_exists = vec![false; 2];
|
let mut message_exists = vec![false; 2];
|
||||||
|
|
||||||
for (i, v) in committee.iter().enumerate() {
|
for (i, v) in committee.iter().enumerate() {
|
||||||
let custody_bit = match custody_bitfield.get(i) {
|
let validator_signed = aggregation_bitfield.get(i).map_err(|_| {
|
||||||
|
Error::Invalid(Invalid::BadAggregationBitfieldLength(
|
||||||
|
committee.len(),
|
||||||
|
aggregation_bitfield.len(),
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if validator_signed {
|
||||||
|
let custody_bit: bool = match custody_bitfield.get(i) {
|
||||||
Ok(bit) => bit,
|
Ok(bit) => bit,
|
||||||
// Invalidate signature if custody_bitfield.len() < committee
|
// Invalidate signature if custody_bitfield.len() < committee
|
||||||
Err(_) => return false,
|
Err(_) => {
|
||||||
|
return Err(Error::Invalid(Invalid::BadCustodyBitfieldLength(
|
||||||
|
committee.len(),
|
||||||
|
custody_bitfield.len(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
message_exists[custody_bit as usize] = true;
|
message_exists[custody_bit as usize] = true;
|
||||||
@ -216,10 +228,11 @@ fn verify_attestation_signature(
|
|||||||
Some(validator) => {
|
Some(validator) => {
|
||||||
aggregate_pubs[custody_bit as usize].add(&validator.pubkey);
|
aggregate_pubs[custody_bit as usize].add(&validator.pubkey);
|
||||||
}
|
}
|
||||||
// Invalidate signature if validator index is unknown.
|
// Return error if validator index is unknown.
|
||||||
None => return false,
|
None => return Err(Error::BeaconStateError(BeaconStateError::UnknownValidator)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Message when custody bitfield is `false`
|
// Message when custody bitfield is `false`
|
||||||
let message_0 = AttestationDataAndCustodyBit {
|
let message_0 = AttestationDataAndCustodyBit {
|
||||||
@ -251,5 +264,10 @@ fn verify_attestation_signature(
|
|||||||
|
|
||||||
let domain = spec.get_domain(attestation_epoch, Domain::Attestation, &state.fork);
|
let domain = spec.get_domain(attestation_epoch, Domain::Attestation, &state.fork);
|
||||||
|
|
||||||
aggregate_signature.verify_multiple(&messages[..], domain, &keys[..])
|
verify!(
|
||||||
|
aggregate_signature.verify_multiple(&messages[..], domain, &keys[..]),
|
||||||
|
Invalid::BadSignature
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user