Skip to content

[BCH] G3a populated won-block path: stratum work-source + finding3 + GBT mempool-sync - #573

Merged
frstrtr merged 6 commits into
masterfrom
bch/g3a-populated-mempoolsync
Jul 2, 2026
Merged

[BCH] G3a populated won-block path: stratum work-source + finding3 + GBT mempool-sync#573
frstrtr merged 6 commits into
masterfrom
bch/g3a-populated-mempoolsync

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 27, 2026

Copy link
Copy Markdown
Owner

BCH G3a — populated won-block path (full stack vs master)

Lands the BCH populated-block won path proven on regtest: won block 000305008237a228 @h326, nTx=7 (6 mempool txs + coinbase), both broadcaster legs fire, tip advances 325 -> 326.

Scope / real diff vs master

This branch is a STACK, not the +91/-1 mempool-sync fix alone. finding3 is NOT on master, so the PR carries the whole stack:

  • G2 stratum work-source standupsrc/impl/bch/stratum/work_source.{hpp,cpp}, coinbase_outputs.hpp, pool_entrypoint.hpp, main_bch.cpp, coinbase-author KAT. Gives c2pool-bch a --pool/stratum-serve entrypoint.
  • finding3 — set_difficulty SHA256d-multiplier fix + RPC submitblock connect-race hardening (both broadcaster legs fire at won block).
  • G3a mempool-sync fix (the focus) — 2 slices in src/impl/bch/coin/:
    1. EmbeddedDaemon::sync_mempool_from_rpc() feeds BCHN GBT txs into m_pool (one-shot at run() startup; per-tip refresh deferred to a later fenced non-blocking slice).
    2. Mempool::add_tx_with_known_fee() + GBT-fee passthrough (fee_known=true so fee-based selection includes them). The real 2nd bug was fee-selection, not template-rebuild.

Net diff vs master: +1718 / -17 across 16 files, all under src/impl/bch/ + src/c2pool/main_bch.cpp + the BCH build.yml allowlist (correctly fenced, no cross-coin surface).

Phantom member

config->m_regtest has been re-homed onto the EmbeddedDaemon is_regtest ctor param + bool m_regtest. Confirmed via git grep: ZERO references to config->m_regtest under src/impl/bch/ at this head.

Verification

  • Build GREEN on VM905; coinbase KATs PASS.
  • Won-block e2e proven on live regtest BCHN-v29 (block above).
  • CI full rollup runs on this PR — gating the merge on a CLEAN rollup per standing rule.

Merge operator-gated; not self-merging.

@frstrtr
frstrtr force-pushed the bch/g3a-populated-mempoolsync branch from 9fc913e to 8a96158 Compare July 1, 2026 17:11
frstrtr added 6 commits July 2, 2026 07:45
…ol-merged-v36

The oracle (data.py ~945) fires the subsidy/200 finder fee only in the
not-v36_active branch; the v36 gentx pays no finder fee (pure PPLNS
accounting). The BCH v36 coinbase builder was deducting subsidy/200 from
the donation output and crediting the miner -- a payout-value divergence
from the canonical merged-v36 gentx. Byte-parity is the HARD invariant,
so the sv>=36 path now deducts nothing. Pre-v36 (v35) finder fee remains
in the legacy not-v36 path, untouched. Consensus-bearing (moves payout
values) -- merge stays operator-gated.

BCH-only scope: src/impl/bch/stratum/work_source.cpp. No core, no
bitcoin_family. Syntax-clean. Branch-only on bch/g2-work-source.
…acle

Extract the oracle-conforming coinbase OUTPUT-ASSEMBLY (donation forced last,
>=1-sat marker rule, amount-asc/script-asc sort, dests[-4000:] cap) out of
BCHWorkSource::build_connection_coinbase into the pure header-only
assemble_v36_coinbase_outputs(), so the byte-shape is pinned against the
p2pool-merged-v36 oracle (data.py generate_transaction v36 branch) rather than
asserted against the builder itself.

coinbase_author_kat_test (3 cases, ground-truth from scripts/gen_g2_oracle.py,
a verbatim transcription of the data.py v36 amounts/dests/payouts block):
  1. ordering: amount-asc with a B==C tie exercising the script-asc tiebreak,
     donation marker forced last, <1-sat marker decrement of the largest.
  2. donation forced last even when its amount ties the largest PPLNS payout.
  3. finder-fee removal byte-diff: assembled bytes equal the oracle v36 gentx
     and differ from the pre-v36 199/200-haircut + subsidy/200 finder-fee
     control -- proving the fee was removed, not self-authored.

Wired into the pure BCH_ABLA_TESTS CMake list and BOTH build.yml COIN_BCH
allowlists (no NOT_BUILT green-by-omission). per-coin isolation: src/impl/bch
only; zero p2pool-merged-v36 surface.
Close the M5 served-IWorkSource gap (slice-b criterion 1): standup_pool_run
now constructs bch::stratum::BCHWorkSource off the embedded daemon HeaderChain
+ Mempool and stands up core::StratumServer on the miner-facing bind. A
mainnet-hit (share-author) block routes through the SAME dual-path broadcaster
(embedded P2P primary + BCHN submitblock fallback) as the won-block sink, via
daemon.broadcast_won_block(block_bytes, HexStr(block_bytes)) returning r.any()
-- so the genuine share coinbase is what reaches the network, not a synthetic
solo-cb leg-C block.

stratum_port==0 disables the front-end (daemon-only run-loop preserved). Header
syntax-clean. src/impl/bch only; p2pool-merged-v36 surface NONE (run-loop
bring-up + block dispatch, not share/PPLNS/coinbase bytes). BCH = SHA256d
standalone parent, no-segwit, CashTokens transparent-carry.
First non-harness c2pool-bch entrypoint. --pool stands up the BCH pool
node + embedded coin daemon via bch::standup_pool_run (the prior 0-caller
production standup), binding the dual-path won-block sink and, with
--stratum [HOST:]PORT, the miner-facing BCHWorkSource + StratumServer so a
genuine share-author coinbase is what gets assembled and broadcast.

Config built without a YAML load (matches --ibd harness): P2P magic
(mainnet/testnet/regtest), BCHN peer, and sharechain PREFIX set by hand
from chainparams. External BCHN-RPC fallback retained. --regtest/--anchor
added; banner + arg dispatch wired.

Structural slice (criterion 1): gives standup_pool_run its first caller.
FOUND->ASSEMBLED->ACCEPTED e2e on fresh-genesis regtest is the next
behavioural slice. bch-fenced (src only), p2pool-merged-v36 surface NONE.
--pool --regtest previously collapsed to testnet params (anchor@955700,
P2P->.110) and served unwinnable testnet difficulty, so a single CPU
could never win a block. Thread regtest as a third net distinct from
mainnet/testnet:

- asert.hpp: asert_regtest() + bch_pow_limit_regtest() (fPowNoRetargeting,
  fixed target at powLimit nBits 0x207fffff; ASERT bypassed on regtest)
- header_chain.hpp: BCHChainParams::regtest() (P2P 18444, cold-start tip
  seeded so served nbits == 0x207fffff before first P2P regtest block)
- embedded_daemon.hpp / pool_entrypoint.hpp / main_bch.cpp: is_regtest
  dispatch threaded through the --pool entrypoint

GBT-from-local-regtest-BCHN (regtest_block::build_from_gbt) deferred to a
follow-on sub-slice. Consensus-neutral: regtest-only behavior, no mainnet
path change. Fenced to src/impl/bch/ + main_bch.cpp dispatch.
…locks

The embedded daemon built coinbase-only templates (nTx=1) on regtest and any
RPC-primary deploy: loose BCHN-mempool txs never reach the embedded P2P relay,
so build_template selected from an empty m_pool. Two fenced fixes:

1. EmbeddedDaemon::sync_mempool_from_rpc() (run()-startup): feed the BCHN GBT
   tx set -- the same set NodeRPC::getwork() consumes -- into m_pool. No-op when
   no external RPC is bound; regtest skips the mainnet/testnet anchor (is_regtest
   stored as a member). One-shot known limitation; per-tip refresh is a tracked
   non-blocking follow-up.

2. Mempool::add_tx_with_known_fee() + GBT per-tx fee passthrough (fee_known=true)
   so get_sorted_txs_with_fees() selects GBT txs into the template and
   coinbasevalue stays accurate.

Proven on live regtest BCHN: won block @h326 nTx=7 (6 mempool + coinbase),
1539-byte relayed body, both broadcaster legs fire (p2p sent, rpc ok, tip
325->326). Fence: src/impl/bch only; no p2pool-merged-v36 surface; external-RPC
fallback preserved.
@frstrtr
frstrtr force-pushed the bch/g3a-populated-mempoolsync branch from 8a96158 to f7486db Compare July 2, 2026 07:46
@frstrtr
frstrtr merged commit 3c3071f into master Jul 2, 2026
22 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