Skip to content

Conversation

@adonesky1
Copy link
Contributor

@adonesky1 adonesky1 commented Dec 22, 2022

Integrates @metamask/scure-bip39 and eth-keyring-controller v9 and adapts accordingly

Context for changes are provided with inline comments 😄

@github-actions
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@adonesky1 adonesky1 force-pushed the integrate-keyringcontroller-v9 branch 5 times, most recently from 45bad6b to 85cde3b Compare December 23, 2022 00:44
@adonesky1 adonesky1 marked this pull request as ready for review December 23, 2022 00:54
@adonesky1 adonesky1 requested a review from a team as a code owner December 23, 2022 00:54
@adonesky1 adonesky1 force-pushed the integrate-keyringcontroller-v9 branch from 1790b5e to 7bf6ca2 Compare January 6, 2023 17:47
@metamaskbot
Copy link
Collaborator

Builds ready [7bf6ca2]
Page Load Metrics (1479 ± 119 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint1073371375024
domContentLoaded119219931466255122
load119219931479248119
domInteractive119219931466255122
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 26583 bytes
  • ui: -35 bytes
  • common: 27892 bytes

highlights:

storybook

const recoveredIndices = Array.from(
new Uint16Array(new Uint8Array(keyring.mnemonic).buffer),
);
return recoveredIndices.map((i) => englishWordlist[i]).join(' ');
Copy link
Contributor Author

@adonesky1 adonesky1 Jan 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPrimaryKeyringMnemonic is used by Snaps which still passes mnemonics around as strings. They will be refactoring to pass mnemonics as Uint8Arrays but until then we must recover and return the string version from the Uint8Array format that is now on the keyring value returned by the KeyringController as of this latest version bump.

throw new Error('Primary keyring mnemonic unavailable.');
}
return keyring.mnemonic;
return uint8ArrayMnemonicToString(keyring.mnemonic);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPrimaryKeyringMnemonic is used by Snaps which still passes mnemonics around as strings. They will be refactoring to pass mnemonics as Uint8Arrays but until then we must recover and return the string version from the Uint8Array format that is now on the keyring value returned by the KeyringController on line 2508 as of this latest version bump.

@metamaskbot
Copy link
Collaborator

Builds ready [d11ff38]
Page Load Metrics (1361 ± 91 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint104161125157
domContentLoaded10971990133818790
load10971990136119091
domInteractive10971990133818790
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 10834 bytes
  • ui: -35 bytes
  • common: 43672 bytes

highlights:

storybook

Comment on lines 25 to 34
const keyringBuilder = keyringController.getKeyringBuilderForType(
KEYRING_TYPES.HD_KEY_TREE,
);
const keyring = keyringBuilder();
const opts = {
mnemonic: seedPhrase,
numberOfAccounts: createdAccounts.length,
};

const keyring = new Keyring(opts);
await keyring.deserialize(opts);
Copy link
Contributor Author

@adonesky1 adonesky1 Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adonesky1 adonesky1 changed the title Integrate keyringcontroller v9 Integrate KeyringController v9 Jan 9, 2023
Comment on lines +210 to +215
const pubAddressHexArr = await simpleKeyrings[0].getAccounts();
const privKeyHex = await simpleKeyrings[0].exportAccount(
pubAddressHexArr[0],
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the new pattern for getting public and private keys for an account.

Comment on lines +516 to +533
const mockMnemonic =
'above mercy benefit hospital call oval domain student sphere interest argue shock';
const mnemonicIndices = mockMnemonic
.split(' ')
.map((word) => englishWordlist.indexOf(word));
const uint8ArrayMnemonic = new Uint8Array(
new Uint16Array(mnemonicIndices).buffer,
);

const mockHDKeyring = {
type: 'HD Key Tree',
mnemonic: uint8ArrayMnemonic,
};
sinon
.stub(metamaskController.keyringController, 'getKeyringsByType')
.returns([mockHDKeyring]);
Copy link
Contributor Author

@adonesky1 adonesky1 Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mocks the way mnemonics are stored on HD keyrings - as Uint8Arrays of the indices of the words relative to the english wordlist - as of MetaMask/eth-hd-keyring#67. This test then demonstrates that even though the mnemonic is stored in this way, the getPrimaryKeyringMnemonic method on MetamaskController returns the mnemonic in it's string form, since this is required by Snaps for now.

@@ -1,4 +1,4 @@
import KeyringController from 'eth-keyring-controller';
import { KeyringController } from 'eth-keyring-controller';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +604 to +657
const additionalKeyringTypes = [
TrezorKeyring,
LedgerBridgeKeyring,
LatticeKeyring,
QRHardwareKeyring,
];
additionalKeyrings = additionalKeyringTypes.map((keyringType) =>
keyringBuilderFactory(keyringType),
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KeyringController constructor now takes keyring builder functions rather than classes.

keyringBuilderFactory takes the class types and makes them into these builder functions.

);

return recoveredIndices.map((i) => englishWordlist[i]).join(' ');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @adonesky1 : just curious, how is above change related to KeyringController ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this helper function is used here. The mnemonic returned on the keyring by this.keyringController.getKeyringsByType(KEYRING_TYPES.HD_KEY_TREE) is now a Uint8Array rather than a plain text string, but the getPrimaryKeyringMnemonic function that is used by snaps still expects it as a string so we need this function to convert it back.

@adonesky1 adonesky1 force-pushed the integrate-keyringcontroller-v9 branch from d11ff38 to 7210370 Compare January 12, 2023 19:31
@adonesky1 adonesky1 requested a review from jpuri January 12, 2023 19:32
@metamaskbot
Copy link
Collaborator

Builds ready [ee8b6ee]
Page Load Metrics (1270 ± 50 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint981961212311
domContentLoaded11071514124010249
load11191514127010450
domInteractive11071514124010249
Bundle size diffs [🚀 Bundle size reduced!]
  • background: -313142 bytes
  • ui: -35 bytes
  • common: 43672 bytes

highlights:

storybook

@codecov-commenter
Copy link

Codecov Report

Merging #17056 (ee8b6ee) into develop (7760f4d) will increase coverage by 0.02%.
The diff coverage is 57.14%.

@@             Coverage Diff             @@
##           develop   #17056      +/-   ##
===========================================
+ Coverage    59.53%   59.55%   +0.02%     
===========================================
  Files          936      936              
  Lines        35959    35959              
  Branches      9213     9212       -1     
===========================================
+ Hits         21407    21413       +6     
+ Misses       14552    14546       -6     
Impacted Files Coverage Δ
app/scripts/lib/util.js 61.66% <0.00%> (+1.24%) ⬆️
app/scripts/metamask-controller.js 60.58% <80.00%> (+0.35%) ⬆️
app/scripts/lib/seed-phrase-verifier.js 90.91% <100.00%> (ø)
ui/store/actions.js 38.99% <100.00%> (-0.03%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@Gudahtt
Copy link
Member

Gudahtt commented Jan 16, 2023

In reviewing this, I've noticed that the format of the mnemonic saved in the vault has changed with this update. This change was missed from the changelog as well. The format isn't especially great either, in that it's unconventional (it's essentially an array that was casted to an object - why not use an array instead?).

This format change means we'll have to be careful when releasing this, because if we roll back whatever release this lands in, vault decryption will fail. So we can't roll this change back. Is this format change worth the trouble? We could switch back to the old one.

@metamaskbot
Copy link
Collaborator

Builds ready [432b7b2]
Page Load Metrics (1457 ± 149 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint1041941392412
domContentLoaded110624491432294141
load110625451457311149
domInteractive110624491432294141
Bundle size diffs [🚀 Bundle size reduced!]
  • background: -300360 bytes
  • ui: 0 bytes
  • common: 28279 bytes

@adonesky1
Copy link
Contributor Author

adonesky1 commented Jan 19, 2023

In reviewing this, I've noticed that the format of the mnemonic saved in the vault has changed with this update. This change was missed from the changelog as well. The format isn't especially great either, in that it's unconventional (it's essentially an array that was casted to an object - why not use an array instead?).

This format change means we'll have to be careful when releasing this, because if we roll back whatever release this lands in, vault decryption will fail. So we can't roll this change back. Is this format change worth the trouble? We could switch back to the old one.

@Gudahtt is aware of this but for broader visibility for anyone else reviewing this PR, this specific concern has been addressed with the updates made to @metamask/eth-hd-keyring here which are integrated into the latest version of @metamask/eth-keyring-controller and now pulled in to this PR.

@adonesky1 adonesky1 force-pushed the integrate-keyringcontroller-v9 branch from 432b7b2 to 8cc60b2 Compare January 20, 2023 17:26
@metamaskbot
Copy link
Collaborator

Builds ready [8cc60b2]
Page Load Metrics (1253 ± 101 ms)
PlatformPageMetricMin (ms)Max (ms)Average (ms)StandardDeviation (ms)MarginOfError (ms)
ChromeHomefirstPaint892111243115
domContentLoaded95015821242209100
load95015821253211101
domInteractive95015821242209100
Bundle size diffs [🚀 Bundle size reduced!]
  • background: -300360 bytes
  • ui: 0 bytes
  • common: 28279 bytes

Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Gudahtt Gudahtt changed the title Integrate KeyringController v9 Integrate KeyringController v10 Jan 20, 2023
@adonesky1 adonesky1 merged commit c508087 into develop Jan 20, 2023
@adonesky1 adonesky1 deleted the integrate-keyringcontroller-v9 branch January 20, 2023 23:03
@github-actions github-actions bot locked and limited conversation to collaborators Jan 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants