Log reason for non-standard transaction rejection

This commit is contained in:
Jeff Garzik 2013-06-05 14:52:06 -04:00 committed by Warren Togami
parent b018b7f25c
commit cb3076a3da
2 changed files with 32 additions and 11 deletions

View File

@ -373,37 +373,51 @@ bool CTxOut::IsDust() const
return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee);
}
bool CTransaction::IsStandard() const
bool CTransaction::IsStandard(string& strReason) const
{
if (nVersion > CTransaction::CURRENT_VERSION)
if (nVersion > CTransaction::CURRENT_VERSION) {
strReason = "version";
return false;
}
if (!IsFinal())
if (!IsFinal()) {
strReason = "not-final";
return false;
}
// 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_SIZE mitigates CPU exhaustion attacks.
unsigned int sz = this->GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz >= MAX_STANDARD_TX_SIZE)
if (sz >= MAX_STANDARD_TX_SIZE) {
strReason = "tx-size";
return false;
}
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
if (txin.scriptSig.size() > 500)
if (txin.scriptSig.size() > 500) {
strReason = "scriptsig-size";
return false;
if (!txin.scriptSig.IsPushOnly())
}
if (!txin.scriptSig.IsPushOnly()) {
strReason = "scriptsig-not-pushonly";
return false;
}
}
BOOST_FOREACH(const CTxOut& txout, vout) {
if (!::IsStandard(txout.scriptPubKey))
if (!::IsStandard(txout.scriptPubKey)) {
strReason = "scriptpubkey";
return false;
if (txout.IsDust())
}
if (txout.IsDust()) {
strReason = "dust";
return false;
}
}
return true;
}
@ -668,8 +682,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
if (!fTestNet && !tx.IsStandard())
return error("CTxMemPool::accept() : nonstandard transaction type");
string strNonStd;
if (!fTestNet && !tx.IsStandard(strNonStd))
return error("CTxMemPool::accept() : nonstandard transaction (%s)",
strNonStd.c_str());
// is it already in the memory pool?
uint256 hash = tx.GetHash();

View File

@ -559,7 +559,12 @@ public:
/** Check for standard transaction types
@return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
bool IsStandard() const;
bool IsStandard(std::string& strReason) const;
bool IsStandard() const
{
std::string strReason;
return IsStandard(strReason);
}
/** Check for standard transaction types
@param[in] mapInputs Map of previous transactions that have outputs we're spending