From 9503e07dc82ca10499441b32816eb7bca219d862 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 28 May 2020 13:35:48 +0900 Subject: [PATCH] Adapt PJ implementation to latest BIP --- .../PayJoin/PayJoinEndpointController.cs | 25 +++++++++---------- BTCPayServer/Services/PayjoinClient.cs | 13 ++-------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs index 0f4d5c928..322bab20c 100644 --- a/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs +++ b/BTCPayServer/Payments/PayJoin/PayJoinEndpointController.cs @@ -127,6 +127,10 @@ namespace BTCPayServer.Payments.PayJoin decimal minfeerate = -1.0m, int v = 1) { + var network = _btcPayNetworkProvider.GetNetwork(cryptoCode); + if (network == null) + return NotFound(); + if (v != 1) { return BadRequest(new JObject @@ -137,11 +141,6 @@ namespace BTCPayServer.Payments.PayJoin }); } - var network = _btcPayNetworkProvider.GetNetwork(cryptoCode); - if (network == null) - { - return BadRequest(CreatePayjoinError("invalid-network", "Incorrect network")); - } await using var ctx = new PayjoinReceiverContext(_invoiceRepository, _explorerClientProvider.GetExplorerClient(network), _payJoinRepository); ObjectResult CreatePayjoinErrorAndLog(int httpCode, PayjoinReceiverWellknownErrors err, string debug) { @@ -174,7 +173,7 @@ namespace BTCPayServer.Payments.PayJoin if (PSBT.TryParse(rawBody, network.NBitcoinNetwork, out var psbt)) { if (!psbt.IsAllFinalized()) - return BadRequest(CreatePayjoinError("psbt-not-finalized", "The PSBT should be finalized")); + return BadRequest(CreatePayjoinError("original-psbt-rejected", "The PSBT should be finalized")); ctx.OriginalTransaction = psbt.ExtractTransaction(); } // BTCPay Server implementation support a transaction instead of PSBT @@ -182,7 +181,7 @@ namespace BTCPayServer.Payments.PayJoin { psbtFormat = false; if (!Transaction.TryParse(rawBody, network.NBitcoinNetwork, out var tx)) - return BadRequest(CreatePayjoinError("invalid-format", "invalid transaction or psbt")); + return BadRequest(CreatePayjoinError("original-psbt-rejected", "invalid transaction or psbt")); ctx.OriginalTransaction = tx; psbt = PSBT.FromTransaction(tx, network.NBitcoinNetwork); psbt = (await explorer.UpdatePSBTAsync(new UpdatePSBTRequest() { PSBT = psbt })).PSBT; @@ -200,11 +199,11 @@ namespace BTCPayServer.Payments.PayJoin var sendersInputType = psbt.GetInputsScriptPubKeyType(); if (psbt.CheckSanity() is var errors && errors.Count != 0) { - return BadRequest(CreatePayjoinError("insane-psbt", $"This PSBT is insane ({errors[0]})")); + return BadRequest(CreatePayjoinError("original-psbt-rejected", $"This PSBT is insane ({errors[0]})")); } if (!psbt.TryGetEstimatedFeeRate(out originalFeeRate)) { - return BadRequest(CreatePayjoinError("need-utxo-information", + return BadRequest(CreatePayjoinError("original-psbt-rejected", "You need to provide Witness UTXO information to the PSBT.")); } @@ -212,19 +211,19 @@ namespace BTCPayServer.Payments.PayJoin // to leak global xpubs if (psbt.GlobalXPubs.Any()) { - return BadRequest(CreatePayjoinError("leaking-data", + return BadRequest(CreatePayjoinError("original-psbt-rejected", "GlobalXPubs should not be included in the PSBT")); } if (psbt.Outputs.Any(o => o.HDKeyPaths.Count != 0) || psbt.Inputs.Any(o => o.HDKeyPaths.Count != 0)) { - return BadRequest(CreatePayjoinError("leaking-data", + return BadRequest(CreatePayjoinError("original-psbt-rejected", "Keypath information should not be included in the PSBT")); } if (psbt.Inputs.Any(o => !o.IsFinalized())) { - return BadRequest(CreatePayjoinError("psbt-not-finalized", "The PSBT Should be finalized")); + return BadRequest(CreatePayjoinError("original-psbt-rejected", "The PSBT Should be finalized")); } //////////// @@ -232,7 +231,7 @@ namespace BTCPayServer.Payments.PayJoin if (!mempool.Success) { ctx.DoNotBroadcast(); - return BadRequest(CreatePayjoinError("invalid-transaction", + return BadRequest(CreatePayjoinError("original-psbt-rejected", $"Provided transaction isn't mempool eligible {mempool.RPCCodeMessage}")); } var enforcedLowR = ctx.OriginalTransaction.Inputs.All(IsLowR); diff --git a/BTCPayServer/Services/PayjoinClient.cs b/BTCPayServer/Services/PayjoinClient.cs index 7f065c831..eb3e13572 100644 --- a/BTCPayServer/Services/PayjoinClient.cs +++ b/BTCPayServer/Services/PayjoinClient.cs @@ -293,28 +293,19 @@ namespace BTCPayServer.Services public enum PayjoinReceiverWellknownErrors { - LeakingData, - PSBTNotFinalized, Unavailable, - OutOfUTXOS, NotEnoughMoney, - InsanePSBT, VersionUnsupported, - NeedUTXOInformation, - InvalidTransaction + OriginalPSBTRejected } public class PayjoinReceiverHelper { static IEnumerable<(PayjoinReceiverWellknownErrors EnumValue, string ErrorCode, string Message)> Get() { - yield return (PayjoinReceiverWellknownErrors.LeakingData, "leaking-data", "Key path information or GlobalXPubs should not be included in the original PSBT."); - yield return (PayjoinReceiverWellknownErrors.PSBTNotFinalized, "psbt-not-finalized", "The original PSBT must be finalized."); yield return (PayjoinReceiverWellknownErrors.Unavailable, "unavailable", "The payjoin endpoint is not available for now."); yield return (PayjoinReceiverWellknownErrors.NotEnoughMoney, "not-enough-money", "The receiver added some inputs but could not bump the fee of the payjoin proposal."); - yield return (PayjoinReceiverWellknownErrors.InsanePSBT, "insane-psbt", "Some consistency check on the PSBT failed."); yield return (PayjoinReceiverWellknownErrors.VersionUnsupported, "version-unsupported", "This version of payjoin is not supported."); - yield return (PayjoinReceiverWellknownErrors.NeedUTXOInformation, "need-utxo-information", "The witness UTXO or non witness UTXO is missing."); - yield return (PayjoinReceiverWellknownErrors.InvalidTransaction, "invalid-transaction", "The original transaction is invalid for payjoin"); + yield return (PayjoinReceiverWellknownErrors.OriginalPSBTRejected, "original-psbt-rejected", "The receiver rejected the original PSBT."); } public static string GetErrorCode(PayjoinReceiverWellknownErrors err) {