From ff82f15246d54b6712724e8d03f162b6b516986c Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Sun, 12 May 2019 11:07:41 +0900 Subject: [PATCH] Always rebase keys before signing, refacotring some code --- BTCPayServer/Controllers/WalletsController.cs | 46 +++++++++---------- BTCPayServer/DerivationSchemeSettings.cs | 21 +++++++++ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index d108af089..7c79c545f 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -117,8 +117,7 @@ namespace BTCPayServer.Controllers [ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId) { - var store = await Repository.FindStore(walletId.StoreId, GetUserId()); - DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store); + DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId); if (paymentMethod == null) return NotFound(); @@ -151,7 +150,7 @@ namespace BTCPayServer.Controllers if (walletId?.StoreId == null) return NotFound(); var store = await Repository.FindStore(walletId.StoreId, GetUserId()); - DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store); + DerivationSchemeSettings paymentMethod = GetDerivationSchemeSettings(walletId, store); if (paymentMethod == null) return NotFound(); var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode); @@ -227,8 +226,7 @@ namespace BTCPayServer.Controllers if (!ModelState.IsValid) return View(vm); - var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); - var derivationScheme = GetPaymentMethod(walletId, storeData); + DerivationSchemeSettings derivationScheme = await GetDerivationSchemeSettings(walletId); var psbt = await CreatePSBT(network, derivationScheme, vm, cancellation); if (command == "ledger") @@ -241,6 +239,7 @@ namespace BTCPayServer.Controllers { if (command == "analyze-psbt") return ViewPSBT(psbt.PSBT); + derivationScheme.RebaseKeyPaths(psbt.PSBT); return FilePSBT(psbt.PSBT, $"Send-{vm.Amount.Value}-{network.CryptoCode}-to-{destination[0].ToString()}.psbt"); } catch (NBXplorerException ex) @@ -306,18 +305,7 @@ namespace BTCPayServer.Controllers psbtRequest.ExplicitChangeAddress = psbtDestination.Destination; } psbtDestination.SubstractFees = sendModel.SubstractFees; - if (derivationSettings.AccountKeyPath != null && derivationSettings.AccountKeyPath.Indexes.Length != 0) - { - psbtRequest.RebaseKeyPaths = new List() - { - new PSBTRebaseKeyRules() - { - AccountKeyPath = derivationSettings.AccountKeyPath, - AccountKey = derivationSettings.AccountKey, - MasterFingerprint = derivationSettings.RootFingerprint is HDFingerprint fp ? fp : default - } - }; - } + psbtRequest.RebaseKeyPaths = derivationSettings.GetPSBTRebaseKeyRules().ToList(); var psbt = (await nbx.CreatePSBTAsync(derivationSettings.AccountDerivation, psbtRequest, cancellationToken)); if (psbt == null) throw new NotSupportedException("You need to update your version of NBXplorer"); @@ -400,6 +388,7 @@ namespace BTCPayServer.Controllers } else { + (await GetDerivationSchemeSettings(walletId)).RebaseKeyPaths(psbt); return FilePSBT(psbt, "psbt-export.psbt"); } } @@ -410,8 +399,7 @@ namespace BTCPayServer.Controllers if (transaction != null) { var wallet = _walletProvider.GetWallet(network); - var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); - var derivationSettings = GetPaymentMethod(walletId, storeData); + var derivationSettings = await GetDerivationSchemeSettings(walletId); wallet.InvalidateCache(derivationSettings.AccountDerivation); StatusMessage = $"Transaction broadcasted successfully ({transaction.GetHash().ToString()})"; } @@ -492,8 +480,7 @@ namespace BTCPayServer.Controllers { if (walletId?.StoreId == null) return NotFound(); - var store = await Repository.FindStore(walletId.StoreId, GetUserId()); - DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store); + DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId); if (paymentMethod == null) return NotFound(); @@ -536,8 +523,7 @@ namespace BTCPayServer.Controllers { if (walletId?.StoreId == null) return NotFound(); - var store = await Repository.FindStore(walletId.StoreId, GetUserId()); - DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store); + DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId); if (paymentMethod == null) return NotFound(); var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode); @@ -565,7 +551,7 @@ namespace BTCPayServer.Controllers return null; } - private DerivationSchemeSettings GetPaymentMethod(WalletId walletId, StoreData store) + private DerivationSchemeSettings GetDerivationSchemeSettings(WalletId walletId, StoreData store) { if (store == null || !store.HasClaim(Policies.CanModifyStoreSettings.Key)) return null; @@ -577,6 +563,12 @@ namespace BTCPayServer.Controllers return paymentMethod; } + private async Task GetDerivationSchemeSettings(WalletId walletId) + { + var store = (await Repository.FindStore(walletId.StoreId, GetUserId())); + return GetDerivationSchemeSettings(walletId, store); + } + private static async Task GetBalanceString(BTCPayWallet wallet, DerivationStrategyBase derivationStrategy) { using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))) @@ -618,7 +610,7 @@ namespace BTCPayServer.Controllers if (network == null) throw new FormatException("Invalid value for crypto code"); var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); - var derivationSettings = GetPaymentMethod(walletId, storeData); + var derivationSettings = GetDerivationSchemeSettings(walletId, storeData); var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); @@ -685,6 +677,10 @@ namespace BTCPayServer.Controllers PSBT = PSBT.Parse(psbt, network.NBitcoinNetwork), ChangeAddress = string.IsNullOrEmpty(hintChange) ? null : BitcoinAddress.Create(hintChange, network.NBitcoinNetwork) }; + + + derivationSettings.RebaseKeyPaths(psbtResponse.PSBT); + signTimeout.CancelAfter(TimeSpan.FromMinutes(5)); psbtResponse.PSBT = await hw.SignTransactionAsync(psbtResponse.PSBT, psbtResponse.ChangeAddress?.ScriptPubKey, signTimeout.Token); result = new SendToAddressResult() { PSBT = psbtResponse.PSBT.ToBase64() }; diff --git a/BTCPayServer/DerivationSchemeSettings.cs b/BTCPayServer/DerivationSchemeSettings.cs index 7f2c52951..016cd3eee 100644 --- a/BTCPayServer/DerivationSchemeSettings.cs +++ b/BTCPayServer/DerivationSchemeSettings.cs @@ -143,6 +143,19 @@ namespace BTCPayServer } } + public IEnumerable GetPSBTRebaseKeyRules() + { + if (AccountKey != null && AccountKeyPath != null && RootFingerprint is HDFingerprint fp) + { + yield return new NBXplorer.Models.PSBTRebaseKeyRules() + { + AccountKey = AccountKey, + AccountKeyPath = AccountKeyPath, + MasterFingerprint = fp + }; + } + } + public string Label { get; set; } [JsonIgnore] @@ -163,5 +176,13 @@ namespace BTCPayServer { return Network.NBXplorerNetwork.Serializer.ToString(this); } + + public void RebaseKeyPaths(PSBT psbt) + { + foreach (var rebase in GetPSBTRebaseKeyRules()) + { + psbt.RebaseKeyPaths(rebase.AccountKey, rebase.AccountKeyPath, rebase.MasterFingerprint); + } + } } }