return ReadFromDisk(txdb, prevout, txindex);
}
-bool CTransaction::IsStandard() const
+bool CTransaction::IsStandard(string& strReason) const
{
if (nVersion > CTransaction::CURRENT_VERSION)
+ {
+ strReason = "version";
return false;
+ }
unsigned int nDataOut = 0;
txnouttype whichType;
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)
+ // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
+ // keys. (remember the 520 byte limit on redeemScript size) That works
+ // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624
+ // bytes of scriptSig, which we round off to 1650 bytes for some minor
+ // future-proofing. That's also enough to spend a 20-of-20
+ // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
+ // considered standard)
+ if (txin.scriptSig.size() > 1650)
+ {
+ strReason = "scriptsig-size";
return false;
+ }
if (!txin.scriptSig.IsPushOnly())
+ {
+ strReason = "scriptsig-not-pushonly";
return false;
+ }
if (!txin.scriptSig.HasCanonicalPushes()) {
+ strReason = "txin-scriptsig-not-canonicalpushes";
return false;
}
}
BOOST_FOREACH(const CTxOut& txout, vout) {
if (!::IsStandard(txout.scriptPubKey, whichType)) {
+ strReason = "scriptpubkey";
return false;
}
if (whichType == TX_NULL_DATA)
nDataOut++;
else {
if (txout.nValue == 0) {
+ strReason = "txout-value=0";
return false;
}
if (!txout.scriptPubKey.HasCanonicalPushes()) {
+ strReason = "txout-scriptsig-not-canonicalpushes";
return false;
}
}
// only one OP_RETURN txout is permitted
if (nDataOut > 1) {
+ strReason = "multi-op-return";
return false;
}
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());
// Do we already have it?
uint256 hash = tx.GetHash();