mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-03 17:36:59 +01:00
If an input already used in a payjoin is reused in another, we should not attempt to broadcast the original transaction.
This commit is contained in:
parent
749d26fafa
commit
a128685b83
3 changed files with 17 additions and 10 deletions
|
@ -87,6 +87,19 @@ namespace BTCPayServer.Tests
|
||||||
Assert.True(await repo.TryLock(outpoint));
|
Assert.True(await repo.TryLock(outpoint));
|
||||||
Assert.True(await repo.TryUnlock(outpoint));
|
Assert.True(await repo.TryUnlock(outpoint));
|
||||||
Assert.False(await repo.TryUnlock(outpoint));
|
Assert.False(await repo.TryUnlock(outpoint));
|
||||||
|
|
||||||
|
// Make sure that if any can't be locked, all are not locked
|
||||||
|
var outpoint1 = RandomOutpoint();
|
||||||
|
var outpoint2 = RandomOutpoint();
|
||||||
|
Assert.True(await repo.TryLockInputs(new[] { outpoint1 }));
|
||||||
|
Assert.False(await repo.TryLockInputs(new[] { outpoint1, outpoint2 }));
|
||||||
|
Assert.True(await repo.TryLockInputs(new[] { outpoint2 }));
|
||||||
|
|
||||||
|
outpoint1 = RandomOutpoint();
|
||||||
|
outpoint2 = RandomOutpoint();
|
||||||
|
Assert.True(await repo.TryLockInputs(new[] { outpoint1 }));
|
||||||
|
Assert.False(await repo.TryLockInputs(new[] { outpoint2, outpoint1 }));
|
||||||
|
Assert.True(await repo.TryLockInputs(new[] { outpoint2 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,10 +914,6 @@ retry:
|
||||||
.SendEstimatedFees(new FeeRate(100m))
|
.SendEstimatedFees(new FeeRate(100m))
|
||||||
.BuildTransaction(true);
|
.BuildTransaction(true);
|
||||||
|
|
||||||
//Attempt 1: Send a signed tx to invoice 1 that does not pay the invoice at all
|
|
||||||
//Result: reject
|
|
||||||
// Assert.False((await tester.PayTester.HttpClient.PostAsync(endpoint,
|
|
||||||
// new StringContent(Invoice2Coin1.ToHex(), Encoding.UTF8, "text/plain"))).IsSuccessStatusCode);
|
|
||||||
|
|
||||||
//Attempt 2: Create two transactions using different inputs and send them to the same invoice.
|
//Attempt 2: Create two transactions using different inputs and send them to the same invoice.
|
||||||
//Result: Second Tx should be rejected.
|
//Result: Second Tx should be rejected.
|
||||||
|
|
|
@ -83,35 +83,30 @@ namespace BTCPayServer.Payments.PayJoin
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly InvoiceRepository _invoiceRepository;
|
private readonly InvoiceRepository _invoiceRepository;
|
||||||
private readonly ExplorerClientProvider _explorerClientProvider;
|
private readonly ExplorerClientProvider _explorerClientProvider;
|
||||||
private readonly StoreRepository _storeRepository;
|
|
||||||
private readonly BTCPayWalletProvider _btcPayWalletProvider;
|
private readonly BTCPayWalletProvider _btcPayWalletProvider;
|
||||||
private readonly PayJoinRepository _payJoinRepository;
|
private readonly PayJoinRepository _payJoinRepository;
|
||||||
private readonly EventAggregator _eventAggregator;
|
private readonly EventAggregator _eventAggregator;
|
||||||
private readonly NBXplorerDashboard _dashboard;
|
private readonly NBXplorerDashboard _dashboard;
|
||||||
private readonly DelayedTransactionBroadcaster _broadcaster;
|
private readonly DelayedTransactionBroadcaster _broadcaster;
|
||||||
private readonly WalletRepository _walletRepository;
|
|
||||||
private readonly BTCPayServerEnvironment _env;
|
private readonly BTCPayServerEnvironment _env;
|
||||||
|
|
||||||
public PayJoinEndpointController(BTCPayNetworkProvider btcPayNetworkProvider,
|
public PayJoinEndpointController(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
InvoiceRepository invoiceRepository, ExplorerClientProvider explorerClientProvider,
|
InvoiceRepository invoiceRepository, ExplorerClientProvider explorerClientProvider,
|
||||||
StoreRepository storeRepository, BTCPayWalletProvider btcPayWalletProvider,
|
BTCPayWalletProvider btcPayWalletProvider,
|
||||||
PayJoinRepository payJoinRepository,
|
PayJoinRepository payJoinRepository,
|
||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
NBXplorerDashboard dashboard,
|
NBXplorerDashboard dashboard,
|
||||||
DelayedTransactionBroadcaster broadcaster,
|
DelayedTransactionBroadcaster broadcaster,
|
||||||
WalletRepository walletRepository,
|
|
||||||
BTCPayServerEnvironment env)
|
BTCPayServerEnvironment env)
|
||||||
{
|
{
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_invoiceRepository = invoiceRepository;
|
_invoiceRepository = invoiceRepository;
|
||||||
_explorerClientProvider = explorerClientProvider;
|
_explorerClientProvider = explorerClientProvider;
|
||||||
_storeRepository = storeRepository;
|
|
||||||
_btcPayWalletProvider = btcPayWalletProvider;
|
_btcPayWalletProvider = btcPayWalletProvider;
|
||||||
_payJoinRepository = payJoinRepository;
|
_payJoinRepository = payJoinRepository;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_dashboard = dashboard;
|
_dashboard = dashboard;
|
||||||
_broadcaster = broadcaster;
|
_broadcaster = broadcaster;
|
||||||
_walletRepository = walletRepository;
|
|
||||||
_env = env;
|
_env = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,6 +280,8 @@ namespace BTCPayServer.Payments.PayJoin
|
||||||
|
|
||||||
if (!await _payJoinRepository.TryLockInputs(ctx.OriginalTransaction.Inputs.Select(i => i.PrevOut).ToArray()))
|
if (!await _payJoinRepository.TryLockInputs(ctx.OriginalTransaction.Inputs.Select(i => i.PrevOut).ToArray()))
|
||||||
{
|
{
|
||||||
|
// We do not broadcast, since we might double spend a delayed transaction of a previous payjoin
|
||||||
|
ctx.DoNotBroadcast();
|
||||||
return CreatePayjoinErrorAndLog(503, PayjoinReceiverWellknownErrors.Unavailable, "Some of those inputs have already been used to make another payjoin transaction");
|
return CreatePayjoinErrorAndLog(503, PayjoinReceiverWellknownErrors.Unavailable, "Some of those inputs have already been used to make another payjoin transaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
Loading…
Add table
Reference in a new issue