|
| 1 | +// --------------------------------------------------------------------------- |
| 2 | +// DGB+DOGE (phase DC) — dual-target SELECTION scaffold KAT. |
| 3 | +// |
| 4 | +// Fenced / test-only. Pins the pure DC decision contract (coin/aux_dual_target_ |
| 5 | +// select.hpp) the eventual DC wiring must satisfy, BEFORE the AUX_DOGE node seam |
| 6 | +// is touched. Non-circular: every golden is restated by value (the fabe6d6d tag, |
| 7 | +// the embed-when-aux+job rule, the independent threshold table, the no-op |
| 8 | +// invariant) — it mirrors #475 (fabe6d6d builder) / #486 (embed-at-mint nullopt |
| 9 | +// no-op) without including their (not-yet-landed) headers, so it cannot drift |
| 10 | +// against them and stands alone on master. |
| 11 | +// |
| 12 | +// Pure helpers, links only core (uint256). Consumes nothing in src/impl/doge. |
| 13 | +// MUST appear in BOTH test/CMakeLists.txt AND the build.yml --target allowlist |
| 14 | +// or it becomes a NOT_BUILT sentinel that reds master (#143 trap). |
| 15 | +// --------------------------------------------------------------------------- |
| 16 | + |
| 17 | +#include <gtest/gtest.h> |
| 18 | + |
| 19 | +#include <impl/dgb/coin/aux_dual_target_select.hpp> |
| 20 | +#include <core/uint256.hpp> |
| 21 | + |
| 22 | +using dgb::coin::aux_mint_decision; |
| 23 | +using dgb::coin::select_submit; |
| 24 | +using dgb::coin::selection_is_consistent; |
| 25 | +using dgb::coin::MM_COMMITMENT_TAG; |
| 26 | + |
| 27 | +// 1) fabe6d6d mint anchor (#475). Non-circular literal golden — the tag the |
| 28 | +// real MM-commitment builder prepends. Guards against a silent tag reshape. |
| 29 | +TEST(DGB_AuxDualTargetSelect, MmCommitmentTagIsFabe6d6d) { |
| 30 | + EXPECT_EQ(MM_COMMITMENT_TAG[0], 0xfa); |
| 31 | + EXPECT_EQ(MM_COMMITMENT_TAG[1], 0xbe); |
| 32 | + EXPECT_EQ(MM_COMMITMENT_TAG[2], 0x6d); |
| 33 | + EXPECT_EQ(MM_COMMITMENT_TAG[3], 0x6d); |
| 34 | +} |
| 35 | + |
| 36 | +// 2) MINT-TIME embed truth table (#486). Embed IFF aux enabled AND DOGE job. |
| 37 | +// The three non-embed corners are the byte-identical no-op (#486 nullopt). |
| 38 | +TEST(DGB_AuxDualTargetSelect, MintEmbedsOnlyWhenAuxEnabledAndDogeJob) { |
| 39 | + EXPECT_TRUE (aux_mint_decision(/*aux*/true, /*job*/true ).embed_commitment); |
| 40 | + EXPECT_FALSE(aux_mint_decision(/*aux*/true, /*job*/false).embed_commitment); |
| 41 | + EXPECT_FALSE(aux_mint_decision(/*aux*/false, /*job*/true ).embed_commitment); |
| 42 | + EXPECT_FALSE(aux_mint_decision(/*aux*/false, /*job*/false).embed_commitment); |
| 43 | +} |
| 44 | + |
| 45 | +// 3) SUBMIT-TIME independent thresholds — same pow_hash, two independent targets |
| 46 | +// (mirrors dc_proof DualTargetIndependentThresholds). DGB-parent is the |
| 47 | +// harder (smaller) target; DOGE-aux is easier (larger). |
| 48 | +TEST(DGB_AuxDualTargetSelect, SubmitFiresIndependentThresholds) { |
| 49 | + const uint256 DGB_TARGET = uint256S("0000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 50 | + const uint256 DOGE_TARGET = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 51 | + |
| 52 | + const uint256 below_both = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); |
| 53 | + const uint256 doge_only = uint256S("000000000affffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 54 | + const uint256 above_both = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 55 | + |
| 56 | + // below both -> both paths fire |
| 57 | + auto a = select_submit(below_both, DGB_TARGET, /*job*/true, DOGE_TARGET); |
| 58 | + EXPECT_TRUE(a.fire_dgb_parent); |
| 59 | + EXPECT_TRUE(a.fire_doge_aux); |
| 60 | + |
| 61 | + // between -> DOGE-aux fires, DGB-parent does NOT (the common case) |
| 62 | + auto b = select_submit(doge_only, DGB_TARGET, /*job*/true, DOGE_TARGET); |
| 63 | + EXPECT_FALSE(b.fire_dgb_parent); |
| 64 | + EXPECT_TRUE (b.fire_doge_aux); |
| 65 | + |
| 66 | + // above both -> neither fires |
| 67 | + auto c = select_submit(above_both, DGB_TARGET, /*job*/true, DOGE_TARGET); |
| 68 | + EXPECT_FALSE(c.fire_dgb_parent); |
| 69 | + EXPECT_FALSE(c.fire_doge_aux); |
| 70 | +} |
| 71 | + |
| 72 | +// 4) No DOGE job suppresses the DOGE-aux path even on a target hit, and leaves |
| 73 | +// the DGB-parent path untouched (standalone-parent default build behaviour). |
| 74 | +TEST(DGB_AuxDualTargetSelect, NoDogeJobSuppressesAuxPathOnly) { |
| 75 | + const uint256 DGB_TARGET = uint256S("0000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 76 | + const uint256 DOGE_TARGET = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); |
| 77 | + const uint256 below_both = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); |
| 78 | + |
| 79 | + auto f = select_submit(below_both, DGB_TARGET, /*job*/false, DOGE_TARGET); |
| 80 | + EXPECT_TRUE (f.fire_dgb_parent); // parent path independent of aux |
| 81 | + EXPECT_FALSE(f.fire_doge_aux); // no job minted -> no aux win |
| 82 | +} |
| 83 | + |
| 84 | +// 5) LOAD-BEARING DC<->DB linkage: fire_doge_aux ==> embed_commitment. A DOGE |
| 85 | +// win without a minted commitment is the impossible state the guard rejects. |
| 86 | +TEST(DGB_AuxDualTargetSelect, DogeWinRequiresMintedCommitment) { |
| 87 | + // reachable: aux on + job -> minted -> a DOGE fire is consistent |
| 88 | + EXPECT_TRUE(selection_is_consistent( |
| 89 | + aux_mint_decision(true, true), |
| 90 | + dgb::coin::DualTargetFire{true, true})); |
| 91 | + // reachable: no DOGE fire is always consistent regardless of mint |
| 92 | + EXPECT_TRUE(selection_is_consistent( |
| 93 | + aux_mint_decision(false, false), |
| 94 | + dgb::coin::DualTargetFire{true, false})); |
| 95 | + // impossible: DOGE fire without a minted commitment -> guard rejects |
| 96 | + EXPECT_FALSE(selection_is_consistent( |
| 97 | + aux_mint_decision(false, true), |
| 98 | + dgb::coin::DualTargetFire{false, true})); |
| 99 | +} |
0 commit comments