mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-23 07:04:26 +01:00
Fix: Boltcard would get bricked during reset from the balance view with wrong card (#6400)
This commit is contained in:
@@ -1416,7 +1416,8 @@ namespace BTCPayServer.Tests
|
||||
Assert.DoesNotContain(null, card1keys);
|
||||
var card2 = await client.RegisterBoltcard(test4.Id, new RegisterBoltcardRequest()
|
||||
{
|
||||
UID = uid
|
||||
UID = uid,
|
||||
OnExisting = OnExistingBehavior.UpdateVersion
|
||||
});
|
||||
Assert.Equal(1, card2.Version);
|
||||
Assert.StartsWith("lnurlw://", card2.LNURLW);
|
||||
|
||||
@@ -189,6 +189,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
if (pp is null)
|
||||
return PullPaymentNotFound();
|
||||
var issuerKey = await _settingsRepository.GetIssuerKey(_env);
|
||||
BoltcardPICCData? picc = null;
|
||||
|
||||
// LNURLW is used by deeplinks
|
||||
if (request?.LNURLW is not null)
|
||||
@@ -204,11 +205,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
ModelState.AddModelError(nameof(request.LNURLW), "The LNURLW should contains a 'p=' parameter");
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
if (issuerKey.TryDecrypt(p) is not BoltcardPICCData picc)
|
||||
if (issuerKey.TryDecrypt(p) is not BoltcardPICCData o)
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.LNURLW), "The LNURLW 'p=' parameter cannot be decrypted");
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
picc = o;
|
||||
request.UID = picc.Uid;
|
||||
}
|
||||
|
||||
@@ -230,8 +232,54 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_ => request.OnExisting
|
||||
};
|
||||
|
||||
var version = await _dbContextFactory.LinkBoltcardToPullPayment(pullPaymentId, issuerKey, request.UID, request.OnExisting);
|
||||
var keys = issuerKey.CreatePullPaymentCardKey(request.UID, version, pullPaymentId).DeriveBoltcardKeys(issuerKey);
|
||||
BoltcardKeys keys;
|
||||
int version;
|
||||
|
||||
var registration = await _dbContextFactory.GetBoltcardRegistration(issuerKey, request.UID);
|
||||
if (request.OnExisting is OnExistingBehavior.UpdateVersion ||
|
||||
(request.OnExisting is null && registration?.PullPaymentId is null))
|
||||
{
|
||||
version = await _dbContextFactory.LinkBoltcardToPullPayment(pullPaymentId, issuerKey, request.UID, request.OnExisting);
|
||||
keys = issuerKey.CreatePullPaymentCardKey(request.UID, version, pullPaymentId).DeriveBoltcardKeys(issuerKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (registration?.PullPaymentId is null)
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.UID), "This card isn't registered");
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
if (pullPaymentId != registration.PullPaymentId)
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.UID), "This card is registered on a different pull payment");
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
var ppId = registration.PullPaymentId;
|
||||
version = registration.Version;
|
||||
int retryCount = 0;
|
||||
retry:
|
||||
keys = issuerKey.CreatePullPaymentCardKey(request!.UID, version, ppId).DeriveBoltcardKeys(issuerKey);
|
||||
|
||||
// The server version may be higher than the card.
|
||||
// If that is the case, let's try a few versions until we find the right one
|
||||
// by checking c.
|
||||
if (request?.LNURLW is { } lnurlw &&
|
||||
ExtractC(lnurlw) is string c &&
|
||||
picc is not null)
|
||||
{
|
||||
if (!keys.AuthenticationKey.CheckSunMac(c, picc))
|
||||
{
|
||||
retryCount++;
|
||||
version--;
|
||||
if (version < 0 || retryCount > 5)
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.UID), "Unable to get keys of this card, it might be caused by a version mismatch");
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var boltcardUrl = Url.Action(nameof(UIBoltcardController.GetWithdrawRequest), "UIBoltcard");
|
||||
boltcardUrl = Request.GetAbsoluteUri(boltcardUrl);
|
||||
@@ -250,7 +298,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return Ok(resp);
|
||||
}
|
||||
|
||||
private string? ExtractP(string? url)
|
||||
public static string? Extract(string? url, string param, int size)
|
||||
{
|
||||
if (url is null || !Uri.TryCreate(url, UriKind.Absolute, out var uri))
|
||||
return null;
|
||||
@@ -258,11 +306,13 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
if (num == -1)
|
||||
return null;
|
||||
string input = uri.AbsoluteUri.Substring(num);
|
||||
Match match = Regex.Match(input, "p=([a-f0-9A-F]{32})");
|
||||
Match match = Regex.Match(input, param + "=([a-f0-9A-F]{" + size + "})");
|
||||
if (!match.Success)
|
||||
return null;
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
public static string? ExtractP(string? url) => Extract(url, "p", 32);
|
||||
public static string? ExtractC(string? url) => Extract(url, "c", 16);
|
||||
|
||||
[HttpGet("~/api/v1/pull-payments/{pullPaymentId}")]
|
||||
[AllowAnonymous]
|
||||
|
||||
Reference in New Issue
Block a user