Skip to content

feat: Prevent miner slashing on API outages by distinguishing tx-not-found from provider-unreachable#10

Open
bittoby wants to merge 1 commit intoentrius:testfrom
bittoby:feat/verify-transaction-error-handling
Open

feat: Prevent miner slashing on API outages by distinguishing tx-not-found from provider-unreachable#10
bittoby wants to merge 1 commit intoentrius:testfrom
bittoby:feat/verify-transaction-error-handling

Conversation

@bittoby
Copy link
Copy Markdown

@bittoby bittoby commented Apr 6, 2026

Summary

Right now verify_transaction() returns None for both "transaction does not exist" and "API is down." The validator treats both the same way - it assumes the miner never sent funds, and eventually slashes them.

This means a miner who fulfilled a swap correctly can still lose collateral just because Blockstream was temporarily unreachable.

This PR adds a three-state return (VerifyResult) so the validator can tell the difference and hold off on slashing when verification is inconclusive.

What changed

  • New VerifyResult type in base.py with three states: FOUND, NOT_FOUND, ERROR
  • Bitcoin provider returns the correct state instead of collapsing everything into None. Retries up to 3 times on transient failures (5xx, 429, connection errors) before returning ERROR
  • Subtensor provider same three-state return -- separates "subtensor unreachable" from "tx not in any scanned block"
  • Swap verifier propagates a VERIFIED / FAILED / UNCERTAIN outcome up to the forward loop
  • Forward loop (_timeout_expired): skips timeout vote on FULFILLED swaps when verification returned UNCERTAIN. ACTIVE swaps and swaps that definitively failed verification still timeout normally
  • Pending confirms: keeps items in the queue on provider error instead of dropping them
  • Timeout extension: votes to extend when provider is unreachable, rather than letting the swap expire silently
  • Axon handler / miner fulfillment: updated to use the new return type with clearer log messages

How it protects miners

Before:

API down -> verify returns None -> validator can not confirm -> timeout -> miner slashed

After:

API down -> verify returns ERROR -> validator marks UNCERTAIN -> defers timeout -> retries next step

Miner only gets slashed when the API is reachable and the transaction genuinely does not exist.

Test plan

  • VerifyResult / VerifyStatus construction and properties
  • Bitcoin provider returns correct state for 200, 404, 429, 500, connection error
  • Retry logic fires on transient failures and succeeds after recovery
  • RPC-found skips Blockstream, RPC-error falls through to Blockstream
  • SwapTracker verify error tracking (mark, check, clear)
  • Timeout protection: FULFILLED + verify error = deferred, ACTIVE + verify error = still timed out, FULFILLED + no error = still timed out

@bittoby
Copy link
Copy Markdown
Author

bittoby commented Apr 6, 2026

@anderdc @LandynDev Ready for review. Please give me any feedbacks.

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.

1 participant