Fix: No need to select the Signing Key for signing through multi sig process (#6674)

This commit is contained in:
Nicolas Dorier
2025-04-21 17:11:50 +09:00
committed by GitHub
parent 541e514d9f
commit a2d94a265b
5 changed files with 35 additions and 24 deletions

View File

@@ -93,7 +93,7 @@ namespace BTCPayServer.Controllers.Greenfield
request.ExistingMnemonic is null ? "NBXplorerGenerated" : "ImportedSeed"; request.ExistingMnemonic is null ? "NBXplorerGenerated" : "ImportedSeed";
derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys; derivationSchemeSettings.IsHotWallet = request.SavePrivateKeys;
derivationSchemeSettings.Label = request.Label; derivationSchemeSettings.Label = request.Label;
var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings(); var accountSettings = derivationSchemeSettings.AccountKeySettings[0];
accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath; accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath;
accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint; accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint;
derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString(); derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString();

View File

@@ -582,9 +582,13 @@ namespace BTCPayServer.Controllers.Greenfield
var signingKey = ExtKey.Parse(signingKeyStr, network.NBitcoinNetwork); var signingKey = ExtKey.Parse(signingKeyStr, network.NBitcoinNetwork);
var signingKeySettings = derivationScheme.GetSigningAccountKeySettings(); var signingKeySettings = derivationScheme.GetSigningAccountKeySettings(signingKey);
signingKeySettings.RootFingerprint ??= signingKey.GetPublicKey().GetHDFingerPrint(); RootedKeyPath? rootedKeyPath = signingKeySettings?.GetRootedKeyPath();
RootedKeyPath rootedKeyPath = signingKeySettings.GetRootedKeyPath(); if (rootedKeyPath is null || signingKeySettings is null)
{
return this.CreateAPIError(503, "not-available",
"The private key saved for this wallet doesn't match the derivation scheme");
}
psbt.PSBT.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath); psbt.PSBT.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
var accountKey = signingKey.Derive(rootedKeyPath.KeyPath); var accountKey = signingKey.Derive(rootedKeyPath.KeyPath);

View File

@@ -310,7 +310,7 @@ public partial class UIStoresController
derivationSchemeSettings.IsHotWallet = method == WalletSetupMethod.HotWallet; derivationSchemeSettings.IsHotWallet = method == WalletSetupMethod.HotWallet;
} }
var accountSettings = derivationSchemeSettings.GetSigningAccountKeySettings(); var accountSettings = derivationSchemeSettings.AccountKeySettings[0];
accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath; accountSettings.AccountKeyPath = response.AccountKeyPath.KeyPath;
accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint; accountSettings.RootFingerprint = response.AccountKeyPath.MasterFingerprint;
derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString(); derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString();

View File

@@ -1476,29 +1476,26 @@ namespace BTCPayServer.Controllers
var settings = GetDerivationSchemeSettings(walletId); var settings = GetDerivationSchemeSettings(walletId);
if (settings is null) if (settings is null)
return NotFound(); return NotFound();
var signingKeySettings = settings.GetSigningAccountKeySettings(); var signingKeySettings = settings.GetSigningAccountKeySettings(extKey);
if (signingKeySettings.RootFingerprint is null) if (signingKeySettings is null)
signingKeySettings.RootFingerprint = extKey.GetPublicKey().GetHDFingerPrint(); {
// Let's try best effort if RootFingerprint isn't configured, but AccountKeyPath is
RootedKeyPath rootedKeyPath = signingKeySettings.GetRootedKeyPath(); signingKeySettings = settings.AccountKeySettings
if (rootedKeyPath == null) .Where(a => a.RootFingerprint is null && a.AccountKeyPath is not null)
.FirstOrDefault();
if (signingKeySettings is not null)
signingKeySettings.RootFingerprint = extKey.GetPublicKey().GetHDFingerPrint();
}
RootedKeyPath? rootedKeyPath = signingKeySettings?.GetRootedKeyPath();
if (rootedKeyPath is null || signingKeySettings is null)
{ {
ModelState.AddModelError(nameof(viewModel.SeedOrKey), ModelState.AddModelError(nameof(viewModel.SeedOrKey),
"The master fingerprint and/or account key path of your seed are not set in the wallet settings."); "The master fingerprint and/or account key path of your seed are not set in the wallet settings.");
return View(nameof(SignWithSeed), viewModel); return View(nameof(SignWithSeed), viewModel);
} }
// The user gave the root key, let's try to rebase the PSBT, and derive the account private key // The user gave the root key, let's try to rebase the PSBT, and derive the account private key
if (rootedKeyPath.MasterFingerprint == extKey.GetPublicKey().GetHDFingerPrint()) psbt.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
{ signingKey = extKey.Derive(rootedKeyPath.KeyPath);
psbt.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
signingKey = extKey.Derive(rootedKeyPath.KeyPath);
}
else
{
ModelState.AddModelError(nameof(viewModel.SeedOrKey),
"The master fingerprint does not match the one set in your wallet settings. Probable causes are: wrong seed, wrong passphrase or wrong fingerprint in your wallet settings.");
return View(nameof(SignWithSeed), viewModel);
}
psbt.Settings.SigningOptions = new SigningOptions() psbt.Settings.SigningOptions = new SigningOptions()
{ {

View File

@@ -78,16 +78,26 @@ namespace BTCPayServer
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public BitcoinExtPubKey ExplicitAccountKey { get; set; } public BitcoinExtPubKey ExplicitAccountKey { get; set; }
#nullable enable
public AccountKeySettings GetSigningAccountKeySettings() public AccountKeySettings GetSigningAccountKeySettings()
{ {
return (AccountKeySettings ?? []).Single(a => a.AccountKey == SigningKey); return (AccountKeySettings ?? []).Single(a => a.AccountKey == SigningKey);
} }
public AccountKeySettings GetSigningAccountKeySettingsOrDefault() public AccountKeySettings? GetSigningAccountKeySettings(IHDKey rootKey)
=> GetSigningAccountKeySettings(rootKey.GetPublicKey().GetHDFingerPrint());
public AccountKeySettings? GetSigningAccountKeySettings(HDFingerprint rootFingerprint)
{
return (AccountKeySettings ?? []).Where(a => a.RootFingerprint == rootFingerprint).FirstOrDefault();
}
public AccountKeySettings? GetSigningAccountKeySettingsOrDefault()
{ {
return (AccountKeySettings ?? []).SingleOrDefault(a => a.AccountKey == SigningKey); return (AccountKeySettings ?? []).SingleOrDefault(a => a.AccountKey == SigningKey);
} }
#nullable restore
public AccountKeySettings[] AccountKeySettings { get; set; } public AccountKeySettings[] AccountKeySettings { get; set; }
public IEnumerable<NBXplorer.Models.PSBTRebaseKeyRules> GetPSBTRebaseKeyRules() public IEnumerable<NBXplorer.Models.PSBTRebaseKeyRules> GetPSBTRebaseKeyRules()