lighthouse/consensus
Paul Hauner 5276dd0cb0 Fix edge-case when finding the finalized descendant (#3924)
## Issue Addressed

NA

## Description

We were missing an edge case when checking to see if a block is a descendant of the finalized checkpoint. This edge case is described for one of the tests in this PR:

a119edc739/consensus/proto_array/src/proto_array_fork_choice.rs (L1018-L1047)

This bug presented itself in the following mainnet log:

```
Jan 26 15:12:42.841 ERRO Unable to validate attestation error: MissingBeaconState(0x7c30cb80ec3d4ec624133abfa70e4c6cfecfca456bfbbbff3393e14e5b20bf25), peer_id: 16Uiu2HAm8RPRciXJYtYc5c3qtCRdrZwkHn2BXN3XP1nSi1gxHYit, type: "unaggregated", slot: Slot(5660161), beacon_block_root: 0x4a45e59da7cb9487f4836c83bdd1b741b4f31c67010c7ae343fa6771b3330489
```

Here the BN is rejecting an attestation because of a "missing beacon state". Whilst it was correct to reject the attestation, it should have rejected it because it attests to a block that conflicts with finality rather than claiming that the database is inconsistent.

The block that this attestation points to (`0x4a45`) is block `C` in the above diagram. It is a non-canonical block in the first slot of an epoch that conflicts with the finalized checkpoint. Due to our lazy pruning of proto array, `0x4a45` was still present in proto-array. Our missed edge-case in [`ForkChoice::is_descendant_of_finalized`](38514c07f2/consensus/fork_choice/src/fork_choice.rs (L1375-L1379)) would have indicated to us that the block is a descendant of the finalized block. Therefore, we would have accepted the attestation thinking that it attests to a descendant of the finalized *checkpoint*.

Since we didn't have the shuffling for this erroneously processed block, we attempted to read its state from the database. This failed because we prune states from the database by keeping track of the tips of the chain and iterating back until we find a finalized block. This would have deleted `C` from the database, hence the `MissingBeaconState` error.
2023-02-09 23:51:18 +00:00
..
cached_tree_hash Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
fork_choice Fix edge-case when finding the finalized descendant (#3924) 2023-02-09 23:51:18 +00:00
int_to_bytes Update to Rust 1.59 and 2021 edition (#3038) 2022-02-25 00:10:17 +00:00
merkle_proof Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
proto_array Fix edge-case when finding the finalized descendant (#3924) 2023-02-09 23:51:18 +00:00
safe_arith Inline safe_arith methods (#3229) 2022-05-31 06:09:12 +00:00
serde_utils Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
ssz Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
ssz_derive Update to Rust 1.59 and 2021 edition (#3038) 2022-02-25 00:10:17 +00:00
ssz_types Prioritise important parts of block processing (#3696) 2022-11-30 05:22:58 +00:00
state_processing Clippy 1.67 (#3916) 2023-01-27 09:48:42 +00:00
swap_or_not_shuffle Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
tree_hash Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00
tree_hash_derive Use SmallVec for TreeHash packed encoding (#3581) 2022-09-16 08:54:06 +00:00
types Verify execution block hashes during finalized sync (#3794) 2023-01-09 03:11:59 +00:00