Currently when prysm receives an attestation for which it hasn't seen the target block, it gets put in a pending attestation queue. This queue is being emptied twice per slot, at even intervals.
The purpose of the queue handler is two-fold:
In the current design we have
We want to move from a fixed timed system, to an on-demand system, where we call to clear the pending attestations as soon as we process a block. This suggests that we need to separate the two functions of the queue as we may want request blocks at different times than when we process the attestations.
I propose to divide the functionality to be completely on-demand, that is
This can be easily achieved in the following steps
i. get rid of the processPendingAtts
function entirely
ii. Modify savePendingAtt
to in addition to saving the pending attestation in the queue, to request the block and save it in a list of requested blocks.
There are only two places where this function is called and its on validation, both in validateCommiteeIndexBeaconAttestation
and validateBlockInAttestation
. Thus whenever we are validating an attestation, this will add a little overhead of checking if the block has already been requested, and a bigger overhead of actually making the request.
The check to see if the block has already been requested is as simple as checking if the root appears in blkRootToPendingAtts
, that is, if we have a root in that map then we can safely assume that we have already requesteed the block.
iii. Write a function processPendingAttsForBlock
that takes a block Root bRoot
, and simply processes all the attestations in blkRootToPendingAtts[bRoot]
and then clears this entry in the map. Thus the signature of this function would be
iv. Call this function in the subscriber after receiving every block, hence the call will be here and look like
The approach above affects resource consumption in a couple of different ways.
The expensive tasks are signature verification, both for the attestation and the blocks. So in principle the possible extra requests that we may get from the scenario in 2 is not so bad.
A hybrid model would be to add this extra path:
When receiving an attestation for a block we haven't seen:
This avoids the extra request in the non-exceptional slot 0 scenario.
Do not request any block, just save the attestations and never requests the corresponding blocks. If we haven't seen the block then we will soon drop the attestation. I favor this approach as it has several performance advantages.