Skip to content

main: retry submitblock, fall back to a second node, keep the block on disk - #104

Open
asilgulsar1 wants to merge 1 commit into
LayerTwo-Labs:mainfrom
asilgulsar1:submitblock-retry
Open

asilgulsar1 wants to merge 1 commit into
LayerTwo-Labs:mainfrom
asilgulsar1:submitblock-retry

Conversation

@asilgulsar1

Copy link
Copy Markdown

We run simplepool in solo mode for eCash.com (ECX, BIP300/301) behind the CUSF enforcer. These came out of a review of the solo path before we rely on it.

A found block is marked rejected after one submitblock attempt that gets no usable answer: connection refused, a timeout, HTTP other than 200/500, or an RPC error. rejected is final for reconcile, and the block hex is logged only at DEBUG. So an enforcer restart at the moment a share solves a block loses that block.

  • The block is written to <db dir>/found-blocks/<ms>.hex before submission.
  • An attempt with no usable answer is retried with backoff for up to 120 s.
  • New optional submit_fallback_url / _user / _pass set a second node, tried on each failed round (with the enforcer as bitcoind_url, the node behind it; a submitblock-only rpcauth user is documented in proxy.conf.example).
  • duplicate, duplicate-inconclusive and inconclusive are not treated as refusals.
  • Only a node's refusal (BITCOIND_SUBMIT_REFUSED) is filed rejected. A block no node answered for is filed pending, and reconcile settles it from the chain.

Retries run on the finder's connection thread with no lock held (cb_lock is released before on_block, and the job is a counted reference), so only that connection waits.

Tests: test_submit_answers (null, duplicate*, inconclusive, a reject reason, duplicate-invalid, and no server at all). We also ran it end to end against a mock enforcer and node: 503 + fallback → pending via the fallback; 503, no fallback → pending after 119 s, file saved; duplicate → pending; a reject reason → rejected.

Open question for maintainers: filing a block nobody answered for as pending changes what pending means: it no longer guarantees a node accepted it. If you'd rather keep that, a separate status (e.g. unconfirmed) would do.

Tested: make test passes on this branch alone, and the new test fails on main without the fix. This PR is independent of the five others opened alongside it, and all six merge together cleanly. Happy to add a CHANGELOG entry if you'd like one.

🤖 Generated with Claude Code

…n disk

A found block was marked 'rejected' after a single submitblock attempt that
got no usable answer (connection refused, timeout, non-200/500, RPC error).
'rejected' is final for reconcile, and the block hex is only logged at DEBUG,
so an enforcer restart at the moment a share solved a block lost the block.

- The block is written to <db dir>/found-blocks/<ms>.hex before submission.
- An attempt with no usable answer is retried with backoff for up to 120 s.
- Optional submit_fallback_url/_user/_pass: a second node tried on each
  failed round (e.g. the node behind the enforcer, as a submitblock-only
  rpcauth user).
- "duplicate", "duplicate-inconclusive" and "inconclusive" are not refusals.
- Only a node's refusal (BITCOIND_SUBMIT_REFUSED) is filed 'rejected'; a
  block no node answered for is filed 'pending', and reconcile settles it
  from the chain like any other.

Retries run on the finder's connection thread, holding no lock: only that
connection waits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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