dash: S8 embedded P2P relay arm — won-block dual-path broadcaster#769
Merged
Conversation
Close the DASH broadcaster dual-path gate. Until now a won DASH block
broadcast only via the submitblock-RPC arm (external dashd); the embedded
P2P relay code existed but was unwired into main_dash's won-block sink, so
DASH was single-path and could not broadcast daemonless.
- New src/impl/dash/coin/won_block_dispatch.hpp: broadcast_won_block() fires
a won block down BOTH arms, mirroring the DGB block_broadcast.hpp dual-arm
contract conformed to the DASH stratum path (block already reconstructed):
ARM A embedded P2P relay (ALWAYS-PRIMARY, daemonless) -- E1 CoinClient
submit_block_p2p_raw; a won block reaches the network on this arm
alone with no local dashd.
ARM B submitblock RPC backup (on-demand) -- fired whenever a local dashd
is armed; also covers a cold/faulted relay.
Each arm is guarded so a throwing sink can never skip the other; reaching
NEITHER sink logs LOUDLY and reports any()==false (never a silent drop).
- main_dash run_node: build the P2pRelaySink (posts CoinClient submit onto
the io thread; empty when no --coin-p2p-connect peer or --no-p2p-relay)
and the RpcSubmitSink (empty when no dashd creds), and route the
DASHWorkSource won-block sink through broadcast_won_block. New
--no-p2p-relay flag suppresses ARM A only (A/B isolation). Run-loop banner
now reports both arms' armed state.
- test/test_dash_won_block_dualpath.cpp: forced-won-block KAT asserting both
arms carry byte-identical bytes/hex, daemonless P2P-only and RPC-only each
reach the network, no-arm reaches NEITHER sink (fail-loud), and a throwing
primary falls through to the backup. Registered in test/CMakeLists.txt and
both build.yml --target allowlists.
Reward/consensus-neutral (broadcast path only). Per-coin isolation: only
src/impl/dash + main_dash + additive test/CI entries; other coins byte-unchanged.
… target so CI builds it The standalone test_dash_won_block_dualpath executable was never in build.yml's --target allowlist, so CI never built it and CTest failed with 'Could not find executable ... test_dash_won_block_dualpath'. Fold its source into the existing test_dash_broadcaster_full target (already allowlisted in both build legs). Separate TU with its own anonymous namespace and distinct DashWonBlockDualPath suite; gtest_main provides main() -- no symbol clash.
frstrtr
marked this pull request as ready for review
July 20, 2026 14:42
This was referenced Jul 20, 2026
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.
S8 — DASH won-block dual-path broadcaster (embedded P2P relay wired)
Closes the DASH broadcaster dual-path gate. DASH was single-path: a won block broadcast only via the submitblock-RPC arm (external dashd, proven live at block 2507753). The embedded P2P relay code existed but was unwired into
main_dash's won-block sink, so DASH could not broadcast daemonless. This wires the embedded arm — mirroring the DGB reference that already passes this gate (make_on_block_found/block_broadcast.hpp).What changed (fenced to
src/impl/dash+main_dash)src/impl/dash/coin/won_block_dispatch.hpp(new) —dash::coin::broadcast_won_block()fires a won block down BOTH arms, a contract-mirror ofdgb::coin::broadcast_won_blockconformed to the DASH stratum path (block already reconstructed to wire bytes byDASHWorkSource):CoinClient::submit_block_p2p_rawpushes the packed block onto the coin P2P net. With no local dashd, a won block reaches the network on this arm alone.NodeRPC::submit_block_hex, fired whenever a local dashd is armed (also covers a cold/faulted relay;ignore_failure=trueso a duplicate after an ARM-A accept never masks the win).any()==false— never a silent lost subsidy.src/c2pool/main_dash.cpp—run_nodebuilds theP2pRelaySink(posts theCoinClientsubmit onto the io thread; empty when no--coin-p2p-connectpeer or--no-p2p-relay) and theRpcSubmitSink(empty when no dashd creds), and routes theDASHWorkSourcewon-block sink throughbroadcast_won_block. New--no-p2p-relayflag suppresses ARM A only (A/B isolation, matching DGB's toggle). Run-loop banner now reports both arms' armed state. Stale "block-submission deferred / S8" comments updated.test/test_dash_won_block_dualpath.cpp(new) — forced-won-block KAT mirroringdgb_forced_won_share_dualpath_test. 5 cases: both arms carry byte-identical bytes/hex + cross-arm identity; daemonless P2P-only reaches network; RPC-only reaches network; no-arm reaches NEITHER sink (fail-loud); throwing-primary falls through to backup. Registered intest/CMakeLists.txt.Posture
Embedded P2P relay = always-primary (daemonless); submitblock-RPC = on-demand backup (fires with local dashd OR relay fault). Never silent-drop. Reward/consensus-neutral — broadcast path only (no PoW/share/coinbase-commitment/PPLNS touched). Per-coin isolation held: other coins byte-unchanged.
Local verification (this branch)
conan install+cmakeconfigure: OKcmake --build --target c2pool-dash: builds + links cleancmake --build --target test_dash_won_block_dualpath+ run: 5/5 PASSc2pool-dash --run --testnet --no-p2p-relay --stratum 13333: banner printsARM A ... = SUPPRESSED (--no-p2p-relay)/ARM B ... = off (no dashd creds)and stands up/tears down cleanly.tools/ci/check_test_target_allowlist.py: OK (116 targets).The new KAT must be added to the
build.yml--targetallowlist (both CI legs, lines ~141 and ~323) or it becomes a NOT_BUILT/CTest-Not-Run sentinel. This repo's OAuth token lacksworkflowscope, so the branch could not carry the.github/workflows/build.ymledit (push + Git Data API both denied on the workflow path). Please apply this at the two-party merge (append the token to the DASH group in BOTH--targetlists):Draft — integrator reviews + two-party merge (no self-merge). CI's dual-path KAT leg goes green once the build.yml token above is applied (verified locally: builds + 5/5).