Skip to content

[Tokenomics] Eliminate precision loss in validator reward distribution #1758

@bryanchriswhite

Description

@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: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 calling distributeValidatorRewards()
  • 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 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    consensus-breakingIMPORTANT! If the PR with this tag is merged, next release WILL HAVE TO BE an upgrade.on-chainOn-chain business logictokenomicsToken Economics - what else do you need?

    Type

    Projects

    Status

    🔖 Ready

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions