mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-06 22:23:56 -05:00
**What type of PR is this?** Feature **What does this PR do? Why is it needed?** Adds data column support to backfill. **Acknowledgements** - [x] I have read [CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md). - [x] I have included a uniquely named [changelog fragment file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd). - [x] I have added a description to this PR with sufficient context for reviewers to understand this PR. --------- Co-authored-by: Kasey <kasey@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Preston Van Loon <preston@pvl.dev>
136 lines
4.9 KiB
Go
136 lines
4.9 KiB
Go
package das
|
|
|
|
import (
|
|
"github.com/OffchainLabs/prysm/v7/config/params"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
|
"github.com/OffchainLabs/prysm/v7/time/slots"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// NeedSpan represents the need for a resource over a span of slots.
|
|
type NeedSpan struct {
|
|
Begin primitives.Slot
|
|
End primitives.Slot
|
|
}
|
|
|
|
// At returns whether blocks/blobs/columns are needed At the given slot.
|
|
func (n NeedSpan) At(slot primitives.Slot) bool {
|
|
return slot >= n.Begin && slot < n.End
|
|
}
|
|
|
|
// CurrentNeeds fields can be used to check whether the given resource type is needed
|
|
// at a given slot. The values are based on the current slot, so this value shouldn't
|
|
// be retained / reused across slots.
|
|
type CurrentNeeds struct {
|
|
Block NeedSpan
|
|
Blob NeedSpan
|
|
Col NeedSpan
|
|
}
|
|
|
|
// SyncNeeds holds configuration and state for determining what data is needed
|
|
// at any given slot during backfill based on the current slot.
|
|
type SyncNeeds struct {
|
|
current func() primitives.Slot
|
|
deneb primitives.Slot
|
|
fulu primitives.Slot
|
|
|
|
oldestSlotFlagPtr *primitives.Slot
|
|
validOldestSlotPtr *primitives.Slot
|
|
blockRetention primitives.Epoch
|
|
|
|
blobRetentionFlag primitives.Epoch
|
|
blobRetention primitives.Epoch
|
|
colRetention primitives.Epoch
|
|
}
|
|
|
|
type CurrentSlotter func() primitives.Slot
|
|
|
|
func NewSyncNeeds(current CurrentSlotter, oldestSlotFlagPtr *primitives.Slot, blobRetentionFlag primitives.Epoch) (SyncNeeds, error) {
|
|
deneb, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
|
if err != nil {
|
|
return SyncNeeds{}, errors.Wrap(err, "deneb fork slot")
|
|
}
|
|
fuluBoundary := min(params.BeaconConfig().FuluForkEpoch, slots.MaxSafeEpoch())
|
|
fulu, err := slots.EpochStart(fuluBoundary)
|
|
if err != nil {
|
|
return SyncNeeds{}, errors.Wrap(err, "fulu fork slot")
|
|
}
|
|
sn := SyncNeeds{
|
|
current: func() primitives.Slot { return current() },
|
|
deneb: deneb,
|
|
fulu: fulu,
|
|
blobRetentionFlag: blobRetentionFlag,
|
|
}
|
|
// We apply the --blob-retention-epochs flag to both blob and column retention.
|
|
sn.blobRetention = max(sn.blobRetentionFlag, params.BeaconConfig().MinEpochsForBlobsSidecarsRequest)
|
|
sn.colRetention = max(sn.blobRetentionFlag, params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest)
|
|
|
|
// Override spec minimum block retention with user-provided flag only if it is lower than the spec minimum.
|
|
sn.blockRetention = primitives.Epoch(params.BeaconConfig().MinEpochsForBlockRequests)
|
|
if oldestSlotFlagPtr != nil {
|
|
oldestEpoch := slots.ToEpoch(*oldestSlotFlagPtr)
|
|
if oldestEpoch < sn.blockRetention {
|
|
sn.validOldestSlotPtr = oldestSlotFlagPtr
|
|
} else {
|
|
log.WithField("backfill-oldest-slot", *oldestSlotFlagPtr).
|
|
WithField("specMinSlot", syncEpochOffset(current(), sn.blockRetention)).
|
|
Warn("Ignoring user-specified slot > MIN_EPOCHS_FOR_BLOCK_REQUESTS.")
|
|
}
|
|
}
|
|
|
|
return sn, nil
|
|
}
|
|
|
|
// Currently is the main callback given to the different parts of backfill to determine
|
|
// what resources are needed at a given slot. It assumes the current instance of SyncNeeds
|
|
// is the result of calling initialize.
|
|
func (n SyncNeeds) Currently() CurrentNeeds {
|
|
current := n.current()
|
|
c := CurrentNeeds{
|
|
Block: n.blockSpan(current),
|
|
Blob: NeedSpan{Begin: syncEpochOffset(current, n.blobRetention), End: n.fulu},
|
|
Col: NeedSpan{Begin: syncEpochOffset(current, n.colRetention), End: current},
|
|
}
|
|
// Adjust the minimums forward to the slots where the sidecar types were introduced
|
|
c.Blob.Begin = max(c.Blob.Begin, n.deneb)
|
|
c.Col.Begin = max(c.Col.Begin, n.fulu)
|
|
|
|
return c
|
|
}
|
|
|
|
func (n SyncNeeds) blockSpan(current primitives.Slot) NeedSpan {
|
|
if n.validOldestSlotPtr != nil { // assumes validation done in initialize()
|
|
return NeedSpan{Begin: *n.validOldestSlotPtr, End: current}
|
|
}
|
|
return NeedSpan{Begin: syncEpochOffset(current, n.blockRetention), End: current}
|
|
}
|
|
|
|
func (n SyncNeeds) BlobRetentionChecker() RetentionChecker {
|
|
return func(slot primitives.Slot) bool {
|
|
current := n.Currently()
|
|
return current.Blob.At(slot)
|
|
}
|
|
}
|
|
|
|
func (n SyncNeeds) DataColumnRetentionChecker() RetentionChecker {
|
|
return func(slot primitives.Slot) bool {
|
|
current := n.Currently()
|
|
return current.Col.At(slot)
|
|
}
|
|
}
|
|
|
|
// syncEpochOffset subtracts a number of epochs as slots from the current slot, with underflow checks.
|
|
// It returns slot 1 if the result would be 0 or underflow. It doesn't return slot 0 because the
|
|
// genesis block needs to be specially synced (it doesn't have a valid signature).
|
|
func syncEpochOffset(current primitives.Slot, subtract primitives.Epoch) primitives.Slot {
|
|
minEpoch := min(subtract, slots.MaxSafeEpoch())
|
|
// compute slot offset - offset is a number of slots to go back from current (not an absolute slot).
|
|
offset := slots.UnsafeEpochStart(minEpoch)
|
|
// Undeflow protection: slot 0 is the genesis block, therefore the signature in it is invalid.
|
|
// To prevent us from rejecting a batch, we restrict the minimum backfill batch till only slot 1
|
|
if offset >= current {
|
|
return 1
|
|
}
|
|
return current - offset
|
|
}
|