From 68e20b25c3c0035449fb34ec6133a4c34a4dac97 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 9 May 2024 08:59:49 -0700 Subject: [PATCH] remove duplicate references to electrum path for maintainability --- cw_bitcoin/lib/bitcoin_wallet.dart | 52 +++++++++++--------- cw_bitcoin/lib/electrum_wallet.dart | 11 +++-- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 9 ++-- lib/bitcoin/cw_bitcoin.dart | 12 ++--- lib/view_model/wallet_creation_vm.dart | 6 +-- tool/configure.dart | 1 + 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 8576f81d7..ea2c60642 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -2,6 +2,7 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:convert/convert.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/psbt_transaction_builder.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -39,21 +40,21 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { Map? initialChangeAddressIndex, String? passphrase, }) : super( - mnemonic: mnemonic, - passphrase: passphrase, - xpub: xpub, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - networkType: networkParam == null - ? bitcoin.bitcoin - : networkParam == BitcoinNetwork.mainnet - ? bitcoin.bitcoin - : bitcoin.testnet, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: seedBytes, - currency: CryptoCurrency.btc) { + mnemonic: mnemonic, + passphrase: passphrase, + xpub: xpub, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + networkType: networkParam == null + ? bitcoin.bitcoin + : networkParam == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : bitcoin.testnet, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: seedBytes, + currency: CryptoCurrency.btc) { walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, @@ -129,7 +130,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { ); // set the default if not present: - walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'"; + final electrumPath = electrum_derivations[DerivationType.electrum]!.first.derivationPath!; + walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? electrumPath; walletInfo.derivationInfo!.derivationType = snp.derivationType ?? DerivationType.electrum; Uint8List? seedBytes = null; @@ -177,7 +179,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { void setLedger(Ledger setLedger, LedgerDevice setLedgerDevice) { _ledger = setLedger; _ledgerDevice = setLedgerDevice; - _bitcoinLedgerApp = BitcoinLedgerApp(_ledger!, derivationPath: walletInfo.derivationInfo!.derivationPath!); + _bitcoinLedgerApp = + BitcoinLedgerApp(_ledger!, derivationPath: walletInfo.derivationInfo!.derivationPath!); } @override @@ -200,16 +203,17 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!; psbtReadyInputs.add(PSBTReadyUtxoWithAddress( - utxo: utxo.utxo, - rawTx: rawTx, - ownerDetails: utxo.ownerDetails, - ownerDerivationPath: publicKeyAndDerivationPath.derivationPath, - ownerMasterFingerprint: masterFingerprint, - ownerPublicKey: publicKeyAndDerivationPath.publicKey, + utxo: utxo.utxo, + rawTx: rawTx, + ownerDetails: utxo.ownerDetails, + ownerDerivationPath: publicKeyAndDerivationPath.derivationPath, + ownerMasterFingerprint: masterFingerprint, + ownerPublicKey: publicKeyAndDerivationPath.publicKey, )); } - final psbt = PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF); + final psbt = + PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF); final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt); return BtcTransaction.fromRaw(hex.encode(rawHex)); diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index d6a2e42ce..2b86570f9 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -17,6 +17,7 @@ import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; @@ -51,7 +52,6 @@ class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet; abstract class ElectrumWalletBase extends WalletBase with Store { - String ELECTRUM_DERIVATION = "m/0'"; ElectrumWalletBase( {required String password, required WalletInfo walletInfo, @@ -102,10 +102,11 @@ abstract class ElectrumWalletBase } if (seedBytes != null) { + final electrumPath = electrum_derivations[DerivationType.electrum]!.first.derivationPath!; return currency == CryptoCurrency.bch ? bitcoinCashHDWallet(seedBytes) : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath(_hardenedDerivationPath(derivationInfo?.derivationPath ?? "m/0'")); + .derivePath(_hardenedDerivationPath(derivationInfo?.derivationPath ?? electrumPath)); } return bitcoin.HDWallet.fromBase58(xpub!); @@ -249,8 +250,9 @@ abstract class ElectrumWalletBase final address = addressTypeFromStr(utx.address, network); final hd = utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd; + final electrumPath = electrum_derivations[DerivationType.electrum]!.first.derivationPath!; final derivationPath = - "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}" + "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? electrumPath)}" "/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}" "/${utx.bitcoinAddressRecord.index}"; final pubKeyHex = hd.derive(utx.bitcoinAddressRecord.index).pubKey!; @@ -378,8 +380,9 @@ abstract class ElectrumWalletBase final hd = utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd; + final electrumPath = electrum_derivations[DerivationType.electrum]!.first.derivationPath!; final derivationPath = - "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}" + "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? electrumPath)}" "/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}" "/${utx.bitcoinAddressRecord.index}"; final pubKeyHex = hd.derive(utx.bitcoinAddressRecord.index).pubKey!; diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 0b469eab7..92548784e 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; +import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/utils/file.dart'; @@ -57,9 +59,10 @@ class ElectrumWalletSnapshot { var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; - final derivationType = - DerivationType.values[(data['derivationTypeIndex'] as int?) ?? DerivationType.electrum.index]; - final derivationPath = data['derivationPath'] as String? ?? "m/0'"; + final electrumPath = electrum_derivations[DerivationType.electrum]!.first.derivationPath!; + final derivationType = DerivationType + .values[(data['derivationTypeIndex'] as int?) ?? DerivationType.electrum.index]; + final derivationPath = data['derivationPath'] as String? ?? electrumPath; try { regularAddressIndexByType = { diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 56c9c7dff..f24b653bd 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -298,12 +298,7 @@ class CWBitcoin extends Bitcoin { List types = await compareDerivationMethods(mnemonic: mnemonic, node: node); if (types.length == 1 && types.first == DerivationType.electrum) { return [ - DerivationInfo( - derivationType: DerivationType.electrum, - derivationPath: "m/0'", - description: "Electrum", - scriptType: "p2wpkh", - ) + electrum_derivations[DerivationType.electrum]!.first ]; } @@ -395,6 +390,11 @@ class CWBitcoin extends Bitcoin { return list; } + @override + Map> getElectrumDerivations() { + return electrum_derivations; + } + @override bool hasTaprootInput(PendingTransaction pendingTransaction) { return (pendingTransaction as PendingBitcoinTransaction).hasTaprootInputs; diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index f825f0c47..841a88e7e 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; @@ -98,10 +99,7 @@ abstract class WalletCreationVMBase with Store { ); case WalletType.bitcoin: case WalletType.litecoin: - return DerivationInfo( - derivationType: DerivationType.electrum, - derivationPath: "m/0'", - ); + return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first; default: return null; } diff --git a/tool/configure.dart b/tool/configure.dart index 126851997..c04f5dcd1 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -186,6 +186,7 @@ abstract class Bitcoin { {required String mnemonic, required Node node}); Future> getDerivationsFromMnemonic( {required String mnemonic, required Node node, String? passphrase}); + Map> getElectrumDerivations(); Future setAddressType(Object wallet, dynamic option); ReceivePageOption getSelectedAddressType(Object wallet); List getBitcoinReceivePageOptions();