Skip to content

Version v1.2.11: gate sender attestations on validators ∪ AAOs#214

Merged
dylanjeffers merged 2 commits intomainfrom
dj-aao-sender-gate
Apr 28, 2026
Merged

Version v1.2.11: gate sender attestations on validators ∪ AAOs#214
dylanjeffers merged 2 commits intomainfrom
dj-aao-sender-gate

Conversation

@dylanjeffers
Copy link
Copy Markdown
Contributor

@dylanjeffers dylanjeffers commented Apr 28, 2026

Summary

Ships as v1.2.11 (`.version.json` bumped in this PR). Fixes a gap in both `GetRewardSenderAttestation` (add) and `GetDeleteRewardSenderAttestation` (delete): they previously gated only on the validator set, but the rewards-manager program's eligible senders are actually the union of validators and AAOs (per L1 `EthRewardsManager` governance).

  • Add was over-restrictive: would reject any AAO trying to register as a sender via the public attestation flow.
  • Delete was under-restrictive (the dangerous one): would happily sign a delete attestation for a live AAO, since the AAO eth address isn't a validator. Three of those collected = a valid `DeleteSenderPublic` tx that rips the AAO out of the rewards-manager program.

What changed

  • New table `eth_anti_abuse_oracles` synced from `EthRewardsManager.getAntiAbuseOracleAddresses()` alongside the existing validator/SP sync in `hydrateEthData`.
  • `EthService.GetAntiAbuseOracleAddresses(ctx)` accessor.
  • New shared `gatherEligibleSenderAddresses` helper on `CoreService` that returns the union.
  • Both handlers now reject based on this union (add: must ∈ set; delete: must ∉ set).
  • Updated error messages to reflect the broader set.
  • `pkg/version/.version.json`: `1.2.10` → `1.2.11`.

Implication for AAO key rotation runbook

L1 governance proposal to add the new AAO must land before running `rewards_cli register`, since the gate now defers to L1 as the source of truth. Updated rotation order:

```

  1. Generate keypair offline
  2. L1 governance: setAntiAbuseOracleAddresses([old, new]) ← BOTH valid
  3. Wait for eth-bridge sync (~1 polling interval)
  4. Solana register new ← gate sees new ∈ AAOs ✓
  5. Roll AAO container to new key
  6. Bake
  7. L1 governance: setAntiAbuseOracleAddresses([new]) ← drop old
  8. Wait for eth-bridge sync
  9. Solana delete old ← gate sees old ∉ AAOs ✓
    ```

Test plan

  • CI green
  • Local: confirm migration applies cleanly to a fresh eth db
  • Local: confirm `hydrateEthData` populates `eth_anti_abuse_oracles` from L1
  • Local: confirm both handlers behave correctly across the four cases (validator, AAO, neither, both empty)
  • After merge: trigger `Create Release` workflow with `version=v1.2.11`
  • Roll v1.2.11 to `edge`/`stable` so the 3 static reward senders pick it up before `rewards_cli delete` is exercised against live state

dylanjeffers and others added 2 commits April 28, 2026 15:33
Both GetRewardSenderAttestation (add) and GetDeleteRewardSenderAttestation
(delete) previously gated only on the validator set. The rewards-manager
program's "registered senders" are actually the union of validators and
AAOs (per L1 EthRewardsManager governance), so:

  - The add handler was over-restrictive: it would reject any AAO trying
    to register as a sender via the public attestation flow.
  - The delete handler was under-restrictive: it would happily sign a
    delete attestation for a live AAO, since the AAO eth address isn't
    a validator. Three of those collected = a valid DeleteSenderPublic
    tx that rips the AAO out of the program.

Fix by syncing the L1 EthRewardsManager.getAntiAbuseOracleAddresses()
list into a new eth_anti_abuse_oracles table (alongside the existing
eth_registered_endpoints sync in hydrateEthData), exposing a public
GetAntiAbuseOracleAddresses accessor on EthService, and computing the
eligible-sender union in both handlers via a shared helper.

After this:
  - Add: address must be in {validators ∪ AAOs}
  - Delete: address must NOT be in {validators ∪ AAOs}

Implication for AAO key rotation: the L1 governance proposal to add the
new AAO must land before rewards_cli register can succeed, since the
gate now defers to L1 as the source of truth.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps version so the gate fix in this PR can ship as v1.2.11.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers changed the title Gate sender attestations on validators ∪ anti-abuse oracles Version v1.2.11: gate sender attestations on validators ∪ AAOs Apr 28, 2026
@dylanjeffers dylanjeffers marked this pull request as ready for review April 28, 2026 22:45
@dylanjeffers dylanjeffers merged commit ef209c6 into main Apr 28, 2026
6 checks passed
@dylanjeffers dylanjeffers deleted the dj-aao-sender-gate branch April 28, 2026 22:52
dylanjeffers added a commit to AudiusProject/api that referenced this pull request Apr 29, 2026
## Summary

Adds \`rewards_cli delete <sender-eth-addr>\` to remove a registered
sender from the Reward Manager program. Sibling of the existing
\`register\` subcommand and reuses the same config / fee-payer /
transaction-sender stack.

- Fills out the previously-empty \`reward_manager.DeleteSenderPublic\`
Go binding (mirrors \`CreateSenderPublic\` — account layout, builder,
validation, tree encoding).
- New \`delete.go\` subcommand: gathers attestations from
caller-supplied (or config-default) OpenAudio nodes via the new
\`GetDeleteRewardSenderAttestation\` RPC, dedupes by attester eth
address, builds one secp256k1 instruction per attester signing the exact
\`\"del\" + RM_state(32) + sender_eth(20)\` payload, then a
\`DeleteSenderPublic\` instruction.
- Pinned to \`go-openaudio\` v1.2.11, which ships the validators ∪ AAOs
gate on the sender-attestation handlers
([go-openaudio#214](OpenAudio/go-openaudio#214)).
- Supports \`--dry-run\` to print the built tx without sending.

Caller picks ≥3 distinct-operator nodes (e.g. via \`--nodes
node1,node2,node3\`); the dedupe-by-attester guards against accidental
dupes.

## Pre-flight before running for real

The script needs **3 attester nodes that simultaneously satisfy two
conditions**:

1. **Running go-openaudio v1.2.11+** so the validators ∪ AAOs gate is
active (otherwise the attester could be tricked into signing a delete
for a live AAO).
2. **Registered as a sender PDA in the Solana rewards-manager program**
so the program will accept their secp256k1 signatures (the program's
\`validate_secp_add_delete_sender\` checks each signer's eth address
against the eth addresses stored in the \`expected_signers\` sender PDAs
you pass in the \`DeleteSenderPublic\` instruction).

Current prod state of the 3 documented static reward senders (per
\`config/config.go\`):

| Endpoint | Owner | Sender? | v1.2.11? |
|---|---|---|---|
| \`creatornode.audius.co\` | \`0xe5b2…aB68d\` (Audius) | yes (per
static config) | **no — on v1.2.10** |
| \`audius-cn1.tikilabs.com\` | \`0xe488…8d0a\` (tikilabs) | yes (per
static config) | unknown — origin unreachable |
| \`audius.bragi.cc\` | \`0xC88C…094a\` (bragi) | yes (per static
config) | yes ✓ |

Other v1.2.11 nodes (e.g. \`creatornode2.audius.co\`,
\`validator.stuffisup.com\`, \`audius-creator-*.theblueprint.xyz\`) may
or may not be registered senders — verify before using.

## Usage

\`\`\`bash
rewards_cli delete <sender-eth-addr> \\
  --nodes node1.example,node2.example,node3.example \\
  --refunder <solana-pubkey>     # optional, defaults to fee payer
  --keypair ~/.config/solana/id.json \\
  --rpc https://api.mainnet-beta.solana.com \\
  --dry-run                       # print tx without sending
\`\`\`

## Test plan

- [ ] CI green
- [ ] Identify 3 distinct-owner nodes that are both (a) on v1.2.11 and
(b) registered senders in the rewards-manager program
- [ ] \`--dry-run\` against a no-op target (e.g. an address with no
Solana sender PDA) — verify tx structure (3 secp256k1 ixs +
DeleteSenderPublic ix with correct accounts)
- [ ] Live send against a known stale/deletable target, confirm sender
PDA closed and rent refunded

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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