/// <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); }
/// <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"); }