Skip to content

RewardAttester.Validate: treat reward.Amount as max cap#219

Merged
dylanjeffers merged 4 commits into
mainfrom
fix-reward-amount-strict-equality
May 18, 2026
Merged

RewardAttester.Validate: treat reward.Amount as max cap#219
dylanjeffers merged 4 commits into
mainfrom
fix-reward-amount-strict-equality

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Summary

Trending tracks and trending underground top-10 challenges pay rank-dependent amounts (1000 for ranks 1-5, 100 for ranks 6-10). After api#783 fixes the API to send per-rank user_challenges.amount, validators reject ranks 6-10 with amount does not match reward amount (the static config has 1000 for both tt and tut).

This change relaxes the validator-side equality check to a max cap. The per-claim amount is determined upstream by the discovery node from user_challenges, and the claim authority signature is verified separately in Authenticate(). The validator's amount check serves as a sanity bound, not the source of truth.

Behavior change

  • claim.Amount > reward.Amount → reject (catastrophic over-attestation guard, unchanged in spirit)
  • claim.Amount == reward.Amount → accept (unchanged)
  • claim.Amount < reward.Amount (and > 0) → now accepts (was reject)
  • claim.Amount == 0 → reject with missing amount (preserves previous behavior, which strict equality caught incidentally)

Real-world repro

Today's /disburse 2026-05-01 from the trending-challenge-rewards bot left 4 winners stuck:

  • 3 of them (FloppyDriveMusic, CymaticsBass, dilemmamusic182) are ranks 6-10 with user_challenges.amount=100. All 3 reachable validators (creatornode.audius.co, audius.bragi.cc, v.monophonic.digital) reject amount=100 against their config of tt:1000/tut:1000. The API gets 0 validator attestations, need 3 and the claim never lands.
  • The 4th (Nonkalonk) is a separate AAO denial, not addressed here.

Test plan

  • go test ./pkg/rewards/... (existing assertions updated to reflect cap semantics; new assertion that amount equal-to-cap still works)
  • Local: stand up validator + send a claim for amount < cap, confirm signed attestation returned
  • After release: have content-node operators upgrade. Re-run /disburse 2026-05-01 to clear the 3 stuck rank 6-10 winners.

Followups

  • Currently audius-cn1.tikilabs.com is returning HTTP 522 — with that down, only 3 of 4 prod validators are usable, no margin if any one fails. Worth pinging that operator independently.
  • The static reward.Amount config is now best understood as a per-claim ceiling rather than a fixed payout. Consider renaming the field to MaxAmount in a future cleanup.

🤖 Generated with Claude Code

dylanjeffers and others added 3 commits April 30, 2026 18:00
A gitlink at .claude/worktrees/agent-aad269c9 was accidentally
committed in #200. Without a corresponding .gitmodules entry, the
checkout action's submodule cleanup step fails on every push to
main with "fatal: No url found for submodule path", which in turn
skips the tag-edge job and prevents :edge from auto-promoting on
merge. Drop the gitlink and add .claude/ to .gitignore so local
Claude Code worktrees don't get committed again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…quality

Trending tracks and trending underground top-10 challenges pay
rank-dependent amounts (1000 for ranks 1-5, 100 for ranks 6-10), but
RewardAttester.Validate enforced strict equality between claim.Amount
and the static reward.Amount config (1000 for tt/tut). With the API
fixed to send per-rank user_challenges.amount, validators reject
ranks 6-10 with 'amount does not match reward amount', leaving those
winners undisbursed.

Per-claim amount is determined upstream by the discovery node from
user_challenges, and the claim authority signature is checked
separately in Authenticate(). The validator's job here is to act as a
sanity bound, not the source of truth on amount. Treat reward.Amount
as a max cap and explicitly reject amount=0 (preserving the previous
'missing amount' behavior that strict equality incidentally caught).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
// Allow any positive amount up to the static reward config amount. Some
// rewards (notably trending tracks/underground top 10) pay rank-dependent
// amounts that are <= the headline reward.Amount; the actual per-claim
// amount is determined by the discovery node from user_challenges.amount

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update comment to not mention discovery node

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or just remove this comment entirely, not too useful for just a > check lol

@raymondjacobson

Copy link
Copy Markdown
Contributor

Looks like the new test fails

--- FAIL: TestRewardsLifecycle (8.45s)
--- PASS: TestRewardsLifecycle/Create,_Delete,_and_Query_Rewards (3.51s)
--- PASS: TestRewardsLifecycle/Test_Reward_Attestations_with_Claim_Authorities (2.69s)
--- FAIL: TestRewardsLifecycle/Test_with_Amount_Validation (1.23s)

Test 2 previously asserted that amount=50 fails when reward cap is 100.
Under the new cap behavior (any amount <= cap is valid), 50 should succeed.
Update to assert below-cap succeeds and add a new test 2b asserting that
exceeding the cap (150 > 100) correctly fails.
@dylanjeffers dylanjeffers merged commit 9003f3a into main May 18, 2026
4 checks passed
@dylanjeffers dylanjeffers deleted the fix-reward-amount-strict-equality branch May 18, 2026 17:37
@raymondjacobson raymondjacobson mentioned this pull request May 19, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants