Skip to content

Commit f3d8a37

Browse files
committed
Fix DigiDollar chained miner validation and functional regressions
Pass the mempool into BlockAssembler DigiDollar validation so chained DigiDollar transfers built on unconfirmed mempool ancestors are accepted during block assembly, matching mempool admission behavior instead of silently dropping valid descendants from candidate blocks. Add a focused miner regression that constructs a mint plus two chained DigiDollar transfers entirely from mempool state and asserts the assembled block includes the whole chain. Replace the old digidollar_transactions functional file with strict end-to-end coverage of real shipped RPC behavior, including mint confirmation, cross-node send accounting, exact-amount redemption, parameter validation, and oracle/collateral sanity checks. Update the oracle and protection assertions to match the current RPC schemas instead of stale placeholder fields. Also fix the Bug #11/#13 regression runner to call the correct unconfirmed blockheight test method so the suite actually exercises the intended coverage.
1 parent 5188782 commit f3d8a37

4 files changed

Lines changed: 232 additions & 704 deletions

File tree

src/node/miner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ bool BlockAssembler::ValidateDDForBlockInclusion(const CTransaction& tx, const C
195195
chainparams,
196196
&m_chainstate.CoinsTip(),
197197
false,
198-
txLookup
198+
txLookup,
199+
m_mempool
199200
);
200201

201202
TxValidationState tx_state;

src/test/miner_dd_validation_tests.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,21 @@ struct MinerDDValidationSetup : public TestChain100Setup {
144144
return MakeTransactionRef(tx);
145145
}
146146

147+
CTransactionRef BuildDDTransfer(const COutPoint& prevout, const XOnlyPubKey& recipient, CAmount dd_amount)
148+
{
149+
CMutableTransaction tx;
150+
tx.SetDigiDollarType(DD_TX_TRANSFER);
151+
tx.vin.emplace_back(prevout);
152+
tx.vout.emplace_back(0, DigiDollar::CreateDigiDollarP2TR(recipient, dd_amount));
153+
154+
CScript op_return = CScript() << OP_RETURN
155+
<< std::vector<unsigned char>{'D', 'D'}
156+
<< CScriptNum(2)
157+
<< CScriptNum(dd_amount);
158+
tx.vout.emplace_back(0, op_return);
159+
return MakeTransactionRef(tx);
160+
}
161+
147162
bool ValidateMintAtPrice(const CTransaction& tx, int next_height, CAmount oracle_price_micro_usd, std::string* reject_reason = nullptr) const
148163
{
149164
DigiDollar::ValidationContext ctx(next_height, oracle_price_micro_usd, 300, Params());
@@ -327,4 +342,48 @@ BOOST_FIXTURE_TEST_CASE(test_block_validity_retry, MinerDDValidationSetup)
327342
BOOST_CHECK_EQUAL(block_template->block.vtx.size(), 1U);
328343
}
329344

345+
BOOST_FIXTURE_TEST_CASE(block_includes_chained_dd_transfers_from_mempool, MinerDDValidationSetup)
346+
{
347+
constexpr CAmount kPrice = 50000;
348+
constexpr CAmount kDDAmount = 10000;
349+
constexpr CAmount kFee = 1000;
350+
351+
MockOracleManager::GetInstance().SetMockPrice(kPrice);
352+
353+
const int next_height = NextBlockHeight();
354+
const CAmount required = RequiredCollateralAt(kDDAmount, 30, next_height, kPrice);
355+
const COutPoint funding = ConfirmOpTrueFunding(required + kFee);
356+
const CTransactionRef mint = BuildDDMint(funding, required + kFee, required, kDDAmount, next_height, kFee);
357+
358+
std::string reject_reason;
359+
BOOST_REQUIRE(ValidateMintAtPrice(*mint, next_height, kPrice, &reject_reason));
360+
361+
CKey transfer1_key;
362+
transfer1_key.MakeNewKey(true);
363+
const XOnlyPubKey transfer1_xonly(transfer1_key.GetPubKey());
364+
365+
CKey transfer2_key;
366+
transfer2_key.MakeNewKey(true);
367+
const XOnlyPubKey transfer2_xonly(transfer2_key.GetPubKey());
368+
369+
const COutPoint mint_dd_out(mint->GetHash(), 1);
370+
const CTransactionRef transfer1 = BuildDDTransfer(mint_dd_out, transfer1_xonly, kDDAmount);
371+
const COutPoint transfer1_dd_out(transfer1->GetHash(), 0);
372+
const CTransactionRef transfer2 = BuildDDTransfer(transfer1_dd_out, transfer2_xonly, kDDAmount);
373+
374+
AddToMempool(mint, kFee);
375+
AddToMempool(transfer1, kFee);
376+
AddToMempool(transfer2, kFee);
377+
378+
BlockAssembler::Options options;
379+
options.blockMinFeeRate = CFeeRate(0);
380+
options.test_block_validity = false;
381+
382+
auto block_template = BuildTemplate(options);
383+
BOOST_REQUIRE(block_template);
384+
BOOST_CHECK(BlockHasTx(block_template->block, mint->GetHash()));
385+
BOOST_CHECK(BlockHasTx(block_template->block, transfer1->GetHash()));
386+
BOOST_CHECK(BlockHasTx(block_template->block, transfer2->GetHash()));
387+
}
388+
330389
BOOST_AUTO_TEST_SUITE_END()

test/functional/digidollar_bug11_bug13_regression.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def run_test(self):
320320
self.log.info("BUG #13: DD transaction blockheight tests")
321321
self.log.info("=" * 60)
322322
self.test_bug13_confirmed_tx_has_blockheight()
323-
self.test_bug13_unconfirmed_tx_has_blockheight()
323+
self.test_bug13_unconfirmed_tx_has_negative_blockheight()
324324
self.test_bug13_blockheight_matches_actual_block()
325325
self.test_bug13_multiple_confirmations()
326326

0 commit comments

Comments
 (0)