Use parent_root for finalized chain check #1884
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Use
block.parent_root
instead ofhash_tree_root(block)
to determine if the block descends from the finalized root.This has two outcomes:
block
instore.blocks
only if it is valid.Reasoning
I will make an argument that the following two checks are equal:
Check 1 (existing)
Check 2 (proposed)
Argument
In
get_ancestor
, there are effectively two paths:if block.slot > slot
, recurse usingblock.parent_root
.root
.Considering we've established that prior to both checks we have
assert block.slot > finalized_slot
, the only possible path inget_ancestor
is (1). This recursion in path 1 is equivalent to check 2.Why am I raising this?
Optimization
Firstly, this removes a redundant block lookup. However, it's not significant and shouldn't be a driving factor, IMO.
Ergonomics
My motivation is that it allows for calling
store.blocks[hash_tree_root(block)] = block
only once the block is valid. This is important for implementations (like Lighthouse) because it means we don't need to roll back on an invalid block.I'd like to implement this for Lighthouse and similar to #1880 it would nice to get feedback from spec authors and link to this PR in our code.
Spec bug
Seeing as the spec doesn't implement a rollback, I also believe that this PR fixes a bug that we can call: "Fork choice store is corrupted if an invalid block is suppplied to
on_block
".Consider we have some
signed_block
with an invalid signature and it is the first block to be added toStore
after genesis. Inon_block
that block will be added tostore.blocks
. Then, the invalid signature will causeon_block
to terminate prior to adding the respective state tostore.block_states
.Consider that there are now two objects in
store.blocks
:genesis_block
)invalid_block
)But only one object in
store.block_states
:Now consider the call stack the next time
get_head
is called:get_head(store)
get_filtered_block_store(store)
filter_block_tree(store, tree_hash_root(genesis_block_root), {})
filter_block_tree(store, tree_hash_root(invalid_block), {})
During (4) we will run:
This will raise an exception.