Merge pull request #1609 from NicolasDorier/pj3

Adapt PJ implementation to latest BIP
This commit is contained in:
Nicolas Dorier 2020-05-29 08:58:38 +09:00 committed by GitHub
commit 47baa219fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 24 deletions

View file

@ -127,6 +127,10 @@ namespace BTCPayServer.Payments.PayJoin
decimal minfeerate = -1.0m,
int v = 1)
{
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(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<BTCPayNetwork>(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);

View file

@ -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)
{