mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-25 12:06:05 +00:00
fixes
This commit is contained in:
parent
e72f196c23
commit
3053ea4d10
5 changed files with 49 additions and 41 deletions
|
@ -65,7 +65,8 @@ String bufferToBin(Uint8List data) {
|
||||||
return q2;
|
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 dataBitLen = data.length * 8;
|
||||||
final wordBitLen = logBase(wordlist.length, 2).ceil();
|
final wordBitLen = logBase(wordlist.length, 2).ceil();
|
||||||
final wordCount = (dataBitLen / wordBitLen).floor();
|
final wordCount = (dataBitLen / wordBitLen).floor();
|
||||||
|
@ -90,15 +91,16 @@ List<bool> prefixMatches(String source, List<String> prefixes) {
|
||||||
return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList();
|
return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> generateMnemonic(
|
Future<String> generateElectrumMnemonic({int strength = 264, String prefix = segwit}) async {
|
||||||
{int strength = 264, String prefix = segwit}) async {
|
|
||||||
final wordBitlen = logBase(wordlist.length, 2).ceil();
|
final wordBitlen = logBase(wordlist.length, 2).ceil();
|
||||||
final wordCount = strength / wordBitlen;
|
final wordCount = strength / wordBitlen;
|
||||||
final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil();
|
final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil();
|
||||||
var result = '';
|
var result = '';
|
||||||
|
|
||||||
do {
|
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);
|
maskBytes(bytes, strength);
|
||||||
result = encode(bytes);
|
result = encode(bytes);
|
||||||
} while (!prefixMatches(result, [prefix]).first);
|
} while (!prefixMatches(result, [prefix]).first);
|
||||||
|
@ -107,21 +109,17 @@ Future<String> generateMnemonic(
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async {
|
Future<Uint8List> mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async {
|
||||||
final pbkdf2 = cryptography.Pbkdf2(
|
final pbkdf2 =
|
||||||
macAlgorithm: cryptography.Hmac.sha512(),
|
cryptography.Pbkdf2(macAlgorithm: cryptography.Hmac.sha512(), iterations: 2048, bits: 512);
|
||||||
iterations: 2048,
|
|
||||||
bits: 512);
|
|
||||||
final text = normalizeText(mnemonic);
|
final text = normalizeText(mnemonic);
|
||||||
// pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce)
|
// pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce)
|
||||||
final key = await pbkdf2.deriveKey(
|
final key = await pbkdf2.deriveKey(
|
||||||
secretKey: cryptography.SecretKey(text.codeUnits),
|
secretKey: cryptography.SecretKey(text.codeUnits), nonce: 'electrum'.codeUnits);
|
||||||
nonce: 'electrum'.codeUnits);
|
|
||||||
final bytes = await key.extractBytes();
|
final bytes = await key.extractBytes();
|
||||||
return Uint8List.fromList(bytes);
|
return Uint8List.fromList(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchesAnyPrefix(String mnemonic) =>
|
bool matchesAnyPrefix(String mnemonic) => prefixMatches(mnemonic, [segwit]).any((el) => el);
|
||||||
prefixMatches(mnemonic, [segwit]).any((el) => el);
|
|
||||||
|
|
||||||
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
||||||
try {
|
try {
|
||||||
|
@ -208,10 +206,8 @@ String removeCJKSpaces(String source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
String normalizeText(String source) {
|
String normalizeText(String source) {
|
||||||
final res = removeCombiningCharacters(unorm.nfkd(source).toLowerCase())
|
final res =
|
||||||
.trim()
|
removeCombiningCharacters(unorm.nfkd(source).toLowerCase()).trim().split('/\s+/').join(' ');
|
||||||
.split('/\s+/')
|
|
||||||
.join(' ');
|
|
||||||
|
|
||||||
return removeCJKSpaces(res);
|
return removeCJKSpaces(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,28 +37,33 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: seedBytes,
|
seedBytes: seedBytes,
|
||||||
currency: CryptoCurrency.btc) {
|
currency: CryptoCurrency.btc) {
|
||||||
walletAddresses = BitcoinWalletAddresses(
|
walletAddresses = BitcoinWalletAddresses(walletInfo,
|
||||||
walletInfo,
|
|
||||||
electrumClient: electrumClient,
|
electrumClient: electrumClient,
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||||
mainHd: hd,
|
mainHd: hd,
|
||||||
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
|
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
|
||||||
.derivePath(walletInfo.derivationPath!),
|
.derivePath(walletInfo.derivationPath!),
|
||||||
networkType: networkType);
|
networkType: networkType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<BitcoinWallet> create({
|
static Future<BitcoinWallet> create(
|
||||||
required String mnemonic,
|
{required String mnemonic,
|
||||||
required String password,
|
required String password,
|
||||||
required WalletInfo walletInfo,
|
required WalletInfo walletInfo,
|
||||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
ElectrumBalance? initialBalance,
|
ElectrumBalance? initialBalance,
|
||||||
int initialRegularAddressIndex = 0,
|
int initialRegularAddressIndex = 0,
|
||||||
int initialChangeAddressIndex = 0
|
int initialChangeAddressIndex = 0}) async {
|
||||||
}) async {
|
late Uint8List seedBytes;
|
||||||
|
if (walletInfo.derivationType == DerivationType.electrum2) {
|
||||||
|
seedBytes = await mnemonicToSeedBytes(mnemonic);
|
||||||
|
} else {
|
||||||
|
// TODO: add bip39 seed
|
||||||
|
seedBytes = await mnemonicToSeedBytes(mnemonic);
|
||||||
|
}
|
||||||
return BitcoinWallet(
|
return BitcoinWallet(
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: password,
|
password: password,
|
||||||
|
@ -66,7 +71,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
unspentCoinsInfo: unspentCoinsInfo,
|
unspentCoinsInfo: unspentCoinsInfo,
|
||||||
initialAddresses: initialAddresses,
|
initialAddresses: initialAddresses,
|
||||||
initialBalance: initialBalance,
|
initialBalance: initialBalance,
|
||||||
seedBytes: await mnemonicToSeedBytes(mnemonic),
|
seedBytes: seedBytes,
|
||||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||||
initialChangeAddressIndex: initialChangeAddressIndex);
|
initialChangeAddressIndex: initialChangeAddressIndex);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +84,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
}) async {
|
}) async {
|
||||||
final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password);
|
final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password);
|
||||||
|
|
||||||
|
|
||||||
walletInfo.derivationType = snp.derivationType;
|
walletInfo.derivationType = snp.derivationType;
|
||||||
walletInfo.derivationPath = snp.derivationPath;
|
walletInfo.derivationPath = snp.derivationPath;
|
||||||
|
|
||||||
|
@ -87,6 +91,17 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
if (walletInfo.derivationPath == null) {
|
if (walletInfo.derivationPath == null) {
|
||||||
walletInfo.derivationPath = "m/0'/1";
|
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(
|
return BitcoinWallet(
|
||||||
mnemonic: snp.mnemonic,
|
mnemonic: snp.mnemonic,
|
||||||
|
@ -95,7 +110,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
||||||
unspentCoinsInfo: unspentCoinsInfo,
|
unspentCoinsInfo: unspentCoinsInfo,
|
||||||
initialAddresses: snp.addresses,
|
initialAddresses: snp.addresses,
|
||||||
initialBalance: snp.balance,
|
initialBalance: snp.balance,
|
||||||
seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
|
seedBytes: seedBytes,
|
||||||
initialRegularAddressIndex: snp.regularAddressIndex,
|
initialRegularAddressIndex: snp.regularAddressIndex,
|
||||||
initialChangeAddressIndex: snp.changeAddressIndex);
|
initialChangeAddressIndex: snp.changeAddressIndex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,10 @@ class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
|
||||||
@override
|
@override
|
||||||
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
|
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
|
||||||
// default derivation type/path for bitcoin wallets:
|
// default derivation type/path for bitcoin wallets:
|
||||||
// TODO: figure out what the default derivation type is
|
// TODO: figure out what the default derivation path is
|
||||||
// credentials.walletInfo!.derivationType = DerivationType.bip39;
|
|
||||||
credentials.walletInfo!.derivationPath = "m/0'/1";
|
credentials.walletInfo!.derivationPath = "m/0'/1";
|
||||||
|
|
||||||
final wallet = await BitcoinWalletBase.create(
|
final wallet = await BitcoinWalletBase.create(
|
||||||
mnemonic: await generateMnemonic(),
|
mnemonic: await generateElectrumMnemonic(strength: 132),
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource);
|
||||||
|
@ -115,9 +113,9 @@ class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
|
||||||
|
|
||||||
static Future<List<DerivationType>> compareDerivationMethods(
|
static Future<List<DerivationType>> compareDerivationMethods(
|
||||||
{required String mnemonic, required Node node}) async {
|
{required String mnemonic, required Node node}) async {
|
||||||
// if the mnemonic is 12 words, then it could be electrum 1.0,
|
// 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
|
// if the mnemonic is 24 words, then it could be electrum 2.0
|
||||||
// bip39 is possible with any number of words
|
// bip39 is possible with any number of words
|
||||||
int wordCount = mnemonic.split(" ").length;
|
int wordCount = mnemonic.split(" ").length;
|
||||||
if (wordCount == 24) {
|
if (wordCount == 24) {
|
||||||
return [DerivationType.bip39, DerivationType.electrum1];
|
return [DerivationType.bip39, DerivationType.electrum1];
|
||||||
|
|
|
@ -27,7 +27,7 @@ class LitecoinWalletService extends WalletService<
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async {
|
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials) async {
|
||||||
final wallet = await LitecoinWalletBase.create(
|
final wallet = await LitecoinWalletBase.create(
|
||||||
mnemonic: await generateMnemonic(),
|
mnemonic: await generateElectrumMnemonic(),
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
unspentCoinsInfo: unspentCoinsInfoSource);
|
unspentCoinsInfo: unspentCoinsInfoSource);
|
||||||
|
|
|
@ -50,7 +50,6 @@ abstract class WalletCreationVMBase with Store {
|
||||||
walletCreationService.checkIfExists(name);
|
walletCreationService.checkIfExists(name);
|
||||||
final dirPath = await pathForWalletDir(name: name, type: type);
|
final dirPath = await pathForWalletDir(name: name, type: type);
|
||||||
final path = await pathForWallet(name: name, type: type);
|
final path = await pathForWallet(name: name, type: type);
|
||||||
print("options: $options");
|
|
||||||
final credentials = restoreWallet != null
|
final credentials = restoreWallet != null
|
||||||
? getCredentialsFromRestoredWallet(options, restoreWallet)
|
? getCredentialsFromRestoredWallet(options, restoreWallet)
|
||||||
: getCredentials(options);
|
: getCredentials(options);
|
||||||
|
|
Loading…
Reference in a new issue