Example #1
0
        /// <summary>
        /// Sign the transaction with a private key
        /// <para>ScriptSigs should be filled with either previous scriptPubKeys or redeem script (for P2SH)</para>
        /// <para>For more complex scenario, use TransactionBuilder</para>
        /// </summary>
        /// <param name="secret"></param>
        public void Sign(Key key, bool assumeP2SH)
        {
            TransactionBuilder builder = new TransactionBuilder();

            builder.AddKeys(key);
            for (int i = 0; i < Inputs.Count; i++)
            {
                var txin = Inputs[i];
                if (Script.IsNullOrEmpty(txin.ScriptSig))
                {
                    throw new InvalidOperationException("ScriptSigs should be filled with either previous scriptPubKeys or redeem script (for P2SH)");
                }
                if (assumeP2SH)
                {
                    var p2shSig = PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(txin.ScriptSig);
                    if (p2shSig == null)
                    {
                        builder.AddCoins(new ScriptCoin(txin.PrevOut, new TxOut()
                        {
                            ScriptPubKey = txin.ScriptSig.PaymentScript,
                        }, txin.ScriptSig));
                    }
                    else
                    {
                        builder.AddCoins(new ScriptCoin(txin.PrevOut, new TxOut()
                        {
                            ScriptPubKey = p2shSig.RedeemScript.PaymentScript
                        }, p2shSig.RedeemScript));
                    }
                }
                else
                {
                    builder.AddCoins(new Coin(txin.PrevOut, new TxOut()
                    {
                        ScriptPubKey = txin.ScriptSig
                    }));
                }
            }
            builder.SignTransactionInPlace(this);
        }
Example #2
0
        /// <summary>
        /// Sign the transaction with a private key
        /// <para>ScriptSigs should be filled with either previous scriptPubKeys or redeem script (for P2SH)</para>
        /// <para>For more complex scenario, use TransactionBuilder</para>
        /// </summary>
        /// <param name="secret"></param>
        public void Sign(Key key, bool assumeP2SH)
        {
            List <Coin> coins = new List <Coin>();

            for (int i = 0; i < Inputs.Count; i++)
            {
                var txin = Inputs[i];
                if (Script.IsNullOrEmpty(txin.ScriptSig))
                {
                    throw new InvalidOperationException("ScriptSigs should be filled with either previous scriptPubKeys or redeem script (for P2SH)");
                }
                if (assumeP2SH)
                {
                    var p2shSig = PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(txin.ScriptSig);
                    if (p2shSig == null)
                    {
                        coins.Add(new ScriptCoin(txin.PrevOut, new TxOut()
                        {
                            ScriptPubKey = txin.ScriptSig.PaymentScript,
                        }, txin.ScriptSig));
                    }
                    else
                    {
                        coins.Add(new ScriptCoin(txin.PrevOut, new TxOut()
                        {
                            ScriptPubKey = p2shSig.RedeemScript.PaymentScript
                        }, p2shSig.RedeemScript));
                    }
                }
                else
                {
                    coins.Add(new Coin(txin.PrevOut, new TxOut()
                    {
                        ScriptPubKey = txin.ScriptSig
                    }));
                }
            }
            Sign(key, coins.ToArray());
        }
        private Script CreateScriptSig(TransactionSigningContext ctx, TxIn input, int n, Script scriptPubKey)
        {
            var originalScriptSig = input.ScriptSig;

            input.ScriptSig = scriptPubKey;

            var pubKeyHashParams = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);

            if (pubKeyHashParams != null)
            {
                var key = FindKey(ctx, pubKeyHashParams);
                if (key == null)
                {
                    return(originalScriptSig);
                }
                var hash = input.ScriptSig.SignatureHash(ctx.Transaction, n, ctx.SigHash);
                var sig  = key.Sign(hash);
                return(PayToPubkeyHashTemplate.Instance.GenerateScriptSig(new TransactionSignature(sig, ctx.SigHash), key.PubKey));
            }

            var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);

            if (multiSigParams != null)
            {
                var alreadySigned = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(originalScriptSig);
                if (alreadySigned == null && !Script.IsNullOrEmpty(originalScriptSig))                //Maybe a P2SH
                {
                    var ops = originalScriptSig.ToOps().ToList();
                    ops.RemoveAt(ops.Count - 1);
                    alreadySigned = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(new Script(ops));
                }
                List <TransactionSignature> signatures = new List <TransactionSignature>();
                if (alreadySigned != null)
                {
                    signatures.AddRange(alreadySigned);
                }
                var keys =
                    multiSigParams
                    .PubKeys
                    .Select(p => FindKey(ctx, p))
                    .ToArray();

                int sigCount = signatures.Where(s => s != TransactionSignature.Empty && s != null).Count();
                for (int i = 0; i < keys.Length; i++)
                {
                    if (sigCount == multiSigParams.SignatureCount)
                    {
                        break;
                    }

                    if (i >= signatures.Count)
                    {
                        signatures.Add(null);
                    }
                    if (keys[i] != null)
                    {
                        var hash = input.ScriptSig.SignatureHash(ctx.Transaction, n, ctx.SigHash);
                        var sig  = keys[i].Sign(hash);
                        signatures[i] = new TransactionSignature(sig, ctx.SigHash);
                        sigCount++;
                    }
                }

                IEnumerable <TransactionSignature> sigs = signatures;
                if (sigCount == multiSigParams.SignatureCount)
                {
                    sigs = sigs.Where(s => s != TransactionSignature.Empty && s != null);
                }

                return(PayToMultiSigTemplate.Instance.GenerateScriptSig(sigs));
            }

            var pubKeyParams = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey);

            if (pubKeyParams != null)
            {
                var key = FindKey(ctx, pubKeyParams);
                if (key == null)
                {
                    return(originalScriptSig);
                }
                var hash = input.ScriptSig.SignatureHash(ctx.Transaction, n, ctx.SigHash);
                var sig  = key.Sign(hash);
                return(PayToPubkeyTemplate.Instance.GenerateScriptSig(new TransactionSignature(sig, ctx.SigHash)));
            }

            throw new NotSupportedException("Unsupported scriptPubKey");
        }