|
| 1 | +#pragma once |
| 2 | +// --------------------------------------------------------------------------- |
| 3 | +// dgb::coin::reconstruct_won_block -- the won-block reconstructor's (#82) BODY: |
| 4 | +// the single composition that the dispatch handler (won_block_dispatch.hpp, |
| 5 | +// make_on_block_found) injects as its WonBlockReconstructor. It ties the three |
| 6 | +// previously-landed sub-slices into one faithful port of p2pool data.py |
| 7 | +// Share.as_block(tracker, known_txs): |
| 8 | +// |
| 9 | +// gentx = self.check(tracker, known_txs) # coinbase tx |
| 10 | +// other_txs = [known_txs[h] |
| 11 | +// for h in self.get_other_tx_hashes(tracker)] # ref-walk |
| 12 | +// return dict(header=self.header, txs=[gentx]+other_txs) |
| 13 | +// |
| 14 | +// Composition (each step is its own unit-tested SSOT slice): |
| 15 | +// 1. resolve_other_tx_hashes (other_tx_resolver.hpp, sub-slice 1 / #174) |
| 16 | +// share.transaction_hash_refs --ancestry walk--> ordered other_tx hashes |
| 17 | +// 2. assemble_other_txs (other_tx_assembler.hpp, sub-slice 2 / #176) |
| 18 | +// ordered hashes --known_txs lookup--> deserialized MutableTransactions |
| 19 | +// 3. assemble_won_block (block_assembly.hpp, as_block FRAMING / #168) |
| 20 | +// small_header + gentx + merkle_link + other_txs --> {bytes, hex} |
| 21 | +// (merkle_root recomputed from gentx_hash up the share merkle_link; |
| 22 | +// txs = [gentx] ++ other_txs; BlockType codec = live submitblock path) |
| 23 | +// |
| 24 | +// The gentx enters as an already-deserialized MutableTransaction + its txid |
| 25 | +// (gentx_hash), exactly as block_assembly_test models it. In the run-loop this |
| 26 | +// binds to the SSOT gentx that generate_share_transaction exposes via its |
| 27 | +// out_gentx parameter (#173): GentxCoinbase{bytes, txid}. Turning those SSOT |
| 28 | +// non-witness bytes back into a MutableTransaction is the inverse of #173's |
| 29 | +// exposure -- a distinct param-stream codec concern with its own round-trip KAT |
| 30 | +// (the explicitly-next slice) -- so it is kept OUT of this pure-composition body |
| 31 | +// to keep the as_block ordering + merkle math build-verifiable and KAT-able NOW. |
| 32 | +// |
| 33 | +// All three tracker/mempool operations are INJECTED as callables (the same |
| 34 | +// seam-first decomposition the sub-slices already use), so the whole |
| 35 | +// reconstruction is unit-testable against a synthetic ancestry + known-tx set |
| 36 | +// without standing up a live ShareTracker / mempool. In the run-loop they bind |
| 37 | +// to (cf. won_block_dispatch.hpp / the sub-slice run-loop notes): |
| 38 | +// nth_parent_fn = chain.get_nth_parent_via_skip(h, n) |
| 39 | +// new_tx_hashes_fn = chain.get_share(h)->m_tx_info.m_new_transaction_hashes |
| 40 | +// known_txs_fn = node known-tx store (mempool + peer-relayed tx cache) |
| 41 | +// |
| 42 | +// Failure posture inherited from the sub-slices: a ref that walks past the |
| 43 | +// known sharechain, a tx_count out of range, or an unknown other_tx hash each |
| 44 | +// throw std::out_of_range -- a partial/wrong reconstruction would hash to the |
| 45 | +// wrong merkle root and be rejected by the daemon, so failing loudly here is |
| 46 | +// strictly safer than broadcasting a malformed block. |
| 47 | +// |
| 48 | +// Per-coin isolation: src/impl/dgb/ only. p2pool-merged-v36 surface: NONE -- |
| 49 | +// pure composition of already-validated share_info + already-relayed txs + the |
| 50 | +// proven BlockType serializer; no share format, PoW, coinbase commitment, or |
| 51 | +// PPLNS math is touched. DGB-Scrypt is a STANDALONE parent in the V36 default |
| 52 | +// build (no merged-coinbase leg). |
| 53 | +// --------------------------------------------------------------------------- |
| 54 | + |
| 55 | +#include <functional> |
| 56 | +#include <string> |
| 57 | +#include <utility> |
| 58 | +#include <vector> |
| 59 | + |
| 60 | +#include <core/uint256.hpp> |
| 61 | + |
| 62 | +#include "block_assembly.hpp" // assemble_won_block, SmallBlockHeaderType, BlockType |
| 63 | +#include "other_tx_resolver.hpp" // resolve_other_tx_hashes |
| 64 | +#include "other_tx_assembler.hpp" // assemble_other_txs |
| 65 | +#include "transaction.hpp" // MutableTransaction |
| 66 | +#include "../share_types.hpp" // TxHashRefs, MerkleLink, uint256 |
| 67 | + |
| 68 | +namespace dgb |
| 69 | +{ |
| 70 | +namespace coin |
| 71 | +{ |
| 72 | + |
| 73 | +// The reconstructed parent block, ready for broadcast_won_block's dual path: |
| 74 | +// bytes : the blob the embedded P2P relay sends |
| 75 | +// hex : the same block for the external submitblock (RPC) fallback |
| 76 | +struct ReconstructedWonBlock |
| 77 | +{ |
| 78 | + std::vector<unsigned char> bytes; |
| 79 | + std::string hex; |
| 80 | +}; |
| 81 | + |
| 82 | +// Reconstruct the full serialized parent block for a won share. |
| 83 | +// |
| 84 | +// small_header : share.m_min_header (version|prev|time|bits|nonce) |
| 85 | +// merkle_link : share.m_merkle_link (gentx -> merkle root branch) |
| 86 | +// gentx : the share's coinbase tx, already deserialized (block tx 0) |
| 87 | +// gentx_hash : its txid (double-SHA256) == p2pool gentx_hash, for the |
| 88 | +// merkle_root walk |
| 89 | +// won_share_hash : hash of the share that found the block (ref-walk origin) |
| 90 | +// refs : share.m_tx_info.m_transaction_hash_refs, in order |
| 91 | +// nth_parent_fn : (start, n) -> hash of the n-th parent (n==0 -> start); |
| 92 | +// IsNull() if the walk runs off the known sharechain |
| 93 | +// new_tx_hashes_fn : share_hash -> that share's new_transaction_hashes |
| 94 | +// known_txs_fn : hash -> pointer to the known MutableTransaction, or |
| 95 | +// nullptr if absent |
| 96 | +// |
| 97 | +// Returns {bytes, hex} with hex == HexStr(bytes). Throws std::out_of_range on |
| 98 | +// any malformed-share / incomplete-known-txs condition (see the per-step slices). |
| 99 | +inline ReconstructedWonBlock |
| 100 | +reconstruct_won_block( |
| 101 | + const SmallBlockHeaderType& small_header, |
| 102 | + const ::dgb::MerkleLink& merkle_link, |
| 103 | + const MutableTransaction& gentx, |
| 104 | + const uint256& gentx_hash, |
| 105 | + const uint256& won_share_hash, |
| 106 | + const std::vector<TxHashRefs>& refs, |
| 107 | + const std::function<uint256(const uint256&, uint64_t)>& nth_parent_fn, |
| 108 | + const std::function<const std::vector<uint256>&(const uint256&)>& new_tx_hashes_fn, |
| 109 | + const std::function<const MutableTransaction*(const uint256&)>& known_txs_fn) |
| 110 | +{ |
| 111 | + // 1. share.transaction_hash_refs -> ordered other_tx hashes (ancestry walk). |
| 112 | + const std::vector<uint256> other_tx_hashes = |
| 113 | + resolve_other_tx_hashes(won_share_hash, refs, nth_parent_fn, new_tx_hashes_fn); |
| 114 | + |
| 115 | + // 2. ordered hashes -> deserialized MutableTransactions (known_txs lookup). |
| 116 | + const std::vector<MutableTransaction> other_txs = |
| 117 | + assemble_other_txs(other_tx_hashes, known_txs_fn); |
| 118 | + |
| 119 | + // 3. small_header + gentx + merkle_link + other_txs -> {bytes, hex}. |
| 120 | + // (merkle_root recomputed from gentx_hash up merkle_link; [gentx]++others.) |
| 121 | + auto framed = assemble_won_block(small_header, gentx, gentx_hash, merkle_link, other_txs); |
| 122 | + |
| 123 | + return ReconstructedWonBlock{std::move(framed.first), std::move(framed.second)}; |
| 124 | +} |
| 125 | + |
| 126 | +} // namespace coin |
| 127 | +} // namespace dgb |
0 commit comments