Skip to content

Commit b911048

Browse files
committed
Reject attestations on gossip that attest to blocks prior to the current split point
1 parent 7d598ed commit b911048

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

beacon_node/beacon_chain/src/attestation_verification.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,16 @@ pub enum Error {
266266
attestation: Hash256,
267267
expected: Option<Hash256>,
268268
},
269+
/// The attestation conflicts with finalization, no need to propagate.
270+
///
271+
/// ## Peer scoring
272+
///
273+
/// It's unclear if this attestation is valid, but it conflicts with finality and shouldn't be
274+
/// propogated.
275+
NotFinalizedDescendant {
276+
attestation_block_root: Hash256,
277+
attestation_slot: Slot,
278+
},
269279
/// There was an error whilst processing the attestation. It is not known if it is valid or invalid.
270280
///
271281
/// ## Peer scoring
@@ -848,6 +858,9 @@ impl<'a, T: BeaconChainTypes> IndexedUnaggregatedAttestation<'a, T> {
848858
// [New in Electra:EIP7549]
849859
verify_committee_index(attestation)?;
850860

861+
// Do not process an attestation that doesn't descend from the finalized root.
862+
verify_attestation_is_finalized_checkpoint_or_descendant(attestation, chain)?;
863+
851864
// Attestations must be for a known block. If the block is unknown, we simply drop the
852865
// attestation and do not delay consideration for later.
853866
//
@@ -1361,6 +1374,30 @@ pub fn verify_committee_index<E: EthSpec>(attestation: AttestationRef<E>) -> Res
13611374
Ok(())
13621375
}
13631376

1377+
fn verify_attestation_is_finalized_checkpoint_or_descendant<T: BeaconChainTypes>(
1378+
attestation: AttestationRef<T::EthSpec>,
1379+
chain: &BeaconChain<T>,
1380+
) -> Result<(), Error> {
1381+
// If we have a split block newer than finalization then we also ban attestations which are not
1382+
// descended from that split block.
1383+
let fork_choice = chain.canonical_head.fork_choice_read_lock();
1384+
let split = chain.store.get_split_info();
1385+
let attestation_block_root = attestation.data().beacon_block_root;
1386+
let is_descendant_from_split_block =
1387+
split.slot == 0 || fork_choice.is_descendant(split.block_root, attestation_block_root);
1388+
1389+
if fork_choice.is_finalized_checkpoint_or_descendant(attestation_block_root)
1390+
&& is_descendant_from_split_block
1391+
{
1392+
Ok(())
1393+
} else {
1394+
Err(Error::NotFinalizedDescendant {
1395+
attestation_block_root,
1396+
attestation_slot: attestation.data().slot,
1397+
})
1398+
}
1399+
}
1400+
13641401
/// Assists in readability.
13651402
type CommitteesPerSlot = u64;
13661403

beacon_node/network/src/network_beacon_processor/gossip_methods.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2893,6 +2893,27 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
28932893
);
28942894
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore);
28952895
}
2896+
AttnError::NotFinalizedDescendant {
2897+
attestation_block_root,
2898+
attestation_slot,
2899+
} => {
2900+
error!(
2901+
self.log,
2902+
"Could not verify the attestation for gossip. Rejecting the attestation";
2903+
"attestation_block_root" => ?attestation_block_root,
2904+
"slot" => ?attestation_slot,
2905+
"type" => ?attestation_type,
2906+
"peer_id" => %peer_id,
2907+
);
2908+
// There's no reason for an honest and non-buggy client to be gossiping
2909+
// attestations that blatantly conflict with finalization.
2910+
self.gossip_penalize_peer(
2911+
peer_id,
2912+
PeerAction::LowToleranceError,
2913+
"gossip_attestation_invalid",
2914+
);
2915+
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Reject);
2916+
}
28962917
}
28972918

28982919
debug!(

0 commit comments

Comments
 (0)