19#include <unordered_set>
26 if ((base_fee != 0 || mod_fee != 0) && !
GetDust(tx, dust_relay_rate).empty()) {
35 if (!
Assume(std::ranges::all_of(package, [](
const auto& tx){
return tx !=
nullptr;}))) {
40 std::map<Txid, CTransactionRef> map_txid_ref;
41 for (
const auto& tx : package) {
42 map_txid_ref[tx->GetHash()] = tx;
45 for (
const auto& tx : package) {
46 std::unordered_set<Txid, SaltedTxidHasher> processed_parent_set;
47 std::unordered_set<COutPoint, SaltedOutpointHasher> unspent_parent_dust;
49 for (
const auto& tx_input : tx->vin) {
50 const Txid& parent_txid{tx_input.prevout.hash};
52 if (processed_parent_set.contains(parent_txid))
continue;
56 if (
auto it = map_txid_ref.find(parent_txid); it != map_txid_ref.end()) {
57 parent_ref = it->second;
59 parent_ref = tx_pool.
get(parent_txid);
64 for (uint32_t out_index = 0; out_index < parent_ref->vout.size(); out_index++) {
65 const auto& tx_output = parent_ref->vout[out_index];
66 if (
IsDust(tx_output, dust_relay_rate)) {
67 unspent_parent_dust.insert(
COutPoint(parent_txid, out_index));
72 processed_parent_set.insert(parent_txid);
75 if (unspent_parent_dust.empty()) {
81 for (
const auto& tx_input : tx->vin) {
82 unspent_parent_dust.erase(tx_input.prevout);
85 if (!unspent_parent_dust.empty()) {
86 out_child_txid = tx->GetHash();
88 strprintf(
"tx %s did not spend parent's ephemeral dust", out_child_txid.
ToString()));
int64_t CAmount
Amount in satoshis (Can be negative)
#define Assume(val)
Assume is the identity function.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
An outpoint - a combination of a transaction hash and an index n into its vout.
The basic transaction that is broadcasted on the network and contained in blocks.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
CTransactionRef get(const uint256 &hash) const
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
std::string ToString() const
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
bool CheckEphemeralSpends(const Package &package, CFeeRate dust_relay_rate, const CTxMemPool &tx_pool, TxValidationState &out_child_state, Txid &out_child_txid)
Must be called for each transaction(package) if any dust is in the package.
bool PreCheckEphemeralTx(const CTransaction &tx, CFeeRate dust_relay_rate, CAmount base_fee, CAmount mod_fee, TxValidationState &state)
These utility functions ensure that ephemeral dust is safely created and spent without unduly risking...
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
std::vector< uint32_t > GetDust(const CTransaction &tx, CFeeRate dust_relay_rate)
Get the vout index numbers of all dust outputs.
std::shared_ptr< const CTransaction > CTransactionRef