From 07d1d6bdf9d6615e03f0b814cab473c9fa15ea17 Mon Sep 17 00:00:00 2001 From: kasey <489222+kasey@users.noreply.github.com> Date: Mon, 29 Dec 2025 15:35:46 -0500 Subject: [PATCH] Fix validation bug in --backfill-oldest-slot (#16173) **What type of PR is this?** Bug fix **What does this PR do? Why is it needed?** Validation of `--backfill-oldest-slot` fails for values > 1056767, because the validation code is comparing the slot/32 to `MIN_EPOCHS_FOR_BLOCK_REQUESTS` (33024), instead of comparing it to `current_epoch - MIN_EPOCHS_FOR_BLOCK_REQUESTS`. **Which issues(s) does this PR fix?** Fixes # **Other notes for review** **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 with sufficient context for reviewers to understand this PR. - [x] I have tested that my changes work as expected and I added a testing plan to the PR description (if applicable). --------- Co-authored-by: Kasey Kirkham --- beacon-chain/das/needs.go | 4 ++-- beacon-chain/das/needs_test.go | 34 +++++++++++++++++++++------- changelog/kasey_fix-backfill-flag.md | 2 ++ 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 changelog/kasey_fix-backfill-flag.md diff --git a/beacon-chain/das/needs.go b/beacon-chain/das/needs.go index bd7b53c077..425165ace3 100644 --- a/beacon-chain/das/needs.go +++ b/beacon-chain/das/needs.go @@ -67,9 +67,9 @@ func NewSyncNeeds(current CurrentSlotter, oldestSlotFlagPtr *primitives.Slot, bl // 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 { + if *oldestSlotFlagPtr <= syncEpochOffset(current(), sn.blockRetention) { sn.validOldestSlotPtr = oldestSlotFlagPtr } else { log.WithField("backfill-oldest-slot", *oldestSlotFlagPtr). diff --git a/beacon-chain/das/needs_test.go b/beacon-chain/das/needs_test.go index 6986f7933a..6b9e863633 100644 --- a/beacon-chain/das/needs_test.go +++ b/beacon-chain/das/needs_test.go @@ -128,6 +128,9 @@ func TestSyncNeedsInitialize(t *testing.T) { slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch minBlobEpochs := params.BeaconConfig().MinEpochsForBlobsSidecarsRequest minColEpochs := params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest + denebSlot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch) + fuluSlot := slots.UnsafeEpochStart(params.BeaconConfig().FuluForkEpoch) + minSlots := slots.UnsafeEpochStart(primitives.Epoch(params.BeaconConfig().MinEpochsForBlockRequests)) currentSlot := primitives.Slot(10000) currentFunc := func() primitives.Slot { return currentSlot } @@ -141,6 +144,7 @@ func TestSyncNeedsInitialize(t *testing.T) { expectedCol primitives.Epoch name string input SyncNeeds + current func() primitives.Slot }{ { name: "basic initialization with no flags", @@ -174,13 +178,13 @@ func TestSyncNeedsInitialize(t *testing.T) { { name: "valid oldestSlotFlagPtr (earlier than spec minimum)", blobRetentionFlag: 0, - oldestSlotFlagPtr: func() *primitives.Slot { - slot := primitives.Slot(10) - return &slot - }(), + oldestSlotFlagPtr: &denebSlot, expectValidOldest: true, expectedBlob: minBlobEpochs, expectedCol: minColEpochs, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, }, { name: "invalid oldestSlotFlagPtr (later than spec minimum)", @@ -210,6 +214,9 @@ func TestSyncNeedsInitialize(t *testing.T) { { name: "both blob retention flag and oldest slot set", blobRetentionFlag: minBlobEpochs + 5, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, oldestSlotFlagPtr: func() *primitives.Slot { slot := primitives.Slot(100) return &slot @@ -232,16 +239,27 @@ func TestSyncNeedsInitialize(t *testing.T) { expectedBlob: 5000, expectedCol: 5000, }, + { + name: "regression for deneb start", + blobRetentionFlag: 8212500, + expectValidOldest: true, + oldestSlotFlagPtr: &denebSlot, + current: func() primitives.Slot { + return fuluSlot + minSlots + }, + expectedBlob: 8212500, + expectedCol: 8212500, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - result, err := NewSyncNeeds(currentFunc, tc.oldestSlotFlagPtr, tc.blobRetentionFlag) + if tc.current == nil { + tc.current = currentFunc + } + result, err := NewSyncNeeds(tc.current, tc.oldestSlotFlagPtr, tc.blobRetentionFlag) require.NoError(t, err) - // Check that current, deneb, fulu are set correctly - require.Equal(t, currentSlot, result.current()) - // Check retention calculations require.Equal(t, tc.expectedBlob, result.blobRetention) require.Equal(t, tc.expectedCol, result.colRetention) diff --git a/changelog/kasey_fix-backfill-flag.md b/changelog/kasey_fix-backfill-flag.md new file mode 100644 index 0000000000..4cb4e74216 --- /dev/null +++ b/changelog/kasey_fix-backfill-flag.md @@ -0,0 +1,2 @@ +#### Fixed +- Fix validation logic for `--backfill-oldest-slot`, which was rejecting slots newer than 1056767.