public ScriptTemplate FindTemplate() { return(StandardScripts.GetTemplateFromScriptPubKey(this)); }
public static bool IsStandardTransaction(Transaction tx) { if (tx.Version > Transaction.CURRENT_VERSION || tx.Version < 1) { return(false); } //// Treat non-final transactions as non-standard to prevent a specific type //// of double-spend attack, as well as DoS attacks. (if the transaction //// can't be mined, the attacker isn't expending resources broadcasting it) //// Basically we don't want to propagate transactions that can't included in //// the next block. //// //// However, IsFinalTx() is confusing... Without arguments, it uses //// chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height() //// is set to the value of nHeight in the block. However, when IsFinalTx() //// is called within CBlock::AcceptBlock(), the height of the block *being* //// evaluated is what is used. Thus if we want to know if a transaction can //// be part of the *next* block, we need to call IsFinalTx() with one more //// than chainActive.Height(). //// //// Timestamps on the other hand don't get any special treatment, because we //// can't know what timestamp the next block will have, and there aren't //// timestamp applications where it matters. //if (!IsFinalTx(tx, chainActive.Height() + 1)) { // reason = "non-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. int sz = tx.GetSerializedSize(); if (sz >= Transaction.MAX_STANDARD_TX_SIZE) { return(false); } foreach (TxIn txin in tx.Inputs) { // 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.Length > 500) { return(false); } if (!txin.ScriptSig.IsPushOnly) { return(false); } if (!txin.ScriptSig.HasCanonicalPushes) { return(false); } } uint nDataOut = 0; foreach (TxOut txout in tx.Outputs) { var template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey); if (template == null) { return(false); } if (template.Type == TxOutType.TX_NULL_DATA) { nDataOut++; } else if (txout.IsDust) { return(false); } } // only one OP_RETURN txout is permitted if (nDataOut > 1) { return(false); } return(true); }
public bool IsRelevantAndUpdate(Transaction tx) { if (tx == null) { throw new ArgumentNullException("tx"); } var hash = tx.GetHash(); bool fFound = false; // Match if the filter contains the hash of tx // for finding tx when they appear in a block if (isFull) { return(true); } if (isEmpty) { return(false); } if (Contains(hash)) { fFound = true; } for (uint i = 0; i < tx.Outputs.Count; i++) { TxOut txout = tx.Outputs[(int)i]; // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx // If this matches, also add the specific output that was matched. // This means clients don't have to update the filter themselves when a new relevant tx // is discovered in order to find spending transactions, which avoids round-tripping and race conditions. foreach (Op op in txout.ScriptPubKey.ToOps()) { if (op.PushData != null && op.PushData.Length != 0 && Contains(op.PushData)) { fFound = true; if ((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_ALL) { Insert(new OutPoint(hash, i)); } else if ((nFlags & (byte)BloomFlags.UPDATE_MASK) == (byte)BloomFlags.UPDATE_P2PUBKEY_ONLY) { var template = StandardScripts.GetTemplateFromScriptPubKey(txout.ScriptPubKey); if (template != null && (template.Type == TxOutType.TX_PUBKEY || template.Type == TxOutType.TX_MULTISIG)) { Insert(new OutPoint(hash, i)); } } break; } } } if (fFound) { return(true); } foreach (TxIn txin in tx.Inputs) { // Match if the filter contains an outpoint tx spends if (Contains(txin.PrevOut)) { return(true); } // Match if the filter contains any arbitrary script data element in any scriptSig in tx foreach (Op op in txin.ScriptSig.ToOps()) { if (op.PushData != null && op.PushData.Length != 0 && Contains(op.PushData)) { return(true); } } } return(false); }
public virtual ScriptTemplate GetTemplateFromScriptPubKey(Script script) { return(StandardScripts.GetTemplateFromScriptPubKey(script)); }