Skip to content

Commit

Permalink
fix: reintroduce mutex for createNewVaultAndRestore
Browse files Browse the repository at this point in the history
  • Loading branch information
mikesposito committed Jun 30, 2023
1 parent 619db53 commit 8314b41
Showing 1 changed file with 69 additions and 58 deletions.
127 changes: 69 additions & 58 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import {
ERC20,
ERC721,
} from '@metamask/controller-utils';
import { wordlist } from '@metamask/scure-bip39/dist/wordlists/english';

///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
Expand Down Expand Up @@ -2724,80 +2725,90 @@ export default class MetamaskController extends EventEmitter {
* of UTF-8 bytes.
*/
async createNewVaultAndRestore(password, encodedSeedPhrase) {
let accounts, lastBalance;

const seedPhraseAsBuffer = Buffer.from(encodedSeedPhrase);

const { keyringController } = this;

// clear known identities
this.preferencesController.setAddresses([]);
const releaseLock = await this.createVaultMutex.acquire();
try {
let accounts, lastBalance;

// clear permissions
this.permissionController.clearState();
const seedPhraseAsBuffer = Buffer.from(encodedSeedPhrase);

///: BEGIN:ONLY_INCLUDE_IN(snaps)
// Clear snap state
this.snapController.clearState();
// Clear notification state
this.notificationController.clear();
///: END:ONLY_INCLUDE_IN
// clear known identities
this.preferencesController.setAddresses([]);

// clear accounts in accountTracker
this.accountTracker.clearAccounts();
// clear permissions
this.permissionController.clearState();

// clear cachedBalances
this.cachedBalancesController.clearCachedBalances();
///: BEGIN:ONLY_INCLUDE_IN(snaps)
// Clear snap state
this.snapController.clearState();
// Clear notification state
this.notificationController.clear();
///: END:ONLY_INCLUDE_IN

// clear unapproved transactions
this.txController.txStateManager.clearUnapprovedTxs();
// clear accounts in accountTracker
this.accountTracker.clearAccounts();

// create new vault
const vault = await this.coreKeyringController.createNewVaultAndRestore(
password,
seedPhraseAsBuffer,
);
// clear cachedBalances
this.cachedBalancesController.clearCachedBalances();

const ethQuery = new EthQuery(this.provider);
accounts = await keyringController.getAccounts();
lastBalance = await this.getBalance(
accounts[accounts.length - 1],
ethQuery,
);
// clear unapproved transactions
this.txController.txStateManager.clearUnapprovedTxs();

const [primaryKeyring] = keyringController.getKeyringsByType(
KeyringType.hdKeyTree,
);
if (!primaryKeyring) {
throw new Error('MetamaskController - No HD Key Tree found');
}
// create new vault
const vault = await this.coreKeyringController.createNewVaultAndRestore(
password,
this._bufferToUint8Array(seedPhraseAsBuffer),
);

// seek out the first zero balance
while (lastBalance !== '0x0') {
await keyringController.addNewAccount(primaryKeyring);
accounts = await keyringController.getAccounts();
const ethQuery = new EthQuery(this.provider);
accounts = await this.coreKeyringController.getAccounts();
lastBalance = await this.getBalance(
accounts[accounts.length - 1],
ethQuery,
);
}

// remove extra zero balance account potentially created from seeking ahead
if (accounts.length > 1 && lastBalance === '0x0') {
await this.removeAccount(accounts[accounts.length - 1]);
accounts = await keyringController.getAccounts();
}
// seek out the first zero balance
while (lastBalance !== '0x0') {
await this.coreKeyringController.addNewAccount(accounts.length);
accounts = await this.coreKeyringController.getAccounts();
lastBalance = await this.getBalance(
accounts[accounts.length - 1],
ethQuery,
);
}

// This must be set as soon as possible to communicate to the
// keyring's iframe and have the setting initialized properly
// Optimistically called to not block MetaMask login due to
// Ledger Keyring GitHub downtime
const transportPreference =
this.preferencesController.getLedgerTransportPreference();
this.setLedgerTransportPreference(transportPreference);
// remove extra zero balance account potentially created from seeking ahead
if (accounts.length > 1 && lastBalance === '0x0') {
await this.removeAccount(accounts[accounts.length - 1]);
accounts = await this.coreKeyringController.getAccounts();
}

this.selectFirstIdentity();
return vault;
// This must be set as soon as possible to communicate to the
// keyring's iframe and have the setting initialized properly
// Optimistically called to not block MetaMask login due to
// Ledger Keyring GitHub downtime
const transportPreference =
this.preferencesController.getLedgerTransportPreference();
this.setLedgerTransportPreference(transportPreference);

this.selectFirstIdentity();
return vault;
} finally {
releaseLock();
}
}

/**
* Get a Uint8Array mnemonic from Buffer.
*
* @param {Buffer} mnemonic - The mnemonic phrase as a Buffer
* @returns {Uint8Array} The mnemonic phrase as a Uint8Array
*/
_bufferToUint8Array(mnemonic) {
const indices = mnemonic
.toString()
.split(' ')
.map((word) => wordlist.indexOf(word));
return new Uint8Array(new Uint16Array(indices).buffer);
}

/**
Expand Down

0 comments on commit 8314b41

Please sign in to comment.