Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
test_address_resolution test_compute_share_target \
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 \
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 nmc_host_dualpath_test nmc_fallback_path_conformance_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \
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 \
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 \
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
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 \
-j$(nproc)
Expand Down Expand Up @@ -214,7 +214,7 @@ jobs:
test_address_resolution test_compute_share_target \
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 \
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 nmc_host_dualpath_test nmc_fallback_path_conformance_test dgb_gentx_share_path_test dgb_conn_pplns_producer_test dgb_other_tx_resolver_test \
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 \
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 \
rpc_request_test softfork_check_test genesis_check_test algo_select_test digishield_walk_test header_chain_test \
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 \
v37_test \
Expand Down
72 changes: 72 additions & 0 deletions src/impl/dgb/coin/aux_doge_mm_commitment.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once
// ---------------------------------------------------------------------------
// DGB+DOGE merged-mining (phase DB) -- DGB-side AuxPoW coinbase-commitment
// entry point. THIN DELEGATION to the canonical cross-coin SSOT producer
// c2pool::merged::build_auxpow_commitment. This header carries NO duplicate
// build logic of its own.
//
// RATIONALE (integrator adjudication 2026-06-25, thread "core builder = MM
// SSOT"). The AuxPoW merged-mining commitment build is a v36-NATIVE SHARED
// structure, not a per-coin transition-compat one. The single producer lives
// in shared A-level scaffolding (src/c2pool/merged/merged_mining.cpp +
// src/core/coinbase_builder.hpp); it is chain_id-parameterized, and DGB/DOGE
// plug in as CHAINS, not as a per-coin build path. A fenced DGB builder that
// "mirrors" the core one is exactly the cross-coin divergence the v36->v37
// standardization goal forbids. DGBs real per-coin value is therefore its
// chain_id slot + fabe6d6d GOLDENS pinned to the canonical builder (see the
// KAT aux_doge_mm_commitment_test.cpp), NOT a second copy of the machinery.
//
// This header exposes only a DGB-namespaced symbol that forwards verbatim to
// the SSOT, so DGB-as-parent call sites read naturally while the bytes are
// produced in exactly one place.
//
// CANONICAL LAYOUT (owned by the SSOT; reproduced here for readers only):
// [4] fa be 6d 6d MM magic
// [32] aux_merkle_root big-endian (byte 31 first)
// [4] merkle_size little-endian
// [4] merkle_nonce little-endian
// Total: 44 bytes.
//
// FENCED -- NOT REWIRED. No live caller invokes this yet; the mint/work-source
// path is untouched. Live wiring (DB embed-at-mint / DC dual-target) routes
// THROUGH the core builder and is gated on ltc-doge concurrence + operator tap.
// ---------------------------------------------------------------------------

#include <cstdint>
#include <vector>

#include <core/uint256.hpp>
#include <c2pool/merged/merged_mining.hpp> // SSOT: c2pool::merged::build_auxpow_commitment

namespace dgb {
namespace coin {

// MM merged-mining magic marker: 0xfa 0xbe 0x6d 0x6d ("\xfa\xbe" + "mm").
// Pinned by the KAT and available to readers/asserts; the bytes themselves are
// emitted by the SSOT, never reconstructed here.
inline constexpr unsigned char AUX_MM_MAGIC[4] = {0xfa, 0xbe, 0x6d, 0x6d};

// Size in bytes of the canonical AuxPoW merged-mining commitment blob
// (magic(4) + aux_merkle_root(32) + merkle_size(4) + merkle_nonce(4)).
inline constexpr std::size_t AUX_MM_COMMITMENT_SIZE = 44;

// Build the canonical merged-mining coinbase commitment for a DGB-as-parent
// coinbase. THIN DELEGATION -- forwards verbatim to the cross-coin SSOT
// c2pool::merged::build_auxpow_commitment; there is NO DGB-local layout logic.
//
// aux_merkle_root -- auxiliary (DOGE) blockchain merkle root.
// merkle_size -- aux merkle-tree size.
// merkle_nonce -- aux merkle nonce.
//
// Returns exactly AUX_MM_COMMITMENT_SIZE (44) bytes.
inline std::vector<unsigned char> build_aux_mm_commitment(
const uint256& aux_merkle_root,
uint32_t merkle_size,
uint32_t merkle_nonce)
{
return c2pool::merged::build_auxpow_commitment(
aux_merkle_root, merkle_size, merkle_nonce);
}

} // namespace coin
} // namespace dgb
16 changes: 16 additions & 0 deletions src/impl/dgb/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,22 @@ if (BUILD_TESTING AND GTest_FOUND)
dgb_coin pool sharechain)
gtest_add_tests(dgb_aux_doge_db_commitment_bind_test "" AUTO)

# --- DGB+DOGE (phase DB) -- DGB-side AuxPoW merged-mining coinbase ---
# commitment BUILDER KAT. FENCED / test-only: pins the canonical
# fabe6d6d || aux_root(32 BE) || size(4 LE) || nonce(4 LE) byte layout
# emitted by dgb::coin::build_aux_mm_commitment, non-circularly (goldens
# hand-built from raw inputs, not the builder). Pure dgb/+core value
# transform -- no ltc/doge linkage, flag-agnostic (builds in default AND
# -DAUX_DOGE arms). MUST appear in BOTH this registration AND the build.yml
# --target allowlist or it becomes a NOT_BUILT sentinel that reds master
# (cf. DGB #137 / #143).
add_executable(dgb_aux_doge_mm_commitment_test aux_doge_mm_commitment_test.cpp)
target_link_libraries(dgb_aux_doge_mm_commitment_test PRIVATE
GTest::gtest_main GTest::gtest
core
c2pool_payout c2pool_merged_mining c2pool_hashrate c2pool_storage)
gtest_add_tests(dgb_aux_doge_mm_commitment_test "" AUTO)

# --- DGB+DOGE (phase DC) -- DGB-as-parent AuxPoW PROOF byte-parity + dual ---
# Proves the neutral producer build_auxpow_proof (c2pool/merged) is byte-
# identical to the typed doge::coin::CAuxPow<dgb::coin::MutableTransaction>
Expand Down
163 changes: 163 additions & 0 deletions src/impl/dgb/test/aux_doge_mm_commitment_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// ---------------------------------------------------------------------------
// DGB+DOGE merged-mining (phase DB) — KAT for the DGB-side AuxPoW coinbase
// merged-mining commitment builder. Fenced / test-only.
//
// Pins the EXACT byte layout emitted by dgb::coin::build_aux_mm_commitment for
// fixed (aux_merkle_root, merkle_size, merkle_nonce) inputs:
//
// fa be 6d 6d || aux_root(32, big-endian) || size(4 LE) || nonce(4 LE)
//
// NON-CIRCULAR. The expected commitment bytes are hand-constructed in each
// case from the raw inputs (magic literal + reversed root bytes + manually
// little-endian-split size/nonce), NOT by re-invoking the builder. The test is
// therefore a true layout anchor: a re-shaped builder cannot self-confirm.
//
// SSOT DELEGATION GUARD. Each case ALSO asserts the DGB entry point is
// byte-identical to the canonical cross-coin producer
// c2pool::merged::build_auxpow_commitment. Per the integrator adjudication
// (core builder = MM SSOT), DGB owns no build body of its own; this pins
// DGBs chain slot + goldens to the one canonical builder (delegation), not a
// fenced copy. Mirrors the NMC SSOT drift-guard auxpow_merkle_test.cpp.
//
// Mirrors the established DGB aux-test style (unhex/tohex helpers) of the
// sibling src/impl/dgb/test/aux_doge_db_commitment_bind_test.cpp. MUST appear
// in BOTH test/CMakeLists.txt AND the build.yml --target allowlist or it
// becomes a NOT_BUILT sentinel that reds master (cf. DGB #137 / #143).
// ---------------------------------------------------------------------------

#include <gtest/gtest.h>

#include <impl/dgb/coin/aux_doge_mm_commitment.hpp> // the fenced builder under test
#include <c2pool/merged/merged_mining.hpp> // SSOT drift-guard: build_auxpow_commitment
#include <core/uint256.hpp>

#include <cstdint>
#include <string>
#include <vector>

namespace {

std::vector<unsigned char> unhex(const std::string& h) {
std::vector<unsigned char> v; v.reserve(h.size() / 2);
auto nyb = [](char c) -> int { return (c <= '9') ? c - '0' : (c | 0x20) - 'a' + 10; };
for (size_t i = 0; i + 1 < h.size(); i += 2)
v.push_back(static_cast<unsigned char>((nyb(h[i]) << 4) | nyb(h[i + 1])));
return v;
}
std::string tohex(const std::vector<unsigned char>& v) {
static const char* H = "0123456789abcdef";
std::string s; s.reserve(v.size() * 2);
for (unsigned char b : v) { s.push_back(H[b >> 4]); s.push_back(H[b & 0xf]); }
return s;
}

// Build a uint256 whose internal little-endian byte image == root_le[0..31].
// (base_uint(vector) reads the vector little-endian, so on a little-endian host
// reinterpret_cast<uint8_t*>(pn)[i] == root_le[i].) Requires exactly 32 bytes.
uint256 root_from_le_bytes(const std::vector<unsigned char>& root_le) {
EXPECT_EQ(root_le.size(), 32u);
return uint256(root_le);
}

// NON-CIRCULAR expected blob: magic || reverse(root_le) || size_LE || nonce_LE.
// Hand-assembled from the raw inputs — does NOT call the builder.
std::vector<unsigned char> expected_commitment(
const std::vector<unsigned char>& root_le,
uint32_t size,
uint32_t nonce)
{
std::vector<unsigned char> e;
// magic
e.push_back(0xfa); e.push_back(0xbe); e.push_back(0x6d); e.push_back(0x6d);
// root, big-endian (reverse of the internal little-endian image)
for (int i = 31; i >= 0; --i) e.push_back(root_le[i]);
// size, little-endian
e.push_back(static_cast<unsigned char>(size & 0xFF));
e.push_back(static_cast<unsigned char>((size >> 8) & 0xFF));
e.push_back(static_cast<unsigned char>((size >> 16) & 0xFF));
e.push_back(static_cast<unsigned char>((size >> 24) & 0xFF));
// nonce, little-endian
e.push_back(static_cast<unsigned char>(nonce & 0xFF));
e.push_back(static_cast<unsigned char>((nonce >> 8) & 0xFF));
e.push_back(static_cast<unsigned char>((nonce >> 16) & 0xFF));
e.push_back(static_cast<unsigned char>((nonce >> 24) & 0xFF));
return e;
}

} // namespace

// 0) Structural: blob is exactly 44 bytes and starts with the fabe6d6d magic.
TEST(DGB_AuxDogeMMCommitment, SizeAndMagic) {
auto root_le = unhex(std::string(64, '0'));
auto blob = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), 0, 0);
ASSERT_EQ(blob.size(), 44u);
EXPECT_EQ(blob.size(), dgb::coin::AUX_MM_COMMITMENT_SIZE);
EXPECT_EQ(tohex({blob.begin(), blob.begin() + 4}), "fabe6d6d");
// SSOT delegation: structural blob is the core builders output verbatim.
EXPECT_EQ(tohex(blob),
tohex(c2pool::merged::build_auxpow_commitment(
root_from_le_bytes(root_le), 0, 0)));
}

// 1) All-zero root, size=1, nonce=0 — canonical degenerate (single-aux) case.
TEST(DGB_AuxDogeMMCommitment, KAT_ZeroRoot_Size1_Nonce0) {
auto root_le = unhex(std::string(64, '0'));
const uint32_t size = 1, nonce = 0;
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
auto want = expected_commitment(root_le, size, nonce);
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
auto ssot = c2pool::merged::build_auxpow_commitment(
root_from_le_bytes(root_le), size, nonce);
EXPECT_EQ(tohex(got), tohex(ssot));
EXPECT_EQ(tohex(got), tohex(want));
// Fully pinned literal: magic || 32 zero bytes || 01000000 || 00000000
EXPECT_EQ(tohex(got),
"fabe6d6d"
"0000000000000000000000000000000000000000000000000000000000000000"
"01000000"
"00000000");
}

// 2) Distinct-byte root, multi-byte LE size + nonce — exercises root reversal
// and full little-endian width of both 32-bit fields.
TEST(DGB_AuxDogeMMCommitment, KAT_PatternedRoot_SizeNonceLE) {
// Internal little-endian image: byte i == i (00 01 02 ... 1f).
std::vector<unsigned char> root_le;
for (int i = 0; i < 32; ++i) root_le.push_back(static_cast<unsigned char>(i));
const uint32_t size = 0x04030201u, nonce = 0xdeadbeefu;
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
auto want = expected_commitment(root_le, size, nonce);
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
auto ssot = c2pool::merged::build_auxpow_commitment(
root_from_le_bytes(root_le), size, nonce);
EXPECT_EQ(tohex(got), tohex(ssot));
EXPECT_EQ(tohex(got), tohex(want));
// Fully pinned literal: root big-endian is 1f..00; size LE=01020304; nonce LE=efbeadde.
EXPECT_EQ(tohex(got),
"fabe6d6d"
"1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"
"01020304"
"efbeadde");
}

// 3) Real-shaped DOGE-style root, max size, mid nonce.
TEST(DGB_AuxDogeMMCommitment, KAT_RealishRoot_MaxSize) {
// Internal little-endian image of a non-symmetric 32-byte root.
auto root_le = unhex(
"112233445566778899aabbccddeeff00"
"fedcba98765432100123456789abcdef");
const uint32_t size = 0xffffffffu, nonce = 0x00c0ffeeu;
auto got = dgb::coin::build_aux_mm_commitment(root_from_le_bytes(root_le), size, nonce);
auto want = expected_commitment(root_le, size, nonce);
// SSOT delegation: DGB entry point forwards verbatim to the core builder.
auto ssot = c2pool::merged::build_auxpow_commitment(
root_from_le_bytes(root_le), size, nonce);
EXPECT_EQ(tohex(got), tohex(ssot));
EXPECT_EQ(tohex(got), tohex(want));
// Fully pinned literal.
EXPECT_EQ(tohex(got),
"fabe6d6d"
"efcdab89674523011032547698badcfe00ffeeddccbbaa998877665544332211"
"ffffffff"
"eeffc000");
}
Loading