btc: arm submitblock RPC backup (ARM B) of the dual-path broadcaster (#744)#787
Merged
Conversation
…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
force-pushed
the
btc/broadcaster-arm-b-submitblock
branch
from
July 21, 2026 02:59
22da04b to
b6e6bda
Compare
frstrtr
marked this pull request as ready for review
July 22, 2026 05:08
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.
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_connect→submit_block_p2p_raw) live-wired, but ARM B (submitblock RPC backup) was code-present-but-unarmed:m_rpcwas 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-onlybitcoin.confcredential parser (twin ofdgb/coin/rpc_conf.hpp); rpcpassword stays off the process table.Node::arm_submit_rpc()— constructs+connectsNodeRPCfor submitblock (no getwork), plushas_rpc().main_btc— loads creds (default~/.bitcoin/bitcoin.conf), arms whenarmed(), else UNARMED.--coin-rpc/--coin-rpc-authflags.Commit 2 — harden the newly-live reward path (review fixes)
Arming ARM B made four previously-dead defects live. All fixed:
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. Newbtc/coin/genesis.hpp+btc_genesis_hash(IS_TESTNET); per-net BTC genesis (mirrors DGB).genesis_check_test.cpppins it.std::stoiaborted the node at startup on a malformedrpcportin the default conf (read with no flags). Newparse_port(digits-only, range-checked, never throws) → junk degrades to UNARMED. 3 KATs.JsonRpcExceptionout ofsubmit_block_hex;broadcast_block_for_connecthad 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.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
std::stoibug 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.