From 6dd7ef183afb5a9982fc6b67a8c869f5deffe1e0 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 21 Nov 2024 14:36:25 -0600 Subject: [PATCH] fix probable infinite loop causing view only refresh to stay stuck forever --- lib/pages/receive_view/receive_view.dart | 27 +++++++++++++++--- .../sub_widgets/desktop_receive.dart | 26 ++++++++++++++--- .../wallet/intermediate/bip39_hd_wallet.dart | 28 +++++++++++++++++++ .../extended_keys_interface.dart | 9 ++++++ 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index 636a05ab8..43a5c6c8d 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -35,6 +35,7 @@ import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/wallet/impl/bitcoin_wallet.dart'; import '../../wallets/wallet/intermediate/bip39_hd_wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart'; +import '../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -109,11 +110,29 @@ class _ReceiveViewState extends ConsumerState { final Address? address; if (wallet is Bip39HDWallet && wallet is! BCashInterface) { - final type = DerivePathType.values.firstWhere( - (e) => e.getAddressType() == _walletAddressTypes[_currentIndex], - ); + DerivePathType? type; + if (wallet.isViewOnly && wallet is ExtendedKeysInterface) { + final voData = await wallet.getViewOnlyWalletData() + as ExtendedKeysViewOnlyWalletData; + for (final t in wallet.cryptoCurrency.supportedDerivationPathTypes) { + final testPath = wallet.cryptoCurrency.constructDerivePath( + derivePathType: t, + chain: 0, + index: 0, + ); + if (testPath.startsWith(voData.xPubs.first.path)) { + type = t; + break; + } + } + } else { + type = DerivePathType.values.firstWhere( + (e) => e.getAddressType() == _walletAddressTypes[_currentIndex], + ); + } + address = await wallet.generateNextReceivingAddress( - derivePathType: type, + derivePathType: type!, ); final isar = ref.read(mainDBProvider).isar; await isar.writeTxn(() async { diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart index 87f62a6f4..b90cc2f6a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart @@ -39,6 +39,7 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/impl/bitcoin_wallet.dart'; import '../../../../wallets/wallet/intermediate/bip39_hd_wallet.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/bcash_interface.dart'; +import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart'; @@ -106,11 +107,28 @@ class _DesktopReceiveState extends ConsumerState { final Address? address; if (wallet is Bip39HDWallet && wallet is! BCashInterface) { - final type = DerivePathType.values.firstWhere( - (e) => e.getAddressType() == _walletAddressTypes[_currentIndex], - ); + DerivePathType? type; + if (wallet.isViewOnly && wallet is ExtendedKeysInterface) { + final voData = await wallet.getViewOnlyWalletData() + as ExtendedKeysViewOnlyWalletData; + for (final t in wallet.cryptoCurrency.supportedDerivationPathTypes) { + final testPath = wallet.cryptoCurrency.constructDerivePath( + derivePathType: t, + chain: 0, + index: 0, + ); + if (testPath.startsWith(voData.xPubs.first.path)) { + type = t; + break; + } + } + } else { + type = DerivePathType.values.firstWhere( + (e) => e.getAddressType() == _walletAddressTypes[_currentIndex], + ); + } address = await wallet.generateNextReceivingAddress( - derivePathType: type, + derivePathType: type!, ); final isar = ref.read(mainDBProvider).isar; await isar.writeTxn(() async { diff --git a/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart b/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart index e270cb7c9..832ce3e13 100644 --- a/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart +++ b/lib/wallets/wallet/intermediate/bip39_hd_wallet.dart @@ -76,6 +76,34 @@ abstract class Bip39HDWallet extends Bip39Wallet return address; } + @override + List get standardReceivingAddressFilters => [ + // view only only have a single derivation path currently + if (!isViewOnly) + FilterCondition.equalTo( + property: r"type", + value: info.mainAddressType, + ), + const FilterCondition.equalTo( + property: r"subType", + value: AddressSubType.receiving, + ), + ]; + + @override + List get standardChangeAddressFilters => [ + // view only only have a single derivation path currently + if (!isViewOnly) + FilterCondition.equalTo( + property: r"type", + value: info.mainAddressType, + ), + const FilterCondition.equalTo( + property: r"subType", + value: AddressSubType.change, + ), + ]; + /// Generates a receiving address. If none /// are in the current wallet db it will generate at index 0, otherwise the /// highest index found in the current wallet db. diff --git a/lib/wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart b/lib/wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart index 8b41dc122..affb6d7de 100644 --- a/lib/wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart +++ b/lib/wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart @@ -5,16 +5,25 @@ import 'electrumx_interface.dart'; abstract class XKey { XKey({required this.path}); final String path; + + @override + String toString() => "Path: $path"; } class XPub extends XKey { XPub({required super.path, required this.encoded}); final String encoded; + + @override + String toString() => "XPub { path: $path, encoded: $encoded }"; } class XPriv extends XKey { XPriv({required super.path, required this.encoded}); final String encoded; + + @override + String toString() => "XPriv { path: $path, encoded: $encoded }"; } mixin ExtendedKeysInterface