From b423b4eec123a841bf4ab298f1d79a98fae5eb48 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Sun, 4 Nov 2018 14:59:28 +0900 Subject: [PATCH] Do not allow rescan of wallet which are not segwit --- BTCPayServer.Tests/TestAccount.cs | 8 ++++---- BTCPayServer.Tests/UnitTest1.cs | 5 +++-- BTCPayServer/Controllers/WalletsController.cs | 3 +++ BTCPayServer/Extensions.cs | 14 ++++++++++++++ .../Models/WalletViewModels/RescanWalletModel.cs | 3 ++- BTCPayServer/Views/Wallets/WalletRescan.cshtml | 8 ++++++++ 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs index 5840dba42..5669a8818 100644 --- a/BTCPayServer.Tests/TestAccount.cs +++ b/BTCPayServer.Tests/TestAccount.cs @@ -73,16 +73,16 @@ namespace BTCPayServer.Tests public BTCPayNetwork SupportedNetwork { get; set; } - public WalletId RegisterDerivationScheme(string crytoCode) + public WalletId RegisterDerivationScheme(string crytoCode, bool segwit = false) { - return RegisterDerivationSchemeAsync(crytoCode).GetAwaiter().GetResult(); + return RegisterDerivationSchemeAsync(crytoCode, segwit).GetAwaiter().GetResult(); } - public async Task RegisterDerivationSchemeAsync(string cryptoCode) + public async Task RegisterDerivationSchemeAsync(string cryptoCode, bool segwit = false) { SupportedNetwork = parent.NetworkProvider.GetNetwork(cryptoCode); var store = parent.PayTester.GetController(UserId, StoreId); ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork); - DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + "-[legacy]"); + DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + (segwit ? "" : "-[legacy]")); var vm = (StoreViewModel)((ViewResult)store.UpdateStore()).Model; vm.SpeedPolicy = SpeedPolicy.MediumSpeed; await store.UpdateStore(vm); diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 25ce56b17..6eadcfadb 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -593,15 +593,16 @@ namespace BTCPayServer.Tests tester.Start(); var acc = tester.NewAccount(); acc.GrantAccess(); - acc.RegisterDerivationScheme("BTC"); + acc.RegisterDerivationScheme("BTC", true); var btcDerivationScheme = acc.DerivationScheme; - acc.RegisterDerivationScheme("LTC"); + acc.RegisterDerivationScheme("LTC", true); var walletController = tester.PayTester.GetController(acc.UserId); WalletId walletId = new WalletId(acc.StoreId, "LTC"); var rescan = Assert.IsType(Assert.IsType(walletController.WalletRescan(walletId).Result).Model); Assert.False(rescan.Ok); Assert.True(rescan.IsFullySync); + Assert.True(rescan.IsSegwit); Assert.False(rescan.IsSupportedByCurrency); Assert.False(rescan.IsServerAdmin); diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index bd98a3bdc..8b89fb25f 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -280,6 +280,9 @@ namespace BTCPayServer.Controllers var vm = new RescanWalletModel(); vm.IsFullySync = _dashboard.IsFullySynched(); + // We need to ensure it is segwit, + // because hardware wallet support need the parent transactions to sign, which NBXplorer don't have. (Nor does a pruned node) + vm.IsSegwit = paymentMethod.DerivationStrategyBase.IsSegwit(); vm.IsServerAdmin = User.Claims.Any(c => c.Type == Policies.CanModifyServerSettings.Key && c.Value == "true"); vm.IsSupportedByCurrency = _dashboard.Get(walletId.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanScanTxoutSet == true; var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode); diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index 0769b8379..8e7b694e4 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -32,6 +32,7 @@ using System.Globalization; using BTCPayServer.Services; using BTCPayServer.Data; using Microsoft.EntityFrameworkCore.Infrastructure; +using NBXplorer.DerivationStrategy; namespace BTCPayServer { @@ -128,6 +129,19 @@ namespace BTCPayServer resp.Headers[name] = value; } + public static bool IsSegwit(this DerivationStrategyBase derivationStrategyBase) + { + if (IsSegwitCore(derivationStrategyBase)) + return true; + return (derivationStrategyBase is P2SHDerivationStrategy p2shStrat && IsSegwitCore(p2shStrat.Inner)); + } + + private static bool IsSegwitCore(DerivationStrategyBase derivationStrategyBase) + { + return (derivationStrategyBase is P2WSHDerivationStrategy) || + (derivationStrategyBase is DirectDerivationStrategy direct) && direct.Segwit; + } + public static string GetAbsoluteRoot(this HttpRequest request) { return string.Concat( diff --git a/BTCPayServer/Models/WalletViewModels/RescanWalletModel.cs b/BTCPayServer/Models/WalletViewModels/RescanWalletModel.cs index 26e855279..ea2b41d1d 100644 --- a/BTCPayServer/Models/WalletViewModels/RescanWalletModel.cs +++ b/BTCPayServer/Models/WalletViewModels/RescanWalletModel.cs @@ -12,7 +12,8 @@ namespace BTCPayServer.Models.WalletViewModels public bool IsServerAdmin { get; set; } public bool IsSupportedByCurrency { get; set; } public bool IsFullySync { get; set; } - public bool Ok => IsServerAdmin && IsSupportedByCurrency && IsFullySync; + public bool IsSegwit { get; set; } + public bool Ok => IsServerAdmin && IsSupportedByCurrency && IsFullySync && IsSegwit; [Range(1000, 10_000)] public int BatchSize { get; set; } = 3000; diff --git a/BTCPayServer/Views/Wallets/WalletRescan.cshtml b/BTCPayServer/Views/Wallets/WalletRescan.cshtml index d03e6bdc3..8f11b3f3f 100644 --- a/BTCPayServer/Views/Wallets/WalletRescan.cshtml +++ b/BTCPayServer/Views/Wallets/WalletRescan.cshtml @@ -36,6 +36,14 @@ {

This full node do not support rescan of the UTXO set

} + @if (Model.IsSegwit) + { +

This wallet is compatible with segwit

+ } + else + { +

This wallet is not compatible with segwit

+ } }