Skip to content

Check justified checkpoint root in fork choice #2741

@paulhauner

Description

@paulhauner

Description

Credits to @hwwhww for bringing this to our attention.

In fork choice, Lighthouse checks checkpoint epochs:

/// This is the equivalent to the `filter_block_tree` function in the eth2 spec:
///
/// https://github.com/ethereum/eth2.0-specs/blob/v0.10.0/specs/phase0/fork-choice.md#filter_block_tree
///
/// Any node that has a different finalized or justified epoch should not be viable for the
/// head.
fn node_is_viable_for_head(&self, node: &ProtoNode) -> bool {
(node.justified_epoch == self.justified_epoch || self.justified_epoch == Epoch::new(0))
&& (node.finalized_epoch == self.finalized_epoch
|| self.finalized_epoch == Epoch::new(0))
}

However, the specification declares:

    correct_justified = (
        store.justified_checkpoint.epoch == GENESIS_EPOCH
        or head_state.current_justified_checkpoint == store.justified_checkpoint
    )
    correct_finalized = (
        store.finalized_checkpoint.epoch == GENESIS_EPOCH
        or head_state.finalized_checkpoint == store.finalized_checkpoint
    )

We have to check "checkpoints" are equal. So Lighthouse needs to update to check both epoch and root, not just the epoch.

Steps to resolve

In order to support this, we need to add the root information to the ProtoNode:

pub justified_epoch: Epoch,

... and also the ProtoArray:

pub justified_epoch: Epoch,

This will require a database migration. I think it should be fairly simple to migrate the ProtoNode, the roots of all the justified ancestors should be in the ProtoArray, so we should just be able to find the roots by just iterating backwards until we find the first ancestor where ancestor.slot <= start_slot(node.justified_epoch).

For ProtoArray, I think we should be able to get the root for the justified checkpoint from the ForkChoiceStore, which is persisted alongside it. We'd need to do some more reading to ensure there's a 1:1 relationship between these values, though.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions