|
|
|
@ -15,6 +15,43 @@
|
|
|
|
|
|
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
|
|
|
|
|
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
|
|
|
|
|
{
|
|
|
|
|
// "Dust" is defined in terms of dustRelayFee,
|
|
|
|
|
// which has units satoshis-per-kilobyte.
|
|
|
|
|
// If you'd pay more than 1/3 in fees
|
|
|
|
|
// to spend something, then we consider it dust.
|
|
|
|
|
// A typical spendable non-segwit txout is 34 bytes big, and will
|
|
|
|
|
// need a CTxIn of at least 148 bytes to spend:
|
|
|
|
|
// so dust is a spendable txout less than
|
|
|
|
|
// 546*dustRelayFee/1000 (in satoshis).
|
|
|
|
|
// A typical spendable segwit txout is 31 bytes big, and will
|
|
|
|
|
// need a CTxIn of at least 67 bytes to spend:
|
|
|
|
|
// so dust is a spendable txout less than
|
|
|
|
|
// 294*dustRelayFee/1000 (in satoshis).
|
|
|
|
|
if (txout.scriptPubKey.IsUnspendable())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
|
|
|
|
|
int witnessversion = 0;
|
|
|
|
|
std::vector<unsigned char> witnessprogram;
|
|
|
|
|
|
|
|
|
|
if (txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
|
|
|
|
// sum the sizes of the parts of a transaction input
|
|
|
|
|
// with 75% segwit discount applied to the script size.
|
|
|
|
|
nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
|
|
|
|
|
} else {
|
|
|
|
|
nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 3 * dustRelayFee.GetFee(nSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee)
|
|
|
|
|
{
|
|
|
|
|
return (txout.nValue < GetDustThreshold(txout, dustRelayFee));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check transaction inputs to mitigate two
|
|
|
|
|
* potential denial-of-service attacks:
|
|
|
|
@ -106,7 +143,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
|
|
|
|
|
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
|
|
|
|
|
reason = "bare-multisig";
|
|
|
|
|
return false;
|
|
|
|
|
} else if (txout.IsDust(dustRelayFee)) {
|
|
|
|
|
} else if (IsDust(txout, ::dustRelayFee)) {
|
|
|
|
|
reason = "dust";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|