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(); TransactionBuilder builder = new TransactionBuilder(); builder.Extensions.Add(new EscrowBuilderExtension()); builder.AddCoins(InternalState.EscrowedCoin); builder.AddKeys(InternalState.EscrowKey); var clientKey = InternalState.GetClientEscrowPubKey(); builder.AddKnownSignature(clientKey, clientSignature); builder.SignTransactionInPlace(offer); if (!builder.Verify(offer)) { throw new PuzzleException("invalid-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 size = new OfferBuilderExtension().EstimateScriptSigSize(offerCoin.Redeem); fulfill.Outputs[0].Value -= feeRate.GetFee(size); var signature = fulfill.Inputs.AsIndexedInputs().First().Sign(InternalState.FulfillKey, offerCoin, SigHash.All); var fulfillScript = SolverScriptBuilder.CreateFulfillScript(signature, solutions); fulfill.Inputs[0].ScriptSig = fulfillScript + Op.GetPushOp(offerCoin.Redeem.ToBytes()); InternalState.OfferClientSignature = clientSignature; InternalState.Status = SolverServerStates.Completed; return(new TrustedBroadcastRequest { Key = InternalState.FulfillKey, PreviousScriptPubKey = offerCoin.ScriptPubKey, Transaction = fulfill }); }
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); }
private PubKey AssertValidSignature(TransactionSignature clientSignature, Transaction offer) { var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); var coin = InternalState.EscrowedCoin.Clone(); coin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); var signedHash = offer.Inputs.AsIndexedInputs().First().GetSignatureHash(coin, clientSignature.SigHash); var clientKey = InternalState.GetClientEscrowPubKey(); if (!clientKey.Verify(signedHash, clientSignature.Signature)) { throw new PuzzleException("invalid-client-signature"); } return(clientKey); }
public TrustedBroadcastRequest GetSignedOfferTransaction() { AssertState(SolverServerStates.Completed); var offerTransaction = GetUnsignedOfferTransaction(); TransactionBuilder txBuilder = new TransactionBuilder(); txBuilder.Extensions.Add(new EscrowBuilderExtension()); txBuilder.AddCoins(EscrowedCoin); txBuilder.AddKnownSignature(InternalState.EscrowKey.PubKey, InternalState.OfferSignature); txBuilder.AddKnownSignature(InternalState.GetClientEscrowPubKey(), InternalState.OfferClientSignature); txBuilder.SignTransactionInPlace(offerTransaction); return(new TrustedBroadcastRequest { Key = InternalState.EscrowKey, Transaction = offerTransaction, PreviousScriptPubKey = EscrowedCoin.ScriptPubKey }); }