Skip to content

Commit 54974e2

Browse files
authored
Merge pull request #241 from frstrtr/dgb/embedded-template-tx-passthrough
dgb: embedded template transactions[] as caller-supplied SSOT input (Option 1 seam)
2 parents 9f06128 + 0f52ac0 commit 54974e2

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

src/impl/dgb/coin/template_builder.hpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ class CoinNodeInterface {
7272
// NON-CONSENSUS: this function only SHAPES values; it never derives or alters
7373
// the consensus-bearing coinbasevalue. That value is computed by the caller
7474
// through the #207 resolve_coinbase_value -> subsidy_func SSOT and passed in
75-
// verbatim. The builder fabricates nothing: transactions[] stays empty
76-
// (embedded mempool tx selection is not wired, fees stay 0), previousblockhash
75+
// verbatim. The builder fabricates nothing: transactions[] is a caller-supplied
76+
// pass-through (empty by default until a mempool tx source is wired -- truthful
77+
// absence, never a fabricated tx; the fee total is folded into coinbasevalue
78+
// UPSTREAM via resolve_coinbase_value, not here), previousblockhash
7779
// is emitted ONLY when the caller supplies a real tip hash (truthful absence,
7880
// never a fabricated id), and `bits` is held back entirely -- DGB Core's live
7981
// next-target is MultiShield V4 (a global 5-algo window == V37), so a
@@ -96,6 +98,16 @@ struct WorkTemplateInputs {
9698
// caller (work source: u256_be_display_hex). nullopt -> previousblockhash
9799
// omitted from the template.
98100
std::optional<std::string> previousblockhash;
101+
// GBT transactions[] array, already shaped by the caller (per-tx
102+
// {data,txid,hash,fee} objects, the same shape btc's template_builder
103+
// emits). The builder passes it through VERBATIM and shapes nothing -- the
104+
// identical truthful-absence discipline as previousblockhash: it defaults
105+
// to an empty array, so a caller that has wired no transaction source (the
106+
// current embedded + stratum paths) emits an empty transactions[] and
107+
// fabricates nothing. The fee total those txs carry is folded into
108+
// coinbasevalue UPSTREAM via resolve_coinbase_value(total_fees) (#207 SSOT);
109+
// the builder never derives the reward, so this field is display-only shape.
110+
nlohmann::json transactions = nlohmann::json::array();
99111
};
100112

101113
inline nlohmann::json build_work_template(const WorkTemplateInputs& in)
@@ -122,7 +134,7 @@ inline nlohmann::json build_work_template(const WorkTemplateInputs& in)
122134
tmpl["version"] = version;
123135
tmpl["curtime"] = in.curtime;
124136
tmpl["mintime"] = mintime;
125-
tmpl["transactions"] = nlohmann::json::array();
137+
tmpl["transactions"] = in.transactions; // caller-supplied; empty by default
126138

127139
// previousblockhash: truthful conditional emit (see struct notes).
128140
if (in.previousblockhash)

src/impl/dgb/test/template_builder_test.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ TEST(DgbTemplateBuilder, EmptyChainMintimeIsZero)
8686
EXPECT_EQ(t.at("mintime").get<int64_t>(), 0);
8787
}
8888

89-
// transactions[] is always an empty array (embedded tx selection unwired);
89+
// transactions[] is an empty array BY DEFAULT (no tx source wired into the
90+
// inputs); bits is NEVER emitted (MultiShield V4 next-target is V37 -- the
9091
// bits is NEVER emitted (MultiShield V4 next-target is V37 — a Scrypt-only
9192
// walk would be a known-wrong difficulty).
9293
TEST(DgbTemplateBuilder, EmptyTransactionsAndNoBits)
@@ -112,6 +113,34 @@ TEST(DgbTemplateBuilder, PreviousblockhashConditionalEmit)
112113
EXPECT_FALSE(without.contains("previousblockhash"));
113114
}
114115

116+
// transactions[] is a caller-supplied pass-through: a shaped array round-trips
117+
// into the template VERBATIM (the seam a wired mempool source emits through),
118+
// while an unset input stays an empty array (truthful absence by default). This
119+
// is the same conditional-shape contract previousblockhash holds.
120+
TEST(DgbTemplateBuilder, TransactionsPassThroughVerbatim)
121+
{
122+
auto in = make_inputs();
123+
nlohmann::json tx = nlohmann::json::object();
124+
tx["data"] = "0100000001abcd";
125+
tx["txid"] = std::string(64, '1');
126+
tx["hash"] = std::string(64, '1');
127+
tx["fee"] = 4200;
128+
in.transactions = nlohmann::json::array();
129+
in.transactions.push_back(tx);
130+
131+
auto t = build_work_template(in);
132+
ASSERT_TRUE(t.at("transactions").is_array());
133+
ASSERT_EQ(t.at("transactions").size(), 1u);
134+
// byte-identical pass-through: the builder shapes nothing of its own.
135+
EXPECT_EQ(t.at("transactions").dump(), in.transactions.dump());
136+
EXPECT_EQ(t.at("transactions")[0].at("fee").get<int64_t>(), 4200);
137+
138+
// Unset -> empty array (default): never absent, never fabricated.
139+
auto def = build_work_template(make_inputs());
140+
ASSERT_TRUE(def.at("transactions").is_array());
141+
EXPECT_TRUE(def.at("transactions").empty());
142+
}
143+
115144
// Divergence guard: identical inputs -> byte-identical template. This is the
116145
// whole point of the SSOT — the work source and embedded path cannot diverge.
117146
TEST(DgbTemplateBuilder, DeterministicForIdenticalInputs)

0 commit comments

Comments
 (0)