Skip to content

Commit 1b44221

Browse files
committed
test(dash-g1): injectable block-version seam + byte-parity golden KAT
Make build_embedded_workdata version an injectable trailing-default param (default 0x20000000, the BIP9 no-signaling baseline) so every existing caller is byte-for-byte unchanged. Add G1GoldenVersionSeamEchoesInjectedVersion: the seam echoes a pinned version exactly, the default preserves the prior hardcoded projection, and a non-default version drifts ONLY m_version. SAFE-ADDITIVE, fenced to embedded_gbt.hpp + test_dash_embedded_gbt.cpp, non-consensus (default value unchanged). Companion to the curtime seam (#622).
1 parent e602287 commit 1b44221

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

src/impl/dash/coin/embedded_gbt.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ inline DashWorkData build_embedded_workdata(
6262
uint32_t bits_for_next,
6363
uint32_t mtp_at_tip,
6464
uint8_t address_version,
65-
uint8_t address_p2sh_version)
65+
uint8_t address_p2sh_version,
66+
// Seam: injectable block version. Defaults to 0x20000000 (BIP9 "no
67+
// signaling" baseline) so every existing caller is byte-for-byte
68+
// unchanged (SAFE-ADDITIVE); the G1 golden KAT pins it, and a real
69+
// BIP9-deployment-aware value can later be threaded in without touching
70+
// the default header projection.
71+
uint32_t version = 0x20000000u)
6672
{
6773
DashWorkData w;
6874
w.m_height = prev_height + 1;
@@ -74,7 +80,7 @@ inline DashWorkData build_embedded_workdata(
7480
// GBT returns MTP+1 as mintime so miners don't accidentally
7581
// produce stale-time blocks.
7682
w.m_mintime = mtp_at_tip + 1;
77-
w.m_version = 0x20000000; // TODO: real BIP9 bits
83+
w.m_version = version; // seam: default 0x20000000 (BIP9 baseline)
7884

7985
// Subsidy + tx selection.
8086
int64_t reward = compute_dash_block_reward_post_v20(w.m_height);

test/test_dash_embedded_gbt.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,63 @@ TEST(DashEmbeddedGbt, GbtXcheckMatchesIdenticalDetectsFieldDrift) {
408408
rpc_count.m_packed_payments.pop_back();
409409
EXPECT_FALSE(gbt_xcheck(w, rpc_count));
410410
}
411+
412+
// ════════════════════════════════════════════════════════════════════════
413+
// G1 golden: injectable block-version seam.
414+
//
415+
// Companion to the curtime seam. build_embedded_workdata hardcoded
416+
// m_version = 0x20000000 (BIP9 "no signaling" baseline). With the trailing
417+
// defaulted `version` param, a fixed-input call yields a byte-for-byte
418+
// reproducible version projection, and a real BIP9-deployment-aware value
419+
// can later be threaded through without disturbing the default.
420+
//
421+
// Oracle discipline (non-circular): the default is asserted against the BIP9
422+
// baseline constant 0x20000000, and the injected path is asserted to echo the
423+
// pinned input exactly — the seam performs no version arithmetic of its own.
424+
// ════════════════════════════════════════════════════════════════════════
425+
426+
TEST(DashEmbeddedGbt, G1GoldenVersionSeamEchoesInjectedVersion) {
427+
UTXOViewCache utxo(nullptr);
428+
uint256 prev = mint_hash(88);
429+
utxo.add_coin(Outpoint(prev, 0), Coin(100'000, {}, /*height=*/1, /*cb=*/false));
430+
Mempool mp;
431+
mp.set_utxo(&utxo);
432+
auto tx = make_spend(prev, 0, 90'000, /*salt=*/9); // fee = 10'000
433+
ASSERT_TRUE(mp.add_tx(tx));
434+
435+
auto payout = p2pkh_script(0x55);
436+
auto mnstates = single_mn(payout);
437+
438+
uint256 prev_hash = raw256(0xD4);
439+
const uint32_t bits = 0x1b104be3u; // pinned oracle GBT nBits
440+
const uint32_t mtp = 1'700'000'000u;
441+
const uint32_t PINNED_VERSION = 0x20000004u; // BIP9 baseline + bit 2 set
442+
443+
// Injected version is echoed byte-for-byte — the seam adds no arithmetic.
444+
auto injected = build_embedded_workdata(
445+
H - 1, prev_hash, mnstates, mp,
446+
bits, mtp, DASH_PUBKEY_VER, DASH_P2SH_VER, PINNED_VERSION);
447+
EXPECT_EQ(injected.m_version, PINNED_VERSION);
448+
449+
// Deterministic: same fixed inputs -> identical version projection.
450+
auto injected2 = build_embedded_workdata(
451+
H - 1, prev_hash, mnstates, mp,
452+
bits, mtp, DASH_PUBKEY_VER, DASH_P2SH_VER, PINNED_VERSION);
453+
EXPECT_EQ(injected.m_version, injected2.m_version);
454+
455+
// Default arg preserves the prior hardcoded projection: omitting version
456+
// still yields the BIP9 "no signaling" baseline, so no caller is changed.
457+
auto baseline = build_embedded_workdata(
458+
H - 1, prev_hash, mnstates, mp,
459+
bits, mtp, DASH_PUBKEY_VER, DASH_P2SH_VER);
460+
EXPECT_EQ(baseline.m_version, 0x20000000u);
461+
462+
// The version seam is orthogonal to every other header field: injecting a
463+
// non-default version changes ONLY m_version, nothing else drifts.
464+
EXPECT_EQ(injected.m_height, baseline.m_height);
465+
EXPECT_EQ(injected.m_previous_block, baseline.m_previous_block);
466+
EXPECT_EQ(injected.m_bits, baseline.m_bits);
467+
EXPECT_EQ(injected.m_mintime, baseline.m_mintime);
468+
EXPECT_EQ(injected.m_coinbase_value, baseline.m_coinbase_value);
469+
EXPECT_EQ(injected.m_payment_amount, baseline.m_payment_amount);
470+
}

0 commit comments

Comments
 (0)