Skip to content

Commit f06ce5b

Browse files
committed
dgb: collapse phase-DB MM-commitment builder into SSOT KAT-pin (#475 rework)
Per integrator adjudication (core builder = MM SSOT): the AuxPoW merged-mining commitment build is a v36-NATIVE SHARED structure, not a per-coin path. The single producer lives in shared A-level scaffolding (c2pool/merged/ merged_mining.cpp + core/coinbase_builder.hpp) and is chain_id-parameterized; DGB/DOGE plug in as chains. A fenced DGB builder that mirrors it is exactly the cross-coin divergence the v36->v37 standardization goal forbids. Drop the duplicate 44-byte build body from src/impl/dgb/coin/ aux_doge_mm_commitment.hpp. dgb::coin::build_aux_mm_commitment is now a thin delegation that forwards verbatim to c2pool::merged::build_auxpow_commitment, keeping a DGB-namespaced entry point with zero DGB-local layout logic. The AUX_MM_MAGIC / AUX_MM_COMMITMENT_SIZE constants remain as reader/KAT pins. aux_doge_mm_commitment_test.cpp keeps its non-circular hand-built fabe6d6d goldens (3 KAT + SizeAndMagic, fully literal hex) AND now asserts each is byte-identical to the core SSOT output (delegation drift-guard), mirroring the NMC auxpow_merkle_test SSOT guard. This pins DGBs chain slot + goldens to the one canonical builder instead of a fenced copy. FENCED / NOT REWIRED: no live caller; mint/work-source path untouched. DB embed-at-mint and DC dual-target wire THROUGH the core builder and are gated on ltc-doge concurrence + operator tap. Both build arms green: 4/4 default and 4/4 -DAUX_DOGE=ON. No CMake/build.yml change (test already links c2pool_merged_mining).
1 parent 9b15588 commit f06ce5b

4 files changed

Lines changed: 253 additions & 2 deletions

File tree

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ jobs:
8282
test_address_resolution test_compute_share_target \
8383
test_utxo test_dgb_subsidy test_dgb_coinbase_value dgb_share_test dgb_redistribute_test dgb_block_assembly_test dgb_witness_commitment_test dgb_header_sample_build_test dgb_header_ingest_test dgb_mempool_ingest_test \
8484
dgb_gentx_coinbase_test dgb_connection_coinbase_test dgb_pplns_payout_split_test nmc_auxpow_merkle_test nmc_template_builder_test nmc_auxpow_wire_test nmc_reconstruct_won_block_test nmc_mempool_name_test nmc_block_broadcast_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \
85-
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test dgb_compact_blocks_bip152_parity_test \
85+
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_mm_commitment_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test dgb_compact_blocks_bip152_parity_test \
8686
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
8787
dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_redistribute_delegate_ghal_test dgb_share_weight_decay_test dgb_naughty_propagation_test dgb_hash_format_parity_test v37_test \
8888
-j$(nproc)
@@ -214,7 +214,7 @@ jobs:
214214
test_address_resolution test_compute_share_target \
215215
test_utxo test_dgb_subsidy test_dgb_coinbase_value dgb_share_test dgb_redistribute_test dgb_block_assembly_test dgb_witness_commitment_test dgb_header_sample_build_test dgb_header_ingest_test dgb_mempool_ingest_test \
216216
dgb_gentx_coinbase_test dgb_connection_coinbase_test dgb_pplns_payout_split_test nmc_auxpow_merkle_test nmc_template_builder_test nmc_auxpow_wire_test nmc_reconstruct_won_block_test nmc_mempool_name_test nmc_block_broadcast_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \
217-
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test dgb_compact_blocks_bip152_parity_test \
217+
dgb_other_tx_assembler_test dgb_reconstruct_won_block_test dgb_reconstruct_closure_test dgb_gentx_unpack_test dgb_work_source_test dgb_template_builder_test dgb_embedded_coin_node_test dgb_embedded_tx_select_test dgb_template_other_txs_test dgb_coinbase_value_parity_test dgb_submit_classify_test dgb_aux_parent_coinbase_parity_test dgb_template_capture_test dgb_aux_doge_db_commitment_bind_test dgb_aux_doge_mm_commitment_test dgb_aux_doge_dc_proof_test dgb_aux_doge_bind_parsers_test dgb_compact_blocks_bip152_parity_test \
218218
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
219219
dgb_coin_node_seam_test dgb_block_broadcast_test dgb_won_block_dispatch_test dgb_forced_won_share_dualpath_test dgb_scrypt_pow_test dgb_nonce_grinder_test dgb_regrind_block_test dgb_won_block_finalize_test dgb_share_target_genesis_test dgb_pool_msg_wire_test dgb_get_shares_walk_test dgb_download_stops_test dgb_think_p1_walk_bounds_test dgb_think_p1_desired_emit_test dgb_think_p6_desired_cutoff_test dgb_think_p4_head_keys_test dgb_think_p3_best_head_test dgb_g1_oracle_byte_parity_test dgb_think_p2_walk_bounds_test dgb_expected_time_to_block_test dgb_tail_score_endpoints_test dgb_pool_attempts_per_second_test dgb_pool_efficiency_test dgb_think_p5_best_share_punish_test dgb_auto_ratchet_tail_guard_test dgb_binomial_conf_interval_test dgb_desired_version_tally_test dgb_get_height_and_last_endpoints_test dgb_chain_walk_window_test dgb_redistribute_delegate_ghal_test dgb_share_weight_decay_test dgb_naughty_propagation_test dgb_hash_format_parity_test test_coin_broadcaster test_multiaddress_pplns test_pplns_stress \
220220
v37_test \
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
// ---------------------------------------------------------------------------
3+
// DGB+DOGE merged-mining (phase DB) -- DGB-side AuxPoW coinbase-commitment
4+
// entry point. THIN DELEGATION to the canonical cross-coin SSOT producer
5+
// c2pool::merged::build_auxpow_commitment. This header carries NO duplicate
6+
// build logic of its own.
7+
//
8+
// RATIONALE (integrator adjudication 2026-06-25, thread "core builder = MM
9+
// SSOT"). The AuxPoW merged-mining commitment build is a v36-NATIVE SHARED
10+
// structure, not a per-coin transition-compat one. The single producer lives
11+
// in shared A-level scaffolding (src/c2pool/merged/merged_mining.cpp +
12+
// src/core/coinbase_builder.hpp); it is chain_id-parameterized, and DGB/DOGE
13+
// plug in as CHAINS, not as a per-coin build path. A fenced DGB builder that
14+
// "mirrors" the core one is exactly the cross-coin divergence the v36->v37
15+
// standardization goal forbids. DGBs real per-coin value is therefore its
16+
// chain_id slot + fabe6d6d GOLDENS pinned to the canonical builder (see the
17+
// KAT aux_doge_mm_commitment_test.cpp), NOT a second copy of the machinery.
18+
//
19+
// This header exposes only a DGB-namespaced symbol that forwards verbatim to
20+
// the SSOT, so DGB-as-parent call sites read naturally while the bytes are
21+
// produced in exactly one place.
22+
//
23+
// CANONICAL LAYOUT (owned by the SSOT; reproduced here for readers only):
24+
// [4] fa be 6d 6d MM magic
25+
// [32] aux_merkle_root big-endian (byte 31 first)
26+
// [4] merkle_size little-endian
27+
// [4] merkle_nonce little-endian
28+
// Total: 44 bytes.
29+
//
30+
// FENCED -- NOT REWIRED. No live caller invokes this yet; the mint/work-source
31+
// path is untouched. Live wiring (DB embed-at-mint / DC dual-target) routes
32+
// THROUGH the core builder and is gated on ltc-doge concurrence + operator tap.
33+
// ---------------------------------------------------------------------------
34+
35+
#include <cstdint>
36+
#include <vector>
37+
38+
#include <core/uint256.hpp>
39+
#include <c2pool/merged/merged_mining.hpp> // SSOT: c2pool::merged::build_auxpow_commitment
40+
41+
namespace dgb {
42+
namespace coin {
43+
44+
// MM merged-mining magic marker: 0xfa 0xbe 0x6d 0x6d ("\xfa\xbe" + "mm").
45+
// Pinned by the KAT and available to readers/asserts; the bytes themselves are
46+
// emitted by the SSOT, never reconstructed here.
47+
inline constexpr unsigned char AUX_MM_MAGIC[4] = {0xfa, 0xbe, 0x6d, 0x6d};
48+
49+
// Size in bytes of the canonical AuxPoW merged-mining commitment blob
50+
// (magic(4) + aux_merkle_root(32) + merkle_size(4) + merkle_nonce(4)).
51+
inline constexpr std::size_t AUX_MM_COMMITMENT_SIZE = 44;
52+
53+
// Build the canonical merged-mining coinbase commitment for a DGB-as-parent
54+
// coinbase. THIN DELEGATION -- forwards verbatim to the cross-coin SSOT
55+
// c2pool::merged::build_auxpow_commitment; there is NO DGB-local layout logic.
56+
//
57+
// aux_merkle_root -- auxiliary (DOGE) blockchain merkle root.
58+
// merkle_size -- aux merkle-tree size.
59+
// merkle_nonce -- aux merkle nonce.
60+
//
61+
// Returns exactly AUX_MM_COMMITMENT_SIZE (44) bytes.
62+
inline std::vector<unsigned char> build_aux_mm_commitment(
63+
const uint256& aux_merkle_root,
64+
uint32_t merkle_size,
65+
uint32_t merkle_nonce)
66+
{
67+
return c2pool::merged::build_auxpow_commitment(
68+
aux_merkle_root, merkle_size, merkle_nonce);
69+
}
70+
71+
} // namespace coin
72+
} // namespace dgb

src/impl/dgb/test/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,22 @@ if (BUILD_TESTING AND GTest_FOUND)
566566
dgb_coin pool sharechain)
567567
gtest_add_tests(dgb_aux_doge_db_commitment_bind_test "" AUTO)
568568

569+
# --- DGB+DOGE (phase DB) -- DGB-side AuxPoW merged-mining coinbase ---
570+
# commitment BUILDER KAT. FENCED / test-only: pins the canonical
571+
# fabe6d6d || aux_root(32 BE) || size(4 LE) || nonce(4 LE) byte layout
572+
# emitted by dgb::coin::build_aux_mm_commitment, non-circularly (goldens
573+
# hand-built from raw inputs, not the builder). Pure dgb/+core value
574+
# transform -- no ltc/doge linkage, flag-agnostic (builds in default AND
575+
# -DAUX_DOGE arms). MUST appear in BOTH this registration AND the build.yml
576+
# --target allowlist or it becomes a NOT_BUILT sentinel that reds master
577+
# (cf. DGB #137 / #143).
578+
add_executable(dgb_aux_doge_mm_commitment_test aux_doge_mm_commitment_test.cpp)
579+
target_link_libraries(dgb_aux_doge_mm_commitment_test PRIVATE
580+
GTest::gtest_main GTest::gtest
581+
core
582+
c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage)
583+
gtest_add_tests(dgb_aux_doge_mm_commitment_test "" AUTO)
584+
569585
# --- DGB+DOGE (phase DC) -- DGB-as-parent AuxPoW PROOF byte-parity + dual ---
570586
# Proves the neutral producer build_auxpow_proof (c2pool/merged) is byte-
571587
# identical to the typed doge::coin::CAuxPow<dgb::coin::MutableTransaction>
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// ---------------------------------------------------------------------------
2+
// DGB+DOGE merged-mining (phase DB) — KAT for the DGB-side AuxPoW coinbase
3+
// merged-mining commitment builder. Fenced / test-only.
4+
//
5+
// Pins the EXACT byte layout emitted by dgb::coin::build_aux_mm_commitment for
6+
// fixed (aux_merkle_root, merkle_size, merkle_nonce) inputs:
7+
//
8+
// fa be 6d 6d || aux_root(32, big-endian) || size(4 LE) || nonce(4 LE)
9+
//
10+
// NON-CIRCULAR. The expected commitment bytes are hand-constructed in each
11+
// case from the raw inputs (magic literal + reversed root bytes + manually
12+
// little-endian-split size/nonce), NOT by re-invoking the builder. The test is
13+
// therefore a true layout anchor: a re-shaped builder cannot self-confirm.
14+
//
15+
// SSOT DELEGATION GUARD. Each case ALSO asserts the DGB entry point is
16+
// byte-identical to the canonical cross-coin producer
17+
// c2pool::merged::build_auxpow_commitment. Per the integrator adjudication
18+
// (core builder = MM SSOT), DGB owns no build body of its own; this pins
19+
// DGBs chain slot + goldens to the one canonical builder (delegation), not a
20+
// fenced copy. Mirrors the NMC SSOT drift-guard auxpow_merkle_test.cpp.
21+
//
22+
// Mirrors the established DGB aux-test style (unhex/tohex helpers) of the
23+
// sibling src/impl/dgb/test/aux_doge_db_commitment_bind_test.cpp. MUST appear
24+
// in BOTH test/CMakeLists.txt AND the build.yml --target allowlist or it
25+
// becomes a NOT_BUILT sentinel that reds master (cf. DGB #137 / #143).
26+
// ---------------------------------------------------------------------------
27+
28+
#include <gtest/gtest.h>
29+
30+
#include <impl/dgb/coin/aux_doge_mm_commitment.hpp> // the fenced builder under test
31+
#include <c2pool/merged/merged_mining.hpp> // SSOT drift-guard: build_auxpow_commitment
32+
#include <core/uint256.hpp>
33+
34+
#include <cstdint>
35+
#include <string>
36+
#include <vector>
37+
38+
namespace {
39+
40+
std::vector<unsigned char> unhex(const std::string& h) {
41+
std::vector<unsigned char> v; v.reserve(h.size() / 2);
42+
auto nyb = [](char c) -> int { return (c <= '9') ? c - '0' : (c | 0x20) - 'a' + 10; };
43+
for (size_t i = 0; i + 1 < h.size(); i += 2)
44+
v.push_back(static_cast<unsigned char>((nyb(h[i]) << 4) | nyb(h[i + 1])));
45+
return v;
46+
}
47+
std::string tohex(const std::vector<unsigned char>& v) {
48+
static const char* H = "0123456789abcdef";
49+
std::string s; s.reserve(v.size() * 2);
50+
for (unsigned char b : v) { s.push_back(H[b >> 4]); s.push_back(H[b & 0xf]); }
51+
return s;
52+
}
53+
54+
// Build a uint256 whose internal little-endian byte image == root_le[0..31].
55+
// (base_uint(vector) reads the vector little-endian, so on a little-endian host
56+
// reinterpret_cast<uint8_t*>(pn)[i] == root_le[i].) Requires exactly 32 bytes.
57+
uint256 root_from_le_bytes(const std::vector<unsigned char>& root_le) {
58+
EXPECT_EQ(root_le.size(), 32u);
59+
return uint256(root_le);
60+
}
61+
62+
// NON-CIRCULAR expected blob: magic || reverse(root_le) || size_LE || nonce_LE.
63+
// Hand-assembled from the raw inputs — does NOT call the builder.
64+
std::vector<unsigned char> expected_commitment(
65+
const std::vector<unsigned char>& root_le,
66+
uint32_t size,
67+
uint32_t nonce)
68+
{
69+
std::vector<unsigned char> e;
70+
// magic
71+
e.push_back(0xfa); e.push_back(0xbe); e.push_back(0x6d); e.push_back(0x6d);
72+
// root, big-endian (reverse of the internal little-endian image)
73+
for (int i = 31; i >= 0; --i) e.push_back(root_le[i]);
74+
// size, little-endian
75+
e.push_back(static_cast<unsigned char>(size & 0xFF));
76+
e.push_back(static_cast<unsigned char>((size >> 8) & 0xFF));
77+
e.push_back(static_cast<unsigned char>((size >> 16) & 0xFF));
78+
e.push_back(static_cast<unsigned char>((size >> 24) & 0xFF));
79+
// nonce, little-endian
80+
e.push_back(static_cast<unsigned char>(nonce & 0xFF));
81+
e.push_back(static_cast<unsigned char>((nonce >> 8) & 0xFF));
82+
e.push_back(static_cast<unsigned char>((nonce >> 16) & 0xFF));
83+
e.push_back(static_cast<unsigned char>((nonce >> 24) & 0xFF));
84+
return e;
85+
}
86+
87+
} // namespace
88+
89+
// 0) Structural: blob is exactly 44 bytes and starts with the fabe6d6d magic.
90+
TEST(DGB_AuxDogeMMCommitment, SizeAndMagic) {
91+
auto root_le = unhex(std::string(64, '0'));
92+
auto blob = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), 0, 0);
93+
ASSERT_EQ(blob.size(), 44u);
94+
EXPECT_EQ(blob.size(), dgb::coin::AUX_MM_COMMITMENT_SIZE);
95+
EXPECT_EQ(tohex({blob.begin(), blob.begin() + 4}), "fabe6d6d");
96+
// SSOT delegation: structural blob is the core builders output verbatim.
97+
EXPECT_EQ(tohex(blob),
98+
tohex(c2pool::merged::build_auxpow_commitment(
99+
root_from_le_bytes(root_le), 0, 0)));
100+
}
101+
102+
// 1) All-zero root, size=1, nonce=0 — canonical degenerate (single-aux) case.
103+
TEST(DGB_AuxDogeMMCommitment, KAT_ZeroRoot_Size1_Nonce0) {
104+
auto root_le = unhex(std::string(64, '0'));
105+
const uint32_t size = 1, nonce = 0;
106+
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
107+
auto want = expected_commitment(root_le, size, nonce);
108+
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
109+
auto ssot = c2pool::merged::build_auxpow_commitment(
110+
root_from_le_bytes(root_le), size, nonce);
111+
EXPECT_EQ(tohex(got), tohex(ssot));
112+
EXPECT_EQ(tohex(got), tohex(want));
113+
// Fully pinned literal: magic || 32 zero bytes || 01000000 || 00000000
114+
EXPECT_EQ(tohex(got),
115+
"fabe6d6d"
116+
"0000000000000000000000000000000000000000000000000000000000000000"
117+
"01000000"
118+
"00000000");
119+
}
120+
121+
// 2) Distinct-byte root, multi-byte LE size + nonce — exercises root reversal
122+
// and full little-endian width of both 32-bit fields.
123+
TEST(DGB_AuxDogeMMCommitment, KAT_PatternedRoot_SizeNonceLE) {
124+
// Internal little-endian image: byte i == i (00 01 02 ... 1f).
125+
std::vector<unsigned char> root_le;
126+
for (int i = 0; i < 32; ++i) root_le.push_back(static_cast<unsigned char>(i));
127+
const uint32_t size = 0x04030201u, nonce = 0xdeadbeefu;
128+
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
129+
auto want = expected_commitment(root_le, size, nonce);
130+
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
131+
auto ssot = c2pool::merged::build_auxpow_commitment(
132+
root_from_le_bytes(root_le), size, nonce);
133+
EXPECT_EQ(tohex(got), tohex(ssot));
134+
EXPECT_EQ(tohex(got), tohex(want));
135+
// Fully pinned literal: root big-endian is 1f..00; size LE=01020304; nonce LE=efbeadde.
136+
EXPECT_EQ(tohex(got),
137+
"fabe6d6d"
138+
"1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"
139+
"01020304"
140+
"efbeadde");
141+
}
142+
143+
// 3) Real-shaped DOGE-style root, max size, mid nonce.
144+
TEST(DGB_AuxDogeMMCommitment, KAT_RealishRoot_MaxSize) {
145+
// Internal little-endian image of a non-symmetric 32-byte root.
146+
auto root_le = unhex(
147+
"112233445566778899aabbccddeeff00"
148+
"fedcba98765432100123456789abcdef");
149+
const uint32_t size = 0xffffffffu, nonce = 0x00c0ffeeu;
150+
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
151+
auto want = expected_commitment(root_le, size, nonce);
152+
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
153+
auto ssot = c2pool::merged::build_auxpow_commitment(
154+
root_from_le_bytes(root_le), size, nonce);
155+
EXPECT_EQ(tohex(got), tohex(ssot));
156+
EXPECT_EQ(tohex(got), tohex(want));
157+
// Fully pinned literal.
158+
EXPECT_EQ(tohex(got),
159+
"fabe6d6d"
160+
"efcdab89674523011032547698badcfe00ffeeddccbbaa998877665544332211"
161+
"ffffffff"
162+
"eeffc000");
163+
}

0 commit comments

Comments
 (0)