From 3053ea4d10ec05ea0927f854757649d1d06a5993 Mon Sep 17 00:00:00 2001 From: fosse Date: Fri, 25 Aug 2023 11:59:24 -0400 Subject: [PATCH] fixes --- cw_bitcoin/lib/bitcoin_mnemonic.dart | 28 ++++++------ cw_bitcoin/lib/bitcoin_wallet.dart | 47 ++++++++++++++------- cw_bitcoin/lib/bitcoin_wallet_service.dart | 12 +++--- cw_bitcoin/lib/litecoin_wallet_service.dart | 2 +- lib/view_model/wallet_creation_vm.dart | 1 - 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_mnemonic.dart b/cw_bitcoin/lib/bitcoin_mnemonic.dart index f4ebd7e5d..15374ed5d 100644 --- a/cw_bitcoin/lib/bitcoin_mnemonic.dart +++ b/cw_bitcoin/lib/bitcoin_mnemonic.dart @@ -65,7 +65,8 @@ String bufferToBin(Uint8List data) { return q2; } -String encode(Uint8List data) { +String encode(Uint8List originalData) { + final data = Uint8List.fromList(originalData); // Create a modifiable copy final dataBitLen = data.length * 8; final wordBitLen = logBase(wordlist.length, 2).ceil(); final wordCount = (dataBitLen / wordBitLen).floor(); @@ -90,15 +91,16 @@ List prefixMatches(String source, List prefixes) { return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList(); } -Future generateMnemonic( - {int strength = 264, String prefix = segwit}) async { +Future generateElectrumMnemonic({int strength = 264, String prefix = segwit}) async { final wordBitlen = logBase(wordlist.length, 2).ceil(); final wordCount = strength / wordBitlen; final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil(); var result = ''; do { - final bytes = await secRandom(byteCount); + final originalBytes = await secRandom(byteCount); + // create a modifiable copy, however I'm not sure why this is necessary + final bytes = Uint8List.fromList(originalBytes); maskBytes(bytes, strength); result = encode(bytes); } while (!prefixMatches(result, [prefix]).first); @@ -107,21 +109,17 @@ Future generateMnemonic( } Future mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async { - final pbkdf2 = cryptography.Pbkdf2( - macAlgorithm: cryptography.Hmac.sha512(), - iterations: 2048, - bits: 512); + final pbkdf2 = + cryptography.Pbkdf2(macAlgorithm: cryptography.Hmac.sha512(), iterations: 2048, bits: 512); final text = normalizeText(mnemonic); // pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce) final key = await pbkdf2.deriveKey( - secretKey: cryptography.SecretKey(text.codeUnits), - nonce: 'electrum'.codeUnits); + secretKey: cryptography.SecretKey(text.codeUnits), nonce: 'electrum'.codeUnits); final bytes = await key.extractBytes(); return Uint8List.fromList(bytes); } -bool matchesAnyPrefix(String mnemonic) => - prefixMatches(mnemonic, [segwit]).any((el) => el); +bool matchesAnyPrefix(String mnemonic) => prefixMatches(mnemonic, [segwit]).any((el) => el); bool validateMnemonic(String mnemonic, {String prefix = segwit}) { try { @@ -208,10 +206,8 @@ String removeCJKSpaces(String source) { } String normalizeText(String source) { - final res = removeCombiningCharacters(unorm.nfkd(source).toLowerCase()) - .trim() - .split('/\s+/') - .join(' '); + final res = + removeCombiningCharacters(unorm.nfkd(source).toLowerCase()).trim().split('/\s+/').join(' '); return removeCJKSpaces(res); } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 741fe8abf..c6351bb9e 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -37,28 +37,33 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc) { - walletAddresses = BitcoinWalletAddresses( - walletInfo, + walletAddresses = BitcoinWalletAddresses(walletInfo, electrumClient: electrumClient, initialAddresses: initialAddresses, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath(walletInfo.derivationPath!), + .derivePath(walletInfo.derivationPath!), networkType: networkType); } - static Future create({ - required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0 - }) async { + static Future create( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { + late Uint8List seedBytes; + if (walletInfo.derivationType == DerivationType.electrum2) { + seedBytes = await mnemonicToSeedBytes(mnemonic); + } else { + // TODO: add bip39 seed + seedBytes = await mnemonicToSeedBytes(mnemonic); + } return BitcoinWallet( mnemonic: mnemonic, password: password, @@ -66,7 +71,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), + seedBytes: seedBytes, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex); } @@ -79,7 +84,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { }) async { final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); - walletInfo.derivationType = snp.derivationType; walletInfo.derivationPath = snp.derivationPath; @@ -87,6 +91,17 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { if (walletInfo.derivationPath == null) { walletInfo.derivationPath = "m/0'/1"; } + if (walletInfo.derivationType == null) { + walletInfo.derivationType = DerivationType.electrum2; + } + + late Uint8List seedBytes; + if (walletInfo.derivationType == DerivationType.electrum2) { + seedBytes = await mnemonicToSeedBytes(snp.mnemonic); + } else { + // TODO: add bip39 seed + seedBytes = await mnemonicToSeedBytes(snp.mnemonic); + } return BitcoinWallet( mnemonic: snp.mnemonic, @@ -95,7 +110,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: snp.addresses, initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + seedBytes: seedBytes, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex); } diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index ffd0d028c..c24f2d92d 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -34,12 +34,10 @@ class BitcoinWalletService extends WalletService create(BitcoinNewWalletCredentials credentials) async { // default derivation type/path for bitcoin wallets: - // TODO: figure out what the default derivation type is - // credentials.walletInfo!.derivationType = DerivationType.bip39; + // TODO: figure out what the default derivation path is credentials.walletInfo!.derivationPath = "m/0'/1"; - final wallet = await BitcoinWalletBase.create( - mnemonic: await generateMnemonic(), + mnemonic: await generateElectrumMnemonic(strength: 132), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); @@ -115,9 +113,9 @@ class BitcoinWalletService extends WalletService> compareDerivationMethods( {required String mnemonic, required Node node}) async { - // if the mnemonic is 12 words, then it could be electrum 1.0, - // if the mnemonic is 24 words, then it could be electrum 2.0 - // bip39 is possible with any number of words + // if the mnemonic is 12 words, then it could be electrum 1.0, + // if the mnemonic is 24 words, then it could be electrum 2.0 + // bip39 is possible with any number of words int wordCount = mnemonic.split(" ").length; if (wordCount == 24) { return [DerivationType.bip39, DerivationType.electrum1]; diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index b13ac7a7f..2ea6cd45e 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -27,7 +27,7 @@ class LitecoinWalletService extends WalletService< @override Future create(BitcoinNewWalletCredentials credentials) async { final wallet = await LitecoinWalletBase.create( - mnemonic: await generateMnemonic(), + mnemonic: await generateElectrumMnemonic(), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 89a57669f..aa1efe4d3 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -50,7 +50,6 @@ abstract class WalletCreationVMBase with Store { walletCreationService.checkIfExists(name); final dirPath = await pathForWalletDir(name: name, type: type); final path = await pathForWallet(name: name, type: type); - print("options: $options"); final credentials = restoreWallet != null ? getCredentialsFromRestoredWallet(options, restoreWallet) : getCredentials(options);