Multi-block PSE - Final Features and TODO Cleanup#111
Conversation
…dId assertion in distributeAction
…ross exclusion lifecycle
… distribution risk
…countKeeper in migration test
…ribution in integration tests
TxCorpi0x
left a comment
There was a problem hiding this comment.
@TxCorpi0x made 1 comment.
Reviewable status: 0 of 35 files reviewed, 1 unresolved discussion (waiting on akhlopiachyi, masihyeganeh, metalarm10, miladz68, and ysv).
x/pse/keeper/distribute_test.go line 354 at r1 (raw file):
}}, } err = pseKeeper.BeginCommunityDistribution(ctx, scheduledDistribution, bondDenom)
This issue is not clear to me:
UpdateDistributionScheduleprevents updates during ongoing distribution, but UpdateExcludedAddresses does not have this check. So the exclusion may happen during phase 2, which modifies TotalScore in the middle of the round.
- Adding exclusion: reduces total denom → increases payouts for remaining delegators in later batches
- Removing exclusion: increases total denom → decreases payouts for remaining delegators in later batches
It is worth having test coverage for that
metalarm10
left a comment
There was a problem hiding this comment.
@metalarm10 made 1 comment.
Reviewable status: 0 of 35 files reviewed, 1 unresolved discussion (waiting on akhlopiachyi, masihyeganeh, miladz68, TxCorpi0x, and ysv).
x/pse/keeper/distribute_test.go line 354 at r1 (raw file):
Previously, TxCorpi0x wrote…
This issue is not clear to me:
UpdateDistributionScheduleprevents updates during ongoing distribution, butUpdateExcludedAddressesdoes not have this check. So the exclusion may happen during phase 2, which modifiesTotalScorein the middle of the round.
- Adding exclusion: reduces total denom → increases payouts for remaining delegators in later batches
- Removing exclusion: increases total denom → decreases payouts for remaining delegators in later batches
It is worth having test coverage for that
Done.
TxCorpi0x
left a comment
There was a problem hiding this comment.
@TxCorpi0x reviewed 35 files and all commit messages, and resolved 1 discussion.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on akhlopiachyi, masihyeganeh, miladz68, and ysv).
ysv
left a comment
There was a problem hiding this comment.
@ysv reviewed 29 files and all commit messages, and made 5 comments.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on akhlopiachyi, masihyeganeh, metalarm10, and miladz68).
a discussion (no related file):
ExcludedAddressScorestore: NewMap[AccAddr -> Int]collection. AddedaddScoreForAddresshelper that routes score writes based on exclusion status: excluded addresses accumulate toExcludedAddressScoreinstead ofAccountScoreSnapshotandTotalScore. Score is restored toAccountScoreSnapshoton re-inclusion. Preserved across genesis export/import.
But we still keep DelegationTimeEntries for excluded addresses, right ?
a discussion (no related file):
TODO myself: check deeper
- Fairness bonus: Normalizes batch-ordering bias. After each delegator receives tokens in distribution phase, bonus score credited to next distribution:
bonusScore = distributedAmount × elapsed_seconds.
x/pse/keeper/delegation.go line 75 at r3 (raw file):
// addToExcludedScore atomically adds a score value to an excluded address's accumulated score. // Unlike addToScore, this does NOT update TotalScore - excluded addresses don't participate in distribution. func (k Keeper) addToExcludedScore(ctx context.Context, addr sdk.AccAddress, score sdkmath.Int) error {
do we resent this score together with 'main score' in the end of PSE distribution ?
x/pse/keeper/delegation.go line 129 at r3 (raw file):
// moveExcludedScoreToSnapshot moves accumulated ExcludedAddressScore back into AccountScoreSnapshot+TotalScore. // Called when an address is re-included (removed from the exclusion list). func (k Keeper) moveExcludedScoreToSnapshot(ctx context.Context, distributionID uint64, addr sdk.AccAddress) error {
nit: as idea to differentiate Excluded score and 'other one' maybe you can name it something like 'main'
so it will be:
- moveExcludedScoreToMain & moveMainScoreToExcluded
- addToExcludedScore & addToMainScore
etc.
Renaming of store isn't critical
x/pse/keeper/distribution.go line 92 at r3 (raw file):
communityCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, communityAmount)) return k.bankKeeper.SendCoinsFromModuleToModule( ctx, types.ClearingAccountCommunity, types.ClearingAccountCommunityBuffer, communityCoins,
nit; name suggestion Buffer -> intermediary (similar to name in banking)
If not painful I would rename
Code quote:
ClearingAccountCommunityBuffer…te score between periods
metalarm10
left a comment
There was a problem hiding this comment.
@metalarm10 made 2 comments.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on akhlopiachyi, masihyeganeh, miladz68, and ysv).
a discussion (no related file):
Previously, ysv (Yaroslav Savchuk) wrote…
ExcludedAddressScorestore: NewMap[AccAddr -> Int]collection. AddedaddScoreForAddresshelper that routes score writes based on exclusion status: excluded addresses accumulate toExcludedAddressScoreinstead ofAccountScoreSnapshotandTotalScore. Score is restored toAccountScoreSnapshoton re-inclusion. Preserved across genesis export/import.But we still keep DelegationTimeEntries for excluded addresses, right ?
Correct, hooks still fire and record delegation time entries for excluded addresses, with proper shares + timestamp.
x/pse/keeper/delegation.go line 75 at r3 (raw file):
Previously, ysv (Yaroslav Savchuk) wrote…
do we resent this score together with 'main score' in the end of PSE distribution ?
Done. Added pruning of ExcludedAddressScore in cleanup at the end of each distribution round. Now score accumulation will start fresh for each period.
ysv
left a comment
There was a problem hiding this comment.
@ysv reviewed 8 files and all commit messages, made 1 comment, and resolved 3 discussions.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on akhlopiachyi, masihyeganeh, metalarm10, and miladz68).
x/pse/types/params.go line 13 at r4 (raw file):
ClearingAccountCommunity = "pse_community" // ClearingAccountCommunityBuffer is a short-lived buffer account used during community distribution. ClearingAccountCommunityBuffer = "pse_community_buffer"
nit: does it makes sense to put this account separately ?
Either in the beginning or end of these contstants
Code quote:
ClearingAccountCommunityBuffer = "pse_community_buffer"
metalarm10
left a comment
There was a problem hiding this comment.
@metalarm10 made 3 comments and resolved 3 discussions.
Reviewable status: 21 of 35 files reviewed, all discussions resolved (waiting on akhlopiachyi, masihyeganeh, miladz68, TxCorpi0x, and ysv).
x/pse/keeper/delegation.go line 129 at r3 (raw file):
Previously, ysv (Yaroslav Savchuk) wrote…
nit: as idea to differentiate Excluded score and 'other one' maybe you can name it something like 'main'
so it will be:
- moveExcludedScoreToMain & moveMainScoreToExcluded
- addToExcludedScore & addToMainScore
etc.Renaming of store isn't critical
Done
x/pse/keeper/distribution.go line 92 at r3 (raw file):
Previously, ysv (Yaroslav Savchuk) wrote…
nit; name suggestion Buffer -> intermediary (similar to name in banking)
If not painful I would rename
Done
x/pse/types/params.go line 13 at r4 (raw file):
Previously, ysv (Yaroslav Savchuk) wrote…
nit: does it makes sense to put this account separately ?
Either in the beginning or end of these contstants
Done
TxCorpi0x
left a comment
There was a problem hiding this comment.
@TxCorpi0x reviewed 14 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on akhlopiachyi, masihyeganeh, miladz68, and ysv).
ysv
left a comment
There was a problem hiding this comment.
@ysv reviewed 14 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on akhlopiachyi, masihyeganeh, and miladz68).
Description
This PR Closes Following Tasks:
Summary
ExcludedAddressScorestore: NewMap[AccAddr -> Int]collection. AddedaddScoreForAddresshelper that routes score writes based on exclusion status: excluded addresses accumulate toExcludedAddressScoreinstead ofAccountScoreSnapshotandTotalScore. Score is restored toAccountScoreSnapshoton re-inclusion. Preserved across genesis export/import.bonusScore = distributedAmount × elapsed_seconds.pse_community_buffer: New tampon module account. At distribution start, only the current round's community allocation movespse_community->pse_community_buffer. Phase 2 distributes from the buffer; leftover sent to community pool. Limits blast radius on failure.DistributionBatchSizeparam: Replaces hardcodeddefaultBatchSize = 100. Configurable viaMsgUpdateDistributionBatchSizegovernance message. Initialized to 100 in v7 upgrade.pse_community_bufferaccount and initializesDistributionBatchSize.MsgUpdateDistributionBatchSizeas non-deterministic.(x/pse/spec/README.md):Updated to document multi-block distribution flow.Testing
Test_ExcludedAddress_FullLifecycle/TestExcludedAddress_ScoreLifecycle: excluded score preserved, restored, and genesis-safe.TestDistribution_FairnessBonus/_SkippedWhenStartedAtZero: bonus score normalization and backward compat guard.TestMsgUpdateAllocationSchedule_RejectedDuringOngoingDistribution: schedule update blocked during active distribution.TestMsgUpdateDistributionBatchSize: valid update, zero rejection, wrong authority rejection.TestCommunityBuffer_AccountInitialized/TestCommunityBuffer_FundIsolation: buffer account existence and fund isolation.TestPSEDistribution(integration): extended to assertpse_community_bufferdrains to zero after each of 3 distributions.DistributionBatchSizeinitialized to 100 by v7.LastProcessedDistributionIDassertions in multiple-distributions tests.The final state of all multiblock PSE tests is listed in this document: https://docs.google.com/document/d/15Xi_35mS4zIk4f48oSA4iDojiSvJAVxpXqKqCDhdIu0/edit?usp=sharing
Reviewers checklist:
Authors checklist
This change is