2021-03-24 13:48:33 +09:00
|
|
|
using System.Collections.Generic;
|
2022-07-23 13:26:13 +02:00
|
|
|
using System.Linq;
|
2020-03-30 00:28:22 +09:00
|
|
|
using System.Threading.Tasks;
|
2020-04-13 15:43:25 +09:00
|
|
|
using BTCPayServer.Data;
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2020-03-30 00:28:22 +09:00
|
|
|
using NBitcoin;
|
|
|
|
|
|
|
|
namespace BTCPayServer.Payments.PayJoin
|
|
|
|
{
|
2022-07-23 13:26:13 +02:00
|
|
|
public class UTXOLocker : IUTXOLocker
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
|
|
|
|
2022-07-23 13:26:13 +02:00
|
|
|
public UTXOLocker(ApplicationDbContextFactory dbContextFactory)
|
2020-04-13 15:43:25 +09:00
|
|
|
{
|
|
|
|
_dbContextFactory = dbContextFactory;
|
|
|
|
}
|
2022-07-23 13:26:13 +02:00
|
|
|
|
2020-04-13 15:43:25 +09:00
|
|
|
public async Task<bool> TryLock(OutPoint outpoint)
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
using var ctx = _dbContextFactory.CreateContext();
|
2022-07-23 13:26:13 +02:00
|
|
|
ctx.PayjoinLocks.Add(new PayjoinLock() {Id = outpoint.ToString()});
|
2020-04-13 15:43:25 +09:00
|
|
|
try
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
return await ctx.SaveChangesAsync() == 1;
|
|
|
|
}
|
2020-04-16 14:25:52 +09:00
|
|
|
catch (DbUpdateException)
|
2020-04-13 15:43:25 +09:00
|
|
|
{
|
|
|
|
return false;
|
2020-03-30 00:28:22 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-13 15:43:25 +09:00
|
|
|
public async Task<bool> TryUnlock(params OutPoint[] outPoints)
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
using var ctx = _dbContextFactory.CreateContext();
|
|
|
|
foreach (OutPoint outPoint in outPoints)
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2022-07-23 13:26:13 +02:00
|
|
|
ctx.PayjoinLocks.Remove(new PayjoinLock() {Id = outPoint.ToString()});
|
2020-04-13 15:43:25 +09:00
|
|
|
}
|
2022-07-23 13:26:13 +02:00
|
|
|
|
2020-04-13 15:43:25 +09:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return await ctx.SaveChangesAsync() == outPoints.Length;
|
|
|
|
}
|
2020-04-16 14:25:52 +09:00
|
|
|
catch (DbUpdateException)
|
2020-04-13 15:43:25 +09:00
|
|
|
{
|
|
|
|
return false;
|
2020-03-30 00:28:22 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-13 15:43:25 +09:00
|
|
|
public async Task<bool> TryLockInputs(OutPoint[] outPoints)
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
using var ctx = _dbContextFactory.CreateContext();
|
|
|
|
foreach (OutPoint outPoint in outPoints)
|
|
|
|
{
|
|
|
|
ctx.PayjoinLocks.Add(new PayjoinLock()
|
|
|
|
{
|
|
|
|
// Random flag so it does not lock same id
|
|
|
|
// as the lock utxo
|
|
|
|
Id = "K-" + outPoint.ToString()
|
2020-06-28 17:55:27 +09:00
|
|
|
});
|
2020-04-13 15:43:25 +09:00
|
|
|
}
|
2022-07-23 13:26:13 +02:00
|
|
|
|
2020-04-13 15:43:25 +09:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return await ctx.SaveChangesAsync() == outPoints.Length;
|
|
|
|
}
|
2020-04-16 14:25:52 +09:00
|
|
|
catch (DbUpdateException)
|
2020-03-30 00:28:22 +09:00
|
|
|
{
|
2020-04-13 15:43:25 +09:00
|
|
|
return false;
|
2020-03-30 00:28:22 +09:00
|
|
|
}
|
|
|
|
}
|
2022-07-23 13:26:13 +02:00
|
|
|
|
|
|
|
public async Task<HashSet<OutPoint>> FindLocks(OutPoint[] outpoints)
|
|
|
|
{
|
|
|
|
var outPointsStr = outpoints.Select(o => o.ToString());
|
|
|
|
await using var ctx = _dbContextFactory.CreateContext();
|
|
|
|
return (await ctx.PayjoinLocks.Where(l => outPointsStr.Contains(l.Id)).ToArrayAsync())
|
|
|
|
.Select(l => OutPoint.Parse(l.Id)).ToHashSet();
|
|
|
|
}
|
2020-03-30 00:28:22 +09:00
|
|
|
}
|
|
|
|
}
|