From e2714b9649910d1869d3dfab3bfef5d0c54d4094 Mon Sep 17 00:00:00 2001 From: frstrtr Date: Fri, 19 Jun 2026 14:17:33 +0000 Subject: [PATCH] dgb: wire get_current_work_template coinbasevalue through #207 SSOT (Stage 4c) get_current_work_template() now emits the next-block height and its coinbasevalue instead of an empty object. The coinbasevalue is derived through the #207 embedded SSOT (coinbase_value -> resolve_coinbase_value -> subsidy_func) keyed on next_block_height() (#209, == tip.height + 1; == base_height for an empty chain). Embedded path: no external-daemon GBT value is plumbed in yet and mempool-fee aggregation is unwired, so total_fees = 0; a present GBT coinbasevalue stays authoritative and fees add on top of subsidy in later slices without changing this SSOT call. The remaining GBT template fields (previousblockhash, bits, version, curtime, mintime, transactions[]) and the build_connection_coinbase gentx assembly land in following Stage 4c/4d slices. Test: +WorkTemplateEmitsHeightAndCoinbaseValueViaSsot pins height + coinbasevalue to the p2pool-dgb-scrypt oracle subsidy at the phase3 era boundary; existing stub-default assertion relaxed. dgb_work_source_test 14/14. --- src/impl/dgb/stratum/work_source.cpp | 25 ++++++++++++++++++++----- src/impl/dgb/test/work_source_test.cpp | 24 +++++++++++++++++++++++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/impl/dgb/stratum/work_source.cpp b/src/impl/dgb/stratum/work_source.cpp index c07029160..94aa0fde2 100644 --- a/src/impl/dgb/stratum/work_source.cpp +++ b/src/impl/dgb/stratum/work_source.cpp @@ -148,11 +148,26 @@ void DGBWorkSource::update_stratum_worker(const std::string& session_id, nlohmann::json DGBWorkSource::get_current_work_template() const { - // Stage 4c: drive dgb::coin::TemplateBuilder over chain_ + mempool_ and - // shape its WorkData into the GBT-style JSON the stratum session expects - // (previousblockhash, bits, version, curtime, mintime, height, - // coinbasevalue, transactions[]). Scrypt nBits, not SHA256d. - return nlohmann::json::object(); + // Stage 4c (coinbasevalue wire): the full GBT-shaped template + // (previousblockhash, bits, version, curtime, mintime, transactions[]) + // is assembled by the embedded dgb::coin::TemplateBuilder in a following + // slice. What lands here is the consensus-bearing reward field: the + // coinbasevalue for the NEXT block, derived through the #207 SSOT + // (coinbase_value -> resolve_coinbase_value -> subsidy_func) keyed on the + // absolute next-block height from the #209 HeaderChain accessor + // (next_block_height() == tip_height()+1, or base_height for an empty + // chain). Embedded path: no external-daemon GBT value is plumbed in yet + // and mempool-fee aggregation is not wired, so total_fees = 0 here. Both + // compose in later slices WITHOUT changing this SSOT call (a present GBT + // coinbasevalue stays authoritative; fees add on top of subsidy). + const uint32_t next_h = chain_.next_block_height(); + const uint64_t coinbasevalue = + coinbase_value(next_h, /*total_fees=*/0, /*gbt_coinbasevalue=*/std::nullopt); + + nlohmann::json tmpl = nlohmann::json::object(); + tmpl["height"] = next_h; + tmpl["coinbasevalue"] = coinbasevalue; + return tmpl; } std::vector DGBWorkSource::get_stratum_merkle_branches() const diff --git a/src/impl/dgb/test/work_source_test.cpp b/src/impl/dgb/test/work_source_test.cpp index 6d0dc6f82..400ac20dd 100644 --- a/src/impl/dgb/test/work_source_test.cpp +++ b/src/impl/dgb/test/work_source_test.cpp @@ -135,8 +135,10 @@ TEST(DgbWorkSource, WorkGenStubsReturnSafeDefaults) // 4a skeleton: every work-generation getter returns its documented // empty/default form (4c fills them in). EXPECT_TRUE(ws->get_current_gbt_prevhash().empty()); + // get_current_work_template() now emits height + coinbasevalue (Stage 4c + // coinbasevalue wire); its dedicated assertions live in + // WorkTemplateEmitsHeightAndCoinbaseValueViaSsot below. EXPECT_TRUE(ws->get_current_work_template().is_object()); - EXPECT_TRUE(ws->get_current_work_template().empty()); EXPECT_TRUE(ws->get_stratum_merkle_branches().empty()); auto parts = ws->get_coinbase_parts(); EXPECT_TRUE(parts.first.empty()); @@ -174,6 +176,26 @@ TEST(DgbWorkSource, ComputeShareDifficultyReturnsNotYetSentinel) EXPECT_DOUBLE_EQ(diff, 0.0); } +// Stage 4c coinbasevalue wire: the work template surfaces the NEXT-block +// height and its coinbasevalue, the latter derived THROUGH the #207 SSOT +// (subsidy_func) keyed on next_block_height() == tip.height + 1 (#209). An +// empty chain makes next_block_height() == base_height, so seeding an oracle +// era boundary pins the value unambiguously to the p2pool-dgb-scrypt subsidy. +TEST(DgbWorkSource, WorkTemplateEmitsHeightAndCoinbaseValueViaSsot) +{ + Fixture fx; + fx.chain.set_base_height(400000); // phase3 first block (oracle boundary) + auto ws = fx.make(); + auto tmpl = ws->get_current_work_template(); + ASSERT_TRUE(tmpl.is_object()); + ASSERT_TRUE(tmpl.contains("height")); + ASSERT_TRUE(tmpl.contains("coinbasevalue")); + // next_h = next_block_height() = base_height (empty chain) = 400000. + EXPECT_EQ(tmpl["height"].get(), 400000u); + // Zero embedded fees, no external GBT -> oracle subsidy at the boundary. + EXPECT_EQ(tmpl["coinbasevalue"].get(), 2434410000ULL); +} + // ── Embedded coinbasevalue: first production caller of subsidy_func ────────── // One pin on each side of every DGB reward-era boundary (p2pool-dgb-scrypt // oracle vectors, test_dgb_subsidy.cpp).