Skip to content

Commit ee1a4b4

Browse files
authored
Merge pull request #177 from frstrtr/dgb/won-block-reconstruct-body
dgb(#82): won-block reconstructor body — compose resolve+assemble+frame (as_block)
2 parents 24971a5 + 3b6f5d8 commit ee1a4b4

4 files changed

Lines changed: 401 additions & 2 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
test_address_resolution test_compute_share_target \
7070
test_utxo test_dgb_subsidy dgb_share_test dgb_block_assembly_test \
7171
dgb_gentx_coinbase_test nmc_auxpow_merkle_test dgb_gentx_share_path_test dgb_other_tx_resolver_test \
72-
dgb_other_tx_assembler_test \
72+
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test \
7373
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
7474
v37_test \
7575
-j$(nproc)
@@ -201,7 +201,7 @@ jobs:
201201
test_address_resolution test_compute_share_target \
202202
test_utxo test_dgb_subsidy dgb_share_test dgb_block_assembly_test \
203203
dgb_gentx_coinbase_test nmc_auxpow_merkle_test dgb_gentx_share_path_test dgb_other_tx_resolver_test \
204-
dgb_other_tx_assembler_test \
204+
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test \
205205
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
206206
test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \
207207
v37_test \
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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

src/impl/dgb/test/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ if (BUILD_TESTING AND GTest_FOUND)
3232
dgb_coin pool sharechain)
3333
gtest_add_tests(dgb_block_assembly_test "" AUTO)
3434

35+
# --- #82: won-block reconstructor BODY (as_block composition) ----------
36+
# Pins coin/reconstruct_won_block.hpp: the single composition the dispatch
37+
# handler injects as its WonBlockReconstructor (resolve_other_tx_hashes ->
38+
# assemble_other_txs -> assemble_won_block). Links the dgb OBJECT lib like
39+
# dgb_block_assembly_test because it pulls block_assembly.hpp (BlockType /
40+
# MutableTransaction / check_merkle_link). MUST appear in BOTH this
41+
# registration AND the build.yml --target allowlist (#143 NOT_BUILT trap).
42+
add_executable(dgb_reconstruct_won_block_test reconstruct_won_block_test.cpp)
43+
target_link_libraries(dgb_reconstruct_won_block_test PRIVATE
44+
GTest::gtest_main GTest::gtest
45+
core dgb
46+
c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage
47+
dgb_coin pool sharechain)
48+
gtest_add_tests(dgb_reconstruct_won_block_test "" AUTO)
49+
3550
# --- M3 RPC-transport standalone regression guards ---------------------
3651
# Header-only guards over the external-daemon RPC coin-layer SSOTs
3752
# (rpc_request.hpp request-shape + version floor + genesis identity, and

0 commit comments

Comments
 (0)