private void Sign(TransactionSigningContext ctx, TxIn input, ICoin coin, int n) { if (coin is StealthCoin) { var stealthCoin = (StealthCoin)coin; var scanKey = FindKey(ctx, stealthCoin.Address.ScanPubKey); if (scanKey == null) { throw new KeyNotFoundException("Scan key for decrypting StealthCoin not found"); } var spendKeys = stealthCoin.Address.SpendPubKeys.Select(p => FindKey(ctx, p)).Where(p => p != null).ToArray(); ctx.AdditionalKeys.AddRange(stealthCoin.Uncover(spendKeys, scanKey)); } if (PayToScriptHashTemplate.Instance.CheckScriptPubKey(coin.ScriptPubKey)) { var scriptCoin = (IScriptCoin)coin; var original = input.ScriptSig; input.ScriptSig = CreateScriptSig(ctx, input, n, scriptCoin.Redeem); if (original != input.ScriptSig) { input.ScriptSig = input.ScriptSig + Op.GetPushOp(scriptCoin.Redeem.ToBytes(true)); } } else { input.ScriptSig = CreateScriptSig(ctx, input, n, coin.ScriptPubKey); } }
public Transaction SignTransactionInPlace(Transaction transaction, SigHash sigHash) { TransactionSigningContext ctx = new TransactionSigningContext(this, transaction); ctx.SigHash = sigHash; foreach (var input in transaction.Inputs.AsIndexedInputs()) { var coin = FindSignableCoin(input.TxIn); if (coin != null) { Sign(ctx, coin, input); } } return(transaction); }
public Transaction SignTransactionInPlace(Transaction transaction, SigHash sigHash) { TransactionSigningContext ctx = new TransactionSigningContext(this, transaction); ctx.SigHash = sigHash; for (int i = 0; i < transaction.Inputs.Count; i++) { var txIn = transaction.Inputs[i]; var coin = FindSignableCoin(txIn); if (coin != null) { Sign(ctx, txIn, coin, i); } } return(transaction); }
private Key FindKey(TransactionSigningContext ctx, PubKey pubKey) { return(_Keys .Concat(ctx.AdditionalKeys) .FirstOrDefault(k => k.PubKey == pubKey)); }
private Key FindKey(TransactionSigningContext ctx, TxDestination id) { return(_Keys .Concat(ctx.AdditionalKeys) .FirstOrDefault(k => k.PubKey.Hash == id)); }
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"); }
public TransactionBuilderKeyRepository(TransactionBuilder txBuilder, TransactionSigningContext ctx) { _Ctx = ctx; _TxBuilder = txBuilder; }
private Key FindKey(TransactionSigningContext ctx, Script scriptPubKey) { var key = _Keys .Concat(ctx.AdditionalKeys) .FirstOrDefault(k => k.PubKey.ScriptPubKey == scriptPubKey || //P2PK k.PubKey.Hash.ScriptPubKey == scriptPubKey || //P2PKH k.PubKey.ScriptPubKey.Hash.ScriptPubKey == scriptPubKey || //P2PK P2SH k.PubKey.Hash.ScriptPubKey.Hash.ScriptPubKey == scriptPubKey); //P2PKH P2SH if(key == null && KeyFinder != null) { key = KeyFinder(scriptPubKey); } return key; }
private Script CreateScriptSig(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn) { var scriptPubKey = coin.GetScriptCode(); var keyRepo = new TransactionBuilderKeyRepository(this, ctx); var signer = new TransactionBuilderSigner(coin, ctx.SigHash, txIn); foreach(var extension in Extensions) { if(extension.CanGenerateScriptSig(scriptPubKey)) { return extension.GenerateScriptSig(scriptPubKey, keyRepo, signer); } } throw new NotSupportedException("Unsupported scriptPubKey"); }
private void Sign(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn) { var input = txIn.TxIn; if(coin is StealthCoin) { var stealthCoin = (StealthCoin)coin; var scanKey = FindKey(ctx, stealthCoin.Address.ScanPubKey.ScriptPubKey); if(scanKey == null) throw new KeyNotFoundException("Scan key for decrypting StealthCoin not found"); var spendKeys = stealthCoin.Address.SpendPubKeys.Select(p => FindKey(ctx, p.ScriptPubKey)).Where(p => p != null).ToArray(); ctx.AdditionalKeys.AddRange(stealthCoin.Uncover(spendKeys, scanKey)); var normalCoin = new Coin(coin.Outpoint, coin.TxOut); if(stealthCoin.Redeem != null) normalCoin = normalCoin.ToScriptCoin(stealthCoin.Redeem); coin = normalCoin; } var scriptSig = CreateScriptSig(ctx, coin, txIn); if(scriptSig == null) return; ScriptCoin scriptCoin = coin as ScriptCoin; Script signatures = null; if(coin.GetHashVersion() == HashVersion.Witness) { signatures = txIn.WitScript; if(scriptCoin != null) { if(scriptCoin.IsP2SH) txIn.ScriptSig = Script.Empty; if(scriptCoin.RedeemType == RedeemType.WitnessV0) signatures = RemoveRedeem(signatures); } } else { signatures = txIn.ScriptSig; if(scriptCoin != null && scriptCoin.RedeemType == RedeemType.P2SH) signatures = RemoveRedeem(signatures); } signatures = CombineScriptSigs(coin, scriptSig, signatures); if(coin.GetHashVersion() == HashVersion.Witness) { txIn.WitScript = signatures; if(scriptCoin != null) { if(scriptCoin.IsP2SH) txIn.ScriptSig = new Script(Op.GetPushOp(scriptCoin.GetP2SHRedeem().ToBytes(true))); if(scriptCoin.RedeemType == RedeemType.WitnessV0) txIn.WitScript = txIn.WitScript + new WitScript(Op.GetPushOp(scriptCoin.Redeem.ToBytes(true))); } } else { txIn.ScriptSig = signatures; if(scriptCoin != null && scriptCoin.RedeemType == RedeemType.P2SH) { txIn.ScriptSig = input.ScriptSig + Op.GetPushOp(scriptCoin.GetP2SHRedeem().ToBytes(true)); } } }
public Transaction SignTransactionInPlace(Transaction transaction, SigHash sigHash) { TransactionSigningContext ctx = new TransactionSigningContext(this, transaction); ctx.SigHash = sigHash; foreach(var input in transaction.Inputs.AsIndexedInputs()) { var coin = FindSignableCoin(input); if(coin != null) { Sign(ctx, coin, input); } } return transaction; }