In d5c564a24f96ec384b2de68bf87e6eb3ad9239d2
related: the code could be simplified a bit (imo) by changing HasDust to GetDust, which would require to move it to policy.h
<details>
<summary>git diff on d5c564a24f</summary>
diff --git a/src/policy/ephemeral_policy.cpp b/src/policy/ephemeral_policy.cpp
index 6854822e35..6066d9b3ac 100644
--- a/src/policy/ephemeral_policy.cpp
+++ b/src/policy/ephemeral_policy.cpp
@@ -5,15 +5,10 @@
#include <policy/ephemeral_policy.h>
#include <policy/policy.h>
-bool HasDust(const CTransactionRef& tx, CFeeRate dust_relay_rate)
-{
- return std::any_of(tx->vout.cbegin(), tx->vout.cend(), [&](const auto& output) { return IsDust(output, dust_relay_rate); });
-}
-
bool CheckValidEphemeralTx(const CTransactionRef& tx, CFeeRate dust_relay_rate, CAmount base_fee, CAmount mod_fee, TxValidationState& state)
{
// We never want to give incentives to mine this transaction alone
- if ((base_fee != 0 || mod_fee != 0) && HasDust(tx, dust_relay_rate)) {
+ if ((base_fee != 0 || mod_fee != 0) && !GetDust(*tx, dust_relay_rate).empty()) {
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "dust", "tx with dust output must be 0-fee");
}
@@ -52,11 +47,8 @@ std::optional<Txid> CheckEphemeralSpends(const Package& package, CFeeRate dust_r
// Check for dust on parents
if (parent_ref) {
- for (uint32_t out_index = 0; out_index < parent_ref->vout.size(); out_index++) {
- const auto& tx_output = parent_ref->vout[out_index];
- if (IsDust(tx_output, dust_relay_rate)) {
- unspent_parent_dust.insert(COutPoint(parent_txid, out_index));
- }
+ for (const auto& out_index : GetDust(*parent_ref, dust_relay_rate)) {
+ unspent_parent_dust.insert(COutPoint{parent_txid, out_index});
}
}
diff --git a/src/policy/ephemeral_policy.h b/src/policy/ephemeral_policy.h
index 26140f9a02..98f40d38ff 100644
--- a/src/policy/ephemeral_policy.h
+++ b/src/policy/ephemeral_policy.h
@@ -34,9 +34,6 @@
* are the only way to bring fees.
*/
-/** Returns true if transaction contains dust */
-bool HasDust(const CTransactionRef& tx, CFeeRate dust_relay_rate);
-
/* All the following checks are only called if standardness rules are being applied. */
/** Must be called for each transaction once transaction fees are known.
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 21c35af5cc..ed33692823 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -67,6 +67,15 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}
+std::vector<uint32_t> GetDust(const CTransaction& tx, CFeeRate dust_relay_rate)
+{
+ std::vector<uint32_t> dust_outputs;
+ for (uint32_t i{0}; i < tx.vout.size(); ++i) {
+ if (IsDust(tx.vout[i], dust_relay_rate)) dust_outputs.push_back(i);
+ }
+ return dust_outputs;
+}
+
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
{
std::vector<std::vector<unsigned char> > vSolutions;
@@ -129,7 +138,6 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
}
unsigned int nDataOut = 0;
- unsigned int num_dust_outputs{0};
TxoutType whichType;
for (const CTxOut& txout : tx.vout) {
if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
@@ -142,13 +150,11 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
reason = "bare-multisig";
return false;
- } else if (IsDust(txout, dust_relay_fee)) {
- num_dust_outputs++;
}
}
// Only MAX_DUST_OUTPUTS_PER_TX dust is permitted(on otherwise valid ephemeral dust)
- if (num_dust_outputs > MAX_DUST_OUTPUTS_PER_TX) {
+ if (GetDust(tx, dust_relay_fee).size() > MAX_DUST_OUTPUTS_PER_TX) {
reason = "dust";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 0488f8dbee..9e36d3f610 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -129,6 +129,9 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
+/** Get the vout index numbers of all dust outputs */
+std::vector<uint32_t> GetDust(const CTransaction& tx, CFeeRate dust_relay_rate);
+
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
</details>
That said, the current code is fine too, and I suspect you'll find this too big of a change for a PR of this size that otherwise seems close to merge.