From b4c03947bdd9aa35f5a033a4167943e0f9b4db21 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 18 Sep 2025 19:12:29 +0900 Subject: [PATCH 1/2] impl: fp reference counting logic --- proto/babylon/incentive/rewards.proto | 6 +- testutil/datagen/incentive.go | 2 +- x/incentive/keeper/grpc_query_test.go | 4 +- x/incentive/keeper/reward_tracker.go | 78 ++++++++++++++-- x/incentive/keeper/reward_tracker_store.go | 7 ++ x/incentive/keeper/reward_tracker_test.go | 19 +++- x/incentive/types/rewards.go | 3 +- x/incentive/types/rewards.pb.go | 102 ++++++++++++++------- 8 files changed, 172 insertions(+), 49 deletions(-) diff --git a/proto/babylon/incentive/rewards.proto b/proto/babylon/incentive/rewards.proto index 7957b548d..1e29c037a 100644 --- a/proto/babylon/incentive/rewards.proto +++ b/proto/babylon/incentive/rewards.proto @@ -22,8 +22,10 @@ message FinalityProviderHistoricalRewards { (gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" ]; - // TODO(rafilx): add reference count for state prunning + // The reference count indicates the number of objects + // which might need to reference this historical entry at any point. // https://github.com/cosmos/cosmos-sdk/blob/d9c53bfefc1e75a3c6b09065ea8b3a836cda0d18/x/distribution/types/distribution.pb.go#L98 + uint32 reference_count = 2; } // FinalityProviderCurrentRewards represents the current rewards of the pool of @@ -31,7 +33,7 @@ message FinalityProviderHistoricalRewards { // Note: This rewards are for the BTC delegators that delegated to this FP // the FP itself is not the owner or can withdraw this rewards. // If a slash event happens with this finality provider, all the delegations -// need to withdraw to the RewardGauge and the related scrutures should be +// need to withdraw to the RewardGauge and the related structures should be // deleted. Key: Prefix + Finality provider bech32 address. message FinalityProviderCurrentRewards { // CurrentRewards is the current rewards that the finality provider have and diff --git a/testutil/datagen/incentive.go b/testutil/datagen/incentive.go index 85a13fd0c..d16611083 100644 --- a/testutil/datagen/incentive.go +++ b/testutil/datagen/incentive.go @@ -160,7 +160,7 @@ func GenRandomBTCDelegationRewardsTracker(r *rand.Rand) itypes.BTCDelegationRewa func GenRandomFPHistRwd(r *rand.Rand) itypes.FinalityProviderHistoricalRewards { rwd := GenRandomCoins(r) - return itypes.NewFinalityProviderHistoricalRewards(rwd) + return itypes.NewFinalityProviderHistoricalRewards(rwd, uint32(1)) } func GenRandomFPHistRwdWithDecimals(r *rand.Rand) itypes.FinalityProviderHistoricalRewards { diff --git a/x/incentive/keeper/grpc_query_test.go b/x/incentive/keeper/grpc_query_test.go index 3a68d310b..4524a0b2d 100644 --- a/x/incentive/keeper/grpc_query_test.go +++ b/x/incentive/keeper/grpc_query_test.go @@ -139,7 +139,7 @@ func FuzzDelegationRewardsQuery(f *testing.F) { // set start historical rewards corresponding to btcRwd.StartPeriodCumulativeReward amtRwdInHistStart := fpCurrentRwd.CurrentRewards.MulInt(types.DecimalRewards).QuoInt(math.NewInt(2)) - startHist := types.NewFinalityProviderHistoricalRewards(amtRwdInHistStart) + startHist := types.NewFinalityProviderHistoricalRewards(amtRwdInHistStart, uint32(1)) sfphrKey := collections.Join(fp.Bytes(), btcRwd.StartPeriodCumulativeReward) @@ -153,7 +153,7 @@ func FuzzDelegationRewardsQuery(f *testing.F) { // set end period historical rewards // end period for calculation is fpCurrentRwd.Period-1 amtRwdInHistEnd := amtRwdInHistStart.Add(fpCurrentRwd.CurrentRewards.MulInt(types.DecimalRewards).QuoInt(fpCurrentRwd.TotalActiveSat)...) - endHist := types.NewFinalityProviderHistoricalRewards(amtRwdInHistEnd) + endHist := types.NewFinalityProviderHistoricalRewards(amtRwdInHistEnd, uint32(1)) efphrKey := collections.Join(fp.Bytes(), fpCurrentRwd.Period-1) diff --git a/x/incentive/keeper/reward_tracker.go b/x/incentive/keeper/reward_tracker.go index a2cff9e50..8690c86b0 100644 --- a/x/incentive/keeper/reward_tracker.go +++ b/x/incentive/keeper/reward_tracker.go @@ -40,7 +40,7 @@ func (k Keeper) BtcDelegationActivated(ctx context.Context, fp, del sdk.AccAddre // BtcDelegationUnbonded it modifies the total amount of satoshi staked // for the delegation (fp, del) and for the finality provider by subtracting. // Since it modifies the active amount it triggers the increment of fp period, -// creationg of new historical reward, withdraw of rewards to gauge +// creation of new historical reward, withdraw of rewards to gauge // and initialization of a new delegation. // It errors out if the unbond amount is higher than the total amount staked. func (k Keeper) BtcDelegationUnbonded(ctx context.Context, fp, del sdk.AccAddress, sat sdkmath.Int) error { @@ -92,7 +92,25 @@ func (k Keeper) btcDelegationModified( ctx context.Context, fp, del sdk.AccAddress, ) error { - return k.btcDelegationModifiedWithPreInitDel(ctx, fp, del, func(ctx context.Context, fp, del sdk.AccAddress) error { return nil }) + endedPeriod, err := k.IncrementFinalityProviderPeriod(ctx, fp) + if err != nil { + return err + } + + if err = k.CalculateBTCDelegationRewardsAndSendToGauge(ctx, fp, del, endedPeriod); err != nil { + return err + } + + btcDelRwdTracker, err := k.GetBTCDelegationRewardsTracker(ctx, fp, del) + if err != nil { + return err + } + + if err := k.decrementReferenceCount(ctx, fp, btcDelRwdTracker.StartPeriodCumulativeReward); err != nil { + return err + } + + return k.initializeBTCDelegation(ctx, fp, del) } // btcDelegationModifiedWithPreInitDel does the procedure when a BTC delegation has @@ -112,11 +130,11 @@ func (k Keeper) btcDelegationModifiedWithPreInitDel( return err } - if err := k.CalculateBTCDelegationRewardsAndSendToGauge(ctx, fp, del, endedPeriod); err != nil { + if err = k.CalculateBTCDelegationRewardsAndSendToGauge(ctx, fp, del, endedPeriod); err != nil { return err } - if err := preInitializeDelegation(ctx, fp, del); err != nil { + if err = preInitializeDelegation(ctx, fp, del); err != nil { return err } @@ -240,7 +258,13 @@ func (k Keeper) IncrementFinalityProviderPeriod(ctx context.Context, fp sdk.AccA return 0, err } - newFpHistoricalRwd := types.NewFinalityProviderHistoricalRewards(fpHistoricalRwd.CumulativeRewardsPerSat.Add(currentRewardsPerSat...)) + // decrement reference count + err = k.decrementReferenceCount(ctx, fp, fpCurrentRwd.Period-1) + if err != nil { + return 0, err + } + + newFpHistoricalRwd := types.NewFinalityProviderHistoricalRewards(fpHistoricalRwd.CumulativeRewardsPerSat.Add(currentRewardsPerSat...), uint32(1)) if err := k.setFinalityProviderHistoricalRewards(ctx, fp, fpCurrentRwd.Period, newFpHistoricalRwd); err != nil { return 0, err } @@ -254,12 +278,43 @@ func (k Keeper) IncrementFinalityProviderPeriod(ctx context.Context, fp sdk.AccA return fpCurrentRwd.Period, nil } +func (k Keeper) incrementReferenceCount(ctx context.Context, fp sdk.AccAddress, period uint64) error { + historical, err := k.GetFinalityProviderHistoricalRewards(ctx, fp, period) + if err != nil { + return err + } + + historical.ReferenceCount++ + if historical.ReferenceCount > 2 { + panic("reference count should never be greater than 2") + } + + return k.setFinalityProviderHistoricalRewards(ctx, fp, period, historical) +} + +func (k Keeper) decrementReferenceCount(ctx context.Context, fp sdk.AccAddress, period uint64) error { + historical, err := k.GetFinalityProviderHistoricalRewards(ctx, fp, period) + if err != nil { + return err + } + + if historical.ReferenceCount == 0 { + panic("cannot set negative reference count") + } + historical.ReferenceCount-- + if historical.ReferenceCount == 0 { + k.deleteFinalityProviderHistoricalRewards(ctx, fp, period) + } + + return k.setFinalityProviderHistoricalRewards(ctx, fp, period, historical) +} + // initializeFinalityProvider initializes a new finality provider current rewards at period 1, empty rewards and zero sats // and also creates a new historical rewards at period 0 and zero rewards as well. // It does not verifies if it exists prior to overwrite, who calls it needs to verify. func (k Keeper) initializeFinalityProvider(ctx context.Context, fp sdk.AccAddress) (types.FinalityProviderCurrentRewards, error) { // historical rewards starts at the period 0 - err := k.setFinalityProviderHistoricalRewards(ctx, fp, 0, types.NewFinalityProviderHistoricalRewards(sdk.NewCoins())) + err := k.setFinalityProviderHistoricalRewards(ctx, fp, 0, types.NewFinalityProviderHistoricalRewards(sdk.NewCoins(), uint32(1))) if err != nil { return types.FinalityProviderCurrentRewards{}, err } @@ -276,16 +331,21 @@ func (k Keeper) initializeFinalityProvider(ctx context.Context, fp sdk.AccAddres // modification to the amount of satoshi staked from this btc delegator to // this finality provider (activivation or unbonding) of BTC delegations, it // should withdraw all rewards (send to gauge) and initialize a new BTCDelegationRewardsTracker. -// TODO: add reference count to keep track of possible prunning state of val rewards func (k Keeper) initializeBTCDelegation(ctx context.Context, fp, del sdk.AccAddress) error { // period has already been incremented prior to call this function // it is needed to store the period ended by this delegation action // as a starting point of the delegation rewards calculation - valCurrentRewards, err := k.GetFinalityProviderCurrentRewards(ctx, fp) + fpCurrentRwd, err := k.GetFinalityProviderCurrentRewards(ctx, fp) + if err != nil { + return err + } + previousPeriod := fpCurrentRwd.Period - 1 + + // increment reference count for the period we're going to track + err = k.incrementReferenceCount(ctx, fp, previousPeriod) if err != nil { return err } - previousPeriod := valCurrentRewards.Period - 1 btcDelRwdTracker, err := k.GetBTCDelegationRewardsTracker(ctx, fp, del) if err != nil { diff --git a/x/incentive/keeper/reward_tracker_store.go b/x/incentive/keeper/reward_tracker_store.go index 0fb8639dc..46d04d5fa 100644 --- a/x/incentive/keeper/reward_tracker_store.go +++ b/x/incentive/keeper/reward_tracker_store.go @@ -213,6 +213,13 @@ func (k Keeper) setFinalityProviderHistoricalRewards(ctx context.Context, fp sdk return k.finalityProviderHistoricalRewards.Set(ctx, collections.Join(fp.Bytes(), period), rwd) } +// deleteFinalityProviderHistoricalRewards deletes the historical rewards of FP based on the (fp, period) pair +func (k Keeper) deleteFinalityProviderHistoricalRewards(ctx context.Context, fp sdk.AccAddress, period uint64) { + if err := k.finalityProviderHistoricalRewards.Remove(ctx, collections.Join(fp.Bytes(), period)); err != nil { + k.Logger(sdk.UnwrapSDKContext(ctx)).Error("error deleting FinalityProviderHistoricalRewards", "error", err) + } +} + // subDelegationSat subtracts an amount of active stake from the BTCDelegationRewardsTracker // and the FinalityProviderCurrentRewards. // There is no need to check if the fp or delegation exists, because they should exist diff --git a/x/incentive/keeper/reward_tracker_test.go b/x/incentive/keeper/reward_tracker_test.go index 6a33649f7..bad524f0d 100644 --- a/x/incentive/keeper/reward_tracker_test.go +++ b/x/incentive/keeper/reward_tracker_test.go @@ -355,7 +355,7 @@ func FuzzCheckCalculateDelegationRewardsBetween(f *testing.F) { endingPeriod := btcRwd.StartPeriodCumulativeReward + 1 // creates a bad historical ending period that has less rewards than the starting one - err = k.setFinalityProviderHistoricalRewards(ctx, fp, endingPeriod, types.NewFinalityProviderHistoricalRewards(historicalStartPeriod.CumulativeRewardsPerSat.QuoInt(math.NewInt(2)))) + err = k.setFinalityProviderHistoricalRewards(ctx, fp, endingPeriod, types.NewFinalityProviderHistoricalRewards(historicalStartPeriod.CumulativeRewardsPerSat.QuoInt(math.NewInt(2)), uint32(1))) require.NoError(t, err) require.Panics(t, func() { _, _ = k.calculateDelegationRewardsBetween(ctx, fp, btcRwd, endingPeriod) @@ -432,7 +432,7 @@ func FuzzCheckIncrementFinalityProviderPeriod(f *testing.F) { require.NoError(t, err) amtRwdInHistorical := fpCurrentRwd.CurrentRewards.MulInt(types.DecimalRewards).QuoInt(math.NewInt(2)) - err = k.setFinalityProviderHistoricalRewards(ctx, fp, fpCurrentRwd.Period-1, types.NewFinalityProviderHistoricalRewards(amtRwdInHistorical)) + err = k.setFinalityProviderHistoricalRewards(ctx, fp, fpCurrentRwd.Period-1, types.NewFinalityProviderHistoricalRewards(amtRwdInHistorical, uint32(1))) require.NoError(t, err) endedPeriod, err = k.IncrementFinalityProviderPeriod(ctx, fp) @@ -469,6 +469,13 @@ func FuzzCheckInitializeBTCDelegation(f *testing.F) { err = k.SetFinalityProviderCurrentRewards(ctx, fp, fpCurrentRwd) require.NoError(t, err) + err = k.initializeBTCDelegation(ctx, fp, del) + require.EqualError(t, err, types.ErrFPHistoricalRewardsNotFound.Error()) + + fpHistoricalRwd := datagen.GenRandomFPHistRwd(r) + err = k.setFinalityProviderHistoricalRewards(ctx, fp, fpCurrentRwd.Period-1, fpHistoricalRwd) + require.NoError(t, err) + err = k.initializeBTCDelegation(ctx, fp, del) require.EqualError(t, err, types.ErrBTCDelegationRewardsTrackerNotFound.Error()) @@ -476,12 +483,18 @@ func FuzzCheckInitializeBTCDelegation(f *testing.F) { err = k.setBTCDelegationRewardsTracker(ctx, fp, del, delBtcRwdTrackerBeforeInitialize) require.NoError(t, err) + // increment period since reference count is already increased in the previous + // initializeBTCDelegation + endedPeriod, err := k.IncrementFinalityProviderPeriod(ctx, fp) + require.NoError(t, err) + require.Equal(t, endedPeriod, fpCurrentRwd.Period) + err = k.initializeBTCDelegation(ctx, fp, del) require.NoError(t, err) actBtcDelRwdTracker, err := k.GetBTCDelegationRewardsTracker(ctx, fp, del) require.NoError(t, err) - require.Equal(t, fpCurrentRwd.Period-1, actBtcDelRwdTracker.StartPeriodCumulativeReward) + require.Equal(t, fpCurrentRwd.Period, actBtcDelRwdTracker.StartPeriodCumulativeReward) require.Equal(t, delBtcRwdTrackerBeforeInitialize.TotalActiveSat, actBtcDelRwdTracker.TotalActiveSat) }) } diff --git a/x/incentive/types/rewards.go b/x/incentive/types/rewards.go index 2fb20f3e8..5ae4d48f9 100644 --- a/x/incentive/types/rewards.go +++ b/x/incentive/types/rewards.go @@ -58,9 +58,10 @@ func NewFinalityProviderCurrentRewards(currentRewards sdk.Coins, period uint64, } } -func NewFinalityProviderHistoricalRewards(cumulativeRewardsPerSat sdk.Coins) FinalityProviderHistoricalRewards { +func NewFinalityProviderHistoricalRewards(cumulativeRewardsPerSat sdk.Coins, referenceCount uint32) FinalityProviderHistoricalRewards { return FinalityProviderHistoricalRewards{ CumulativeRewardsPerSat: cumulativeRewardsPerSat, + ReferenceCount: referenceCount, } } diff --git a/x/incentive/types/rewards.pb.go b/x/incentive/types/rewards.pb.go index 43d3b0a88..106629d98 100644 --- a/x/incentive/types/rewards.pb.go +++ b/x/incentive/types/rewards.pb.go @@ -39,6 +39,10 @@ type FinalityProviderHistoricalRewards struct { // by the total sat amount delegated // https://github.com/cosmos/cosmos-sdk/blob/e76102f885b71fd6e1c1efb692052173c4b3c3a3/x/distribution/keeper/delegation.go#L47 CumulativeRewardsPerSat github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=cumulative_rewards_per_sat,json=cumulativeRewardsPerSat,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"cumulative_rewards_per_sat"` + // The reference count indicates the number of objects + // which might need to reference this historical entry at any point. + // https://github.com/cosmos/cosmos-sdk/blob/d9c53bfefc1e75a3c6b09065ea8b3a836cda0d18/x/distribution/types/distribution.pb.go#L98 + ReferenceCount uint32 `protobuf:"varint,2,opt,name=reference_count,json=referenceCount,proto3" json:"reference_count,omitempty"` } func (m *FinalityProviderHistoricalRewards) Reset() { *m = FinalityProviderHistoricalRewards{} } @@ -81,12 +85,19 @@ func (m *FinalityProviderHistoricalRewards) GetCumulativeRewardsPerSat() github_ return nil } +func (m *FinalityProviderHistoricalRewards) GetReferenceCount() uint32 { + if m != nil { + return m.ReferenceCount + } + return 0 +} + // FinalityProviderCurrentRewards represents the current rewards of the pool of // BTC delegations that delegated for this finality provider is entitled to. // Note: This rewards are for the BTC delegators that delegated to this FP // the FP itself is not the owner or can withdraw this rewards. // If a slash event happens with this finality provider, all the delegations -// need to withdraw to the RewardGauge and the related scrutures should be +// need to withdraw to the RewardGauge and the related structures should be // deleted. Key: Prefix + Finality provider bech32 address. type FinalityProviderCurrentRewards struct { // CurrentRewards is the current rewards that the finality provider have and @@ -217,36 +228,38 @@ func init() { func init() { proto.RegisterFile("babylon/incentive/rewards.proto", fileDescriptor_fa5a587351117eb0) } var fileDescriptor_fa5a587351117eb0 = []byte{ - // 459 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0xbf, 0x8e, 0x13, 0x31, - 0x10, 0xc6, 0xe3, 0x1c, 0xba, 0xc2, 0xa0, 0x03, 0x22, 0xfe, 0xe4, 0x72, 0x92, 0x13, 0xae, 0x8a, - 0x84, 0xb2, 0xe6, 0x00, 0xd1, 0x93, 0x45, 0x88, 0xeb, 0xa2, 0x70, 0x34, 0x34, 0x2b, 0xaf, 0xd7, - 0xca, 0x59, 0xd9, 0x78, 0x22, 0x7b, 0xb2, 0x90, 0x07, 0x40, 0xa2, 0xe4, 0x39, 0x28, 0xa8, 0x68, - 0x78, 0x83, 0x2b, 0x4f, 0x54, 0x88, 0xe2, 0x40, 0xc9, 0x8b, 0xa0, 0xb5, 0x1d, 0x38, 0x0e, 0x3a, - 0x44, 0xb5, 0x3b, 0x3b, 0x9f, 0xe7, 0xfb, 0xe9, 0xf3, 0x2c, 0xed, 0xe6, 0x22, 0x5f, 0x96, 0x60, - 0xb8, 0x36, 0x52, 0x19, 0xd4, 0x95, 0xe2, 0x56, 0xbd, 0x12, 0xb6, 0x70, 0xc9, 0xdc, 0x02, 0x42, - 0xeb, 0x7a, 0x14, 0x24, 0x3f, 0x05, 0x9d, 0x1b, 0x13, 0x98, 0x80, 0xef, 0xf2, 0xfa, 0x2d, 0x08, - 0x3b, 0x4c, 0x82, 0x9b, 0x81, 0xe3, 0xb9, 0x70, 0x8a, 0x57, 0x07, 0xb9, 0x42, 0x71, 0xc0, 0x25, - 0x68, 0x13, 0xfb, 0xbb, 0xa1, 0x9f, 0x85, 0x83, 0xa1, 0x08, 0xad, 0xfd, 0x0f, 0x84, 0xde, 0x79, - 0xaa, 0x8d, 0x28, 0x35, 0x2e, 0x47, 0x16, 0x2a, 0x5d, 0x28, 0xfb, 0x4c, 0x3b, 0x04, 0xab, 0xa5, - 0x28, 0xc7, 0x81, 0xa7, 0xf5, 0x96, 0xd0, 0x8e, 0x5c, 0xcc, 0x16, 0xa5, 0xa8, 0x29, 0xb2, 0x88, - 0x99, 0xcd, 0x95, 0xcd, 0x9c, 0xc0, 0x36, 0xe9, 0x6d, 0xf5, 0x2f, 0xdf, 0xdf, 0x4d, 0xe2, 0xe4, - 0x1a, 0x23, 0x89, 0x18, 0x49, 0x0a, 0xda, 0x0c, 0xef, 0x9d, 0x9c, 0x75, 0x1b, 0xef, 0xbf, 0x75, - 0xfb, 0x13, 0x8d, 0xc7, 0x8b, 0x3c, 0x91, 0x30, 0x8b, 0x18, 0xf1, 0x31, 0x70, 0xc5, 0x94, 0xe3, - 0x72, 0xae, 0x9c, 0x3f, 0xe0, 0xc6, 0xb7, 0x7f, 0xd9, 0x45, 0x88, 0x91, 0xb2, 0xcf, 0x05, 0xee, - 0xbf, 0x69, 0x52, 0x76, 0x11, 0x38, 0x5d, 0x58, 0xab, 0x0c, 0x6e, 0x68, 0x91, 0x5e, 0x95, 0xe1, - 0xcb, 0x86, 0xf4, 0x7f, 0x10, 0xee, 0xc8, 0xdf, 0x5d, 0x6f, 0xd1, 0xed, 0xb9, 0xb2, 0x1a, 0x8a, - 0x76, 0xb3, 0x47, 0xfa, 0x97, 0xc6, 0xb1, 0x6a, 0xbd, 0xa0, 0xd7, 0x10, 0x50, 0x94, 0x99, 0x90, - 0x3e, 0xbc, 0x3a, 0xb0, 0xad, 0x1e, 0xe9, 0x5f, 0x19, 0xde, 0xad, 0x3d, 0xbf, 0x9e, 0x75, 0x6f, - 0x06, 0x07, 0x57, 0x4c, 0x13, 0x0d, 0x7c, 0x26, 0xf0, 0x38, 0x39, 0x34, 0xf8, 0xf9, 0xe3, 0x80, - 0x46, 0xdc, 0x43, 0x83, 0xe3, 0x1d, 0x3f, 0xe4, 0xb1, 0x9f, 0x51, 0xe7, 0xf0, 0x89, 0xd0, 0xbd, - 0xe1, 0x51, 0xfa, 0x44, 0x95, 0x6a, 0x22, 0x50, 0x83, 0x89, 0x1c, 0x47, 0x56, 0xc8, 0xa9, 0xb2, - 0xad, 0x94, 0x32, 0x87, 0xc2, 0x62, 0x16, 0x30, 0xb2, 0x3f, 0xae, 0xaf, 0x4d, 0x3c, 0xe6, 0x9e, - 0x57, 0x8d, 0xbc, 0x28, 0xbd, 0x90, 0xf9, 0x5f, 0xd9, 0x9b, 0xff, 0xcc, 0x3e, 0x1c, 0x9d, 0xac, - 0x18, 0x39, 0x5d, 0x31, 0xf2, 0x7d, 0xc5, 0xc8, 0xbb, 0x35, 0x6b, 0x9c, 0xae, 0x59, 0xe3, 0xcb, - 0x9a, 0x35, 0x5e, 0x3e, 0x3a, 0x17, 0x7f, 0xdc, 0xfe, 0x52, 0xe4, 0x6e, 0xa0, 0x61, 0x53, 0xf2, - 0xea, 0x21, 0x7f, 0x7d, 0xee, 0x97, 0xf1, 0x57, 0x92, 0x6f, 0xfb, 0x6d, 0x7e, 0xf0, 0x23, 0x00, - 0x00, 0xff, 0xff, 0x84, 0xb1, 0xd4, 0x41, 0x54, 0x03, 0x00, 0x00, + // 484 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x93, 0xcd, 0x6e, 0x13, 0x31, + 0x10, 0xc7, 0xe3, 0x16, 0xf5, 0x60, 0x20, 0x85, 0x15, 0x1f, 0x69, 0x2a, 0x6d, 0x42, 0x2e, 0x44, + 0x42, 0x59, 0x53, 0x40, 0xdc, 0xc9, 0x22, 0x44, 0x6f, 0xd1, 0xb6, 0x5c, 0xb8, 0xac, 0xbc, 0x5e, + 0x93, 0x5a, 0xd9, 0x78, 0x22, 0x7b, 0x36, 0x90, 0x07, 0x40, 0xe2, 0xc8, 0x73, 0x70, 0xe6, 0xc2, + 0x1b, 0xf4, 0x58, 0x71, 0x01, 0x71, 0x28, 0x28, 0x79, 0x11, 0xb4, 0x5e, 0xa7, 0x94, 0xc2, 0x0d, + 0x71, 0xda, 0x9d, 0x99, 0xbf, 0x67, 0x7e, 0x33, 0x63, 0xd3, 0x4e, 0xc6, 0xb3, 0x45, 0x01, 0x9a, + 0x29, 0x2d, 0xa4, 0x46, 0x35, 0x97, 0xcc, 0xc8, 0xd7, 0xdc, 0xe4, 0x36, 0x9a, 0x19, 0x40, 0x08, + 0xae, 0x7b, 0x41, 0x74, 0x26, 0x68, 0xdf, 0x18, 0xc3, 0x18, 0x5c, 0x94, 0x55, 0x7f, 0xb5, 0xb0, + 0x1d, 0x0a, 0xb0, 0x53, 0xb0, 0x2c, 0xe3, 0x56, 0xb2, 0xf9, 0x5e, 0x26, 0x91, 0xef, 0x31, 0x01, + 0x4a, 0xfb, 0xf8, 0x4e, 0x1d, 0x4f, 0xeb, 0x83, 0xb5, 0x51, 0x87, 0x7a, 0x5f, 0x08, 0xbd, 0xf3, + 0x4c, 0x69, 0x5e, 0x28, 0x5c, 0x8c, 0x0c, 0xcc, 0x55, 0x2e, 0xcd, 0x73, 0x65, 0x11, 0x8c, 0x12, + 0xbc, 0x48, 0x6a, 0x9e, 0xe0, 0x1d, 0xa1, 0x6d, 0x51, 0x4e, 0xcb, 0x82, 0x57, 0x14, 0xa9, 0xc7, + 0x4c, 0x67, 0xd2, 0xa4, 0x96, 0x63, 0x8b, 0x74, 0x37, 0xfb, 0x97, 0x1f, 0xec, 0x44, 0x3e, 0x73, + 0x85, 0x11, 0x79, 0x8c, 0x28, 0x06, 0xa5, 0x87, 0xf7, 0x8f, 0x4f, 0x3b, 0x8d, 0x0f, 0xdf, 0x3b, + 0xfd, 0xb1, 0xc2, 0xa3, 0x32, 0x8b, 0x04, 0x4c, 0x3d, 0x86, 0xff, 0x0c, 0x6c, 0x3e, 0x61, 0xb8, + 0x98, 0x49, 0xeb, 0x0e, 0xd8, 0xe4, 0xf6, 0xaf, 0x72, 0x1e, 0x62, 0x24, 0xcd, 0x01, 0xc7, 0xe0, + 0x2e, 0xdd, 0x36, 0xf2, 0x95, 0x34, 0x52, 0x0b, 0x99, 0x0a, 0x28, 0x35, 0xb6, 0x36, 0xba, 0xa4, + 0x7f, 0x35, 0x69, 0x9e, 0xb9, 0xe3, 0xca, 0xdb, 0x7b, 0xbb, 0x41, 0xc3, 0x8b, 0x9d, 0xc5, 0xa5, + 0x31, 0x52, 0xe3, 0xba, 0x2d, 0xa4, 0xdb, 0xa2, 0xf6, 0xac, 0x5b, 0xfa, 0x1f, 0xad, 0x34, 0xc5, + 0xef, 0x55, 0x6f, 0xd1, 0xad, 0x99, 0x34, 0x0a, 0x72, 0x07, 0x7e, 0x29, 0xf1, 0x56, 0xf0, 0x82, + 0x5e, 0x43, 0x40, 0x5e, 0xa4, 0x5c, 0xb8, 0x29, 0x57, 0x93, 0xdd, 0xec, 0x92, 0xfe, 0x95, 0xe1, + 0xbd, 0xaa, 0xe6, 0xb7, 0xd3, 0xce, 0xcd, 0xba, 0x82, 0xcd, 0x27, 0x91, 0x02, 0x36, 0xe5, 0x78, + 0x14, 0xed, 0x6b, 0xfc, 0xfc, 0x71, 0x40, 0x3d, 0xee, 0xbe, 0xc6, 0xa4, 0xe9, 0x92, 0x3c, 0x71, + 0x39, 0x0e, 0x38, 0xf6, 0x3e, 0x11, 0xba, 0x3b, 0x3c, 0x8c, 0x9f, 0xca, 0x42, 0x8e, 0x39, 0x2a, + 0xd0, 0x9e, 0xe3, 0xd0, 0x70, 0x31, 0x91, 0x26, 0x88, 0x69, 0x68, 0x91, 0x1b, 0x4c, 0x6b, 0x8c, + 0xf4, 0x8f, 0x3d, 0xb7, 0x88, 0xc3, 0xdc, 0x75, 0xaa, 0x91, 0x13, 0xc5, 0x17, 0x96, 0xf3, 0x57, + 0xf6, 0x8d, 0x7f, 0x66, 0x1f, 0x8e, 0x8e, 0x97, 0x21, 0x39, 0x59, 0x86, 0xe4, 0xc7, 0x32, 0x24, + 0xef, 0x57, 0x61, 0xe3, 0x64, 0x15, 0x36, 0xbe, 0xae, 0xc2, 0xc6, 0xcb, 0xc7, 0xe7, 0xc6, 0xef, + 0x9f, 0x49, 0xc1, 0x33, 0x3b, 0x50, 0xb0, 0x36, 0xd9, 0xfc, 0x11, 0x7b, 0x73, 0xee, 0x6d, 0xb9, + 0x95, 0x64, 0x5b, 0xee, 0xda, 0x3f, 0xfc, 0x19, 0x00, 0x00, 0xff, 0xff, 0xdd, 0x67, 0xcf, 0x8c, + 0x7d, 0x03, 0x00, 0x00, } func (m *FinalityProviderHistoricalRewards) Marshal() (dAtA []byte, err error) { @@ -269,6 +282,11 @@ func (m *FinalityProviderHistoricalRewards) MarshalToSizedBuffer(dAtA []byte) (i _ = i var l int _ = l + if m.ReferenceCount != 0 { + i = encodeVarintRewards(dAtA, i, uint64(m.ReferenceCount)) + i-- + dAtA[i] = 0x10 + } if len(m.CumulativeRewardsPerSat) > 0 { for iNdEx := len(m.CumulativeRewardsPerSat) - 1; iNdEx >= 0; iNdEx-- { { @@ -399,6 +417,9 @@ func (m *FinalityProviderHistoricalRewards) Size() (n int) { n += 1 + l + sovRewards(uint64(l)) } } + if m.ReferenceCount != 0 { + n += 1 + sovRewards(uint64(m.ReferenceCount)) + } return n } @@ -505,6 +526,25 @@ func (m *FinalityProviderHistoricalRewards) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ReferenceCount", wireType) + } + m.ReferenceCount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRewards + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ReferenceCount |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRewards(dAtA[iNdEx:]) From e2ae1e36670f996f56042b695cdfc27261dae716 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 28 Sep 2025 23:10:21 +0900 Subject: [PATCH 2/2] chore: check ref count in the test --- x/incentive/keeper/reward_tracker_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/x/incentive/keeper/reward_tracker_test.go b/x/incentive/keeper/reward_tracker_test.go index bad524f0d..e91d18efe 100644 --- a/x/incentive/keeper/reward_tracker_test.go +++ b/x/incentive/keeper/reward_tracker_test.go @@ -541,14 +541,14 @@ func TestIncrementFinalityProviderPeriod(t *testing.T) { require.Equal(t, fp1EndedPeriod, uint64(1)) checkFpCurrentRwd(t, ctx, k, fp1, fp1EndedPeriod, sdk.NewCoins(), math.NewInt(0)) - checkFpHistoricalRwd(t, ctx, k, fp1, 0, sdk.NewCoins()) + checkFpHistoricalRwdWithRefCount(t, ctx, k, fp1, 0, sdk.NewCoins(), uint32(1)) rwdAddedToPeriod1 := newBaseCoins(2_000000) // 2bbn err = k.AddFinalityProviderRewardsForBtcDelegations(ctx, fp1, rwdAddedToPeriod1) require.NoError(t, err) // historical should not modify the rewards for the period already created - checkFpHistoricalRwd(t, ctx, k, fp1, 0, sdk.NewCoins()) + checkFpHistoricalRwdWithRefCount(t, ctx, k, fp1, 0, sdk.NewCoins(), uint32(1)) checkFpCurrentRwd(t, ctx, k, fp1, fp1EndedPeriod, rwdAddedToPeriod1, math.NewInt(0)) // needs to add some voting power so it can calculate the amount of rewards per share @@ -561,7 +561,7 @@ func TestIncrementFinalityProviderPeriod(t *testing.T) { require.Equal(t, fp1EndedPeriod, uint64(1)) // now the historical that just ended should have as cumulative rewards 4000ubbn 2_000000ubbn/500sats - checkFpHistoricalRwd(t, ctx, k, fp1, fp1EndedPeriod, newBaseCoins(4000).MulInt(types.DecimalRewards)) + checkFpHistoricalRwdWithRefCount(t, ctx, k, fp1, fp1EndedPeriod, newBaseCoins(4000).MulInt(types.DecimalRewards), uint32(1)) checkFpCurrentRwd(t, ctx, k, fp1, fp1EndedPeriod+1, sdk.NewCoins(), satsDelegated) fp2EndedPeriod, err := k.IncrementFinalityProviderPeriod(ctx, fp2) @@ -569,10 +569,11 @@ func TestIncrementFinalityProviderPeriod(t *testing.T) { require.Equal(t, fp2EndedPeriod, uint64(1)) } -func checkFpHistoricalRwd(t *testing.T, ctx sdk.Context, k *Keeper, fp sdk.AccAddress, period uint64, expectedRwd sdk.Coins) { +func checkFpHistoricalRwdWithRefCount(t *testing.T, ctx sdk.Context, k *Keeper, fp sdk.AccAddress, period uint64, expectedRwd sdk.Coins, expectedRefCount uint32) { historical, err := k.GetFinalityProviderHistoricalRewards(ctx, fp, period) require.NoError(t, err) require.Equal(t, historical.CumulativeRewardsPerSat.String(), expectedRwd.String()) + require.Equal(t, historical.ReferenceCount, expectedRefCount) } func checkFpCurrentRwd(t *testing.T, ctx sdk.Context, k *Keeper, fp sdk.AccAddress, expectedPeriod uint64, expectedRwd sdk.Coins, totalActiveSat math.Int) {