@@ -1128,6 +1128,12 @@ fn verify_head_block_is_known<T: BeaconChainTypes>(
1128
1128
}
1129
1129
}
1130
1130
1131
+ if !verify_attestation_is_finalized_checkpoint_or_descendant ( attestation. data ( ) , chain) {
1132
+ return Err ( Error :: HeadBlockFinalized {
1133
+ beacon_block_root : attestation. data ( ) . beacon_block_root ,
1134
+ } ) ;
1135
+ }
1136
+
1131
1137
Ok ( block)
1132
1138
} else if chain. is_pre_finalization_block ( attestation. data ( ) . beacon_block_root ) ? {
1133
1139
Err ( Error :: HeadBlockFinalized {
@@ -1361,6 +1367,29 @@ pub fn verify_committee_index<E: EthSpec>(attestation: AttestationRef<E>) -> Res
1361
1367
Ok ( ( ) )
1362
1368
}
1363
1369
1370
+ fn verify_attestation_is_finalized_checkpoint_or_descendant < T : BeaconChainTypes > (
1371
+ attestation_data : & AttestationData ,
1372
+ chain : & BeaconChain < T > ,
1373
+ ) -> bool {
1374
+ // If we have a split block newer than finalization then we also ban attestations which are not
1375
+ // descended from that split block. It's important not to try checking `is_descendant` if
1376
+ // finality is ahead of the split and the split block has been pruned, as `is_descendant` will
1377
+ // return `false` in this case.
1378
+ let fork_choice = chain. canonical_head . fork_choice_read_lock ( ) ;
1379
+ let attestation_block_root = attestation_data. beacon_block_root ;
1380
+ let finalized_slot = fork_choice
1381
+ . finalized_checkpoint ( )
1382
+ . epoch
1383
+ . start_slot ( T :: EthSpec :: slots_per_epoch ( ) ) ;
1384
+ let split = chain. store . get_split_info ( ) ;
1385
+ let is_descendant_from_split_block = split. slot == 0
1386
+ || split. slot <= finalized_slot
1387
+ || fork_choice. is_descendant ( split. block_root , attestation_block_root) ;
1388
+
1389
+ fork_choice. is_finalized_checkpoint_or_descendant ( attestation_block_root)
1390
+ && is_descendant_from_split_block
1391
+ }
1392
+
1364
1393
/// Assists in readability.
1365
1394
type CommitteesPerSlot = u64 ;
1366
1395
0 commit comments