test(api_remote): retry second mint on scanner-lag 422 - #83
Merged
Conversation
send_commit_roundtrip_moves_balance runs after mint_roundtrip in the single-threaded suite. The second mint requires the FIRST mint's Taproot inscription to be confirmed on Mutinynet (~30 s block time) and observed by the scanner (30 s Esplora poll interval), otherwise /api/mint returns 422 "Unable to get merkle proofs for provided public key". The same scanner-lag is already handled around /api/send in this test via a retry loop. Apply the same pattern to the second mint call so a fresh DEV state (post-reset or right after the first mint) doesn't flake the suite. Falls through to dev_skip! if the deadline elapses, matching the existing /api/send behavior — preserves the "DEV flake skip, real failure assert" semantics.
TaprootFreak
marked this pull request as ready for review
May 23, 2026 12:09
12 tasks
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by #[allow(scanner_polling)] with a justifying comment. Documented in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
3 tasks
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by #[allow(scanner_polling)] with a justifying comment. Documented in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by #[allow(scanner_polling)] with a justifying comment. Documented in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by #[allow(scanner_polling)] with a justifying comment. Documented in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
…#87) The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
The scanner polled Esplora every 30 s for the chain tip, producing up to ~60 s of lag (Mutinynet 30 s blocks + 30 s scanner poll) before new mint inscriptions became visible to /api/mint and /api/send. Test-side stopgaps in api_remote.rs (PR #83) papered over the lag but the underlying breakage manifested in two error classes ("Unable to get merkle proofs" and "Unable to get mmr inclusion proof for the previous root") and gated test execution behind multi-minute retries. Subscribe to mempool.space WebSocket (wss://mutinynet.com/api/v1/ws or the configured ESPLORA_WS_URL) for block events. New tips arrive within tens of milliseconds and feed an mpsc<BlockHash> channel that the existing scanner_runtime drains. The SMT/MMR write path is unchanged - only the trigger source moves from sleep to recv().await. A 90 s liveness watchdog reconnects on half-open WS; reconnect-with-backoff handles transient disconnects; on reconnect, the current tip is fetched via the existing EsploraClient to plug any gap. Publisher: replaces the 5 s PROPAGATION_WAIT_SECS sleep between commit and reveal with a track-tx WS subscription on the commit txid (30 s safety-net timeout - surfaces as a hard error rather than silent fallback). CI lint: a Lint & Build step now fails on tokio::time::{sleep, interval} in scanner*.rs / publisher.rs unless guarded by in CONTRIBUTING.md as a project invariant. ZMQ subscriber (feature = "zmq") is reserved for self-host operators; kept as a dormant feature flag in this PR. The test-side retry stopgaps in api_remote.rs (PR #83) will be removed in a follow-up PR once event-driven scanning is observed stable on DEV. See #84. Closes #84.
4 tasks
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.
Problem
send_commit_roundtrip_moves_balanceruns aftermint_roundtrip_lands_balance_and_proofin the single-threaded suite. Both call/api/mint. The FIRST mint succeeds becausenum_pubkeys = 0at startup → server takes the no-prev-commitment branch. The SECOND mint computesprev_commitment_pubkey = generate_public_key(0)and needs its merkle proof from the SMT — which requires the FIRST mint's Taproot inscription to be (a) confirmed on Mutinynet (~30 s block time) and (b) observed by the scanner (30 s Esplora poll). Until ~60 s elapse, the server returns 422 withUnable to get merkle proofs for provided public key.The test had a retry loop around
/api/sendfor this exact condition (lines ~985-1015) but no retry around the second mint. Result: today'sDeploy DEVjob'sAPI E2E against DEVstep failed atapi_remote.rs:958withassert_eq!(mint_status, StatusCode::OK)because the scanner had not yet caught up between the first and second mint.Fix
Apply the SAME retry pattern from
/api/sendto the second mint call:422 + "Unable to get merkle proofs".SEND_RETRY_DEADLINE/SEND_RETRY_INTERVALconstants (identical scanner-lag, identical timeout).dev_skip!(matches send-side behavior).assert_eq!with body context (now also surfaces error body in failure message, small improvement).Why this scope is sufficient
Audited every
/api/mintcallsite inapi_remote.rs:mint_roundtrip_lands_balance_and_proofmint_empty_body_returns_422mint_invalid_hex_address_returns_422mint_wrong_address_length_returns_422send_commit_roundtrip_moves_balanceget_merkle_proofs(generate_public_key(N-1))No server-side change needed; this is a test-resilience improvement only.
Test plan
Deploy DEV→API E2E against DEVstep green over multiple runs (state-reset + first-mint + second-mint roundtrip).