I'm suggesting to move the ATTESTATION_PROPAGATION_SLOT_RANGE check to the top for beacon_attestation_{subnet_id} validations.
From:
[REJECT] The attestation is for the correct subnet -- i.e. compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.index) == subnet_id, where committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch), which may be pre-computed along with the committee information for the signature check.
[IGNORE] attestation.data.slot is within the last ATTESTATION_PROPAGATION_SLOT_RANGE slots (within a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance) -- i.e. attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot (a client MAY queue future attestations for processing at the appropriate slot)
To:
[IGNORE] attestation.data.slot is within the last ATTESTATION_PROPAGATION_SLOT_RANGE slots (within a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance) -- i.e. attestation.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= attestation.data.slot (a client MAY queue future attestations for processing at the appropriate slot)
[REJECT] The attestation is for the correct subnet -- i.e. compute_subnet_for_attestation(committees_per_slot, attestation.data.slot, attestation.data.index) == subnet_id, where committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch), which may be pre-computed along with the committee information for the signature check.
Reasons:
- slot range check is a stateless check, it's slightly cheaper
- subnet check may open up to dos attack in situation where long period without finality and this mostly depends on client implementation detail. The slot range check can be used to prevent such attack
More info on the attack:
In Prysm's DB scheme, we only hold up to certain hot (post finalization) states in memory. When there's long period without finality, a node could get attacked by receiving attestation that's outside of slot range. Given it's outside of the slot range (eg. >2epochs behind), that's very likely the receiving node will have to do extra computations to compute for the beacon state to satisfy the committee validation and that is committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch) We have observed this pattern in the Onyx testnet when 200 epochs since finality
Reference fix in Prysm: OffchainLabs/prysm#6755
I'm suggesting to move the
ATTESTATION_PROPAGATION_SLOT_RANGEcheck to the top forbeacon_attestation_{subnet_id}validations.From:
To:
Reasons:
More info on the attack:
In Prysm's DB scheme, we only hold up to certain hot (post finalization) states in memory. When there's long period without finality, a node could get attacked by receiving attestation that's outside of slot range. Given it's outside of the slot range (eg. >2epochs behind), that's very likely the receiving node will have to do extra computations to compute for the beacon state to satisfy the committee validation and that is
committees_per_slot = get_committee_count_per_slot(state, attestation.data.target.epoch)We have observed this pattern in the Onyx testnet when 200 epochs since finalityReference fix in Prysm: OffchainLabs/prysm#6755