Beispiel #1
0
 public ScriptTemplate FindTemplate()
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(this));
 }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 public virtual ScriptTemplate GetTemplateFromScriptPubKey(Script script)
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(script));
 }