diff --git a/src/impl/dgb/coin/won_share_inputs.hpp b/src/impl/dgb/coin/won_share_inputs.hpp new file mode 100644 index 000000000..0a9761c57 --- /dev/null +++ b/src/impl/dgb/coin/won_share_inputs.hpp @@ -0,0 +1,62 @@ +#pragma once +// --------------------------------------------------------------------------- +// dgb::coin::won_share_inputs -- the SHARE-SIDE half of the #82 faithful +// won-block reconstruct closure (the closure the run-loop installs as +// ShareTracker::m_on_block_found, today an interim nullopt stub in +// main_dgb.cpp). reconstruct_won_block_from_template (reconstruct_won_block.hpp) +// needs five inputs to frame a broadcastable block: +// +// { small_header, merkle_link, gentx, gentx_hash, template_other_txs } +// +// Two of them the won share ALREADY CARRIES verbatim, version-agnostically: +// +// small_header = share.m_min_header (coin::SmallBlockHeaderType) +// merkle_link = share.m_merkle_link (::dgb::MerkleLink) +// +// This seam pulls exactly those two. It touches no PoW, coinbase commitment, +// share format, or PPLNS math, so the p2pool-merged-v36 surface is NONE -- it +// is a pure read of already-validated share_info fields. +// +// The remaining three inputs land as their own slices and bind in the run-loop +// once they arrive: +// * gentx + gentx_hash -- the inverse of the generate_share_transaction +// out_gentx SSOT exposure (#173): GentxCoinbase{bytes,txid} -> a +// MutableTransaction (the next reconstruct brick); +// * template_other_txs -- the captured-GBT template-retention seam (#271: +// the won block's non-coinbase set is the current_work snapshot the miner +// was handed, NOT the share's tx_hash_refs), empty today, fills as the +// embedded mempool tx-selection lands. +// +// Duck-typed on the share so this header stays OFF share.hpp's +// tracker/base_uint translation unit (the #143 limited-TU build trap) -- any +// type exposing m_min_header (SmallBlockHeaderType) and m_merkle_link +// (::dgb::MerkleLink) binds; in the run-loop, the live dgb::Share. +// +// Per-coin isolation: src/impl/dgb/ only. +// --------------------------------------------------------------------------- + +#include "block_assembly.hpp" // coin::SmallBlockHeaderType (re-exported) +#include "../share_types.hpp" // ::dgb::MerkleLink + +namespace dgb +{ +namespace coin +{ + +// The two reconstruct inputs a won share carries verbatim. +struct WonShareInputs +{ + SmallBlockHeaderType small_header; // <- share.m_min_header + ::dgb::MerkleLink merkle_link; // <- share.m_merkle_link +}; + +// Extract them. Templated on the share to keep this off share.hpp's heavy TU; +// binds to dgb::Share in the run-loop. +template +inline WonShareInputs won_share_inputs(const ShareT& share) +{ + return WonShareInputs{ share.m_min_header, share.m_merkle_link }; +} + +} // namespace coin +} // namespace dgb diff --git a/src/impl/dgb/test/reconstruct_won_block_test.cpp b/src/impl/dgb/test/reconstruct_won_block_test.cpp index bc737373e..c908e8323 100644 --- a/src/impl/dgb/test/reconstruct_won_block_test.cpp +++ b/src/impl/dgb/test/reconstruct_won_block_test.cpp @@ -30,6 +30,7 @@ #include #include "../coin/reconstruct_won_block.hpp" +#include "../coin/won_share_inputs.hpp" using dgb::coin::reconstruct_won_block; using dgb::coin::reconstruct_won_block_from_template; @@ -41,6 +42,8 @@ using dgb::coin::BlockType; using dgb::coin::SmallBlockHeaderType; using dgb::coin::MutableTransaction; using dgb::TxHashRefs; +using dgb::coin::won_share_inputs; +using dgb::coin::WonShareInputs; namespace { @@ -314,4 +317,77 @@ TEST(DgbReconstructWonBlock, EmptyTemplateGentxOnly) EXPECT_EQ(got.hex, HexStr(sp)); } + +// --- Test 7: won_share_inputs extracts the two share-carried inputs verbatim -- +// The share-side half of the faithful reconstruct closure: a won share carries +// small_header (m_min_header) + merkle_link (m_merkle_link) verbatim. The seam +// is a pure read -- no field is transformed, reordered, or dropped. +TEST(DgbReconstructWonBlock, WonShareInputsExtractsHeaderAndMerkleLink) +{ + // Minimal duck-typed stand-in for dgb::Share (keeps this TU off share.hpp's + // tracker/base_uint TU, per won_share_inputs.hpp's #143 note). Exposes the + // two members won_share_inputs reads by name. + struct FakeShare { + SmallBlockHeaderType m_min_header; + ::dgb::MerkleLink m_merkle_link; + }; + + FakeShare s; + s.m_min_header = make_small_header(); + s.m_merkle_link.m_branch = { H("b0"), H("b1") }; + s.m_merkle_link.m_index = 0; + + WonShareInputs got = won_share_inputs(s); + + EXPECT_EQ(got.small_header.m_version, s.m_min_header.m_version); + EXPECT_EQ(got.small_header.m_previous_block, s.m_min_header.m_previous_block); + EXPECT_EQ(got.small_header.m_timestamp, s.m_min_header.m_timestamp); + EXPECT_EQ(got.small_header.m_bits, s.m_min_header.m_bits); + EXPECT_EQ(got.small_header.m_nonce, s.m_min_header.m_nonce); + ASSERT_EQ(got.merkle_link.m_branch.size(), 2u); + EXPECT_EQ(got.merkle_link.m_branch[0], H("b0")); + EXPECT_EQ(got.merkle_link.m_branch[1], H("b1")); + EXPECT_EQ(got.merkle_link.m_index, 0u); +} + +// --- Test 8: won_share_inputs feeds reconstruct_won_block_from_template ------- +// End-to-end seam check: the extracted {small_header, merkle_link} drive a block +// byte-identical to passing those same fields directly. Proves the share-side +// seam is a faithful pass-through into the won-block framing path -- the run-loop +// closure may source small_header/merkle_link via won_share_inputs(share) with +// no change to the reconstructed block. +TEST(DgbReconstructWonBlock, WonShareInputsDrivesTemplateReconstructIdentically) +{ + struct FakeShare { + SmallBlockHeaderType m_min_header; + ::dgb::MerkleLink m_merkle_link; + }; + + FakeShare s; + s.m_min_header = make_small_header(); + // Non-empty link so the merkle-root math actually consumes it. + s.m_merkle_link.m_branch = { H("b0") }; + s.m_merkle_link.m_index = 0; + + auto gentx = make_gentx(); + auto gh = fixed_gentx_hash(); + std::vector template_txs = { make_tx(11), make_tx(22) }; + + WonShareInputs in = won_share_inputs(s); + + auto via_seam = reconstruct_won_block_from_template( + in.small_header, in.merkle_link, gentx, gh, template_txs); + auto direct = reconstruct_won_block_from_template( + s.m_min_header, s.m_merkle_link, gentx, gh, template_txs); + + EXPECT_EQ(via_seam.bytes, direct.bytes); + EXPECT_EQ(via_seam.hex, direct.hex); + + PackStream ps(via_seam.bytes); + BlockType blk; + ps >> blk; + ASSERT_EQ(blk.m_txs.size(), 3u); // gentx + 2 template txs + EXPECT_EQ(blk.m_txs[0].vin[0].prevout.index, 0xffffffffu); +} } // namespace +