Rate-limit the validator axon behind an edge proxy + proof-parsing fix#445
Merged
Conversation
Lets an operator front the axon with a local reverse proxy (e.g. nginx for rate limiting) by setting AXON_PUBLISH=127.0.0.1:<port>, so docker publishes the axon to host loopback instead of 0.0.0.0. Unset keeps the raw internet-facing publish, so existing validators are unchanged.
A reverse proxy (nginx) in front of the validator axon returns 429 on rate-limit. The dendrite couldn't parse nginx's HTML error body, so a 429 showed up as a generic parse failure and the CLI rendered it as 'no response — timeout or validator down' — misleading, and only manually retryable. - render_and_aggregate: detect dendrite.status_code == 429 as a distinct 'rate_limited' category (transient), printed as 'rate limited' instead of 'no response'. Shared by reserve, confirm, and activate. - reserve / confirm / activate: auto-backoff 6s and retry on rate_limited instead of prompting. Only this category is auto-retried, and a 429 was rejected at the edge (the validator never ran it), so there's no double-submit risk. Activate re-signs a fresh timestamp per attempt. Requires the proxy to return a JSON 429 body so the status survives dendrite parsing.
bytes.fromhex() rejects a leading 0x, so a 0x-prefixed sr25519 proof (e.g. from a JS/web client) threw and verify_from_proof returned False, rejecting the swap reserve as 'Invalid source address proof'. CLI proofs are bare hex so they were unaffected. Strip the prefix like the rest of the file (subtensor.py:75, commitments.py:121) so both formats verify.
PunchTheDev
approved these changes
Jun 2, 2026
LandynDev
approved these changes
Jun 2, 2026
This was referenced Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens validator-axon ingress and the swap CLI's handling of edge-proxy rate limiting, plus an unrelated one-line proof-parsing fix.
AXON_PUBLISH) — lets validators run the axon behind an edge proxy that does the rate limiting, instead of exposing it directly.429is rejected at the edge proxy and never reaches the validator, so the CLI now recognizes it as transient, reads it as "rate limited" (not a generic timeout), backs off, and auto-retries with a fresh signed timestamp.0x-prefixed signatures in TAOverify_from_proof—bytes.fromhex()rejects a leading0x, so a0x-prefixed sr25519 proof (e.g. from a JS/web client) threw and the proof check returnedFalse, rejecting the reserve as "Invalid source address proof". CLI proofs are bare hex so they were unaffected. Strips the prefix like the rest of the file already does. Independent of the rate-limiting work.Changes
.env.example,docker-compose.vali.yml—AXON_PUBLISHwiringallways/cli/swap_commands/{swap.py,miner_commands.py},allways/cli/validator_rejections.py— 429 detection + backoff/retryallways/chain_providers/subtensor.py—0xstrip inverify_from_prooftests/test_validator_rejections.py— coverage for the 429 pathNotes
The dest-tx replay false-rejects seen on testnet4 (swaps #39/#42) are not in scope here — that's a testnet4 block-cadence artifact, not a mainnet issue and not caused by the proxy.