-
Notifications
You must be signed in to change notification settings - Fork 25
Description
Objective
Implement batching of validator rewards across claims within settlement batches to eliminate precision loss caused by thousands of small per-claim distributions. Currently, each TLM processor calls distributeValidatorRewards() for every individual claim, resulting in accumulated truncation errors despite the Largest Remainder Method providing perfect precision within individual calls.
Origin Document
This addresses the TODO_CRITICAL comment in x/tokenomics/keeper/token_logic_modules.go:197 which states:
Per-claim validator reward distribution causes significant precision loss. Currently, each TLM processor calls distributeValidatorRewards() for every individual claim, resulting in multiple function calls per settlement batch (e.g. 1000 claims × 2 TLMs). This causes accumulated truncation errors that can exceed 1000+ uPOKT per validator.
Evidence: Our integration test demonstrates this precision loss:
- Expected rewards:
[36667, 36666, 36667](perfect proportional distribution) - Actual rewards:
[38000, 36000, 36000](significant skew toward first validator) - Error magnitude: +1,333 uPOKT for validator 1, -667 uPOKT each for validators 2&3
See comprehensive analysis: Validator Reward Distribution Batching Improvement
Goals
- Eliminate precision loss from cumulative per-claim validator distributions
- Reduce validator distribution function calls from 2000+ to 2 per settlement batch
- Maintain the perfect precision achieved by the Largest Remainder Method
- Improve gas efficiency and performance through reduced function call overhead
- Ensure fair and mathematically accurate validator reward distribution
Deliverables
- Architecture Change: Modify TLM processors (
tlm_global_mint.go,tlm_relay_burn_equals_mint.go) to accumulate validator rewards instead of immediately callingdistributeValidatorRewards() - Batch Distribution: Add a batch validator reward distribution phase in the settlement process (
settle_pending_claims.go) - Accumulator State: Add validator reward accumulation fields to TLM contexts
- Test Updates: Update integration tests to expect perfect precision (remove skipped test in
multi_validator_test.go) - Code Cleanup: Remove the TODO_CRITICAL comment once batching is implemented
Non-goals / Non-deliverables
- Changes to the
distributeValidatorRewards()algorithm itself (Largest Remainder Method is already optimal) - Batching of supplier, DAO, or source owner rewards (separate scope)
- Cross-session reward batching
- Changes to external APIs
General deliverables
- Comments: Update TODO comments and add documentation for the new batching architecture
- Testing: Ensure the skipped precision loss test (
SKIP: Precision loss with many small distributions) passes with perfect precision - Documentation: Update architectural documentation to reflect the batching approach
Technical Context:
Current Problem (1000 claims × 2 TLMs = 2000+ calls):
// In each TLM processor, for each claim:
err := distributeValidatorRewards(ctx, logger, result, stakingKeeper,
validatorRewardAmount, // Small amount like 55 uPOKT
settlementOpReason)
// → Accumulated precision loss across thousands of small distributionsTarget Solution (2 calls per settlement batch):
// Phase 1: Accumulate during claim processing
tlmCtx.accumulatedValidatorRewards = tlmCtx.accumulatedValidatorRewards.Add(validatorRewardAmount)
// Phase 2: Single batch distribution after all claims processed
err := distributeValidatorRewards(ctx, logger, result, stakingKeeper,
tlmCtx.accumulatedValidatorRewards, // Large accumulated amount
settlementOpReason)
// → Perfect precision with Largest Remainder MethodExpected Results:
- Validator rewards: [36667, 36666, 36667] ✅ (mathematically perfect)
- Function calls: 2 per batch instead of 2000+ ✅
- Total conservation: 110,000 uPOKT ✅ (maintained)
- Precision loss: 0 uPOKT ✅ (eliminated)
Creator: @bryanchriswhite
Metadata
Metadata
Assignees
Labels
Type
Projects
Status