Better error message on invalid PSBT in Sign with Seed (#6920)

* Better error message on invalid PSBT in Sign with Seed

* Improve error reporting if a PSBT built by SendWallet is not signable
This commit is contained in:
Nicolas Dorier
2025-09-18 10:49:54 +09:00
committed by GitHub
parent 790616d2a6
commit fa29176a9c
2 changed files with 47 additions and 9 deletions

View File

@@ -86,6 +86,7 @@ namespace BTCPayServer.Controllers
BackUrl = vm.BackUrl
});
}
switch (command)
{
case "vault":
@@ -170,6 +171,7 @@ namespace BTCPayServer.Controllers
{
return View("WalletPSBT", vm);
}
switch (command)
{
case "createpending":
@@ -373,14 +375,25 @@ namespace BTCPayServer.Controllers
vm.FeeRate = feeRate.ToString();
}
var sanityErrors = psbtObject.CheckSanity();
if (sanityErrors.Count != 0)
if (!psbtObject.IsAllFinalized())
{
vm.SetErrors(sanityErrors);
var sanityErrors = new List<PSBTError>();
foreach (var input in psbtObject.Inputs)
{
if (input.IsFinalized())
continue;
if (input.GetSignableCoin(out var missingCoin) is null)
{
sanityErrors.Add(new PSBTError(input.Index, missingCoin));
}
else if (!psbtObject.IsAllFinalized() && !psbtObject.TryFinalize(out var errors))
else if (!input.TryFinalizeInput(out var err))
{
vm.SetErrors(errors);
sanityErrors.Add(err[0]);
}
}
if (sanityErrors.Count > 0)
vm.SetErrors(sanityErrors);
}
var combinedTypeIds = inputToObjects.Values.SelectMany(ids => ids).Concat(outputToObjects.Values)

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
@@ -1289,6 +1290,9 @@ namespace BTCPayServer.Controllers
ChangeAddress = psbtResponse.ChangeAddress?.ToString(),
PSBT = psbt.ToHex()
};
if (!psbt.IsReadyToSign() && command == "sign")
command = "analyze-psbt";
switch (command)
{
case "createpending":
@@ -1512,9 +1516,9 @@ namespace BTCPayServer.Controllers
var psbt = PSBT.Parse(viewModel.SigningContext.PSBT, network.NBitcoinNetwork);
if (!psbt.IsReadyToSign())
if (!psbt.IsReadyToSign(out var errors))
{
ModelState.AddModelError(nameof(viewModel.SigningContext.PSBT), "PSBT is not ready to be signed");
ModelState.AddModelError(nameof(viewModel.SigningContext.PSBT), BuildErrorMessage(errors));
}
if (!ModelState.IsValid)
@@ -1580,6 +1584,27 @@ namespace BTCPayServer.Controllers
});
}
private static string BuildErrorMessage(PSBTError[] errors)
{
StringBuilder errorMessage = new();
errorMessage.Append("PSBT is not ready to be signed.");
if (errors.Length == 1)
{
errorMessage.Append($" ({errors[0]})");
}
else
{
errorMessage.AppendLine();
foreach (var error in errors.Take(5))
{
errorMessage.AppendLine(error.ToString());
}
}
if (errors.Length > 5)
errorMessage.Append($"{errors.Length - 5} more errors...");
return errorMessage.ToString();
}
private WalletPSBTReadyViewModel.StringAmounts ValueToString(Money v, BTCPayNetworkBase network,
FiatRate? rate) =>
new(