mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-06-03 07:52:33 +02:00
Ability to ignore IsStandardTx rejection reasons
This commit is contained in:
parent
ccc3f45e09
commit
d5b82da92c
@ -67,6 +67,10 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
||||
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Note this must assign whichType even if returning false, in case
|
||||
* IsStandardTx ignores the "scriptpubkey" rejection.
|
||||
*/
|
||||
bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
@ -91,21 +95,36 @@ bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
|
||||
{
|
||||
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
||||
reason = "version";
|
||||
static inline bool MaybeReject_(std::string& out_reason, const std::string& reason, const std::string& reason_prefix, const ignore_rejects_type& ignore_rejects) {
|
||||
if (ignore_rejects.count(reason_prefix + reason)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
out_reason = reason_prefix + reason;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MaybeReject(reason) do { \
|
||||
if (MaybeReject_(out_reason, reason, reason_prefix, ignore_rejects)) { \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
|
||||
{
|
||||
const std::string reason_prefix;
|
||||
|
||||
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
||||
MaybeReject("version");
|
||||
}
|
||||
|
||||
// Extremely large transactions with lots of inputs can cost the network
|
||||
// almost as much to process as they cost the sender in fees, because
|
||||
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
||||
// to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
|
||||
unsigned int sz = GetTransactionWeight(tx);
|
||||
if (sz > MAX_STANDARD_TX_WEIGHT) {
|
||||
reason = "tx-size";
|
||||
return false;
|
||||
MaybeReject("tx-size");
|
||||
}
|
||||
|
||||
for (const CTxIn& txin : tx.vin)
|
||||
@ -119,12 +138,10 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
|
||||
// 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
|
||||
// is not considered standard.
|
||||
if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) {
|
||||
reason = "scriptsig-size";
|
||||
return false;
|
||||
MaybeReject("scriptsig-size");
|
||||
}
|
||||
if (!txin.scriptSig.IsPushOnly()) {
|
||||
reason = "scriptsig-not-pushonly";
|
||||
return false;
|
||||
MaybeReject("scriptsig-not-pushonly");
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,28 +149,28 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
|
||||
TxoutType whichType;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
|
||||
reason = "scriptpubkey";
|
||||
if (whichType == TxoutType::WITNESS_UNKNOWN) {
|
||||
reason += "-unknown-witnessversion";
|
||||
MaybeReject("scriptpubkey-unknown-witnessversion");
|
||||
} else {
|
||||
MaybeReject("scriptpubkey");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (whichType == TxoutType::NULL_DATA)
|
||||
if (whichType == TxoutType::NULL_DATA) {
|
||||
nDataOut++;
|
||||
continue;
|
||||
}
|
||||
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
|
||||
reason = "bare-multisig";
|
||||
return false;
|
||||
} else if (IsDust(txout, dust_relay_fee)) {
|
||||
reason = "dust";
|
||||
return false;
|
||||
MaybeReject("bare-multisig");
|
||||
}
|
||||
if (IsDust(txout, dust_relay_fee)) {
|
||||
MaybeReject("dust");
|
||||
}
|
||||
}
|
||||
|
||||
// only one OP_RETURN txout is permitted
|
||||
if (nDataOut > 1) {
|
||||
reason = "multi-op-return";
|
||||
return false;
|
||||
MaybeReject("multi-op-return");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -141,7 +141,7 @@ static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
|
||||
* Check for standard transaction types
|
||||
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
||||
*/
|
||||
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
|
||||
bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& out_reason, const ignore_rejects_type& ignore_rejects=empty_ignore_rejects);
|
||||
/**
|
||||
* Check for standard transaction types
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
|
@ -735,7 +735,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
|
||||
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||
std::string reason;
|
||||
if (m_pool.m_require_standard && !IsStandardTx(tx, m_pool.m_max_datacarrier_bytes, m_pool.m_permit_bare_multisig, m_pool.m_dust_relay_feerate, reason)) {
|
||||
if (m_pool.m_require_standard && !IsStandardTx(tx, m_pool.m_max_datacarrier_bytes, m_pool.m_permit_bare_multisig, m_pool.m_dust_relay_feerate, reason, ignore_rejects)) {
|
||||
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user