Include XPubs in PSBTs for multi sig (#6696)

This commit is contained in:
Nicolas Dorier
2025-04-24 21:36:09 +09:00
committed by GitHub
parent 818d65a4f9
commit dd6c4c771e
7 changed files with 25 additions and 19 deletions

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -19,7 +18,7 @@ namespace BTCPayServer.Blazor.VaultBridge;
public abstract class HWIController : VaultController
{
override protected string VaultUri => "http://127.0.0.1:65092/hwi-bridge/v1";
protected override string VaultUri => "http://127.0.0.1:65092/hwi-bridge/v1";
public string CryptoCode { get; set; }
private static bool IsTrezorT(HwiEnumerateEntry deviceEntry)
@@ -41,7 +40,7 @@ public abstract class HWIController : VaultController
try
{
var network = networkProviders.GetNetwork<BTCPayNetwork>(CryptoCode);
var hwi = new Hwi.HwiClient(network.NBitcoinNetwork)
var hwi = new HwiClient(network.NBitcoinNetwork)
{
Transport = new VaultHWITransport(vaultClient), IgnoreInvalidNetwork = network.NBitcoinNetwork.ChainName != ChainName.Mainnet
};
@@ -206,7 +205,6 @@ public class SignHWIController : HWIController
ui.ShowRetry();
return;
}
derivationSettings.RebaseKeyPaths(psbt);
// otherwise, let the device check if it can sign anything
var signableInputs = psbt.Inputs
@@ -227,7 +225,7 @@ public class SignHWIController : HWIController
if (derivationSettings.IsMultiSigOnServer)
{
var alreadySigned = psbt.Inputs.Any(a =>
a.PartialSigs.Any(a => a.Key == actualPubKey));
a.PartialSigs.Any(o => o.Key == actualPubKey));
if (alreadySigned)
{
ui.ShowFeedback(FeedbackType.Failed, ui.StringLocalizer["This device already signed PSBT."]);

View File

@@ -540,7 +540,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
SelectedInputs = request.SelectedInputs?.Select(point => point.ToString()),
Outputs = outputs,
AlwaysIncludeNonWitnessUTXO = true,
AlwaysIncludeNonWitnessUTXO = derivationScheme.DefaultIncludeNonWitnessUtxo,
InputSelection = request.SelectedInputs?.Any() is true,
FeeSatoshiPerByte = request.FeeRate?.SatoshiPerByte,
NoChange = request.NoChange

View File

@@ -27,7 +27,12 @@ namespace BTCPayServer.Controllers
public async Task<CreatePSBTResponse> CreatePSBT(BTCPayNetwork network, DerivationSchemeSettings derivationSettings, WalletSendModel sendModel, CancellationToken cancellationToken)
{
var nbx = ExplorerClientProvider.GetExplorerClient(network);
CreatePSBTRequest psbtRequest = new();
var psbtRequest = new CreatePSBTRequest()
{
RBF = network.SupportRBF ? true : null,
AlwaysIncludeNonWitnessUTXO = sendModel.AlwaysIncludeNonWitnessUTXO,
IncludeGlobalXPub = derivationSettings.IsMultiSigOnServer,
};
if (sendModel.InputSelection)
{
psbtRequest.IncludeOnlyOutpoints = sendModel.SelectedInputs?.Select(OutPoint.Parse).ToList() ?? new List<OutPoint>();
@@ -40,8 +45,6 @@ namespace BTCPayServer.Controllers
psbtDestination.Amount = Money.Coins(transactionOutput.Amount ?? 0.0m);
psbtDestination.SubstractFees = transactionOutput.SubtractFeesFromOutput;
}
psbtRequest.RBF = network.SupportRBF ? true : null;
psbtRequest.AlwaysIncludeNonWitnessUTXO = sendModel.AlwaysIncludeNonWitnessUTXO;
psbtRequest.FeePreference = new FeePreference();
if (sendModel.FeeSatoshiPerByte is decimal v and > decimal.Zero)
@@ -56,8 +59,7 @@ namespace BTCPayServer.Controllers
var psbt = (await nbx.CreatePSBTAsync(derivationSettings.AccountDerivation, psbtRequest, cancellationToken));
if (psbt == null)
throw new NotSupportedException(StringLocalizer["You need to update your version of NBXplorer"]);
// Not supported by coldcard, remove when they do support it
psbt.PSBT.GlobalXPubs.Clear();
return psbt;
}

View File

@@ -316,6 +316,7 @@ namespace BTCPayServer.Controllers
{
RBF = true,
AlwaysIncludeNonWitnessUTXO = paymentMethod.DefaultIncludeNonWitnessUtxo,
IncludeGlobalXPub = paymentMethod.IsMultiSigOnServer,
IncludeOnlyOutpoints = bumpableUTXOs,
SpendAllMatchingOutpoints = true,
FeePreference = new FeePreference()
@@ -369,6 +370,7 @@ namespace BTCPayServer.Controllers
{
RBF = true,
AlwaysIncludeNonWitnessUTXO = paymentMethod.DefaultIncludeNonWitnessUtxo,
IncludeGlobalXPub = paymentMethod.IsMultiSigOnServer,
IncludeOnlyOutpoints = tx.Transaction.Inputs.Select(i => i.PrevOut).ToList(),
SpendAllMatchingOutpoints = true,
DisableFingerprintRandomization = true,
@@ -1329,6 +1331,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> WalletSendVault([ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId,
WalletSendVaultModel model)
{
TempData.SetStatusSuccess(StringLocalizer["Transaction successfully signed"].Value);
return await RedirectToWalletPSBTReady(walletId, new WalletPSBTReadyViewModel
{
SigningContext = model.SigningContext,

View File

@@ -554,7 +554,8 @@ namespace BTCPayServer
{
PSBT = psbt,
DerivationScheme = derivationSchemeSettings.AccountDerivation,
AlwaysIncludeNonWitnessUTXO = true
AlwaysIncludeNonWitnessUTXO = true,
IncludeGlobalXPub = derivationSchemeSettings.IsMultiSigOnServer
});
if (result == null)
return null;

View File

@@ -1610,6 +1610,7 @@ namespace BTCPayServer.Services
"Transaction fee rate:": "",
"Transaction Id": "",
"Transaction signed successfully, proceeding to review...": "",
"Transaction successfully signed": "",
"transactions": "",
"Translations": "",
"Translations are formatted as JSON; for example, <b>{0}</b> translates <b>{1}</b> to <b>{2}</b>.": "",

View File

@@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HWI/@EntryIndexedValue">HWI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LNURL/@EntryIndexedValue">LNURL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NB/@EntryIndexedValue">NBX</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NBXplorer/@EntryIndexedValue">NBXplorer</s:String>