dgb: v36 donation version-gate (pillar 4 of modern-layer activation) - #82
Merged
Conversation
Add the pre-V36 DGB donation script and gate get_donation_script() on
share version, completing the v36 donation migration for c2pool-dgb:
pre-V36 : farsider350 2-of-3 bare multisig (DGB v35 canonical donation,
from p2pool-dgb-scrypt-350 p2pool/data.py:66 DONATION_SCRIPT)
V36+ : shared COMBINED P2SH 1-of-2 (byte-identical to LTC network)
Previously get_donation_script() ignored the version and always returned
COMBINED; DGB was missing its pre-V36 donation entirely. The v35 bytes are
the farsider350 2-of-3 OP_CHECKMULTISIG script (NOT the LTC P2PK form), so
the migration is DGB-specific. Matches the donation transition in
p2pool-merged-v36. Header-only and additive; no behavioral change until the
modern share-creation/gentx path is wired into a c2pool-dgb binary.
frstrtr
added a commit
that referenced
this pull request
Jun 14, 2026
Phase A (#82) leaf deps for the embedded P2P+mempool layer. 1:1 mirror of src/impl/btc/coin (DGB is structurally BTC-shaped, non-MWEB; Scrypt PoW divergence lives in header_chain.hpp). block.hpp carries the multi-algo note: the version field encodes the mining algo but the 80-byte header layout is single-format and algo-agnostic; algo selection is read in header_chain, not in (de)serialization. node_interface.hpp restores the members the Path-A stub deferred (new_tx/new_headers/full_block/txidcache/known_txs), now that the types exist.
frstrtr
added a commit
that referenced
this pull request
Jun 14, 2026
Phase A (#82). 1:1 mirror of src/impl/btc/coin (non-MWEB). SegWit/wtxid short-IDs apply (DGB activated SegWit). No coin-specific magic/consensus constants in this layer.
frstrtr
added a commit
that referenced
this pull request
Jun 14, 2026
Phase A (#82). 1:1 mirror of src/impl/btc/coin (non-MWEB) speaking the DigiByte Core wire protocol; Scrypt-only. Two P2P-handshake constants carried from BTC are flagged TODO(M3) for reconciliation vs DigiByte Core params: protocol_version (70016) and advertised port (8333 -> DGB mainnet 12024). Neither is consensus. dgb_coin CMake lists the new files but stays unreferenced by add_subdirectory() pending the ci-steward OBJECT-lib wiring.
frstrtr
added a commit
that referenced
this pull request
Jun 14, 2026
Flip per OBJECT-lib convention: register src/impl/dgb at top level and enable the coin subdir under COIN_DGB. dgb_coin now builds standalone (-DCOIN_DGB=ON); libdgb_coin.a links clean, 0 errors. daemon/test stay commented (M3).
frstrtr
added a commit
that referenced
this pull request
Jun 14, 2026
DGB Phase A: embedded P2P + mempool (#82)
This was referenced Jun 17, 2026
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Add two KATs to block_assembly_test proving the won-block witness shape is
governed by whether the gentx carries a witness (i.e. is_segwit_activated at
gentx-build time), not by an unconditional witness branch in the framer:
* SegwitGentxEmitsWitnessBlock: a gentx carrying the BIP141 coinbase witness
reserved value => TX_WITH_WITNESS block (strictly larger than legacy, marker
emitted, reserved value round-trips). DGB SEGWIT_ACTIVATION_VERSION=35.
* LegacyGentxEmitsLegacyBlock: a no-witness gentx => legacy block, no
marker/flag, byte-stable re-serialization (the BCH is_segwit_activated()==0
shape the companion bch test asserts).
block_assembly.hpp: correct the wire-encoding comment from unconditional
(TX_WITH_WITNESS) to the conditional TX_WITH_WITNESS(m_txs) Bitcoin-Core codec.
src/impl/dgb/ only; no p2pool-merged-v36 surface; same dgb_block_assembly_test
target already in test/CMakeLists.txt + both build.yml allowlists.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Pin the embedded-primary / external-digibyted-RPC-fallback contract of dgb::coin::CoinNode (core::coin::ICoinNode) that the won-block dispatch relies on: web_server submits a solved block via m_coin_node->submit_block_hex(), which forwards to NodeRPC::submitblock (the external-daemon fallback that MUST persist alongside embedded). Three invariants, mirroring impl/bch/test/coin_node_seam_test.cpp: 1. no source -> empty WorkView, no throw 2. embedded, no rpc -> WorkView sourced from embedded 3. no rpc sink -> submit_block_hex == false (!m_rpc guard, no crash) The live submitblock call + m_on_block_found tracker callback are wired by the DGB run-loop standup (main_dgb.cpp is selftest-only today); that is the remaining #82 slice and is out of scope here (rpc=nullptr). Registered in test/CMakeLists.txt AND both build.yml --target allowlists (avoids the #143 NOT_BUILT-sentinel trap). 3/3 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Add coin/block_broadcast.hpp -- broadcast_won_block(), the DGB dual-path won-block dispatcher the run-loop wires tracker().m_on_block_found to. Fires BOTH sinks per the broadcaster-gate rule: embedded P2P relay (PRIMARY, supplied as a sink fn until NodeP2P/EmbeddedDaemon lands) AND external digibyted submitblock via the CoinNode seam (FALLBACK, fired ALWAYS, ignore_failure=true so a duplicate after a P2P accept never masks the win). landed_first records the race winner; with neither sink live the call is a safe no-op (any()=false, no throw, null seam never dereferenced). 1:1 contract mirror of bch broadcast_won_block (90a3553); decoupled via std::function P2P sink + ICoinNode* so it is build-verified now. DGB-Scrypt standalone parent -- no merged-coinbase leg in the default build. Complements the #163 RPC-fallback seam half. dgb_block_broadcast_test: 5-case dispatch contract (no-sink no-op, p2p-only, rpc-only, dual-path always-fires-fallback, fallback-no-ack-does-not-mask-p2p) over a fake ICoinNode -- 5/5 PASS, build EXIT=0. Registered in test/CMakeLists.txt AND both build.yml --target allowlists (#143 NOT_BUILT trap avoided). p2pool-merged-v36 surface: NONE (block dispatch only). Per-coin isolation: src/impl/dgb/coin/ only.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
make_on_block_found turns a winning share hash into a broadcast: reconstruct share->block via an injected WonBlockReconstructor, then fire broadcast_won_block down both paths (P2P primary + external digibyted submitblock fallback). The reconstructor is injected so the run-loop dispatch contract is build-verified and run-tested now, before the faithful as_block reassembly is ported. won_block_dispatch_test drives the handler end-to-end: known share fires both paths, unknown/unassemblable share broadcasts nothing, RPC-only still reaches the network, missing reconstructor is a safe no-op. 4/4 PASS. Registered in test/CMakeLists.txt and both build.yml --target allowlists (avoids the #143 NOT_BUILT trap). src/impl/dgb/ only; no p2pool-merged-v36 surface.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…5 KATs (#168) * dgb(#82): faithful as_block FRAMING half — share->block reassembly Port the FRAMING half of p2pool data.py Share.as_block into src/impl/dgb/coin/block_assembly.hpp: reconstruct the full block header merkle_root from the gentx hash walked up the share merkle_link (the SmallBlockHeader stored on a share omits merkle_root), then frame the block txs as [gentx] ++ other_txs (coinbase at index 0) and serialize through the live BlockType codec NodeRPC::submit_block already uses, so the reconstructed block round-trips and a daemon accepts it byte-for-byte. gentx bytes + known_txs lookup stay INJECTED (the gentx-byte build that hits coinbase-byte adjudication is the next reconstructor slice); this pins the framing + merkle_root math now. dgb_block_assembly_test: 5 KATs (empty-branch root==gentx_hash, index-bit side select, coinbase-first round-trip, coinbase-only) registered in BOTH test/CMakeLists.txt and the build.yml --target allowlist. Per-coin isolation: src/impl/dgb/ only; p2pool-merged-v36 surface: none. * dgb(#82): assert won-block witness predicate (is_segwit_activated gate) Add two KATs to block_assembly_test proving the won-block witness shape is governed by whether the gentx carries a witness (i.e. is_segwit_activated at gentx-build time), not by an unconditional witness branch in the framer: * SegwitGentxEmitsWitnessBlock: a gentx carrying the BIP141 coinbase witness reserved value => TX_WITH_WITNESS block (strictly larger than legacy, marker emitted, reserved value round-trips). DGB SEGWIT_ACTIVATION_VERSION=35. * LegacyGentxEmitsLegacyBlock: a no-witness gentx => legacy block, no marker/flag, byte-stable re-serialization (the BCH is_segwit_activated()==0 shape the companion bch test asserts). block_assembly.hpp: correct the wire-encoding comment from unconditional (TX_WITH_WITNESS) to the conditional TX_WITH_WITNESS(m_txs) Bitcoin-Core codec. src/impl/dgb/ only; no p2pool-merged-v36 surface; same dgb_block_assembly_test target already in test/CMakeLists.txt + both build.yml allowlists. --------- Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…-trip KAT Factor the p2pool non-witness coinbase (gentx) wire layout out of generate_share_transaction() (share_check.hpp:933, the verification SSOT) into coin/gentx_coinbase.hpp::assemble_gentx_coinbase() so emission and verification cannot diverge on a byte. Pure: takes already-built scripts/amounts (no tracker/share-template dependency) so it is directly KAT-able; this is the single builder that create_local_share() and the won-block reconstruction body will consume in follow-up slices. KAT vectors are GROUND-TRUTH from the canonical oracle frstrtr/p2pool-dgb-scrypt (util/pack.py byte logic + bitcoin/data.py tx_id_type; donation script 4104ffd0...ac), not self-generated, so a PASS proves build -> non-witness serialize -> double-SHA256 == oracle bytes/txid, not mere self-consistency. Covers the no-segwit and witness-commitment-first layouts; the only DGB<->BCH divergence is the gated segwit predicate at serialize time. dgb_gentx_coinbase_test 3/3 PASS, build EXIT=0; target wired into ctest + BOTH build.yml --target allowlists (#143 NOT_BUILT trap avoided). Scope: factor + KAT only. The won-block-reaches-network wiring (m_on_block_found and submit_block_hex) is fix #82 and stays separate.
This was referenced Jun 18, 2026
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…-trip KAT (#171) Factor the p2pool non-witness coinbase (gentx) wire layout out of generate_share_transaction() (share_check.hpp:933, the verification SSOT) into coin/gentx_coinbase.hpp::assemble_gentx_coinbase() so emission and verification cannot diverge on a byte. Pure: takes already-built scripts/amounts (no tracker/share-template dependency) so it is directly KAT-able; this is the single builder that create_local_share() and the won-block reconstruction body will consume in follow-up slices. KAT vectors are GROUND-TRUTH from the canonical oracle frstrtr/p2pool-dgb-scrypt (util/pack.py byte logic + bitcoin/data.py tx_id_type; donation script 4104ffd0...ac), not self-generated, so a PASS proves build -> non-witness serialize -> double-SHA256 == oracle bytes/txid, not mere self-consistency. Covers the no-segwit and witness-commitment-first layouts; the only DGB<->BCH divergence is the gated segwit predicate at serialize time. dgb_gentx_coinbase_test 3/3 PASS, build EXIT=0; target wired into ctest + BOTH build.yml --target allowlists (#143 NOT_BUILT trap avoided). Scope: factor + KAT only. The won-block-reaches-network wiring (m_on_block_found and submit_block_hex) is fix #82 and stays separate. Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…b-slice 2) Won-block reconstructor connecting tissue (sub-slice 2): coin/other_tx_assembler.hpp bridges the ordered other_tx hash list from resolve_other_tx_hashes (sub-slice 1) to the deserialized MutableTransaction vector that assemble_won_block frames as txs = [gentx] ++ other_txs. Faithful port of the known_txs lookup in p2pool data.py Share.as_block: other_txs = [known_txs[h] for h in transaction_hashes]. The known-tx lookup is INJECTED as a (hash) -> const MutableTransaction* callable (nullptr == unknown), mirroring the seam-first decomposition of sub-slice 1 and won_block_dispatch.hpp, so the bridge is unit-testable against a synthetic known-tx set without a live mempool. A missing hash THROWS std::out_of_range rather than dropping/placeholder-filling the tx: a block with a missing other_tx has the wrong merkle root and is daemon-rejected, so loud failure is strictly safer than emitting a malformed block. Witness framing is not decided here -- the txs are returned verbatim and the block witness shape stays governed by assemble_won_block`s TX_WITH_WITNESS conditional codec. DGB is segwit-active (SEGWIT_ACTIVATION_VERSION, v36 >= it), so the path is live; the KAT pins that a witness-bearing other_tx flips the assembled block to the witness codec via the other_tx leg, not gentx-only. dgb_other_tx_assembler_test: 5/5 PASS -- order-preserve, missing-throws, empty, end-to-end resolve->assemble->frame (coinbase-first, ref order), witness reachability. Wired into test/CMakeLists.txt + both build.yml --target allowlists (#143 NOT_BUILT trap). Per-coin isolation: src/impl/dgb/ only; p2pool-merged-v36 surface: NONE.
This was referenced Jun 18, 2026
Merged
frstrtr
added a commit
that referenced
this pull request
Jun 19, 2026
…coinbase generate_share_transaction (verification path) and create_local_share (emission path) each open-coded the coinbase wire layout (version|vin|vouts|locktime) and the txid double-SHA256. Two byte paths pinned to the same oracle vector = proven-equivalent, not unified: a third edit could still diverge them. Collapse both onto dgb::coin::assemble_gentx_coinbase() (coin/gentx_coinbase.hpp, the #171 SSOT) so emission == verification == one source. Each call site now only builds its per-share inputs (coinbase script, optional segwit witness-commitment script, PPLNS payout outputs, donation, OP_RETURN ref commitment) and hands them to the assembler; the assembler owns wire framing + txid. PackStream tx is reconstructed from the SSOT bytes so the downstream V36 hash_link diagnostics are byte-for-byte unchanged. No oracle vector regeneration. Single-coin scope: src/impl/dgb/ only. dgb build EXIT=0; dgb_share_test 5/5; dgb_gentx_coinbase_test 3/3.
frstrtr
added a commit
that referenced
this pull request
Jun 19, 2026
generate_share_transaction computes the coinbase via assemble_gentx_coinbase (the SSOT proven by #172) but returned only the gentx_hash, discarding the bytes. reconstruct_won_block needs the exact non-witness coinbase bytes -- it is block tx[0] and its txid is the merkle leaf -- not just the hash. Add an optional out_gentx (GentxCoinbase*) param, default nullptr: zero change for the verification callers, surfaces {bytes,txid} for the reconstructor. KAT proves the exposed bytes hash to the returned gentx_hash and deserialize into the coinbase MutableTransaction that assemble_won_block frames, round-tripping byte-identically (non-witness). Single-coin (src/impl/dgb/ only); reuses the existing #172 dgb_gentx_share_path_test target (no new allowlist entry).
frstrtr
added a commit
that referenced
this pull request
Jun 19, 2026
…coinbase generate_share_transaction (verification path) and create_local_share (emission path) each open-coded the coinbase wire layout (version|vin|vouts|locktime) and the txid double-SHA256. Two byte paths pinned to the same oracle vector = proven-equivalent, not unified: a third edit could still diverge them. Collapse both onto dgb::coin::assemble_gentx_coinbase() (coin/gentx_coinbase.hpp, the #171 SSOT) so emission == verification == one source. Each call site now only builds its per-share inputs (coinbase script, optional segwit witness-commitment script, PPLNS payout outputs, donation, OP_RETURN ref commitment) and hands them to the assembler; the assembler owns wire framing + txid. PackStream tx is reconstructed from the SSOT bytes so the downstream V36 hash_link diagnostics are byte-for-byte unchanged. No oracle vector regeneration. Single-coin scope: src/impl/dgb/ only. dgb build EXIT=0; dgb_share_test 5/5; dgb_gentx_coinbase_test 3/3.
frstrtr
added a commit
that referenced
this pull request
Jun 19, 2026
generate_share_transaction computes the coinbase via assemble_gentx_coinbase (the SSOT proven by #172) but returned only the gentx_hash, discarding the bytes. reconstruct_won_block needs the exact non-witness coinbase bytes -- it is block tx[0] and its txid is the merkle leaf -- not just the hash. Add an optional out_gentx (GentxCoinbase*) param, default nullptr: zero change for the verification callers, surfaces {bytes,txid} for the reconstructor. KAT proves the exposed bytes hash to the returned gentx_hash and deserialize into the coinbase MutableTransaction that assemble_won_block frames, round-tripping byte-identically (non-witness). Single-coin (src/impl/dgb/ only); reuses the existing #172 dgb_gentx_share_path_test target (no new allowlist entry).
frstrtr
added a commit
that referenced
this pull request
Jun 19, 2026
dgb: #82 arm2 — bind sharechain m_on_block_found to won-block dispatcher
frstrtr
added a commit
that referenced
this pull request
Jun 20, 2026
dgb(#82): wire won-block P2P-relay PRIMARY arm to live coin-daemon producer
frstrtr
added a commit
that referenced
this pull request
Jun 20, 2026
dgb(#82): faithful won-block reconstruct closure + fail-closed KAT
frstrtr
added a commit
that referenced
this pull request
Jun 20, 2026
dgb(#82): bind 5 won-block reconstruct seams to live tracker (decision (a), deadlock-safe)
This was referenced Jun 20, 2026
Merged
This was referenced Jul 20, 2026
Merged
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.
Scope: pillar 4 (donation migration) only — pillar 1 has no activation surface yet
This PR lands the one part of the v36 modern-layer activation that has a real,
isolated surface in
src/impl/dgb/today: the version-gated donation script.What changed (
src/impl/dgb/config_pool.hpp, additive, header-only)DONATION_SCRIPT(105-byte OP_2 / 3x33B pubkey / OP_3OP_CHECKMULTISIG bare multisig). Bytes are the DGB v35 canonical donation
from farsider350
p2pool-dgb-scrypt-350p2pool/data.py:66— generatedprogrammatically from the verified hex, not hand-transcribed.
get_donation_script(version):>=36-> sharedCOMBINEDP2SH 1-of-2(byte-identical to LTC);
<36-> the farsider350 2-of-3.Previously
get_donation_script()ignored the version and always returnedCOMBINED — DGB was missing its pre-V36 donation entirely. The DGB v35 form is
the 2-of-3 multisig, not the LTC/BTC P2PK form, so this migration is
DGB-specific. Constants confirmed against the directive + operator-confirmed scope.
Why pillar 1 (version-voting / AutoRatchet) is NOT in this PR
Mirroring BTC #81 presumes a modern sharechain stack that DGB does not have yet:
src/c2pool/main_dgb.cpp(onlyc2pool-btcis an executable target)src/impl/dgb/auto_ratchet.hppsrc/impl/dgb/share_check.hpp/share_tracker.hppsrc/impl/dgb/stratum/work_source.{hpp,cpp}There are zero hardcoded
share_version=35sites to replace because DGB hasno share-creation/gentx path. Pillar 1 activation first requires porting the LTC
modern layer (~6.8K LOC) into
src/impl/dgb/+ creatingmain_dgb.cpp+ ac2pool-dgbexecutable target. That is multi-day work (overlaps M3 Phase C),surfaced to integrator as a discovery/scope decision — not foldable into a
short-turn activation PR.
Pillars 2/3
Both absent (not present-inert): no DensePPLNSRing, no anti-hop — the
share_tracker/PPLNS layer is unported.
Boundary / safety
src/impl/dgb/only. Did NOT touchshare_check.hppF10, ltc/, or core.calls
get_donation_scriptuntil the gentx path lands).c2pool-preflight.shexits RED on pre-existingsrc/impl/doge/coin/*->impl/ltc/coin/*cross-coin includes (shared DOGE-auxmodule, not my domain) + a core
sharechain.hppiterator WARN. None touch thisdiff, which only adds two
constexpr std::arraymembers to a dgb header.