Description
As brought up by @mbaxter, it is unclear at this moment how to handle BlocksByRange
requests when a node has synced from a weak subjectivity state.
A few questions:
- What minimum block/epoch ranges (wrt current epoch) are expected to baseline be served by all nodes?
- How does a node know the range a peer will serve?
- If a
BlocksByRange
request is made to a peer and all or some subset of slots in that range are not in custody of the peer, what should be the response?
Question 1
What minimum block ranges (wrt current slot) are expected to baseline be served by all nodes?
The spec current says:
Clients MUST keep a record of signed blocks seen since the start of the weak subjectivity period and MUST support serving requests of blocks up to their own
head_block_root
"weak subjectivity period" is poorly defined in this context. I would suggest that that upper limit of the weak subjectivity period (~5 months at 100% safety decay) is used as a constant in this spec to define the minimum epoch range that a node is expected to backfill and keep around for serving. (The following is adopted from the weak-subjectivity guide):
MIN_EPOCHS_FOR_BLOCK_REQUESTS = (
MIN_VALIDATOR_WITHDRAWABILITY_DELAY
+ MAX_SAFETY_DECAY * CHURN_LIMIT_QUOTIENT // (2 * 100)
)
Where MAX_SAFETY_DECAY = 100
and thus MIN_EPOCHS_FOR_BLOCK_REQUESTS = 33024
(~5 months).
This could be considered overkill for small validator sets or more aggressive safety decays, but using the maximum here does not put an overly large block storage requirement on honest nodes and provides a higher guarantee in baseline quality of service without trying to integrate dynamic WS period lengths into the assumptions in the networking protocol.
Question 2
How does a node know the range a peer will serve?
By default, we can assume that all nodes will serve MIN_EPOCHS_FOR_BLOCK_REQUESTS
worth of blocks from the current epoch. If not, that is grounds for de-scoring. But, many nodes might choose to serve beyond this range (maximally back to genesis).
There are two obvious places to publish this info, in Status
or MetaData
. Status
is generally for info on head state of a node to decide if the node is on chains you care about for syncing, while MetaData
is for more slowly changing information about the node in general.
I can see the argument for using each
- Put lower bound on block serve epoch in
Status
becauseStatus
is already used frequently when crafting block sync requests - Put lower bound on block serve epoch in
MetaData
because it isn't expected to change frequently and can be used to make more static decisions about which peers you want to sync with in general.
Due to the expected slowly changing nature of the piece of data, I have a slight preference for putting it in MetaData
but would like to hear the opinions of others.
For nodes that are still back-filling blocks from a WS state or are block syncing from genesis, it might be worthwhile to signify this in MetaData
as well. We can use FAR_FUTURE_EPOCH
for the earliest block serve epoch to signify this.
Question 3
If a BlocksByRange
request is made to a peer and all or some subset of slots in that range are not in the custody of the peer, what should be the response?
@mbaxter noted the following options available:
- Return an error
- Return an empty response
- Return any sequence of blocks in the range that are available
Both the 2nd and 3rd options provide misleading information about the slot range in question to the requester.
I lean towards (1) -- return an error.