ci: build test_dgb_subsidy in both Linux test jobs (fix master-red NOT_BUILT) - #143
Merged
Conversation
…T_BUILT) test_dgb_subsidy is registered in test/CMakeLists.txt via gtest_discover_tests but was never added to the explicit --target allowlist in the build.yml Build tests / Build c2pool+tests steps, so the executable is absent at ctest time and CTest registers the test_dgb_subsidy_NOT_BUILT sentinel -> Run tests fails (exit 8) on both the Linux x86_64 and Linux x86_64 (AsAN+UBSan) jobs. This has left master CI red since #137 landed the test. Add the target to both allowlists. Target builds clean and the 2 subsidy oracle tests pass.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Register the three standalone M3 regression guards (rpc_request_test / softfork_check_test / genesis_check_test) as ctest targets in src/impl/dgb/test/CMakeLists.txt and add them to BOTH build.yml --target allowlists. Header-only: each links only GTest + nlohmann_json (no OBJECT lib), so they stay buildable while the external-daemon transport rpc.cpp wiring remains deferred (Option-B). Avoids the #143 NOT_BUILT trap: a gtest target present in CMake but absent from the build.yml allowlist becomes a NOT_BUILT sentinel that reds master. Both lists, always. 23/23 guard assertions pass (rpc-request 8, softfork 8, genesis 7).
This was referenced Jun 18, 2026
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Replace the header_chain.hpp namespace stub with the validate() body that drives the Scrypt-only chain: per-header disposition (Scrypt validate / accept-by-continuity / reject), work-neutral accounting, and the Scrypt-only DigiShield retarget-window assembly (averaged target + actual timespan). Work-neutrality SSOT: cumulative work advances iff header_credits_work(), the same predicate scrypt_window_ancestors() consults for the retarget window, so the work-accounting and retarget paths cannot drift. Continuity headers extend the chain but credit zero work and are excluded from the retarget window. THIRD INVARIANT under test: a continuity header inside the nominal window is proven skipped from both avg_target and actual_timespan (a naive all-headers window would corrupt both). The damped DigiShield/MultiShield arith_uint256 multiply layers on RetargetWindow in the following slice. Guard header_chain_test wired into the ctest foreach AND both build.yml --target allowlists (the #143 NOT_BUILT lesson). 6/6 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
validate_and_append now enforces the DigiShield-computed next target on the VALIDATE_SCRYPT path: the declared Scrypt target must EQUAL the next-target computed over the Scrypt-only retarget window ending at the current tip (assembled before the header is appended), the nBits-style consensus rule. A configured HeaderChain(DigiShieldParams, window) arms the gate; a default- constructed chain leaves target_timespan 0 so digishield_next_target() returns the 0 sentinel and the gate is a no-op (existing retarget/work-accounting tests run unconstrained, unchanged). A rejected header never mutates the chain (size + cumulative work preserved). +1 ingest-gate test vector (window 1, deterministic 7/8 next-target): wrong target REJECTED with chain unchanged, exact target VALIDATED_SCRYPT crediting work, continuity header bypasses the gate. Added INTO header_chain_test (no new gtest target -> #143 NOT_BUILT trap avoided). 13/13 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Isolates the consensus quirk flagged at header_chain.hpp DIGISHIELD INSERTION POINT: the Scrypt difficulty window must walk Scrypt-algo ancestors ONLY and skip continuity (non-Scrypt) headers; folding a continuity header into the window corrupts the Scrypt retarget and breaks the THIRD INVARIANT work- neutrality. Adds header_credits_work() as the single SSOT predicate the validate() work-accounting and the retarget walk both consult, so they cannot drift. Header-only (deps: dgb_block_algo.hpp + std), so it links into the standalone GTest guard with no dgb OBJECT lib. - coin/dgb_digishield.hpp: scrypt_window_ancestors(), header_credits_work() - test/digishield_walk_test.cpp: 6 guards (zero-bits Scrypt, interleave skip, leading-continuity run, exhausted chain, zero window, work predicate) - wired into BOTH ctest foreach AND both build.yml --target allowlists (#143) Per-algo DigiShield target math layers on top in the following slice.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Replace the header_chain.hpp namespace stub with the validate() body that drives the Scrypt-only chain: per-header disposition (Scrypt validate / accept-by-continuity / reject), work-neutral accounting, and the Scrypt-only DigiShield retarget-window assembly (averaged target + actual timespan). Work-neutrality SSOT: cumulative work advances iff header_credits_work(), the same predicate scrypt_window_ancestors() consults for the retarget window, so the work-accounting and retarget paths cannot drift. Continuity headers extend the chain but credit zero work and are excluded from the retarget window. THIRD INVARIANT under test: a continuity header inside the nominal window is proven skipped from both avg_target and actual_timespan (a naive all-headers window would corrupt both). The damped DigiShield/MultiShield arith_uint256 multiply layers on RetargetWindow in the following slice. Guard header_chain_test wired into the ctest foreach AND both build.yml --target allowlists (the #143 NOT_BUILT lesson). 6/6 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
validate_and_append now enforces the DigiShield-computed next target on the VALIDATE_SCRYPT path: the declared Scrypt target must EQUAL the next-target computed over the Scrypt-only retarget window ending at the current tip (assembled before the header is appended), the nBits-style consensus rule. A configured HeaderChain(DigiShieldParams, window) arms the gate; a default- constructed chain leaves target_timespan 0 so digishield_next_target() returns the 0 sentinel and the gate is a no-op (existing retarget/work-accounting tests run unconstrained, unchanged). A rejected header never mutates the chain (size + cumulative work preserved). +1 ingest-gate test vector (window 1, deterministic 7/8 next-target): wrong target REJECTED with chain unchanged, exact target VALIDATED_SCRYPT crediting work, continuity header bypasses the gate. Added INTO header_chain_test (no new gtest target -> #143 NOT_BUILT trap avoided). 13/13 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
VALIDATE_SCRYPT path now rejects a declared Scrypt target EASIER than pow_limit (target > pow_limit), mirroring DigiByte Core CheckProofOfWork. This fires on the bootstrap/empty-window path (expected == 0) where the nBits-style retarget-equality gate is a no-op, closing the hole where a sub-minimum-difficulty header could seed/extend the chain during a stall. pow_limit == 0 keeps the gate unconfigured (legacy default-ctor chains unconstrained). +1 vector folded into header_chain_test (no new gtest target; #143 NOT_BUILT trap avoided). 19/19 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
CheckProofOfWork second half: the VALIDATE_SCRYPT path now rejects a header whose scrypt(header) digest exceeds its declared target (hash > target). Half 1 (target <= pow_limit) already landed; this closes the missing PoW-satisfaction guard that was a placeholder. HeaderSample gains a uint64 pow_hash proxy (mirrors ltc coin/header_chain hash field). Context-free check, run after the pow_limit ceiling and before the contextual nBits-equality gate, mirroring DigiByte Core if (UintToArith256(hash) > bnTarget) return false. pow_hash == 0 is the standalone default (trivially satisfies any target) so every existing vector is unchanged; the embedded-daemon port fills the real digest into the same field shape. +1 vector folded INTO header_chain_test (no new gtest target, #143 trap avoided): rejects pow_hash > target, accepts == and < boundary, and confirms a continuity header short-circuits before the PoW check. header_chain_test 20/20 PASS, build EXIT=0.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…7d) (#153) * dgb: M3 §7b DigiShield Scrypt-only ancestor walk + work-credit predicate Isolates the consensus quirk flagged at header_chain.hpp DIGISHIELD INSERTION POINT: the Scrypt difficulty window must walk Scrypt-algo ancestors ONLY and skip continuity (non-Scrypt) headers; folding a continuity header into the window corrupts the Scrypt retarget and breaks the THIRD INVARIANT work- neutrality. Adds header_credits_work() as the single SSOT predicate the validate() work-accounting and the retarget walk both consult, so they cannot drift. Header-only (deps: dgb_block_algo.hpp + std), so it links into the standalone GTest guard with no dgb OBJECT lib. - coin/dgb_digishield.hpp: scrypt_window_ancestors(), header_credits_work() - test/digishield_walk_test.cpp: 6 guards (zero-bits Scrypt, interleave skip, leading-continuity run, exhausted chain, zero window, work predicate) - wired into BOTH ctest foreach AND both build.yml --target allowlists (#143) Per-algo DigiShield target math layers on top in the following slice. * dgb: M3 §7b HeaderChain Scrypt-only validate() + retarget-window body Replace the header_chain.hpp namespace stub with the validate() body that drives the Scrypt-only chain: per-header disposition (Scrypt validate / accept-by-continuity / reject), work-neutral accounting, and the Scrypt-only DigiShield retarget-window assembly (averaged target + actual timespan). Work-neutrality SSOT: cumulative work advances iff header_credits_work(), the same predicate scrypt_window_ancestors() consults for the retarget window, so the work-accounting and retarget paths cannot drift. Continuity headers extend the chain but credit zero work and are excluded from the retarget window. THIRD INVARIANT under test: a continuity header inside the nominal window is proven skipped from both avg_target and actual_timespan (a naive all-headers window would corrupt both). The damped DigiShield/MultiShield arith_uint256 multiply layers on RetargetWindow in the following slice. Guard header_chain_test wired into the ctest foreach AND both build.yml --target allowlists (the #143 NOT_BUILT lesson). 6/6 PASS, build EXIT=0. * dgb: M3 §7b per-algo DigiShield damped retarget multiply digishield_next_target() + DigiShieldParams in coin/header_chain.hpp: consumes the Scrypt-only RetargetWindow (avg_target + actual_timespan over Scrypt ancestors only) and produces the next expanded target via DigiByte DigiShield v3: amplitude filter damped = nominal + (actual-nominal)/8, clamp to [3/4, 3/2] nominal rails, bnNew = avg*damped/nominal, capped to pow_limit. __int128 intermediate (proxy-overflow safe); arith_uint256 swaps in later with the same field shape. Returns 0 on empty window / degenerate nominal so the caller keeps the prior target. header_chain_test: +6 DigiShield cases -- nominal (target unchanged), both clamp rails (ceiling 3/2, floor 3/4 via negative timespan), pow_limit floor, empty-window/zero-nominal safety, and end-to-end over the live continuity- skipped window. 12/12 pass, build EXIT=0. Header-only; reuses the already- wired header_chain_test guard (no new ctest/build.yml target). * dgb: M3 §7b wire DigiShield next-target into HeaderChain ingest gate validate_and_append now enforces the DigiShield-computed next target on the VALIDATE_SCRYPT path: the declared Scrypt target must EQUAL the next-target computed over the Scrypt-only retarget window ending at the current tip (assembled before the header is appended), the nBits-style consensus rule. A configured HeaderChain(DigiShieldParams, window) arms the gate; a default- constructed chain leaves target_timespan 0 so digishield_next_target() returns the 0 sentinel and the gate is a no-op (existing retarget/work-accounting tests run unconstrained, unchanged). A rejected header never mutates the chain (size + cumulative work preserved). +1 ingest-gate test vector (window 1, deterministic 7/8 next-target): wrong target REJECTED with chain unchanged, exact target VALIDATED_SCRYPT crediting work, continuity header bypasses the gate. Added INTO header_chain_test (no new gtest target -> #143 NOT_BUILT trap avoided). 13/13 PASS, build EXIT=0. * dgb: M3 §7b DigiShield damped multiply at true 256-bit width Swap the uint64/__int128 retarget intermediate for a header-only 256-bit unsigned (coin/dgb_arith256.hpp) reproducing arith_uint256 multiply-then- divide with 256-bit overflow truncation -- the consensus arithmetic of DigiByte Core CalculateNextWorkRequired. For uint64-range avg_target the path is bit-identical to the prior intermediate, so the existing 13 vectors are unchanged; +5 boundary vectors prove the divergence above 2^64 and the 256-bit truncation near pow_limit that an __int128 proxy could not reproduce. Header-only, single-coin (src/impl/dgb only), tests added into header_chain_test (no new gtest target). * dgb: M3 §7b ingest-gate pow_limit minimum-difficulty ceiling VALIDATE_SCRYPT path now rejects a declared Scrypt target EASIER than pow_limit (target > pow_limit), mirroring DigiByte Core CheckProofOfWork. This fires on the bootstrap/empty-window path (expected == 0) where the nBits-style retarget-equality gate is a no-op, closing the hole where a sub-minimum-difficulty header could seed/extend the chain during a stall. pow_limit == 0 keeps the gate unconfigured (legacy default-ctor chains unconstrained). +1 vector folded into header_chain_test (no new gtest target; #143 NOT_BUILT trap avoided). 19/19 PASS, build EXIT=0. * dgb: M3 §7b ingest-gate scrypt(header) PoW-satisfaction check CheckProofOfWork second half: the VALIDATE_SCRYPT path now rejects a header whose scrypt(header) digest exceeds its declared target (hash > target). Half 1 (target <= pow_limit) already landed; this closes the missing PoW-satisfaction guard that was a placeholder. HeaderSample gains a uint64 pow_hash proxy (mirrors ltc coin/header_chain hash field). Context-free check, run after the pow_limit ceiling and before the contextual nBits-equality gate, mirroring DigiByte Core if (UintToArith256(hash) > bnTarget) return false. pow_hash == 0 is the standalone default (trivially satisfies any target) so every existing vector is unchanged; the embedded-daemon port fills the real digest into the same field shape. +1 vector folded INTO header_chain_test (no new gtest target, #143 trap avoided): rejects pow_hash > target, accepts == and < boundary, and confirms a continuity header short-circuits before the PoW check. header_chain_test 20/20 PASS, build EXIT=0. * dgb: M3 §7b HeaderSample/retarget field-shape swap to arith_uint256 (u256) Swap HeaderSample::target/pow_hash, RetargetWindow::avg_target, DigiShieldParams::pow_limit and the digishield_next_target() return from uint64 proxies to the full-width u256 (coin/dgb_arith256.hpp). An implicit uint64 widening ctor keeps every uint64-range vector byte-identical, so the ingest PoW-satisfaction + minimum-difficulty ceiling checks and the DigiShield averaging now run at true arith_uint256 width through validate_and_append. Adds u256 operator+= for the window target-sum average. +1 ingest-path boundary vector folded into header_chain_test (no new gtest target): a >2^64 target/digest decides acceptance the same way arith_uint256 would and diverges from a low64-only proxy in both directions. 21/21 PASS. Confined to src/impl/dgb/; no shared base / bitcoin_family / CMake / build.yml touch. --------- Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
Add the daemon-independent, Scrypt-only-walk-safe half of header time validation: a Scrypt header's nTime must be STRICTLY GREATER than the median timestamp of the tip and its (up to) 10 nearest ancestors (DigiByte Core ContextualCheckBlockHeader "time-too-old"). This is the monotonicity floor the demoted nBits re-derivation gate used to imply, recovered without any difficulty recompute -- it reads only timestamps already in the local header chain, so it is safe on a Scrypt-only walk and needs no V4-MultiShield multi-algo window. median_time_past() walks ALL appended headers regardless of algo, mirroring DGB Core's GetMedianTimePast over the block index: continuity (non-Scrypt) headers DO contribute their timestamps to the median even though their PoW is never validated and they are never rejected on the gate (accept-by-continuity is preserved). Genesis (empty chain) returns INT64_MIN -> unconstrained. A rejection never mutates the chain (checked before push_back). +4 tests INTO header_chain_test (no new gtest target -> no build.yml allowlist change, #143 trap avoided): genesis-unconstrained, strict-greater rejection at/below median, continuity timestamps feed the median, continuity header itself bypasses the gate. header_chain_test 25/25 PASS, build EXIT=0.
This was referenced Jun 18, 2026
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
…-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.
frstrtr
added a commit
that referenced
this pull request
Jun 18, 2026
…its SSOT framing Round-trip equivalence KAT (op_return ref_hash is share-derived, cannot pin a fixed oracle vector): generate_share_transaction(share) txid == verbatim re-derivation through the SAME assemble_gentx_coinbase SSOT. Proves the #172 collapse behaviorally, not structurally. 3/3 PASS, txid 9e2b78d5. Wired into ctest + BOTH build.yml allowlists in this commit (#143 NOT_BUILT trap).
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 23, 2026
…lar KAT Lift the open-coded think() Phase-5 best-share resolution from share_tracker.hpp into a header-only SSOT (think_p5_best_share_punish.hpp): walk back off a naughty decorated head, dive to the deepest non-naughty descendant (skipping naughty children, 20-gen bound), and report the punishment of the share finally landed on, per p2pool data.py:2142-2166. FENCED/additive: dgb tree only, share_tracker.hpp NOT yet rewired (the byte-identity delegation is the follow-on). Pure graph traversal, consensus value semantics unchanged. KAT 6/6 with hand-derived non-circular fake-chain anchors; registered in CMake and both build.yml --target allowlist sites (#143 NOT_BUILT guard).
frstrtr
added a commit
that referenced
this pull request
Jun 23, 2026
…rcular KAT Lift the inline want/can/get walk-bound arithmetic from share_tracker.hpp think() Phase 2 into a header-only SSOT (think_p2_walk_bounds.hpp), sibling to the Phase-1 think_p1_walk_bounds.hpp landed in #353. Pins the three integer decisions per verified head against the p2pool data.py:2098-2103 oracle: want = max(CHAIN_LENGTH - head_height, 0) can = last_height if unrooted = max(last_height - 1 - CHAIN_LENGTH, 0) otherwise get = min(want, can) FENCED, additive: dgb/ tree-local only, header-only, share_tracker.hpp is NOT yet rewired (byte-identity delegation is the follow-on). Consensus- neutral pure arithmetic. KAT (4/4) hand-derives expectations from the oracle formula, not the subject. Registered in both the dir CMakeLists.txt and both build.yml --target allowlists (avoids #143 NOT_BUILT sentinel).
frstrtr
added a commit
that referenced
this pull request
Jun 23, 2026
The missing composition between leg-2's faithful won-block reconstruction and a node-B ProcessNewBlock ACCEPT. finalize_won_block_pow takes a reconstructed block (header[0..79] with merkle_root already set -- merkle FIRST, integrator-pinned ordering) and grinds the nonce at [76..79] THROUGH grind_won_nonce -> scrypt_pow_hash (the #286 digest CALL SSOT) until the DGB-Scrypt PoW satisfies the parent target, splices the winning nonce back, and regenerates the RPC-fallback hex in lockstep with the P2P-arm bytes. This closes the "high-hash, proof of work failed" rejection: the forced-won seam reached node B but carried no real PoW. SSOT call-through, never a bypass hash -- a finalized block is by construction one node B's own Scrypt validation accepts. Fail-closed (nullopt) on sub-80-byte input or no-nonce-in-budget, mirroring make_reconstruct_closure's never-a-partial-block posture. Standalone-guard discipline: depends ONLY on nonce_grinder.hpp (real btclibs scrypt + header-only u256); no core, no dgb OBJECT lib, no util/HexStr (local lowercase encoder, byte-identical to HexStr). Test links the SAME _dgb_scrypt_tus set as dgb_nonce_grinder_test. +5 KATs (dgb_won_block_finalize_test, 5/5 green): finalized header pow<=target via the same SSOT; winning nonce spliced LE into [76..79]; hex == bytes; ONLY the 4 nonce bytes mutate (merkle + tx tail untouched); fail-closed on a 79-byte input. Registered in BOTH build.yml --target allowlists (#143 trap). Fenced: src/impl/dgb/** + build.yml allowlist only. p2pool-merged-v36 surface: NONE. DGB-Scrypt standalone parent in the V36 default build.
frstrtr
added a commit
that referenced
this pull request
Jun 23, 2026
Add coin/submit_classify.hpp: the single place mining_submit places a submission Scrypt pow_hash into one of three outcome classes. Tighten-first ladder (block target checked before share target, so a won block -- a superset of an accepted share -- wins the classification): pow_hash <= block_target -> WonBlock (submit_block_fn_ broadcast) pow_hash <= share_target -> ShareAccept (try_mint_share sharechain mint) otherwise -> Reject Inclusive at BOTH boundaries via the same pow<=target == !(pow>target) gate the header_chain satisfaction check and the nonce grinder run, matching DigiByte Core CheckProofOfWork and p2pool-merged-v36 share-accept -- keeps c2pool-dgb bit-compatible with the daemon and the Python reference. Header-only, depends only on dgb_arith256.hpp (u256): no scrypt, no core, no dgb OBJECT lib -- a pure decision over three integers. 7/7 KAT pins the ladder, both inclusive boundaries, the zero-hash superset case, and a safety invariant that an inverted (malformed) target pair can only mis-Reject, never spurious WonBlock. Registered in both build.yml --target allowlists (#143 trap). mining_submit still returns the stage-4d low-difficulty stub -- no behavior change. The header-reconstruct -> scrypt_pow_hash -> classify -> dispatch wiring that makes this the live-invocation point is the following slice. Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr
added a commit
that referenced
this pull request
Jun 23, 2026
…e won-block reconstructor other_txs
The won-block reconstructor (make_reconstruct_closure_from_template) frames the
broadcast block as [gentx] ++ other_txs, where other_txs is the captured GBT
template's non-coinbase set. make_mempool_tx_source already shapes that template
(transactions[] of {data,txid,hash,fee}); the reconstructor consumes deserialized
MutableTransaction. This adds the missing deserialize wire between them:
* deserialize_template_other_txs(json) -- pure transactions[] -> txs[] SSOT;
throws on malformed data (bad hex/trailing bytes) so the closure fails the
won block CLOSED rather than broadcasting a half-decoded tx set.
* make_template_other_txs_fn(captured_template_txs_fn) -- adapts a per-share
captured-transactions[] provider into the template_other_txs_fn the run-loop
installs (per-job capture provider is the run-loop integration, #271).
dgb_template_other_txs_test (5/5): round-trips the PRODUCTION make_mempool_tx_source
output byte-faithfully, proves the funded template txs land in the reconstructed
block ([gentx]++other_txs byte-identical to reconstruct_won_block_from_template),
and proves a bad provider fails closed. Fenced to src/impl/dgb/; no p2pool-merged-v36
surface (decodes the conformant GBT shape back into the in-memory tx). Both
build.yml allowlists updated (#143 NOT_BUILT trap).
This was referenced Jun 23, 2026
dgb(M3): real bind_aux_doge_parsers() body — ODR-use DGB-parent AuxPoW contracts in prod objlib
#400
Merged
This was referenced Jul 17, 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.
Problem
master CI is red on the Linux x86_64 and Linux x86_64 (AsAN+UBSan) jobs. The Run tests step exits 8 with:
Confirmed on the #138 merge run (27717734612) too, so it is pre-existing on master, not introduced by any open DGB PR.
Root cause
test_dgb_subsidy is registered in test/CMakeLists.txt via gtest_discover_tests with DISCOVERY_MODE PRE_TEST, but it was never added to the explicit cmake --build --target allowlist in the build.yml "Build tests" (Linux) and "Build c2pool + tests" (AsAN) steps. The executable is therefore absent at ctest time, CTest registers the *_NOT_BUILT sentinel, and the step fails. This regression landed when #137 added the test without wiring it into the CI allowlist.
Fix
Add test_dgb_subsidy to both target lists (2-line diff). The target builds clean and both subsidy oracle tests pass locally:
DGB-domain (completes the #137 landing). GPG-signed. HOLD merge -- integrator merges on operator tap.