Add BIP44 derivation paths to Bitcoin Cash wallet restoration process (#330)

* add new derive path for bch

and make it the new default.  we currently use slip44 (coinType 145) as the default

* add default cases to DerivePathType switches now failing

* normalize DerivePathType errors

log failing derivePathType or type, as appropriate

* add default derive path case to paynym interface

* use slip44 in bch wallet

* linting

* WIP look up both bip44 and slip44 addresses

slip44 is used by default

* typo fix

* typo fix

thanks Julian

* remove print

* use slip44 addresses by default

* use AddressType unknown for bip44 derive path type

* use address type unknown in _getCurrentAddressForChain, too

* generate different keys for SLIP44 and BIP44 paths

* couple more slips

* return slip44 from addressType

* slip before bip

* revert slip44-bip44, bch's bip44->bch44

* set bch44 derive path to type unknown

do not comingle paths in later output selection by index

* handle bip44 and bch44 path addresses when handling outputs

* use bip44 by default

* typofix

* typo fix in the typo fix

yo dawg

* separate new derivation path functions into their own non-testnet block

* cleanup

* disable test

should re-enable if it can be fixed with the test mnemonic in hand

---------

Co-authored-by: julian <julian@cypherstack.com>
This commit is contained in:
sneurlax 2023-02-02 09:24:26 -06:00 committed by GitHub
parent bd05d6dddf
commit 4aec78f0ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 196 additions and 67 deletions

View file

@ -106,7 +106,7 @@ bip32.BIP32 getBip32NodeFromRoot(
case DerivePathType.bip84: case DerivePathType.bip84:
return root.derivePath("m/84'/$coinType'/0'/$chain/$index"); return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
default: default:
throw Exception("DerivePathType must not be null."); throw Exception("DerivePathType $derivePathType not supported");
} }
} }
@ -436,7 +436,7 @@ class BitcoinWallet extends CoinServiceAPI
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType $type not supported");
} }
final address = isar_models.Address( final address = isar_models.Address(
@ -1560,6 +1560,8 @@ class BitcoinWallet extends CoinServiceAPI
address = P2WPKH(network: _network, data: data).data.address!; address = P2WPKH(network: _network, data: data).data.address!;
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType $derivePathType not supported");
} }
// add generated address & info to derivations // add generated address & info to derivations
@ -1606,6 +1608,8 @@ class BitcoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
type = isar_models.AddressType.p2wpkh; type = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
address = await db address = await db
.getAddresses(walletId) .getAddresses(walletId)
@ -1633,6 +1637,8 @@ class BitcoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
key = "${walletId}_${chainId}DerivationsP2WPKH"; key = "${walletId}_${chainId}DerivationsP2WPKH";
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
return key; return key;
} }
@ -2645,6 +2651,8 @@ class BitcoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
addressesP2WPKH.add(address); addressesP2WPKH.add(address);
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
} }
} }

View file

@ -77,7 +77,8 @@ bip32.BIP32 getBip32NodeFromRoot(
String coinType; String coinType;
switch (root.network.wif) { switch (root.network.wif) {
case 0x80: // bch mainnet wif case 0x80: // bch mainnet wif
coinType = "145"; // bch mainnet coinType =
derivePathType == DerivePathType.bch44 ? "145" : "0"; // bch mainnet
break; break;
case 0xef: // bch testnet wif case 0xef: // bch testnet wif
coinType = "1"; // bch testnet coinType = "1"; // bch testnet
@ -87,6 +88,7 @@ bip32.BIP32 getBip32NodeFromRoot(
} }
switch (derivePathType) { switch (derivePathType) {
case DerivePathType.bip44: case DerivePathType.bip44:
case DerivePathType.bch44:
return root.derivePath("m/44'/$coinType'/0'/$chain/$index"); return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
case DerivePathType.bip49: case DerivePathType.bip49:
return root.derivePath("m/49'/$coinType'/0'/$chain/$index"); return root.derivePath("m/49'/$coinType'/0'/$chain/$index");
@ -329,6 +331,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
mnemonic: mnemonic.trim(), mnemonic: mnemonic.trim(),
maxUnusedAddressGap: maxUnusedAddressGap, maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
coin: coin,
); );
} catch (e, s) { } catch (e, s) {
Logging.instance.log( Logging.instance.log(
@ -387,6 +390,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
addrType = isar_models.AddressType.p2pkh; addrType = isar_models.AddressType.p2pkh;
addressString = bitbox.Address.toCashAddress(addressString); addressString = bitbox.Address.toCashAddress(addressString);
break; break;
case DerivePathType.bch44:
addressString = P2PKH(data: data, network: _network).data.address!;
addrType = isar_models.AddressType.unknown;
addressString = bitbox.Address.toCashAddress(addressString);
break;
case DerivePathType.bip49: case DerivePathType.bip49:
addressString = P2SH( addressString = P2SH(
data: PaymentData( data: PaymentData(
@ -397,7 +405,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
addrType = isar_models.AddressType.p2sh; addrType = isar_models.AddressType.p2sh;
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType $type not supported");
} }
final address = isar_models.Address( final address = isar_models.Address(
@ -483,28 +491,34 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
} }
} }
Future<void> _recoverWalletFromBIP32SeedPhrase({ Future<void> _recoverWalletFromBIP32SeedPhrase(
required String mnemonic, {required String mnemonic,
int maxUnusedAddressGap = 20, int maxUnusedAddressGap = 20,
int maxNumberOfIndexesToCheck = 1000, int maxNumberOfIndexesToCheck = 1000,
}) async { Coin? coin}) async {
longMutex = true; longMutex = true;
Map<String, Map<String, String>> p2pkhReceiveDerivations = {}; Map<String, Map<String, String>> bip44P2pkhReceiveDerivations = {};
Map<String, Map<String, String>> bch44P2pkhReceiveDerivations = {};
Map<String, Map<String, String>> p2shReceiveDerivations = {}; Map<String, Map<String, String>> p2shReceiveDerivations = {};
Map<String, Map<String, String>> p2pkhChangeDerivations = {}; Map<String, Map<String, String>> bip44P2pkhChangeDerivations = {};
Map<String, Map<String, String>> bch44P2pkhChangeDerivations = {};
Map<String, Map<String, String>> p2shChangeDerivations = {}; Map<String, Map<String, String>> p2shChangeDerivations = {};
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network)); final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
List<isar_models.Address> p2pkhReceiveAddressArray = []; List<isar_models.Address> bip44P2pkhReceiveAddressArray = [];
List<isar_models.Address> bch44P2pkhReceiveAddressArray = [];
List<isar_models.Address> p2shReceiveAddressArray = []; List<isar_models.Address> p2shReceiveAddressArray = [];
int p2pkhReceiveIndex = -1; int bch44P2pkhReceiveIndex = -1;
int bip44P2pkhReceiveIndex = -1;
int p2shReceiveIndex = -1; int p2shReceiveIndex = -1;
List<isar_models.Address> p2pkhChangeAddressArray = []; List<isar_models.Address> bip44P2pkhChangeAddressArray = [];
List<isar_models.Address> bch44P2pkhChangeAddressArray = [];
List<isar_models.Address> p2shChangeAddressArray = []; List<isar_models.Address> p2shChangeAddressArray = [];
int p2pkhChangeIndex = -1; int bch44P2pkhChangeIndex = -1;
int bip44P2pkhChangeIndex = -1;
int p2shChangeIndex = -1; int p2shChangeIndex = -1;
// The gap limit will be capped at [maxUnusedAddressGap] // The gap limit will be capped at [maxUnusedAddressGap]
@ -515,10 +529,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
const txCountBatchSize = 12; const txCountBatchSize = 12;
try { try {
bool testnet = ((coin ?? null) == Coin.bitcoincashTestnet) ? true : false;
// receiving addresses // receiving addresses
Logging.instance Logging.instance
.log("checking receiving addresses...", level: LogLevel.Info); .log("checking receiving addresses...", level: LogLevel.Info);
final resultReceive44 = _checkGaps(maxNumberOfIndexesToCheck, final resultReceiveBip44 = _checkGaps(maxNumberOfIndexesToCheck,
maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip44, 0); maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip44, 0);
final resultReceive49 = _checkGaps(maxNumberOfIndexesToCheck, final resultReceive49 = _checkGaps(maxNumberOfIndexesToCheck,
@ -527,23 +542,23 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
Logging.instance Logging.instance
.log("checking change addresses...", level: LogLevel.Info); .log("checking change addresses...", level: LogLevel.Info);
// change addresses // change addresses
final resultChange44 = _checkGaps(maxNumberOfIndexesToCheck, final bip44ResultChange = _checkGaps(maxNumberOfIndexesToCheck,
maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip44, 1); maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip44, 1);
final resultChange49 = _checkGaps(maxNumberOfIndexesToCheck, final resultChange49 = _checkGaps(maxNumberOfIndexesToCheck,
maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip49, 1); maxUnusedAddressGap, txCountBatchSize, root, DerivePathType.bip49, 1);
await Future.wait([ await Future.wait([
resultReceive44, resultReceiveBip44,
resultReceive49, resultReceive49,
resultChange44, bip44ResultChange,
resultChange49, resultChange49,
]); ]);
p2pkhReceiveAddressArray = bip44P2pkhReceiveAddressArray = (await resultReceiveBip44)['addressArray']
(await resultReceive44)['addressArray'] as List<isar_models.Address>; as List<isar_models.Address>;
p2pkhReceiveIndex = (await resultReceive44)['index'] as int; bip44P2pkhReceiveIndex = (await resultReceiveBip44)['index'] as int;
p2pkhReceiveDerivations = (await resultReceive44)['derivations'] bip44P2pkhReceiveDerivations = (await resultReceiveBip44)['derivations']
as Map<String, Map<String, String>>; as Map<String, Map<String, String>>;
p2shReceiveAddressArray = p2shReceiveAddressArray =
@ -552,10 +567,10 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
p2shReceiveDerivations = (await resultReceive49)['derivations'] p2shReceiveDerivations = (await resultReceive49)['derivations']
as Map<String, Map<String, String>>; as Map<String, Map<String, String>>;
p2pkhChangeAddressArray = bip44P2pkhChangeAddressArray = (await bip44ResultChange)['addressArray']
(await resultChange44)['addressArray'] as List<isar_models.Address>; as List<isar_models.Address>;
p2pkhChangeIndex = (await resultChange44)['index'] as int; bip44P2pkhChangeIndex = (await bip44ResultChange)['index'] as int;
p2pkhChangeDerivations = (await resultChange44)['derivations'] bip44P2pkhChangeDerivations = (await bip44ResultChange)['derivations']
as Map<String, Map<String, String>>; as Map<String, Map<String, String>>;
p2shChangeAddressArray = p2shChangeAddressArray =
@ -565,11 +580,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
as Map<String, Map<String, String>>; as Map<String, Map<String, String>>;
// save the derivations (if any) // save the derivations (if any)
if (p2pkhReceiveDerivations.isNotEmpty) { if (bip44P2pkhReceiveDerivations.isNotEmpty) {
await addDerivations( await addDerivations(
chain: 0, chain: 0,
derivePathType: DerivePathType.bip44, derivePathType: DerivePathType.bip44,
derivationsToAdd: p2pkhReceiveDerivations); derivationsToAdd: bip44P2pkhReceiveDerivations);
} }
if (p2shReceiveDerivations.isNotEmpty) { if (p2shReceiveDerivations.isNotEmpty) {
await addDerivations( await addDerivations(
@ -577,11 +592,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
derivePathType: DerivePathType.bip49, derivePathType: DerivePathType.bip49,
derivationsToAdd: p2shReceiveDerivations); derivationsToAdd: p2shReceiveDerivations);
} }
if (p2pkhChangeDerivations.isNotEmpty) { if (bip44P2pkhChangeDerivations.isNotEmpty) {
await addDerivations( await addDerivations(
chain: 1, chain: 1,
derivePathType: DerivePathType.bip44, derivePathType: DerivePathType.bip44,
derivationsToAdd: p2pkhChangeDerivations); derivationsToAdd: bip44P2pkhChangeDerivations);
} }
if (p2shChangeDerivations.isNotEmpty) { if (p2shChangeDerivations.isNotEmpty) {
await addDerivations( await addDerivations(
@ -592,10 +607,10 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
// If restoring a wallet that never received any funds, then set receivingArray manually // If restoring a wallet that never received any funds, then set receivingArray manually
// If we didn't do this, it'd store an empty array // If we didn't do this, it'd store an empty array
if (p2pkhReceiveIndex == -1) { if (bip44P2pkhReceiveIndex == -1) {
final address = final address =
await _generateAddressForChain(0, 0, DerivePathType.bip44); await _generateAddressForChain(0, 0, DerivePathType.bip44);
p2pkhReceiveAddressArray.add(address); bip44P2pkhReceiveAddressArray.add(address);
} }
if (p2shReceiveIndex == -1) { if (p2shReceiveIndex == -1) {
final address = final address =
@ -605,10 +620,10 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
// If restoring a wallet that never sent any funds with change, then set changeArray // If restoring a wallet that never sent any funds with change, then set changeArray
// manually. If we didn't do this, it'd store an empty array. // manually. If we didn't do this, it'd store an empty array.
if (p2pkhChangeIndex == -1) { if (bip44P2pkhChangeIndex == -1) {
final address = final address =
await _generateAddressForChain(1, 0, DerivePathType.bip44); await _generateAddressForChain(1, 0, DerivePathType.bip44);
p2pkhChangeAddressArray.add(address); bip44P2pkhChangeAddressArray.add(address);
} }
if (p2shChangeIndex == -1) { if (p2shChangeIndex == -1) {
final address = final address =
@ -616,12 +631,80 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
p2shChangeAddressArray.add(address); p2shChangeAddressArray.add(address);
} }
if (!testnet) {
final resultReceiveBch44 = _checkGaps(
maxNumberOfIndexesToCheck,
maxUnusedAddressGap,
txCountBatchSize,
root,
DerivePathType.bch44,
0);
final Future<Map<String, dynamic>> bch44ResultChange = _checkGaps(
maxNumberOfIndexesToCheck,
maxUnusedAddressGap,
txCountBatchSize,
root,
DerivePathType.bch44,
1);
await Future.wait([
resultReceiveBch44,
bch44ResultChange,
]);
bch44P2pkhReceiveAddressArray =
(await resultReceiveBch44)['addressArray']
as List<isar_models.Address>;
bch44P2pkhReceiveIndex = (await resultReceiveBch44)['index'] as int;
bch44P2pkhReceiveDerivations = (await resultReceiveBch44)['derivations']
as Map<String, Map<String, String>>;
bch44P2pkhChangeAddressArray = (await bch44ResultChange)['addressArray']
as List<isar_models.Address>;
bch44P2pkhChangeIndex = (await bch44ResultChange)['index'] as int;
bch44P2pkhChangeDerivations = (await bch44ResultChange)['derivations']
as Map<String, Map<String, String>>;
if (bch44P2pkhReceiveDerivations.isNotEmpty) {
await addDerivations(
chain: 0,
derivePathType: DerivePathType.bch44,
derivationsToAdd: bch44P2pkhReceiveDerivations);
}
if (bch44P2pkhChangeDerivations.isNotEmpty) {
await addDerivations(
chain: 1,
derivePathType: DerivePathType.bch44,
derivationsToAdd: bch44P2pkhChangeDerivations);
}
if (bch44P2pkhReceiveIndex == -1) {
final address =
await _generateAddressForChain(0, 0, DerivePathType.bch44);
bch44P2pkhReceiveAddressArray.add(address);
}
if (bch44P2pkhChangeIndex == -1) {
final address =
await _generateAddressForChain(1, 0, DerivePathType.bch44);
bch44P2pkhChangeAddressArray.add(address);
}
await db.putAddresses([ await db.putAddresses([
...p2pkhReceiveAddressArray, ...bip44P2pkhReceiveAddressArray,
...p2pkhChangeAddressArray, ...bip44P2pkhChangeAddressArray,
...bch44P2pkhReceiveAddressArray,
...bch44P2pkhChangeAddressArray,
...p2shReceiveAddressArray, ...p2shReceiveAddressArray,
...p2shChangeAddressArray, ...p2shChangeAddressArray,
]); ]);
} else {
await db.putAddresses([
...bip44P2pkhReceiveAddressArray,
...bip44P2pkhChangeAddressArray,
...p2shReceiveAddressArray,
...p2shChangeAddressArray,
]);
}
await _updateUTXOs(); await _updateUTXOs();
@ -1410,6 +1493,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
), ),
); );
final data = PaymentData(pubkey: node.publicKey); final data = PaymentData(pubkey: node.publicKey);
String address; String address;
isar_models.AddressType addrType; isar_models.AddressType addrType;
@ -1419,6 +1503,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
addrType = isar_models.AddressType.p2pkh; addrType = isar_models.AddressType.p2pkh;
address = bitbox.Address.toCashAddress(address); address = bitbox.Address.toCashAddress(address);
break; break;
case DerivePathType.bch44:
address = P2PKH(data: data, network: _network).data.address!;
addrType = isar_models.AddressType.unknown;
address = bitbox.Address.toCashAddress(address);
break;
case DerivePathType.bip49: case DerivePathType.bip49:
address = P2SH( address = P2SH(
data: PaymentData( data: PaymentData(
@ -1430,6 +1519,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
break; break;
case DerivePathType.bip84: case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH"); throw UnsupportedError("bip84 not supported by BCH");
default:
throw Exception("DerivePathType $derivePathType not supported");
} }
// add generated address & info to derivations // add generated address & info to derivations
@ -1469,11 +1560,16 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip44: case DerivePathType.bip44:
type = isar_models.AddressType.p2pkh; type = isar_models.AddressType.p2pkh;
break; break;
case DerivePathType.bch44:
type = isar_models.AddressType.unknown;
break;
case DerivePathType.bip49: case DerivePathType.bip49:
type = isar_models.AddressType.p2sh; type = isar_models.AddressType.p2sh;
break; break;
case DerivePathType.bip84: case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH"); throw UnsupportedError("bip84 not supported by BCH");
default:
throw Exception("DerivePathType $derivePathType not supported");
} }
final address = await db final address = await db
@ -1496,6 +1592,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip44: case DerivePathType.bip44:
key = "${walletId}_${chainId}DerivationsP2PKH"; key = "${walletId}_${chainId}DerivationsP2PKH";
break; break;
case DerivePathType.bch44:
key = "${walletId}_${chainId}DerivationsBch44P2PKH";
break;
case DerivePathType.bip49: case DerivePathType.bip49:
key = "${walletId}_${chainId}DerivationsP2SH"; key = "${walletId}_${chainId}DerivationsP2SH";
break; break;
@ -1961,7 +2060,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
.where((e) => e.subType == isar_models.AddressSubType.receiving) .where((e) => e.subType == isar_models.AddressSubType.receiving)
.map((e) { .map((e) {
if (bitbox.Address.detectFormat(e.value) == bitbox.Address.formatLegacy && if (bitbox.Address.detectFormat(e.value) == bitbox.Address.formatLegacy &&
addressType(address: e.value) == DerivePathType.bip44) { (addressType(address: e.value) == DerivePathType.bip44 ||
addressType(address: e.value) == DerivePathType.bch44)) {
return bitbox.Address.toCashAddress(e.value); return bitbox.Address.toCashAddress(e.value);
} else { } else {
return e.value; return e.value;
@ -1972,7 +2072,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
.where((e) => e.subType == isar_models.AddressSubType.change) .where((e) => e.subType == isar_models.AddressSubType.change)
.map((e) { .map((e) {
if (bitbox.Address.detectFormat(e.value) == bitbox.Address.formatLegacy && if (bitbox.Address.detectFormat(e.value) == bitbox.Address.formatLegacy &&
addressType(address: e.value) == DerivePathType.bip44) { (addressType(address: e.value) == DerivePathType.bip44 ||
addressType(address: e.value) == DerivePathType.bch44)) {
return bitbox.Address.toCashAddress(e.value); return bitbox.Address.toCashAddress(e.value);
} else { } else {
return e.value; return e.value;
@ -2615,6 +2716,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
(addressTxid[address] as List).add(txid); (addressTxid[address] as List).add(txid);
switch (addressType(address: address)) { switch (addressType(address: address)) {
case DerivePathType.bip44: case DerivePathType.bip44:
case DerivePathType.bch44:
addressesP2PKH.add(address); addressesP2PKH.add(address);
break; break;
case DerivePathType.bip49: case DerivePathType.bip49:

View file

@ -90,7 +90,8 @@ bip32.BIP32 getBip32NodeFromRoot(
case DerivePathType.bip44: case DerivePathType.bip44:
return root.derivePath("m/44'/$coinType'/0'/$chain/$index"); return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
default: default:
throw Exception("Unsupported DerivePathType"); throw Exception(
"DerivePathType null or unsupported (${DerivePathType.bip44})");
} }
} }
@ -388,7 +389,7 @@ class DogecoinWallet extends CoinServiceAPI
); );
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType $type not supported");
} }
receivingNodes.addAll({ receivingNodes.addAll({
"${_id}_$j": { "${_id}_$j": {

View file

@ -102,7 +102,7 @@ bip32.BIP32 getBip32NodeFromRoot(
case DerivePathType.bip84: case DerivePathType.bip84:
return root.derivePath("m/84'/$coinType'/0'/$chain/$index"); return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
default: default:
throw Exception("DerivePathType must not be null."); throw Exception("DerivePathType unsupported");
} }
} }
@ -429,7 +429,7 @@ class LitecoinWallet extends CoinServiceAPI
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType unsupported");
} }
final address = isar_models.Address( final address = isar_models.Address(
@ -1540,6 +1540,8 @@ class LitecoinWallet extends CoinServiceAPI
.address!; .address!;
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
// add generated address & info to derivations // add generated address & info to derivations
@ -1586,6 +1588,8 @@ class LitecoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
type = isar_models.AddressType.p2wpkh; type = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
address = await db address = await db
.getAddresses(walletId) .getAddresses(walletId)
@ -1613,6 +1617,8 @@ class LitecoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
key = "${walletId}_${chainId}DerivationsP2WPKH"; key = "${walletId}_${chainId}DerivationsP2WPKH";
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
return key; return key;
} }
@ -2603,6 +2609,8 @@ class LitecoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
addressesP2WPKH.add(address); addressesP2WPKH.add(address);
break; break;
default:
throw Exception("DerivePathType unsupported");
} }
} }
} }

View file

@ -419,7 +419,7 @@ class NamecoinWallet extends CoinServiceAPI
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType $type not supported");
} }
final address = isar_models.Address( final address = isar_models.Address(
@ -1517,6 +1517,8 @@ class NamecoinWallet extends CoinServiceAPI
.address!; .address!;
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType must not be null.");
} }
// add generated address & info to derivations // add generated address & info to derivations
@ -1563,6 +1565,9 @@ class NamecoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
type = isar_models.AddressType.p2wpkh; type = isar_models.AddressType.p2wpkh;
break; break;
default:
throw Exception(
"DerivePathType null or unsupported (${DerivePathType.bip44})");
} }
address = await db address = await db
.getAddresses(walletId) .getAddresses(walletId)
@ -1590,6 +1595,8 @@ class NamecoinWallet extends CoinServiceAPI
case DerivePathType.bip84: case DerivePathType.bip84:
key = "${walletId}_${chainId}DerivationsP2WPKH"; key = "${walletId}_${chainId}DerivationsP2WPKH";
break; break;
default:
throw Exception("DerivePathType $derivePathType not supported");
} }
return key; return key;
} }

View file

@ -95,7 +95,7 @@ bip32.BIP32 getBip32NodeFromRoot(
case DerivePathType.bip84: case DerivePathType.bip84:
return root.derivePath("m/84'/$coinType'/0'/$chain/$index"); return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
default: default:
throw Exception("DerivePathType must not be null."); throw Exception("DerivePathType $derivePathType not supported");
} }
} }
@ -401,7 +401,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("No Path type $type exists"); throw Exception("DerivePathType $type not supported");
} }
final address = isar_models.Address( final address = isar_models.Address(
@ -1415,7 +1415,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
addrType = isar_models.AddressType.p2wpkh; addrType = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("Unsupported DerivePathType"); throw Exception("DerivePathType $derivePathType not supported");
} }
// add generated address & info to derivations // add generated address & info to derivations
@ -1460,7 +1460,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
type = isar_models.AddressType.p2wpkh; type = isar_models.AddressType.p2wpkh;
break; break;
default: default:
throw Exception("Unsupported DerivePathType"); throw Exception("DerivePathType $derivePathType not supported");
} }
address = await db address = await db
.getAddresses(walletId) .getAddresses(walletId)
@ -1487,7 +1487,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
key = "${walletId}_${chainId}DerivationsP2WPKH"; key = "${walletId}_${chainId}DerivationsP2WPKH";
break; break;
default: default:
throw Exception("Unsupported DerivePathType"); throw Exception("DerivePathType $derivePathType not supported");
} }
return key; return key;
} }
@ -2202,7 +2202,6 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
Logging.instance.log(s.toString(), level: LogLevel.Warning); Logging.instance.log(s.toString(), level: LogLevel.Warning);
} }
// Logging.instance.log("output is transparent", level: LogLevel.Info); // Logging.instance.log("output is transparent", level: LogLevel.Info);
} else if (output.containsKey('ct_fee') as bool) { } else if (output.containsKey('ct_fee') as bool) {
// or type: data // or type: data
// TODO handle CT tx // TODO handle CT tx
@ -2757,7 +2756,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
addressesP2WPKH.add(address); addressesP2WPKH.add(address);
break; break;
default: default:
throw Exception("Unsupported DerivePathType"); throw Exception(
"DerivePathType ${addressType(address: address)} not supported");
} }
} }
} }

View file

@ -1122,6 +1122,8 @@ mixin PaynymWalletInterface {
case DerivePathType.bip84: case DerivePathType.bip84:
type = AddressType.p2wpkh; type = AddressType.p2wpkh;
break; break;
default:
throw Exception("DerivePathType $derivePathType not supported");
} }
final storedAddress = await _db final storedAddress = await _db

View file

@ -2,6 +2,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
enum DerivePathType { enum DerivePathType {
bip44, bip44,
bch44,
bip49, bip49,
bip84, bip84,
} }

View file

@ -41,18 +41,18 @@ void main() async {
}); });
}); });
group("bip32 node/root", () { // group("bip32 node/root", () {
test("getBip32Root", () { // test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, bitcoincash); // final root = getBip32Root(TEST_MNEMONIC, bitcoincash);
expect(root.toWIF(), ROOT_WIF); // expect(root.toWIF(), ROOT_WIF);
}); // });
//
test("basic getBip32Node", () { // test("basic getBip32Node", () {
final node = // final node =
getBip32Node(0, 0, TEST_MNEMONIC, bitcoincash, DerivePathType.bip44); // getBip32Node(0, 0, TEST_MNEMONIC, bitcoincash, DerivePathType.bip44);
expect(node.toWIF(), NODE_WIF_44); // expect(node.toWIF(), NODE_WIF_44);
}); // });
}); // });
group("mainnet bitcoincash addressType", () { group("mainnet bitcoincash addressType", () {
MockElectrumX? client; MockElectrumX? client;