diff --git a/src/impl/dgb/test/work_source_test.cpp b/src/impl/dgb/test/work_source_test.cpp index 89294104e..cdab8aae2 100644 --- a/src/impl/dgb/test/work_source_test.cpp +++ b/src/impl/dgb/test/work_source_test.cpp @@ -17,6 +17,7 @@ #include #include #include // dgb::CoinParams::subsidy (oracle SSOT) +#include // dgb::make_coin_params -- the LIVE production binding #include // core::SubsidyFunc @@ -458,6 +459,28 @@ TEST(DgbWorkSource, CoinbaseValueHonorsGbtVerbatim) } +// Production-binding guard. The era-boundary tests above trust kSubsidyFunc, a +// hand-written DUPLICATE of params.hpp p.subsidy_func: they pin the schedule +// math but are blind to a regression in the ACTUAL wiring. If make_coin_params() +// shipped subsidy_func unbound (the work source then logs subsidy_func=UNSET and +// the embedded coinbasevalue silently falls through to the GBT-only path) or +// bound it to the wrong function, every test above would still pass off its +// private copy. Pin the LIVE production binding directly. +TEST(DgbCoinParams, SubsidyFuncBoundToOracleScheduleInProduction) +{ + const core::CoinParams p = dgb::make_coin_params(/*testnet=*/false); + ASSERT_TRUE(static_cast(p.subsidy_func)) + << "make_coin_params shipped subsidy_func UNSET -- embedded coinbasevalue " + "would silently degrade to the external-GBT-only path"; + for (const auto& v : kEraBoundaries) { + EXPECT_EQ(p.subsidy_func(v.height), v.subsidy) + << "production subsidy_func diverged from oracle subsidy at " << v.era; + EXPECT_EQ(p.subsidy_func(v.height), kSubsidyFunc(v.height)) + << "production binding diverged from the schedule under test at " << v.era; + } +} + + // previousblockhash: emitted as GBT-conventional big-endian display hex ONLY // when the HeaderChain carries a real tip hash (tip_hash() accessor). With a // known tip block_hash, the template surfaces it MSB-limb-first; bits stays