protected override bool CheckScriptSigCore(Network network, Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { if (!scriptSig.IsPushOnly) { return(false); } if (scriptSigOps[0].Code != OpcodeType.OP_0) { return(false); } if (scriptSigOps.Length == 1) { return(false); } if (!scriptSigOps.Skip(1).All(s => TransactionSignature.ValidLength(s.PushData.Length) || s.Code == OpcodeType.OP_0)) { return(false); } if (scriptPubKeyOps != null) { if (!CheckScriptPubKeyCore(scriptPubKey, scriptPubKeyOps)) { return(false); } int?sigCountExpected = scriptPubKeyOps[0].GetInt(); if (sigCountExpected == null) { return(false); } return(sigCountExpected == scriptSigOps.Length + 1); } return(true); }
public override Script GenerateScriptSig(Script scriptPubKey, IKeyRepository keyRepo, ISigner signer) { var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey); TransactionSignature[] signatures = new TransactionSignature[multiSigParams.PubKeys.Length]; var keys = multiSigParams .PubKeys .Select(p => keyRepo.FindKey(p.ScriptPubKey)) .ToArray(); int sigCount = 0; for(int i = 0 ; i < keys.Length ; i++) { if(sigCount == multiSigParams.SignatureCount) break; if(keys[i] != null) { var sig = signer.Sign(keys[i]); signatures[i] = sig; sigCount++; } } IEnumerable<TransactionSignature> sigs = signatures; if(sigCount == multiSigParams.SignatureCount) { sigs = sigs.Where(s => s != TransactionSignature.Empty && s != null); } return PayToMultiSigTemplate.Instance.GenerateScriptSig(sigs); }
public static TransactionSignature[] ExtractScriptSigParameters(Script scriptSig) { var ops = scriptSig.ToOps().ToArray(); if (ops.Length == 3) { return(PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(scriptSig)); } else if (ops.Length == 1) { var sig = new TransactionSignature[1]; try { if (ops[0].Code != OpcodeType.OP_0) { sig[0] = new TransactionSignature(ops[0].PushData); } } catch { return(null); } return(sig); } else { return(null); } }
private TransactionSignature MakeHighS(TransactionSignature sig) { var curveOrder = new NBitcoin.BouncyCastle.Math.BigInteger("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10); var ecdsa = new ECDSASignature(sig.Signature.R, sig.Signature.S.Negate().Mod(curveOrder)); return(new TransactionSignature(ecdsa, sig.SigHash)); }
public override void MergePartialSignatures(InputSigningContext inputSigningContext) { if (inputSigningContext.OriginalTxIn is null || inputSigningContext.TransactionContext.Transaction is null) { return; } var scriptSig = inputSigningContext.OriginalTxIn.ScriptSig; var witScript = inputSigningContext.OriginalTxIn.WitScript; var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(inputSigningContext.Coin.GetScriptCode()); var txIn = inputSigningContext.Input; var scriptPubKey = inputSigningContext.Coin.GetScriptCode(); var sigs = new TransactionSignature[multiSigParams.PubKeys.Length]; int sigCount = 0; for (int i = 0; i < multiSigParams.PubKeys.Length; i++) { if (txIn.PartialSigs.TryGetValue(multiSigParams.PubKeys[i], out sigs[i])) { sigCount++; } } if (sigCount >= multiSigParams.SignatureCount) { return; // We have all signatures already, no need merging here, finalize will take care of it. } List <Op> ops = new List <Op>(); ops.Add(OpcodeType.OP_0); for (int i = 0; i < multiSigParams.PubKeys.Length; i++) { if (sigs[i] is TransactionSignature sig) { ops.Add(Op.GetPushOp(sig.ToBytes())); } else { ops.Add(OpcodeType.OP_0); } } if (txIn.WitnessScript is Script s) { ops.Add(Op.GetPushOp(s.ToBytes())); inputSigningContext.OriginalTxIn.WitScript = new WitScript(ops.ToArray()); if (txIn.RedeemScript is Script p2sh) { inputSigningContext.OriginalTxIn.ScriptSig = new Script(Op.GetPushOp(p2sh.ToBytes())); } } else if (txIn.RedeemScript is Script s2) { ops.Add(Op.GetPushOp(s2.ToBytes())); inputSigningContext.OriginalTxIn.ScriptSig = new Script(ops.ToArray()); } else { inputSigningContext.OriginalTxIn.ScriptSig = new Script(ops.ToArray()); } }
private Transaction BuildSignedCloseTransaction(LocalChannel channel, TransactionSignature remoteClosingSignature, ulong feeSatoshi) { var builder = new CloseChannelTransactionBuilder(channel, _networkParameters); builder.FeeSatoshi = feeSatoshi; return(builder.BuildWithSignatures(remoteClosingSignature)); }
public override Script GenerateScriptSig(Network network, Script scriptPubKey, IKeyRepository keyRepo, ISigner signer) { var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey); var signatures = new TransactionSignature[multiSigParams.PubKeys.Length]; var keys = multiSigParams .PubKeys .Select(p => keyRepo.FindKey(p.ScriptPubKey)) .ToArray(); var sigCount = 0; for (var i = 0; i < keys.Length; i++) { if (sigCount == multiSigParams.SignatureCount) { break; } if (keys[i] != null) { var sig = signer.Sign(keys[i]); signatures[i] = sig; sigCount++; } } IEnumerable <TransactionSignature> sigs = signatures; if (sigCount == multiSigParams.SignatureCount) { sigs = sigs.Where(s => s != TransactionSignature.Empty && s != null); } return(PayToMultiSigTemplate.Instance.GenerateScriptSig(sigs)); }
public override Script CombineScriptSig(Script scriptPubKey, Script a, Script b) { var para = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey); // Combine all the signatures we've got: var aSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(a); if(aSigs == null) return b; var bSigs = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(b); if(bSigs == null) return a; int pubkeyCount = 0; TransactionSignature[] sigs = new TransactionSignature[para.PubKeys.Length]; for(int i = 0 ; i < para.PubKeys.Length ; i++) { var aSig = i < aSigs.Length ? aSigs[i] : null; var bSig = i < bSigs.Length ? bSigs[i] : null; var sig = aSig ?? bSig; if(sig != null) { sigs[pubkeyCount] = sig; pubkeyCount++; } if(pubkeyCount == para.SignatureCount) break; } if(pubkeyCount == para.SignatureCount) sigs = sigs.Where(s => s != null && s != TransactionSignature.Empty).ToArray(); return PayToMultiSigTemplate.Instance.GenerateScriptSig(sigs); }
public IActionResult GiveEscapeKey( [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))] ClassicTumblerParameters tumblerId, int cycleId, string channelId, [FromBody] TransactionSignature clientSignature) { if (tumblerId == null) { throw new ArgumentNullException("tumblerId"); } var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase); if (session.Status != SolverServerStates.WaitingEscape) { return(BadRequest("invalid-state")); } var fee = Services.FeeService.GetFeeRate(); try { var cashout = Services.WalletService.GenerateAddress(); var tx = session.GetSignedEscapeTransaction(clientSignature, fee, cashout.ScriptPubKey); var correlation = GetCorrelation(session); Tracker.AddressCreated(cycleId, TransactionType.ClientEscape, cashout.ScriptPubKey, correlation); Tracker.TransactionCreated(cycleId, TransactionType.ClientEscape, tx.GetHash(), correlation); Services.BroadcastService.Broadcast(tx); } catch (PuzzleException ex) { return(BadRequest(ex.Message)); } return(Ok()); }
public Transaction GetSignedEscapeTransaction(TransactionSignature clientSignature, Script cashout) { AssertState(SolverServerStates.WaitingEscape); var escapeTx = GetUnsignedOfferTransaction(); escapeTx.Outputs[0].ScriptPubKey = cashout; var clientKey = AssertValidSignature(clientSignature, escapeTx); TransactionBuilder builder = new TransactionBuilder(); builder.StandardTransactionPolicy.CheckFee = false; builder.Extensions.Add(new EscrowBuilderExtension()); builder.AddCoins(InternalState.EscrowedCoin); builder.AddKnownSignature(clientKey, clientSignature); //This add the known signature if correct SigHash builder.SignTransactionInPlace(escapeTx, SigHash.None | SigHash.AnyoneCanPay); //This sign SigHash.All builder.AddKeys(InternalState.EscrowKey); builder.SignTransactionInPlace(escapeTx); if (!builder.Verify(escapeTx)) { throw new PuzzleException("invalid-tumbler-signature"); } return(escapeTx); }
/// <summary> /// Creates a scriptSig that can redeem a pay-to-pubkey output. /// If given signature is null, incomplete scriptSig will be created with OP_0 instead of signature /// </summary> public static Script CreateInputScript(TransactionSignature signature) { byte[] sigBytes = signature != null?signature.EncodeToBitcoin() : new byte[] { }; return(new ScriptBuilder().Data(sigBytes).Build()); }
public override void Sign(InputSigningContext inputSigningContext, IKeyRepository keyRepository, ISigner signer) { var scriptCode = inputSigningContext.Coin.GetScriptCode(); var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptCode); TransactionSignature?[] signatures = new TransactionSignature[multiSigParams.PubKeys.Length]; var keys = multiSigParams.PubKeys; int sigcount = 0; for (int i = 0; i < keys.Length && sigcount < multiSigParams.SignatureCount; i++) { var sig = signer.Sign(keys[i]) as TransactionSignature; signatures[i] = sig; if (sig != null) { sigcount++; } } for (int i = 0; i < keys.Length; i++) { var sig = signatures[i]; var key = keys[i]; if (key is PubKey && sig is TransactionSignature s && s != TransactionSignature.Empty) { inputSigningContext.Input.PartialSigs.TryAdd(key, sig); } } }
public TrustedBroadcastRequest FulfillOffer( TransactionSignature clientSignature, Script cashout, FeeRate feeRate) { if (clientSignature == null) { throw new ArgumentNullException(nameof(clientSignature)); } if (feeRate == null) { throw new ArgumentNullException(nameof(feeRate)); } AssertState(SolverServerStates.WaitingFulfillment); Script offerScript = GetOfferScript(); var offer = GetUnsignedOfferTransaction(); PubKey clientKey = AssertValidSignature(clientSignature, offer); TransactionBuilder builder = new TransactionBuilder(); builder.StandardTransactionPolicy.CheckFee = false; builder.Extensions.Add(new EscrowBuilderExtension()); builder.AddCoins(InternalState.EscrowedCoin); builder.AddKeys(InternalState.EscrowKey); builder.AddKnownSignature(clientKey, clientSignature); builder.SignTransactionInPlace(offer); if (!builder.Verify(offer)) { throw new PuzzleException("invalid-tumbler-signature"); } var offerCoin = offer.Outputs.AsCoins().First().ToScriptCoin(offerScript); var solutions = InternalState.SolvedPuzzles.Select(s => s.SolutionKey).ToArray(); Transaction fulfill = new Transaction(); fulfill.Inputs.Add(new TxIn(offerCoin.Outpoint)); fulfill.Outputs.Add(new TxOut(offerCoin.Amount, cashout)); var fulfillScript = SolverScriptBuilder.CreateFulfillScript(NBitcoin.BuilderExtensions.BuilderExtension.DummySignature, solutions); fulfill.Inputs[0].ScriptSig = fulfillScript + Op.GetPushOp(offerCoin.Redeem.ToBytes()); fulfill.Outputs[0].Value -= feeRate.GetFee(fulfill.GetVirtualSize()); var signature = fulfill.Inputs.AsIndexedInputs().First().Sign(InternalState.FulfillKey, offerCoin, SigHash.All); fulfillScript = SolverScriptBuilder.CreateFulfillScript(signature, solutions); fulfill.Inputs[0].ScriptSig = fulfillScript + Op.GetPushOp(offerCoin.Redeem.ToBytes()); InternalState.OfferClientSignature = clientSignature; InternalState.Status = SolverServerStates.WaitingEscape; return(new TrustedBroadcastRequest { Key = InternalState.FulfillKey, PreviousScriptPubKey = offerCoin.ScriptPubKey, Transaction = fulfill }); }
public static bool TryParse(string str, out PartialSignature?sig) { if (str == null) { throw new ArgumentNullException(nameof(str)); } sig = null; try { var bytes = Encoders.Hex.DecodeData(str); if (bytes.Length < 2 + 33 + 1 || bytes[0] != 0x22 || bytes[1] != 0x02) { return(false); } var pk = new NBitcoin.PubKey(bytes.AsSpan().Slice(2, 33).ToArray()); var siglen = bytes[2 + 33]; if (siglen < 75 && bytes.Length != 2 + 33 + 1 + siglen) { return(false); } var sigBytes = bytes.AsSpan().Slice(2 + 33 + 1).ToArray(); if (!TransactionSignature.IsValid(sigBytes)) { return(false); } var s = new TransactionSignature(sigBytes); sig = new PartialSignature(pk, s); return(true); } catch { return(false); } }
public IActionResult FulfillOffer(int cycleId, string channelId, [FromBody] TransactionSignature clientSignature) { var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase); var feeRate = Services.FeeService.GetFeeRate(); if (session.Status != SolverServerStates.WaitingFulfillment) { return(BadRequest("invalid-state")); } try { var cycle = Parameters.CycleGenerator.GetCycle(cycleId); var cashout = Services.WalletService.GenerateAddress($"Cycle {cycle.Start} Tumbler Cashout"); var fulfill = session.FulfillOffer(clientSignature, cashout.ScriptPubKey, feeRate); fulfill.BroadcastAt = new LockTime(cycle.GetPeriods().Payment.End - 1); Repository.Save(cycle.Start, session); var signedOffer = session.GetSignedOfferTransaction(); signedOffer.BroadcastAt = fulfill.BroadcastAt - 1; Services.TrustedBroadcastService.Broadcast($"Cycle {cycle.Start} Client Offer Transaction (planned for: {signedOffer.BroadcastAt})", signedOffer); Services.TrustedBroadcastService.Broadcast($"Cycle {cycle.Start} Tumbler Fulfillment Transaction (planned for: {fulfill.BroadcastAt})", fulfill); return(Json(session.GetSolutionKeys())); } catch (PuzzleException) { return(BadRequest("invalid-offer")); } }
protected override bool CheckScriptSigCore(Network network, Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { if (!scriptSig.IsPushOnly) { return(false); } if (scriptSigOps[0].Code != OpcodeType.OP_0) { return(false); } if (scriptSigOps.Length == 1) { return(false); } if (!scriptSigOps.Skip(1).All(s => TransactionSignature.ValidLength(s.PushData.Length) || s.Code == OpcodeType.OP_0)) { return(false); } if (scriptPubKeyOps != null) { if (!CheckScriptPubKeyCore(scriptPubKey, scriptPubKeyOps)) { return(false); } (PubKey[] pubKeys, int sigCountExpected) = ((StraxBaseNetwork)network).Federations.GetFederation(scriptPubKeyOps[0].PushData).GetFederationDetails(); return(sigCountExpected == scriptSigOps.Length + 1); } return(true); }
/// <summary> /// Generates the scriptSig. /// </summary> /// <param name="signature">The transaction signature. For unsigned inputs this can be <c>null</c> in which case it is encoded as an <c>OP_0</c>.</param> /// <param name="coldPubKey">A flag indicating whether the cold wallet versus the hot wallet is signing.</param> /// <param name="publicKey">The cold or hot wallet public key.</param> /// <returns>The scriptSig.</returns> public Script GenerateScriptSig(TransactionSignature signature, bool coldPubKey, PubKey publicKey) { return(new Script( Op.GetPushOp(signature.ToBytes()), coldPubKey ? OpcodeType.OP_0 : OpcodeType.OP_1, Op.GetPushOp(publicKey.ToBytes()) )); }
protected override bool CheckScriptSigCore(Network network, Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { Op[] ops = scriptSigOps; if (ops.Length != 1) { return(false); } return(ops[0].PushData != null && TransactionSignature.IsValid(network, ops[0].PushData)); }
public async Task <Transaction> ReceiveAsync(ScriptCoin escrowedCoin, TransactionSignature clientSignature, Key escrowKey, FeeRate feeRate) { _ReceiveBatch.FeeRate = feeRate; return(await _ReceiveBatch.WaitTransactionAsync(new ClientEscapeData() { ClientSignature = clientSignature, EscrowedCoin = escrowedCoin, EscrowKey = escrowKey }).ConfigureAwait(false)); }
public string Signature() { PayToMultiSigTemplateParameters multisigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(this.RedeemScript); int index = multisigParams.PubKeys.IndexOf(this.PubKey); TransactionSignature signature = PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(this.Network, new Script(tx.Inputs[0].ScriptSig.ToOps().SkipLast(1)))[index]; return(signature.ToString()); }
public void ReadWrite(BitcoinStream stream) { var bytes = _Signature?.ToBytes(); stream.ReadWriteAsVarString(ref bytes); if (!stream.Serializing) { _Signature = new TransactionSignature(bytes); } }
public WitScript GenerateWitScript(TransactionSignature signature, PubKey publicKey) { if (publicKey == null) { throw new ArgumentNullException("publicKey"); } return(new WitScript( signature == null ? OpcodeType.OP_0 : Op.GetPushOp(signature.ToBytes()), Op.GetPushOp(publicKey.ToBytes()) )); }
private PubKey AssertValidSignature(TransactionSignature clientSignature, Transaction offer) { var signedHash = offer.Inputs.AsIndexedInputs().First().GetSignatureHash(InternalState.EscrowedCoin, clientSignature.SigHash); var clientKey = InternalState.GetClientEscrowPubKey(); if (!clientKey.Verify(signedHash, clientSignature.Signature)) { throw new PuzzleException("invalid-client-signature"); } return(clientKey); }
protected override bool CheckScriptSigCore(Network network, Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { Op[] ops = scriptSigOps; if (ops.Length != 2) { return(false); } return(ops[0].PushData != null && ((ops[0].Code == OpcodeType.OP_0) || TransactionSignature.IsValid(network, ops[0].PushData, ScriptVerify.None)) && ops[1].PushData != null && PubKey.Check(ops[1].PushData, false)); }
public TrustedBroadcastRequest FulfillOffer( TransactionSignature clientSignature, Script cashout, FeeRate feeRate) { if (clientSignature == null) { throw new ArgumentNullException(nameof(clientSignature)); } if (feeRate == null) { throw new ArgumentNullException(nameof(feeRate)); } AssertState(SolverServerStates.WaitingFulfillment); var offer = GetUnsignedOfferTransaction(); PubKey clientKey = AssertValidSignature(clientSignature, offer); offer.Inputs[0].ScriptSig = new Script( Op.GetPushOp(clientSignature.ToBytes()), Op.GetPushOp(CreateOfferSignature().ToBytes()), Op.GetPushOp(InternalState.EscrowedCoin.Redeem.ToBytes()) ); offer.Inputs[0].Witnessify(); if (!offer.Inputs.AsIndexedInputs().First().VerifyScript(_Network, InternalState.EscrowedCoin)) { throw new PuzzleException("invalid-tumbler-signature"); } var solutions = InternalState.SolvedPuzzles.Select(s => s.SolutionKey).ToArray(); Transaction fulfill = new Transaction(); fulfill.Inputs.Add(new TxIn()); fulfill.Outputs.Add(new TxOut(InternalState.OfferCoin.Amount, cashout)); var fulfillScript = SolverScriptBuilder.CreateFulfillScript(null, solutions); fulfill.Inputs[0].ScriptSig = fulfillScript + Op.GetPushOp(InternalState.OfferCoin.Redeem.ToBytes()); fulfill.Inputs[0].Witnessify(); var virtualSize = fulfill.HasWitness ? fulfill.GetVirtualSize(_Network.Consensus.Options.WitnessScaleFactor) : fulfill.GetSerializedSize(); fulfill.Outputs[0].Value -= feeRate.GetFee(virtualSize); InternalState.OfferClientSignature = clientSignature; InternalState.Status = SolverServerStates.WaitingEscape; return(new TrustedBroadcastRequest { Key = InternalState.FulfillKey, PreviousScriptPubKey = InternalState.OfferCoin.ScriptPubKey, Transaction = fulfill }); }
/// <summary> /// Generates the scriptSig. /// </summary> /// <param name="signature">The transaction signature. For unsigned inputs this can be <c>null</c> in which case it is encoded as an <c>OP_0</c>.</param> /// <param name="coldPubKey">A flag indicating whether the cold wallet versus the hot wallet is signing.</param> /// <param name="publicKey">The cold or hot wallet public key.</param> /// <returns>The scriptSig.</returns> public Script GenerateScriptSig(TransactionSignature signature, bool coldPubKey, PubKey publicKey) { Guard.NotNull(signature, nameof(signature)); Guard.NotNull(publicKey, nameof(publicKey)); return(new Script( Op.GetPushOp(signature.ToBytes()), coldPubKey ? OP_0 : OP_1, Op.GetPushOp(publicKey.ToBytes()) )); }
public override Script GenerateScriptSig(Network network, Script scriptPubKey, IKeyRepository keyRepo, ISigner signer) { Key key = keyRepo.FindKey(scriptPubKey); if (key == null) { return(null); } TransactionSignature sig = signer.Sign(key); return(PayToPubkeyTemplate.Instance.GenerateScriptSig(sig)); }
public IActionResult FulfillOffer( [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))] ClassicTumblerParameters tumblerId, int cycleId, string channelId, [FromBody] TransactionSignature signature) { if (tumblerId == null) { throw new ArgumentNullException("tumblerId"); } if (signature == null) { return(BadRequest("Missing Signature")); } var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase); var feeRate = Services.FeeService.GetFeeRate(); if (session.Status != SolverServerStates.WaitingFulfillment) { return(BadRequest("invalid-state")); } try { var cycle = GetCycle(cycleId); var cashout = Services.WalletService.GenerateAddress(); var fulfill = session.FulfillOffer(signature, cashout.ScriptPubKey, feeRate); fulfill.BroadcastAt = new LockTime(cycle.GetPeriods().Payment.End - 1); Repository.Save(cycle.Start, session); var signedOffer = session.GetSignedOfferTransaction(); signedOffer.BroadcastAt = fulfill.BroadcastAt - 1; uint correlation = GetCorrelation(session); var offerScriptPubKey = session.GetInternalState().OfferCoin.ScriptPubKey; Services.BlockExplorerService.Track(offerScriptPubKey); Tracker.AddressCreated(cycle.Start, TransactionType.ClientOffer, offerScriptPubKey, correlation); Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientOffer, correlation, signedOffer); Tracker.AddressCreated(cycle.Start, TransactionType.ClientFulfill, cashout.ScriptPubKey, correlation); if (!Runtime.NoFulFill) { Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientFulfill, correlation, fulfill); } return(Json(Runtime.Cooperative ? session.GetSolutionKeys() : new SolutionKey[0])); } catch (PuzzleException ex) { return(BadRequest(ex.Message)); } }
public async Task <Transaction> ReceiveAsync(ScriptCoin escrowedCoin, TransactionSignature clientSignature, Key escrowKey, FeeRate feeRate) { _ReceiveBatch.FeeRate = feeRate; var task = _ReceiveBatch.WaitTransactionAsync(new ClientEscapeData() { ClientSignature = clientSignature, EscrowedCoin = escrowedCoin, EscrowKey = escrowKey }).ConfigureAwait(false); Logs.Tumbler.LogDebug($"ClientEscape batch count {_ReceiveBatch.BatchCount}"); return(await task); }
public Transaction BuildWithSignatures(TransactionSignature remotePubKeySignature) { var unsigned = Build(); var localPubKeySignature = SignClosingTransaction(unsigned); var witScript = MultiSignatureWitnessScript.Create( _channel.LocalCommitmentTxParameters.FundingKey, _channel.RemoteCommitmentTxParameters.FundingKey, localPubKeySignature, remotePubKeySignature); unsigned.Inputs[0].ScriptSig = Script.Empty; unsigned.Inputs[0].WitScript = witScript; return(unsigned); }
public override Script GenerateScriptSig(Network network, Script scriptPubKey, IKeyRepository keyRepo, ISigner signer) { KeyId parameters = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey); Key key = keyRepo.FindKey(parameters.ScriptPubKey); if (key == null) { return(null); } TransactionSignature sig = signer.Sign(key); return(PayToPubkeyHashTemplate.Instance.GenerateScriptSig(sig, key.PubKey)); }
public PartialSignature(PubKey pubKey, TransactionSignature signature) { if (pubKey == null) { throw new ArgumentNullException(nameof(pubKey)); } if (signature == null) { throw new ArgumentNullException(nameof(signature)); } Signature = signature; PubKey = pubKey; }
public void script_combineSigs() { Key[] keys = new[] { new Key(), new Key(), new Key() }; var txFrom = CreateCreditingTransaction(keys[0].PubKey.Hash.ScriptPubKey); var txTo = CreateSpendingTransaction(new Script(), txFrom); Script scriptPubKey = txFrom.Outputs[0].ScriptPubKey; Script scriptSig = txTo.Inputs[0].ScriptSig; Script empty = new Script(); Script combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, empty); Assert.True(combined.ToBytes().Length == 0); // Single signature case: SignSignature(keys, txFrom, txTo, 0); // changes scriptSig scriptSig = txTo.Inputs[0].ScriptSig; combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); Assert.True(combined == scriptSig); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); Assert.True(combined == scriptSig); Script scriptSigCopy = scriptSig.Clone(); // Signing again will give a different, valid signature: SignSignature(keys, txFrom, txTo, 0); scriptSig = txTo.Inputs[0].ScriptSig; combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); Assert.True(combined == scriptSigCopy || combined == scriptSig); // P2SH, single-signature case: Script pkSingle = PayToPubkeyTemplate.Instance.GenerateScriptPubKey(keys[0].PubKey); scriptPubKey = pkSingle.Hash.ScriptPubKey; txFrom.Outputs[0].ScriptPubKey = scriptPubKey; txTo.Inputs[0].PrevOut = new OutPoint(txFrom, 0); SignSignature(keys, txFrom, txTo, 0, pkSingle); scriptSig = txTo.Inputs[0].ScriptSig; combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); Assert.True(combined == scriptSig); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); scriptSig = txTo.Inputs[0].ScriptSig; Assert.True(combined == scriptSig); scriptSigCopy = scriptSig.Clone(); SignSignature(keys, txFrom, txTo, 0); scriptSig = txTo.Inputs[0].ScriptSig; combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); Assert.True(combined == scriptSigCopy || combined == scriptSig); // dummy scriptSigCopy with placeholder, should always choose non-placeholder: scriptSigCopy = new Script(OpcodeType.OP_0, Op.GetPushOp(pkSingle.ToBytes())); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig); Assert.True(combined == scriptSig); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy); Assert.True(combined == scriptSig); // Hardest case: Multisig 2-of-3 scriptPubKey = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(2, keys.Select(k => k.PubKey).ToArray()); txFrom.Outputs[0].ScriptPubKey = scriptPubKey; txTo.Inputs[0].PrevOut = new OutPoint(txFrom, 0); SignSignature(keys, txFrom, txTo, 0); scriptSig = txTo.Inputs[0].ScriptSig; combined = Script.CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty); Assert.True(combined == scriptSig); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig); Assert.True(combined == scriptSig); // A couple of partially-signed versions: uint256 hash1 = scriptPubKey.SignatureHash(txTo, 0, SigHash.All); var sig1 = new TransactionSignature(keys[0].Sign(hash1), SigHash.All); uint256 hash2 = scriptPubKey.SignatureHash(txTo, 0, SigHash.None); var sig2 = new TransactionSignature(keys[1].Sign(hash2), SigHash.None); uint256 hash3 = scriptPubKey.SignatureHash(txTo, 0, SigHash.Single); var sig3 = new TransactionSignature(keys[2].Sign(hash3), SigHash.Single); // Not fussy about order (or even existence) of placeholders or signatures: Script partial1a = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + OpcodeType.OP_0; Script partial1b = new Script() + OpcodeType.OP_0 + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()); Script partial2a = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig2.ToBytes()); Script partial2b = new Script() + Op.GetPushOp(sig2.ToBytes()) + OpcodeType.OP_0; Script partial3a = new Script() + Op.GetPushOp(sig3.ToBytes()); Script partial3b = new Script() + OpcodeType.OP_0 + OpcodeType.OP_0 + Op.GetPushOp(sig3.ToBytes()); Script partial3c = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig3.ToBytes()) + OpcodeType.OP_0; Script complete12 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + Op.GetPushOp(sig2.ToBytes()); Script complete13 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig1.ToBytes()) + Op.GetPushOp(sig3.ToBytes()); Script complete23 = new Script() + OpcodeType.OP_0 + Op.GetPushOp(sig2.ToBytes()) + Op.GetPushOp(sig3.ToBytes()); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b); Assert.True(combined == partial1a); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a); Assert.True(combined == complete12); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a); Assert.True(combined == complete12); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b); Assert.True(combined == complete12); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b); Assert.True(combined == complete13); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a); Assert.True(combined == complete23); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b); Assert.True(combined == complete23); combined = Script.CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a); Assert.True(combined == partial3c); }