Skip to content

btc: arm submitblock RPC backup (ARM B) of the dual-path broadcaster (#744)#787

Merged
frstrtr merged 2 commits into
masterfrom
btc/broadcaster-arm-b-submitblock
Jul 22, 2026
Merged

btc: arm submitblock RPC backup (ARM B) of the dual-path broadcaster (#744)#787
frstrtr merged 2 commits into
masterfrom
btc/broadcaster-arm-b-submitblock

Conversation

@frstrtr

@frstrtr frstrtr commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Part of #744. DGB is the reference; DASH is now GREEN.

Gap

BTC's dual-path broadcaster had ARM A (embedded P2P relay, submit_block_for_connectsubmit_block_p2p_raw) live-wired, but ARM B (submitblock RPC backup) was code-present-but-unarmed: m_rpc was never constructed in the run path. A won block could not reach a locally-run bitcoind.

Commit 1 — arm ARM B (mirrors DGB #82)

  • btc/coin/rpc_conf.hpp — header-only bitcoin.conf credential parser (twin of dgb/coin/rpc_conf.hpp); rpcpassword stays off the process table.
  • Node::arm_submit_rpc() — constructs+connects NodeRPC for submitblock (no getwork), plus has_rpc().
  • main_btc — loads creds (default ~/.bitcoin/bitcoin.conf), arms when armed(), else UNARMED. --coin-rpc / --coin-rpc-auth flags.

Commit 2 — harden the newly-live reward path (review fixes)

Arming ARM B made four previously-dead defects live. All fixed:

  • B1 (blocker)NodeRPC::check() probed the Litecoin genesis (copied from the LTC impl, a node: consensus core drifted into 2-4 divergent copies across coins (17/43 fns) — reconcile before hoisting; latent cross-coin bug hazard #759-class cross-coin drift) → BTC-mainnet handshake gate always failed → permanent 15s reconnect loop, ARM B degraded on mainnet. New btc/coin/genesis.hpp + btc_genesis_hash(IS_TESTNET); per-net BTC genesis (mirrors DGB). genesis_check_test.cpp pins it.
  • B2 (blocker) — unguarded std::stoi aborted the node at startup on a malformed rpcport in the default conf (read with no flags). New parse_port (digits-only, range-checked, never throws) → junk degrades to UNARMED. 3 KATs.
  • M1 (major) — a daemon unreachable at submit raised JsonRpcException out of submit_block_hex; broadcast_block_for_connect had no throw guards → the exception destroyed ARM A's already-succeeded relay → false "reached NEITHER — lost subsidy" alarm. Both legs now guarded. 3 throwing-leg KATs.
  • M2 (major) — no socket deadline on the beast stream shared with stratum on one single-threaded ioc → a hung bitcoind froze the whole node mid-won-block. Added apply_socket_timeouts() (SO_SND/RCVTIMEO, mirrors DASH dash: decouple blocking coin-RPC + heavy work off the stratum io_context (io-thread-decouple) #781), armed after each (re)connect.

Safety

Broadcast/RPC-transport path only — no PoW hash, share format, coinbase commitment, or PPLNS math touched (consensus-neutral). BTC-fenced. Builds clean (c2pool-btc + btc_share_test); 20 KATs pass (8 conf + 4 genesis + 8 connect incl. 3 new throwing-leg).

Follow-ons

  • Run-path dual-path soak against a live regtest (both arms fire + accept) — gates the un-draft; shared with LTC/BCH.
  • The B2 std::stoi bug exists verbatim in the DGB twin (dgb/coin/rpc_conf.hpp) — fixed separately (see the DGB PR) to keep per-coin fencing.

Draft — for re-review, not merge.

frstrtr added 2 commits July 21, 2026 05:25
…ter (#744)

The embedded coin-net P2P relay (submit_block_for_connect -> submit_block_p2p_raw)
is the always-primary daemonless broadcast arm and was already live-wired. The
submitblock RPC backup (ARM B) existed in btc::coin::Node but m_rpc was never
constructed in the run path (init_rpc was dead code that also forced getwork),
so a won block could not reach a locally-run bitcoind -- the #744 gap.

Add an opt-in submitblock backup mirroring the DGB reference (#82):
- btc/coin/rpc_conf.hpp: header-only bitcoin.conf credential parser (twin of
  dgb/coin/rpc_conf.hpp). rpcpassword stays off the process table; --coin-rpc
  carries HOST:PORT only, --coin-rpc-auth points at the conf file.
- btc::coin::Node::arm_submit_rpc(): constructs+connects NodeRPC for submitblock
  ONLY (no getwork side effect), plus has_rpc().
- main_btc: load creds (default ~/.bitcoin/bitcoin.conf), arm when armed()==true,
  otherwise stay UNARMED (daemonless default, byte-identical to before).
- rpc_conf_test.cpp: 5 KATs (armed/unarmed/missing-file/aliases/endpoint-override).

Broadcast-config path only -- no PoW hash, share format, coinbase commitment, or
PPLNS math is touched (consensus-neutral). BTC-fenced; no shared/core edit.
Builds clean (c2pool-btc + btc_share_test); KATs pass.
…socket deadline (#744/#787)

Arming ARM B (m_rpc) made four previously-dead defects live on the reward path.
Review (review) findings, all fixed:

B1 (blocker) — NodeRPC::check() probed the LITECOIN genesis hash (copied from the
LTC impl, a #759-class cross-coin drift). On BTC mainnet the is_main_chain &&
!has_block gate always failed -> permanent 15s reconnect loop, ARM B degraded on
the one net where a lost block is real money. New btc/coin/genesis.hpp +
btc_genesis_hash(IS_TESTNET); check() now probes the per-net BTC genesis (mirrors
the DGB reference). genesis_check_test.cpp pins it (regression guard vs the LTC
hash).

B2 (blocker) — unguarded std::stoi in rpc_conf.hpp aborted the node at startup on
a malformed rpcport (e.g. rpcport=abc) in the DEFAULT ~/.bitcoin/bitcoin.conf,
crashing operators who never opted in. New conf_detail::parse_port (digits-only,
range-checked, never throws) -> junk degrades to UNARMED. 3 new KATs.

M1 (major) — a daemon unreachable at submit raised JsonRpcException out of
submit_block_hex; broadcast_block_for_connect had no throw guards (unlike the core
SSOT), so the exception destroyed ARM A's already-succeeded relay -> false 'reached
NEITHER -- lost subsidy' alarm for a block that WAS relayed. Both legs now guarded.
3 new throwing-leg KATs.

M2 (major) — no socket deadline on the beast tcp_stream shared with stratum on one
single-threaded ioc; a hung bitcoind froze the whole node mid-won-block. Added
apply_socket_timeouts() (SO_SND/RCVTIMEO, mirrors DASH #781), armed after each
(re)connect.

Also softened the arm_submit_rpc comment (check() does issue read-only probes).
Broadcast/RPC-transport path only -- no PoW, share, coinbase-commitment, or PPLNS
math touched (consensus-neutral). BTC-fenced. Builds clean (c2pool-btc +
btc_share_test); 20 KATs pass.
frstrtr added a commit that referenced this pull request Jul 21, 2026
…socket deadline (#744/#787)

Arming ARM B (m_rpc) made four previously-dead defects live on the reward path.
Review (Fable) findings, all fixed:

B1 (blocker) — NodeRPC::check() probed the LITECOIN genesis hash (copied from the
LTC impl, a #759-class cross-coin drift). On BTC mainnet the is_main_chain &&
!has_block gate always failed -> permanent 15s reconnect loop, ARM B degraded on
the one net where a lost block is real money. New btc/coin/genesis.hpp +
btc_genesis_hash(IS_TESTNET); check() now probes the per-net BTC genesis (mirrors
the DGB reference). genesis_check_test.cpp pins it (regression guard vs the LTC
hash).

B2 (blocker) — unguarded std::stoi in rpc_conf.hpp aborted the node at startup on
a malformed rpcport (e.g. rpcport=abc) in the DEFAULT ~/.bitcoin/bitcoin.conf,
crashing operators who never opted in. New conf_detail::parse_port (digits-only,
range-checked, never throws) -> junk degrades to UNARMED. 3 new KATs.

M1 (major) — a daemon unreachable at submit raised JsonRpcException out of
submit_block_hex; broadcast_block_for_connect had no throw guards (unlike the core
SSOT), so the exception destroyed ARM A's already-succeeded relay -> false 'reached
NEITHER -- lost subsidy' alarm for a block that WAS relayed. Both legs now guarded.
3 new throwing-leg KATs.

M2 (major) — no socket deadline on the beast tcp_stream shared with stratum on one
single-threaded ioc; a hung bitcoind froze the whole node mid-won-block. Added
apply_socket_timeouts() (SO_SND/RCVTIMEO, mirrors DASH #781), armed after each
(re)connect.

Also softened the arm_submit_rpc comment (check() does issue read-only probes).
Broadcast/RPC-transport path only -- no PoW, share, coinbase-commitment, or PPLNS
math touched (consensus-neutral). BTC-fenced. Builds clean (c2pool-btc +
btc_share_test); 20 KATs pass.
@frstrtr
frstrtr force-pushed the btc/broadcaster-arm-b-submitblock branch from 22da04b to b6e6bda Compare July 21, 2026 02:59
frstrtr added a commit that referenced this pull request Jul 21, 2026
dgb: guard rpc_conf port parse against malformed conf (#744/#787 B2)
@frstrtr
frstrtr marked this pull request as ready for review July 22, 2026 05:08
@frstrtr
frstrtr merged commit 3e73364 into master Jul 22, 2026
37 of 38 checks passed
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