Can we have a discussion on when exactly to run the fork choice rule?
We see two possibilities as the following:
SLOT_DURATION seconds, triggering an UpdateHead function in our code along with processing received blocks, running a state transition, etc.For 2, will UpdateHead be called when we receive this block as well?
How does time a play a role here if everything is abstracted away into slot counters? Does it only play a role in certain timestamp verification details such as isValidSlot(block types.Block) bool?
Our client currently favors option 2, in which we do not use an internal clock ticker to run critical beacon node functionality
the fork choice can be written as a pure function of a particular beacon block tree, a focus within that tree (the latest justified head) and a set of (latest) attestations.
given we have discrete inputs to a pure function, we only have to run the fork choice when one of our discrete inputs changes. so setting aside questions of performance, we would run the fork choice when we receive
the ideal node will be calculating fork choice when any of the above changes (i.e. infinite performance); given that we can't build ideal nodes we will have to make some sacrifices in our clients. so we want to run the fork choice as often as possible while still allowing for the other duties of a beacon node (and keep in mind the target hardware is commodity stuff).
and at this point, the answer is to just do the ideal thing and measure how well it works; i think there has been some benchmarking work in the EF beacon chain repo but i'm not sure to what extent. in the meantime, we can make some guesses. the lowest frequency change will be (3) as the justified head will only update at most every epoch. we should be receiving blocks and attestations on the order of every slot but i would guess this is where we run into trouble recalculating the fork choice that frequently. it is worth thinking about how long the ideal node could delay recalculating the fork choice and still be able to make the blocks/attestations they would otherwise -- which seems like on average would be the MIN_ATTESTATION_INCLUSION_DELAY, accounting for the instances when you need to propose a block and would have to move sooner.
as an aside, you could imagine some exotic incremental computation that does incorporate a new fork choice upon every new piece of data but i can't say much more about this.
I think the sane approach here is going to be to run the fork choice at both:
1) After processing a new incoming block
2) at the start of each slot.
For (2), I mean at the start of each slot from a machine's time perspective, not from a block processing perspective. Between the starts of slots, a node will receive attestations both on the wire and within blocks. To keep the fork choice function from being overworked and at the same time to make sure local information is up to date enough for validators and other applications, the start of the slot is the natural target here.
+1 on @ralexstokes explanation. A couple of followup notes
I am in favor of adding explicit guidance on this in the spec, btw
After processing a new incoming block
This is potentially risky, because a single malicious proposer could create a very large number of blocks. I would say either (i) only do it once per slot change, or (ii) do it once per slot change and once upon the first time you receive a block at any given slot.
The single malicious proposer would be slashed by create a very large number of blocks right? I assume a well designed beacon node would just drop rest of the incoming blocks from the malicious proposer
I'd say the question was well answered by Alex, Danny, Vitalik. Closing for now :)
Most helpful comment
the fork choice can be written as a pure function of a particular beacon block tree, a focus within that tree (the latest justified head) and a set of (latest) attestations.
given we have discrete inputs to a pure function, we only have to run the fork choice when one of our discrete inputs changes. so setting aside questions of performance, we would run the fork choice when we receive
the ideal node will be calculating fork choice when any of the above changes (i.e. infinite performance); given that we can't build ideal nodes we will have to make some sacrifices in our clients. so we want to run the fork choice as often as possible while still allowing for the other duties of a beacon node (and keep in mind the target hardware is commodity stuff).
and at this point, the answer is to just do the ideal thing and measure how well it works; i think there has been some benchmarking work in the EF beacon chain repo but i'm not sure to what extent. in the meantime, we can make some guesses. the lowest frequency change will be (3) as the justified head will only update at most every epoch. we should be receiving blocks and attestations on the order of every slot but i would guess this is where we run into trouble recalculating the fork choice that frequently. it is worth thinking about how long the ideal node could delay recalculating the fork choice and still be able to make the blocks/attestations they would otherwise -- which seems like on average would be the
MIN_ATTESTATION_INCLUSION_DELAY, accounting for the instances when you need to propose a block and would have to move sooner.as an aside, you could imagine some exotic incremental computation that does incorporate a new fork choice upon every new piece of data but i can't say much more about this.