Beispiel #1
0
        private static Script CombineSignatures(Script scriptPubKey, TransactionChecker checker, byte[][] sigs1, byte[][] sigs2, HashVersion hashVersion)
        {
            var template = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey);

            if (template is PayToWitPubKeyHashTemplate)
            {
                scriptPubKey = new KeyId(scriptPubKey.ToBytes(true).SafeSubarray(1, 20)).ScriptPubKey;
                template     = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey);
            }
            if (template == null || template is TxNullDataTemplate)
            {
                return(PushAll(Max(sigs1, sigs2)));
            }

            if (template is PayToPubkeyTemplate || template is PayToPubkeyHashTemplate)
            {
                if (sigs1.Length == 0 || sigs1[0].Length == 0)
                {
                    return(PushAll(sigs2));
                }
                else
                {
                    return(PushAll(sigs1));
                }
            }
            if (template is PayToScriptHashTemplate || template is PayToWitTemplate)
            {
                if (sigs1.Length == 0 || sigs1[sigs1.Length - 1].Length == 0)
                {
                    return(PushAll(sigs2));
                }

                if (sigs2.Length == 0 || sigs2[sigs2.Length - 1].Length == 0)
                {
                    return(PushAll(sigs1));
                }

                var redeemBytes = sigs1[sigs1.Length - 1];
                var redeem      = new Script(redeemBytes);
                sigs1 = sigs1.Take(sigs1.Length - 1).ToArray();
                sigs2 = sigs2.Take(sigs2.Length - 1).ToArray();
                Script result = CombineSignatures(redeem, checker, sigs1, sigs2, hashVersion);
                result += Op.GetPushOp(redeemBytes);
                return(result);
            }

            if (template is PayToMultiSigTemplate)
            {
                return(CombineMultisig(scriptPubKey, checker, sigs1, sigs2, hashVersion));
            }

            return(null);
        }
Beispiel #2
0
        private static Script CombineSignatures(Script scriptPubKey, Transaction transaction, int n, byte[][] sigs1, byte[][] sigs2)
        {
            var template = StandardScripts.GetTemplateFromScriptPubKey(scriptPubKey);

            if (template == null || template is TxNullDataTemplate)
            {
                return(PushAll(Max(sigs1, sigs2)));
            }

            if (template is PayToPubkeyTemplate || template is PayToPubkeyHashTemplate)
            {
                if (sigs1.Length == 0 || sigs1[0].Length == 0)
                {
                    return(PushAll(sigs2));
                }
                else
                {
                    return(PushAll(sigs1));
                }
            }

            if (template is PayToScriptHashTemplate)
            {
                if (sigs1.Length == 0 || sigs1[sigs1.Length - 1].Length == 0)
                {
                    return(PushAll(sigs2));
                }
                else if (sigs2.Length == 0 || sigs2[sigs2.Length - 1].Length == 0)
                {
                    return(PushAll(sigs1));
                }
                else
                {
                    var redeemBytes = sigs1[sigs1.Length - 1];
                    var redeem      = new Script(redeemBytes);
                    sigs1 = sigs1.Take(sigs1.Length - 1).ToArray();
                    sigs2 = sigs2.Take(sigs2.Length - 1).ToArray();
                    Script result = CombineSignatures(redeem, transaction, n, sigs1, sigs2);
                    result += Op.GetPushOp(redeemBytes);
                    return(result);
                }
            }

            if (template is PayToMultiSigTemplate)
            {
                return(CombineMultisig(scriptPubKey, transaction, n, sigs1, sigs2));
            }

            throw new NotSupportedException("An impossible thing happen !");
        }
Beispiel #3
0
        public override bool CheckScriptSig(Script scriptSig, Script scriptPubKey)
        {
            var ops = scriptSig.ToOps().ToArray();

            if (ops.Length == 0)
            {
                return(false);
            }
            if (!scriptSig.IsPushOnly)
            {
                return(false);
            }
            if (!VerifyRedeemScript)
            {
                return(true);
            }
            var redeemScript = new Script(ops.Last().PushData);
            var template     = StandardScripts.GetTemplateFromScriptPubKey(redeemScript);

            return(template != null && template.Type != TxOutType.TX_SCRIPTHASH);
        }
Beispiel #4
0
        protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
        {
            var ops = scriptSigOps;

            if (ops.Length == 0)
            {
                return(false);
            }
            if (!scriptSig.IsPushOnly)
            {
                return(false);
            }
            if (!VerifyRedeemScript)
            {
                return(true);
            }
            var redeemScript = new Script(ops[ops.Length - 1].PushData);
            var template     = StandardScripts.GetTemplateFromScriptPubKey(redeemScript);

            return(template != null && template.Type != TxOutType.TX_SCRIPTHASH);
        }
Beispiel #5
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 #6
0
 public ScriptTemplate FindTemplate()
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(this));
 }
 public virtual bool AreInputsStandard(Network network, Transaction tx, CoinsView coinsView)
 {
     return(StandardScripts.AreInputsStandard(network, tx, coinsView));
 }
 public virtual bool IsStandardScriptPubKey(Network network, Script scriptPubKey)
 {
     return(StandardScripts.IsStandardScriptPubKey(network, scriptPubKey));
 }
 public virtual ScriptTemplate GetTemplateFromScriptPubKey(Script script)
 {
     return(StandardScripts.GetTemplateFromScriptPubKey(script));
 }
 public virtual bool AreOutputsStandard(Network network, Transaction tx)
 {
     return(StandardScripts.AreOutputsStandard(network, tx));
 }
 public virtual bool IsStandardTransaction(Transaction tx, Network network)
 {
     return(StandardScripts.IsStandardTransaction(tx, network));
 }
 /// <summary>
 ///     Registers a new standard script template if it does not exist yet based on <see cref="ScriptTemplate.Type" />.
 /// </summary>
 /// <param name="scriptTemplate">The standard script template to register.</param>
 public virtual void RegisterStandardScriptTemplate(ScriptTemplate scriptTemplate)
 {
     StandardScripts.RegisterStandardScriptTemplate(scriptTemplate);
 }
Beispiel #13
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);
        }