Skip to content

Commit 477d8b7

Browse files
danimohsisou
authored andcommitted
WalletInfoCollector: revert more restrictive address scanning of f4b5904
f4b5904 ("Improve syncing/detection during login") changed address scanning to strictly allow an address gap of at most ACCOUNT_MAX_ALLOWED_ADDRESS_GAP, while the implementation we are reverting to is less restrictive by always checking full chunks of size ACCOUNT_MAX_ALLOWED_ADDRESS_GAP, which can result in address gaps between ACCOUNT_MAX_ALLOWED_ADDRESS_GAP and 2*ACCOUNT_MAX_ALLOWED_ADDRESS_GAP-1. This allows to potentially find more of the user's addresses. The more exhaustive scanning is no problem anymore now with the recent perfomance improvements of @nimiq/core. The more detailed status messsages in LoginSuccess of f4b5904 have not been reverted as the only remaining change. The addition of a skip button has already been reverted previously in 1424f5f.
1 parent f9e1b35 commit 477d8b7

File tree

2 files changed

+19
-38
lines changed

2 files changed

+19
-38
lines changed

src/lib/WalletInfoCollector.ts

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { deriveAddressesFromXPub, getBtcNetwork, publicKeyToPayment } from './bi
3333
export type BasicAccountInfo = {
3434
address: string,
3535
path: string,
36-
index: number,
3736
};
3837

3938
export type WalletCollectionResultLedger = {
@@ -234,8 +233,8 @@ export default class WalletInfoCollector {
234233
}
235234

236235
// Kick off first round of account derivation
237-
// let startIndex = 0;
238-
let derivedAccountsPromise = WalletInfoCollector._deriveAccounts(0 /*startIndex */,
236+
let startIndex = 0;
237+
let derivedAccountsPromise = WalletInfoCollector._deriveAccounts(startIndex,
239238
ACCOUNT_MAX_ALLOWED_ADDRESS_GAP, walletType, keyId, keyguardCookieEncryptionKey);
240239

241240
try {
@@ -290,26 +289,25 @@ export default class WalletInfoCollector {
290289
}
291290

292291
let foundAccounts: BasicAccountInfo[];
293-
let lastActiveAccountIndex = 0;
294292
let receiptsError: Error | undefined;
295293
do {
296294
const derivedAccounts = await derivedAccountsPromise;
297295

298-
// // already start deriving next accounts
299-
// // By always advancing in groups of MAX_ALLOWED_GAP addresses per round, it often happens that more
300-
// // addresses are derived and checked for activity than the BIP44 address gap limit
301-
// // (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#address-gap-limit) stipulates,
302-
// // because whenever an active address in a group of addresses is found, the next full group is also
303-
// // derived. Thus the actual gap limit of this implementation is up to (2 x MAX_ALLOWED_GAP) - 1.
304-
// // We argue that this is good UX for users, as potentially more of their active addresses are found,
305-
// // even if they haven't strictly followed to the standard - at only a relatively small cost to the
306-
// // network. For example, if the user adds the accounts derived with indices 0, 19, 39 to his wallet but
307-
// // then only ends up using accounts 0 and 39, the account at index 19 will not be found anymore on
308-
// // reimport. With the current implementation however, at least the account 39 would be found, while an
309-
// // implementation strictly following the specification would stop the search at index 19.
310-
// startIndex += ACCOUNT_MAX_ALLOWED_ADDRESS_GAP;
311-
// derivedAccountsPromise = WalletInfoCollector._deriveAccounts(startIndex,
312-
// ACCOUNT_MAX_ALLOWED_ADDRESS_GAP, walletType, keyId, keyguardCookieEncryptionKey);
296+
// already start deriving next accounts
297+
// By always advancing in groups of MAX_ALLOWED_GAP addresses per round, it often happens that more
298+
// addresses are derived and checked for activity than the BIP44 address gap limit
299+
// (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#address-gap-limit) stipulates,
300+
// because whenever an active address in a group of addresses is found, the next full group is also
301+
// derived. Thus the actual gap limit of this implementation is up to (2 x MAX_ALLOWED_GAP) - 1.
302+
// We argue that this is good UX for users, as potentially more of their active addresses are found,
303+
// even if they haven't strictly followed to the standard - at only a relatively small cost to the
304+
// network. For example, if the user adds the accounts derived with indices 0, 19, 39 to his wallet but
305+
// then only ends up using accounts 0 and 39, the account at index 19 will not be found anymore on
306+
// reimport. With the current implementation however, at least the account 39 would be found, while an
307+
// implementation strictly following the specification would stop the search at index 19.
308+
startIndex += ACCOUNT_MAX_ALLOWED_ADDRESS_GAP;
309+
derivedAccountsPromise = WalletInfoCollector._deriveAccounts(startIndex,
310+
ACCOUNT_MAX_ALLOWED_ADDRESS_GAP, walletType, keyId, keyguardCookieEncryptionKey);
313311

314312
// Already add addresses that are in the initialAccounts
315313
foundAccounts = derivedAccounts.filter((derived) =>
@@ -325,7 +323,6 @@ export default class WalletInfoCollector {
325323
if (!!balance && (balance.balance !== 0 || balance.stake !== 0)) {
326324
foundAccounts.push(account);
327325
hasActivity = true;
328-
lastActiveAccountIndex = Math.max(lastActiveAccountIndex, account.index);
329326
}
330327
}
331328

@@ -343,7 +340,6 @@ export default class WalletInfoCollector {
343340
if (receipts.length > 0) {
344341
foundAccounts.push(account);
345342
hasActivity = true;
346-
lastActiveAccountIndex = Math.max(lastActiveAccountIndex, account.index);
347343
}
348344
} catch (error) {
349345
if (!(error as Error).message.startsWith(ERROR_TRANSACTION_RECEIPTS)) {
@@ -359,14 +355,6 @@ export default class WalletInfoCollector {
359355
WalletInfoCollector._addAccounts(walletInfo, foundAccounts, balances);
360356
onUpdate(walletInfo, await derivedAccountsPromise);
361357
}
362-
363-
// Check the remaining gap after the last checked account
364-
const lastCheckedIndex = accountsToCheck[accountsToCheck.length - 1].index;
365-
const nextStartIndex = lastCheckedIndex + 1;
366-
const remainingGap = ACCOUNT_MAX_ALLOWED_ADDRESS_GAP - (lastCheckedIndex - lastActiveAccountIndex);
367-
if (!remainingGap) break;
368-
derivedAccountsPromise = WalletInfoCollector._deriveAccounts(nextStartIndex,
369-
remainingGap, walletType, keyId, keyguardCookieEncryptionKey);
370358
} while (foundAccounts.length > 0);
371359

372360
const releaseKey = walletType === WalletType.BIP39
@@ -465,10 +453,8 @@ export default class WalletInfoCollector {
465453
keyguardCookieEncryptionKey?: Uint8Array,
466454
): Promise<BasicAccountInfo[]> {
467455
const pathsToDerive: string[] = [];
468-
const indices: number[] = [];
469456
for (let index = startIndex; index < startIndex + count; ++index) {
470457
pathsToDerive.push(`${ACCOUNT_BIP32_BASE_PATH_KEYGUARD}${index}'`);
471-
indices.push(index);
472458
}
473459
const derivedAddresses = await WalletInfoCollector._keyguardClient!.deriveAddresses(keyId, pathsToDerive,
474460
keyguardCookieEncryptionKey);
@@ -479,29 +465,26 @@ export default class WalletInfoCollector {
479465
accounts.push({
480466
path: pathsToDerive[i],
481467
address: userFriendlyAddresses[i],
482-
index: indices[i],
483468
});
484469
}
485470
return accounts;
486471
}
487472

488473
private static async _deriveLedgerAccounts(startIndex: number, count: number): Promise<BasicAccountInfo[]> {
489474
const pathsToDerive: string[] = [];
490-
const indices: number[] = [];
491475
for (let index = startIndex; index < startIndex + count; ++index) {
492476
pathsToDerive.push(getBip32Path({
493477
coin: Coin.NIMIQ,
494478
addressIndex: index,
495479
}));
496-
indices.push(index);
497480
}
498481
return (
499482
await LedgerApi.Nimiq.deriveAddresses(
500483
pathsToDerive,
501484
/* expectedWalletId */ undefined,
502485
Config.ledgerApiNimiqVersion,
503486
)
504-
).map((address, i) => ({ path: address.keyPath, address: address.address, index: indices[i] }));
487+
).map((address) => ({ path: address.keyPath, address: address.address }));
505488
}
506489

507490
private static async _getBalances(

src/views/LoginSuccess.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,9 @@ export default class LoginSuccess extends Vue {
6565
await Promise.all(
6666
this.keyguardResult.map(async (keyResult) => {
6767
// The Keyguard always returns (at least) one derived Address,
68-
const keyguardResultAccounts = keyResult.addresses.map((addressObj, index) => ({
68+
const keyguardResultAccounts = keyResult.addresses.map((addressObj) => ({
6969
address: new Nimiq.Address(addressObj.address).toUserFriendlyAddress(),
7070
path: addressObj.keyPath,
71-
index,
7271
}));
7372
7473
let tryCount = 0;
@@ -187,7 +186,6 @@ export default class LoginSuccess extends Vue {
187186
188187
private onUpdate(walletInfo: WalletInfo, currentlyCheckedAccounts: BasicAccountInfo[]) {
189188
const count = !walletInfo ? 0 : walletInfo.accounts.size;
190-
if (count <= 1) return;
191189
this.status = this.$tc('Imported {count} address so far... | Imported {count} addresses so far...', count);
192190
}
193191

0 commit comments

Comments
 (0)