diff --git a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/snapshot.go b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/snapshot.go index 6e0ed9bf2..3816c8c60 100644 --- a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/snapshot.go +++ b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/snapshot.go @@ -13,11 +13,6 @@ import ( iotago "github.com/iotaledger/iota.go/v4" ) -const ( - // TODO: should be addressed in issue #300. - daysInYear = 365 -) - func (t *Tracker) Import(reader io.ReadSeeker) error { t.mutex.Lock() defer t.mutex.Unlock() @@ -279,18 +274,25 @@ func (t *Tracker) exportPoolRewards(writer io.WriteSeeker, targetEpoch iotago.Ep // export all stored pools // in theory we could save the epoch count only once, because stats and rewards should be the same length + protocolParams := t.apiProvider.APIForEpoch(targetEpoch).ProtocolParameters() + retentionPeriod := iotago.EpochIndex(protocolParams.RewardsParameters().RetentionPeriod) + earliestRewardEpoch := iotago.EpochIndex(0) + if targetEpoch > retentionPeriod { + earliestRewardEpoch = targetEpoch - retentionPeriod + } + if err := stream.WriteCollection(writer, serializer.SeriLengthPrefixTypeAsUint32, func() (int, error) { var epochCount int // Here underflow will not happen because we will stop iterating for epoch 0, because 0 is not greater than zero. // Use safemath here anyway to avoid hard to trace problems stemming from an accidental underflow. - for epoch := targetEpoch; epoch > iotago.EpochIndex(lo.Max(0, int(targetEpoch)-daysInYear)); epoch = lo.PanicOnErr(safemath.SafeSub(epoch, 1)) { + for epoch := targetEpoch; epoch > earliestRewardEpoch; epoch = lo.PanicOnErr(safemath.SafeSub(epoch, 1)) { rewardsMap, err := t.rewardsMap(epoch) if err != nil { return 0, ierrors.Wrapf(err, "unable to get rewards tree for epoch %d", epoch) } - // if the map was not present in storage we can skip this epoch and the previous ones, as we never stored any rewards + // if the map was not present in storage we can skip this epoch if !rewardsMap.WasRestoredFromStorage() { - break + continue } if err := stream.Write(writer, epoch); err != nil { diff --git a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/tracker_test.go b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/tracker_test.go index f1a5ba542..0cd5d8f2e 100644 --- a/pkg/protocol/sybilprotection/sybilprotectionv1/performance/tracker_test.go +++ b/pkg/protocol/sybilprotection/sybilprotectionv1/performance/tracker_test.go @@ -48,7 +48,7 @@ func TestManager_Rewards(t *testing.T) { } ts.ApplyEpochActions(epoch, epochActions) ts.AssertEpochRewards(epoch, epochActions) - // better performin validator should get more rewards + // better performing validator should get more rewards ts.AssertValidatorRewardGreaterThan("A", "B", epoch, epochActions) epoch = iotago.EpochIndex(3) diff --git a/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go b/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go index 25b82dc89..2a2d078d6 100644 --- a/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go +++ b/pkg/protocol/sybilprotection/sybilprotectionv1/sybilprotection.go @@ -5,8 +5,10 @@ import ( "sort" "github.com/iotaledger/hive.go/ads" + "github.com/iotaledger/hive.go/core/safemath" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/kvstore/mapdb" + "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/module" "github.com/iotaledger/hive.go/runtime/options" "github.com/iotaledger/hive.go/runtime/syncutils" @@ -152,7 +154,9 @@ func (o *SybilProtection) CommitSlot(slot iotago.SlotIndex) (committeeRoot iotag timeProvider := apiForSlot.TimeProvider() currentEpoch := timeProvider.EpochFromSlot(slot) nextEpoch := currentEpoch + 1 + prevEpoch := lo.Return1(safemath.SafeSub(currentEpoch, 1)) currentEpochEndSlot := timeProvider.EpochEnd(currentEpoch) + isEpochEndSlot := slot == currentEpochEndSlot maxCommittableAge := apiForSlot.ProtocolParameters().MaxCommittableAge() // Determine the committee root. @@ -188,7 +192,7 @@ func (o *SybilProtection) CommitSlot(slot iotago.SlotIndex) (committeeRoot iotag // Handle performance tracking for the current epoch. { - if slot == currentEpochEndSlot { + if isEpochEndSlot { committee, exists := o.performanceTracker.LoadCommitteeForEpoch(currentEpoch) if !exists { return iotago.Identifier{}, iotago.Identifier{}, ierrors.Wrapf(err, "committee for a finished epoch %d not found", currentEpoch) @@ -203,9 +207,11 @@ func (o *SybilProtection) CommitSlot(slot iotago.SlotIndex) (committeeRoot iotag // Determine the rewards root. { - targetRewardsEpoch := currentEpoch - if slot == currentEpochEndSlot { - targetRewardsEpoch = nextEpoch + // We only update the rewards root if the slot is the last slot of the epoch. + // Otherwise, we reuse the rewards root from the previous epoch. + targetRewardsEpoch := prevEpoch + if isEpochEndSlot { + targetRewardsEpoch = currentEpoch } rewardsRoot, err = o.performanceTracker.RewardsRoot(targetRewardsEpoch)