Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2c11053
temp data structurues for pse
miladz68 Feb 24, 2026
cf9684b
add TotalScore and OngoingDistribution storages to keeper
metalarm10 Feb 26, 2026
4339189
add addToScore helpers for atomic score updates
metalarm10 Feb 26, 2026
bb034c2
rewrite hooks with 3-scenario logic for multi-block distribution
metalarm10 Feb 26, 2026
990fa47
remove redundant addToTotalScore func
metalarm10 Feb 26, 2026
df904d0
add phase-1 batched score conversion
metalarm10 Feb 27, 2026
fac88cf
add phase-2 batched token distribution
metalarm10 Feb 27, 2026
22e966f
rewrite EndBlocker with multi-block phase routing
metalarm10 Feb 27, 2026
6e6aee1
reject schedule update during ongoing distribution
metalarm10 Feb 27, 2026
5ef1e67
remove deprecated score map
metalarm10 Mar 2, 2026
c060559
simplify getCurrentDistributionID to support zero-based IDs
metalarm10 Mar 2, 2026
c309adb
allow zero-based distribution IDs in schedule validation
metalarm10 Mar 2, 2026
03acdeb
fix unit tests for zero-based IDs and multi-block phases
metalarm10 Mar 2, 2026
4f1b21b
remove deprecated single-block distribute functions
metalarm10 Mar 2, 2026
dd72208
fix lint
metalarm10 Mar 2, 2026
ba93470
fix integration test
metalarm10 Mar 2, 2026
6224afd
add v1->v2 state migration for PSE collection key changes
metalarm10 Mar 2, 2026
0f31762
preserve distribution_id in genesis export/import
metalarm10 Mar 2, 2026
cb3b060
add multi-block EndBlocker routing unit tests
metalarm10 Mar 3, 2026
5645f15
fix typo
metalarm10 Mar 3, 2026
dd535a1
reorder formatting for PeekNextAllocationSchedule
metalarm10 Mar 4, 2026
3681d87
fix: remove prevID entry in migrateOngoingEntry to prevent double sco…
metalarm10 Mar 5, 2026
44f2bc8
Merge branch 'master' into john/pse-core-implementation
metalarm10 Mar 5, 2026
cca3d25
rename prevID/currentID to ongoingID/nextID for clarity
metalarm10 Mar 5, 2026
bed8a12
apply division by zero bugfix
metalarm10 Mar 6, 2026
8e9498e
fix PSE fairness: honor earned rewards regardless of undelegations & …
metalarm10 Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions integration-tests/modules/pse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,7 @@ func TestPSEDistribution(t *testing.T) {
requireT.NoError(err)
t.Logf("Distribution 1 at height: %d", height)

scheduledDistributions, err := getScheduledDistribution(ctx, chain)
requireT.NoError(err)
requireT.Len(scheduledDistributions, 2)
awaitScheduleCount(ctx, t, chain, 2)

balancesBefore, scoresBefore, totalScore := getAllDelegatorInfo(ctx, t, chain, height-1)
balancesAfter, _, _ := getAllDelegatorInfo(ctx, t, chain, height)
Expand Down Expand Up @@ -298,9 +296,7 @@ func TestPSEDistribution(t *testing.T) {
requireT.NoError(err)
t.Logf("Distribution 2 at height: %d", height)

scheduledDistributions, err = getScheduledDistribution(ctx, chain)
requireT.NoError(err)
requireT.Len(scheduledDistributions, 1)
awaitScheduleCount(ctx, t, chain, 1)

balancesBefore, scoresBefore, totalScore = getAllDelegatorInfo(ctx, t, chain, height-1)
balancesAfter, _, _ = getAllDelegatorInfo(ctx, t, chain, height)
Expand Down Expand Up @@ -336,9 +332,7 @@ func TestPSEDistribution(t *testing.T) {
requireT.NoError(err)
t.Logf("Distribution 3 at height: %d", height)

scheduledDistributions, err = getScheduledDistribution(ctx, chain)
requireT.NoError(err)
requireT.Empty(scheduledDistributions)
awaitScheduleCount(ctx, t, chain, 0)

balancesBefore, scoresBefore, totalScore = getAllDelegatorInfo(ctx, t, chain, height-1)
balancesAfter, _, _ = getAllDelegatorInfo(ctx, t, chain, height)
Expand Down Expand Up @@ -836,7 +830,7 @@ func awaitScheduledDistributionEvent(
) (int64, communityDistributedEvent, error) {
var observedHeight int64
err := chain.AwaitState(ctx, func(ctx context.Context) error {
query := fmt.Sprintf("tx.pse.v1.EventAllocationDistributed.mode='EndBlock' AND block.height>%d", startHeight)
query := fmt.Sprintf("tx.pse.v1.EventCommunityDistributed.mode='EndBlock' AND block.height>%d", startHeight)
blocks, err := chain.ClientContext.RPCClient().BlockSearch(ctx, query, nil, nil, "")
if err != nil {
return err
Expand Down Expand Up @@ -880,6 +874,22 @@ func getScheduledDistribution(
return pseResponse.ScheduledDistributions, nil
}

func awaitScheduleCount(ctx context.Context, t *testing.T, chain integration.TXChain, expectedCount int) {
t.Helper()
requireT := require.New(t)
err := chain.AwaitState(ctx, func(ctx context.Context) error {
dist, err := getScheduledDistribution(ctx, chain)
if err != nil {
return err
}
if len(dist) != expectedCount {
return fmt.Errorf("expected %d scheduled distributions, got %d", expectedCount, len(dist))
}
return nil
}, integration.WithAwaitStateTimeout(10*time.Second))
requireT.NoError(err)
}

func removeAttributeFromEvent(events []tmtypes.Event, key string) []tmtypes.Event {
newEvents := make([]tmtypes.Event, 0, len(events))
for _, event := range events {
Expand Down
23 changes: 18 additions & 5 deletions x/pse/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ func (k Keeper) GetDelegatorScore(

// SetDelegatorScore sets the score for a delegator.
func (k Keeper) SetDelegatorScore(
ctx context.Context,
distributionID uint64,
delAddr sdk.AccAddress,
score sdkmath.Int,
ctx context.Context, distributionID uint64, delAddr sdk.AccAddress, score sdkmath.Int,
) error {
key := collections.Join(distributionID, delAddr)
return k.AccountScoreSnapshot.Set(ctx, key, score)
Expand All @@ -72,6 +69,22 @@ func (k Keeper) RemoveDelegatorScore(ctx context.Context, distributionID uint64,
return k.AccountScoreSnapshot.Remove(ctx, key)
}

// addToScore atomically adds a score value to a delegator's score snapshot.
func (k Keeper) addToScore(
ctx context.Context, distributionID uint64, delAddr sdk.AccAddress, score sdkmath.Int,
) error {
if score.IsZero() {
return nil
}
lastScore, err := k.GetDelegatorScore(ctx, distributionID, delAddr)
if errors.Is(err, collections.ErrNotFound) {
lastScore = sdkmath.NewInt(0)
} else if err != nil {
return err
}
return k.SetDelegatorScore(ctx, distributionID, delAddr, lastScore.Add(score))
}

// CalculateDelegatorScore calculates the current total score for a delegator.
// This includes both the accumulated score snapshot (from previous periods)
// and the current period score calculated on-demand from active delegations.
Expand All @@ -82,7 +95,7 @@ func (k Keeper) CalculateDelegatorScore(ctx context.Context, delAddr sdk.AccAddr
if err != nil {
return sdkmath.Int{}, err
}
distributionID := distribution.ID // TODO update to handle distribution ID properly.
distributionID := distribution.ID

// Start with the accumulated score from the snapshot (previous periods)
accumulatedScore, err := k.GetDelegatorScore(ctx, distributionID, delAddr)
Expand Down
Loading
Loading