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
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
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 distributions
Target 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 Method
Expected 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
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:197which states:Evidence: Our integration test demonstrates this precision loss:
[36667, 36666, 36667](perfect proportional distribution)[38000, 36000, 36000](significant skew toward first validator)See comprehensive analysis: Validator Reward Distribution Batching Improvement
Goals
Deliverables
tlm_global_mint.go,tlm_relay_burn_equals_mint.go) to accumulate validator rewards instead of immediately callingdistributeValidatorRewards()settle_pending_claims.go)multi_validator_test.go)Non-goals / Non-deliverables
distributeValidatorRewards()algorithm itself (Largest Remainder Method is already optimal)General deliverables
SKIP: Precision loss with many small distributions) passes with perfect precisionTechnical Context:
Current Problem (1000 claims × 2 TLMs = 2000+ calls):
Target Solution (2 calls per settlement batch):
Expected Results:
Creator: @bryanchriswhite