|
|
@ -373,38 +373,52 @@ bool CTxOut::IsDust() const |
|
|
|
return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee); |
|
|
|
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; |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!IsFinal()) |
|
|
|
if (!IsFinal()) { |
|
|
|
|
|
|
|
strReason = "not-final"; |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Extremely large transactions with lots of inputs can cost the network
|
|
|
|
// Extremely large transactions with lots of inputs can cost the network
|
|
|
|
// almost as much to process as they cost the sender in fees, because
|
|
|
|
// almost as much to process as they cost the sender in fees, because
|
|
|
|
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
|
|
|
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
|
|
|
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
|
|
|
|
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
|
|
|
|
unsigned int sz = this->GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); |
|
|
|
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; |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
BOOST_FOREACH(const CTxIn& txin, vin) |
|
|
|
BOOST_FOREACH(const CTxIn& txin, vin) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
|
|
|
|
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
|
|
|
|
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
|
|
|
|
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
|
|
|
|
// ~65-byte public keys, plus a few script ops.
|
|
|
|
// ~65-byte public keys, plus a few script ops.
|
|
|
|
if (txin.scriptSig.size() > 500) |
|
|
|
if (txin.scriptSig.size() > 500) { |
|
|
|
|
|
|
|
strReason = "scriptsig-size"; |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (!txin.scriptSig.IsPushOnly()) |
|
|
|
} |
|
|
|
|
|
|
|
if (!txin.scriptSig.IsPushOnly()) { |
|
|
|
|
|
|
|
strReason = "scriptsig-not-pushonly"; |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
BOOST_FOREACH(const CTxOut& txout, vout) { |
|
|
|
BOOST_FOREACH(const CTxOut& txout, vout) { |
|
|
|
if (!::IsStandard(txout.scriptPubKey)) |
|
|
|
if (!::IsStandard(txout.scriptPubKey)) { |
|
|
|
|
|
|
|
strReason = "scriptpubkey"; |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (txout.IsDust()) |
|
|
|
} |
|
|
|
|
|
|
|
if (txout.IsDust()) { |
|
|
|
|
|
|
|
strReason = "dust"; |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
return true; |
|
|
|
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"); |
|
|
|
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet"); |
|
|
|
|
|
|
|
|
|
|
|
// Rather not work on nonstandard transactions (unless -testnet)
|
|
|
|
// Rather not work on nonstandard transactions (unless -testnet)
|
|
|
|
if (!fTestNet && !tx.IsStandard()) |
|
|
|
string strNonStd; |
|
|
|
return error("CTxMemPool::accept() : nonstandard transaction type"); |
|
|
|
if (!fTestNet && !tx.IsStandard(strNonStd)) |
|
|
|
|
|
|
|
return error("CTxMemPool::accept() : nonstandard transaction (%s)", |
|
|
|
|
|
|
|
strNonStd.c_str()); |
|
|
|
|
|
|
|
|
|
|
|
// is it already in the memory pool?
|
|
|
|
// is it already in the memory pool?
|
|
|
|
uint256 hash = tx.GetHash(); |
|
|
|
uint256 hash = tx.GetHash(); |
|
|
|