Skip to content

dgb(#82): faithful as_block FRAMING half — share->block reassembly + 5 KATs - #168

Merged
frstrtr merged 2 commits into
masterfrom
dgb/won-block-as-block-framing
Jun 18, 2026
Merged

dgb(#82): faithful as_block FRAMING half — share->block reassembly + 5 KATs#168
frstrtr merged 2 commits into
masterfrom
dgb/won-block-as-block-framing

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Closes the FRAMING half of the #82 won-block reconstructor (the HARD as_block piece flagged in the dispatch-wiring PRs #166/#167).

What

src/impl/dgb/coin/block_assembly.hpp — faithful C++ port of the FRAMING half of p2pool data.py Share.as_block:

  • reconstruct_block_header(): rebuilds the full block header merkle_root from the gentx hash walked up the share merkle_link (a share stores only a SmallBlockHeader — no merkle_root), reusing dgb::check_merkle_link (share_check.hpp) as the merkle SSOT.
  • assemble_won_block(): frames txs as [gentx] ++ other_txs (coinbase at index 0) and serializes through the live BlockType codec that NodeRPC::submit_block already uses → reconstructed block round-trips and a daemon accepts it byte-for-byte. Returns {bytes, hex} for the embedded-P2P relay + external-submitblock fallback respectively.

Scope / seam

gentx bytes + known_txs lookup stay INJECTED — the gentx-byte build (coinbase assembly, which will hit the same coinbase-byte adjudication as the BCH lane) and the known_txs resolve are the explicitly-next reconstructor slice. Keeping them as inputs makes this framing build-verifiable + KAT-testable now (same seam-first decomposition as won_block_dispatch.hpp).

Test — dgb_block_assembly_test (5/5 PASS, build EXIT=0)

empty-branch root==gentx_hash · index-bit branch-side select (both orderings differ) · coinbase-first round-trip through BlockType (hex==HexStr(bytes), txs=[gentx]++other) · coinbase-only block. KATs self-derived via the same Hash() the merkle walk uses (no fixture dependency). Registered in BOTH test/CMakeLists.txt AND build.yml --target allowlist (#143 NOT_BUILT trap avoided).

Invariants

Per-coin isolation: src/impl/dgb/ only. p2pool-merged-v36 surface: none (reuses BlockType + check_merkle_link verbatim; no share format / PoW hash / coinbase commitment / PPLNS touched). DGB-Scrypt standalone parent, V36 default build. GPG-signed, no third-party attribution.

HOLD merge — integrator merges on operator push approval.

frstrtr added 2 commits June 18, 2026 18:14
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.
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
frstrtr merged commit 57109ce into master Jun 18, 2026
17 checks passed
frstrtr added a commit that referenced this pull request Jun 19, 2026
…me as_block

Tie the three landed sub-slices into the single composition the dispatch
handler injects as its WonBlockReconstructor:
  resolve_other_tx_hashes (#174) -> assemble_other_txs (#176)
  -> assemble_won_block (#168 framing)

Faithful port of p2pool data.py Share.as_block: produces {bytes, hex} for
broadcast_won_block dual path. Gentx enters as a deserialized
MutableTransaction + txid (the SSOT gentx-bytes -> MutableTransaction unpack,
inverse of #173 exposure, is the next slice). Injected tracker/known_txs
seams keep it unit-testable; out_of_range propagation from each step
preserved (never emit a partial/wrong block).

dgb_reconstruct_won_block_test 5/5 PASS: end-to-end == manual
resolve+assemble+frame (byte-identical), [gentx]++others in ref order,
empty-refs gentx-only, ref-past-chain + unknown-known-tx throw. Wired into
test/CMakeLists.txt + both build.yml --target allowlists (#143 trap).

Per-coin isolation: src/impl/dgb/ only. p2pool-merged-v36 surface: none.
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