From 1d5030af97e45d5beb96d18eb2aca8bf1130af5b Mon Sep 17 00:00:00 2001 From: Maarten Zuidhoorn Date: Mon, 6 Feb 2023 21:49:56 +0100 Subject: [PATCH] Add hardcoded list of human-readable snap derivation paths (#17627) * Add hardcoded list of human-readable snap derivation paths * Fix formatting * Update policies --- app/_locales/en/messages.json | 8 +++ lavamoat/browserify/beta/policy.json | 88 ++++++++++++------------- lavamoat/browserify/flask/policy.json | 92 +++++++++++++-------------- lavamoat/browserify/main/policy.json | 88 ++++++++++++------------- package.json | 1 + shared/constants/snaps.ts | 21 ++++++ ui/helpers/utils/permission.js | 74 +++++++++++++++------ ui/helpers/utils/util.js | 22 +++++++ yarn.lock | 3 +- 9 files changed, 241 insertions(+), 156 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index a9467f26c..3fe272d2d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2716,6 +2716,10 @@ "message": "Control your \"$1\" accounts and assets.", "description": "The description for the `snap_getBip44Entropy` permission. $1 is the name of a protocol, e.g. 'Filecoin'." }, + "permission_manageNamedBip32Keys": { + "message": "Control your $1 accounts and assets.", + "description": "The description for the `snap_getBip32Entropy` permission. $1 is a name for the derivation path, e.g., 'Ethereum accounts'. $2 is the plain derivation path, e.g. 'm/44'/0'/0''." + }, "permission_manageState": { "message": "Store and manage its data on your device.", "description": "The description for the `snap_manageState` permission" @@ -2744,6 +2748,10 @@ "message": "View your public key for $1 ($2).", "description": "The description for the `snap_getBip32PublicKey` permission. $1 is a derivation path, e.g. 'm/44'/0'/0''. $2 is the elliptic curve name, e.g. 'secp256k1'." }, + "permission_viewNamedBip32PublicKeys": { + "message": "View your public key for $1.", + "description": "The description for the `snap_getBip32PublicKey` permission. $1 is a name for the derivation path, e.g., 'Ethereum accounts'." + }, "permissions": { "message": "Permissions" }, diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 2d82f5923..991880f99 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1167,6 +1167,44 @@ "jest-canvas-mock>moo-color>color-name": true } }, + "@metamask/key-tree": { + "packages": { + "@metamask/key-tree>@noble/ed25519": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@noble/secp256k1": true, + "@metamask/key-tree>@scure/base": true, + "@metamask/scure-bip39": true, + "@metamask/utils": true + } + }, + "@metamask/key-tree>@noble/ed25519": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, + "@metamask/key-tree>@noble/secp256k1": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@scure/base": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + } + }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1254,8 +1292,8 @@ }, "@metamask/rpc-methods": { "packages": { - "@metamask/rpc-methods>@metamask/key-tree": true, - "@metamask/snaps-utils>@noble/hashes": true, + "@metamask/key-tree": true, + "@metamask/key-tree>@noble/hashes": true, "@metamask/utils": true } }, @@ -1273,32 +1311,6 @@ "browserify>buffer": true } }, - "@metamask/rpc-methods>@metamask/key-tree": { - "packages": { - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": true, - "@metamask/scure-bip39": true, - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, - "@metamask/utils": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@metamask/rpc-methods>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1309,8 +1321,8 @@ "TextEncoder": true }, "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true } }, "@metamask/smart-transactions-controller": { @@ -1350,18 +1362,6 @@ "crypto.getRandomValues": true } }, - "@metamask/snaps-utils>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/snaps-utils>@scure/base": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - } - }, "@metamask/subject-metadata-controller": { "packages": { "@metamask/base-controller": true @@ -2723,8 +2723,8 @@ }, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@scure/bip32": { "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true } }, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index eeaeaf3d5..9ae2a3e7f 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1167,6 +1167,44 @@ "jest-canvas-mock>moo-color>color-name": true } }, + "@metamask/key-tree": { + "packages": { + "@metamask/key-tree>@noble/ed25519": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@noble/secp256k1": true, + "@metamask/key-tree>@scure/base": true, + "@metamask/scure-bip39": true, + "@metamask/utils": true + } + }, + "@metamask/key-tree>@noble/ed25519": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, + "@metamask/key-tree>@noble/secp256k1": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@scure/base": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + } + }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1339,13 +1377,13 @@ "console.warn": true }, "packages": { + "@metamask/key-tree": true, + "@metamask/key-tree>@noble/hashes": true, "@metamask/permission-controller": true, "@metamask/rpc-methods>@metamask/browser-passworder": true, - "@metamask/rpc-methods>@metamask/key-tree": true, "@metamask/rpc-methods>nanoid": true, "@metamask/snaps-ui": true, "@metamask/snaps-utils": true, - "@metamask/snaps-utils>@noble/hashes": true, "@metamask/utils": true, "@metamask/utils>superstruct": true, "eth-rpc-errors": true @@ -1365,32 +1403,6 @@ "browserify>buffer": true } }, - "@metamask/rpc-methods>@metamask/key-tree": { - "packages": { - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": true, - "@metamask/scure-bip39": true, - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, - "@metamask/utils": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@metamask/rpc-methods>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1401,8 +1413,8 @@ "TextEncoder": true }, "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true } }, "@metamask/smart-transactions-controller": { @@ -1642,8 +1654,8 @@ "document.createElement": true }, "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, "@metamask/snaps-utils>cron-parser": true, "@metamask/snaps-utils>rfdc": true, "@metamask/snaps-utils>validate-npm-package-name": true, @@ -1652,18 +1664,6 @@ "semver": true } }, - "@metamask/snaps-utils>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/snaps-utils>@scure/base": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - } - }, "@metamask/snaps-utils>cron-parser": { "packages": { "browserify>browser-resolve": true, @@ -3047,8 +3047,8 @@ }, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@scure/bip32": { "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true } }, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 2d82f5923..991880f99 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1167,6 +1167,44 @@ "jest-canvas-mock>moo-color>color-name": true } }, + "@metamask/key-tree": { + "packages": { + "@metamask/key-tree>@noble/ed25519": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@noble/secp256k1": true, + "@metamask/key-tree>@scure/base": true, + "@metamask/scure-bip39": true, + "@metamask/utils": true + } + }, + "@metamask/key-tree>@noble/ed25519": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, + "@metamask/key-tree>@noble/secp256k1": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "@metamask/key-tree>@scure/base": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + } + }, "@metamask/logo": { "globals": { "addEventListener": true, @@ -1254,8 +1292,8 @@ }, "@metamask/rpc-methods": { "packages": { - "@metamask/rpc-methods>@metamask/key-tree": true, - "@metamask/snaps-utils>@noble/hashes": true, + "@metamask/key-tree": true, + "@metamask/key-tree>@noble/hashes": true, "@metamask/utils": true } }, @@ -1273,32 +1311,6 @@ "browserify>buffer": true } }, - "@metamask/rpc-methods>@metamask/key-tree": { - "packages": { - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": true, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": true, - "@metamask/scure-bip39": true, - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, - "@metamask/utils": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "@metamask/rpc-methods>@metamask/key-tree>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@metamask/rpc-methods>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1309,8 +1321,8 @@ "TextEncoder": true }, "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true } }, "@metamask/smart-transactions-controller": { @@ -1350,18 +1362,6 @@ "crypto.getRandomValues": true } }, - "@metamask/snaps-utils>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/snaps-utils>@scure/base": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - } - }, "@metamask/subject-metadata-controller": { "packages": { "@metamask/base-controller": true @@ -2723,8 +2723,8 @@ }, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@scure/bip32": { "packages": { - "@metamask/snaps-utils>@noble/hashes": true, - "@metamask/snaps-utils>@scure/base": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true } }, diff --git a/package.json b/package.json index 4ebac80c0..5b254f742 100644 --- a/package.json +++ b/package.json @@ -233,6 +233,7 @@ "@metamask/etherscan-link": "^2.2.0", "@metamask/gas-fee-controller": "^1.0.0", "@metamask/jazzicon": "^2.0.0", + "@metamask/key-tree": "^6.2.1", "@metamask/logo": "^3.1.1", "@metamask/metamask-eth-abis": "^3.0.0", "@metamask/notification-controller": "^1.0.0", diff --git a/shared/constants/snaps.ts b/shared/constants/snaps.ts index 2c0e21a88..7d6d0ea53 100644 --- a/shared/constants/snaps.ts +++ b/shared/constants/snaps.ts @@ -1,4 +1,6 @@ ///: BEGIN:ONLY_INCLUDE_IN(flask) +import type { SupportedCurve } from '@metamask/key-tree'; + type SnapsMetadata = { [snapId: string]: { name: string; @@ -40,4 +42,23 @@ export const SNAPS_METADATA: SnapsMetadata = { name: 'Cronjob Test Snap', }, }; + +type SnapsDerivationPath = { + path: ['m', ...string[]]; + curve: SupportedCurve; + name: string; +}; + +export const SNAPS_DERIVATION_PATHS: SnapsDerivationPath[] = [ + { + path: ['m', `44'`, `0'`], + curve: 'secp256k1', + name: 'Test BIP-32 Path (secp256k1)', + }, + { + path: ['m', `44'`, `0'`], + curve: 'ed25519', + name: 'Test BIP-32 Path (ed25519)', + }, +]; ///: END:ONLY_INCLUDE_IN diff --git a/ui/helpers/utils/permission.js b/ui/helpers/utils/permission.js index c18eff41c..927290ee7 100644 --- a/ui/helpers/utils/permission.js +++ b/ui/helpers/utils/permission.js @@ -14,7 +14,7 @@ import { } from '../../../shared/constants/permissions'; ///: BEGIN:ONLY_INCLUDE_IN(flask) import { SNAPS_METADATA } from '../../../shared/constants/snaps'; -import { coinTypeToProtocolName } from './util'; +import { coinTypeToProtocolName, getSnapDerivationPathName } from './util'; ///: END:ONLY_INCLUDE_IN const UNKNOWN_PERMISSION = Symbol('unknown'); @@ -42,27 +42,59 @@ const PERMISSION_DESCRIPTIONS = deepFreeze({ rightIcon: null, }), [RestrictedMethods.snap_getBip32PublicKey]: (t, _, permissionValue) => - permissionValue.caveats[0].value.map(({ path, curve }) => ({ - label: t('permission_viewBip32PublicKeys', [ - - {path.join('/')} - , - curve, - ]), - leftIcon: 'fas fa-eye', - rightIcon: null, - })), + permissionValue.caveats[0].value.map(({ path, curve }) => { + const friendlyName = getSnapDerivationPathName(path, curve); + if (friendlyName) { + return { + label: t('permission_viewNamedBip32PublicKeys', [ + + {friendlyName} + , + path.join('/'), + ]), + leftIcon: 'fas fa-eye', + rightIcon: null, + }; + } + + return { + label: t('permission_viewBip32PublicKeys', [ + + {path.join('/')} + , + curve, + ]), + leftIcon: 'fas fa-eye', + rightIcon: null, + }; + }), [RestrictedMethods.snap_getBip32Entropy]: (t, _, permissionValue) => - permissionValue.caveats[0].value.map(({ path, curve }) => ({ - label: t('permission_manageBip32Keys', [ - - {path.join('/')} - , - curve, - ]), - leftIcon: 'fas fa-door-open', - rightIcon: null, - })), + permissionValue.caveats[0].value.map(({ path, curve }) => { + const friendlyName = getSnapDerivationPathName(path, curve); + if (friendlyName) { + return { + label: t('permission_manageNamedBip32Keys', [ + + {friendlyName} + , + path.join('/'), + ]), + leftIcon: 'fas fa-door-open', + rightIcon: null, + }; + } + + return { + label: t('permission_manageBip32Keys', [ + + {path.join('/')} + , + curve, + ]), + leftIcon: 'fas fa-door-open', + rightIcon: null, + }; + }), [RestrictedMethods.snap_getBip44Entropy]: (t, _, permissionValue) => permissionValue.caveats[0].value.map(({ coinType }) => ({ label: t('permission_manageBip44Keys', [ diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js index 920cf846c..1dc1d9274 100644 --- a/ui/helpers/utils/util.js +++ b/ui/helpers/utils/util.js @@ -6,6 +6,9 @@ import { DateTime } from 'luxon'; import { getFormattedIpfsUrl } from '@metamask/assets-controllers'; import slip44 from '@metamask/slip44'; import bowser from 'bowser'; +///: BEGIN:ONLY_INCLUDE_IN(flask) +import { isEqual } from 'lodash'; +///: END:ONLY_INCLUDE_IN import { CHAIN_IDS } from '../../../shared/constants/network'; import { toChecksumHexAddress, @@ -18,6 +21,9 @@ import { } from '../../../shared/constants/labels'; import { Numeric } from '../../../shared/modules/Numeric'; import { OUTDATED_BROWSER_VERSIONS } from '../constants/common'; +///: BEGIN:ONLY_INCLUDE_IN(flask) +import { SNAPS_DERIVATION_PATHS } from '../../../shared/constants/snaps'; +///: END:ONLY_INCLUDE_IN // formatData :: ( date: ) -> String export function formatDate(date, format = "M/d/y 'at' T") { @@ -524,3 +530,19 @@ export function coinTypeToProtocolName(coinType) { export function isNullish(value) { return value === null || value === undefined; } + +///: BEGIN:ONLY_INCLUDE_IN(flask) +/** + * @param {string[]} path + * @param {string} curve + * @returns {string | null} + */ +export function getSnapDerivationPathName(path, curve) { + const pathMetadata = SNAPS_DERIVATION_PATHS.find( + (derivationPath) => + derivationPath.curve === curve && isEqual(derivationPath.path, path), + ); + + return pathMetadata?.name ?? null; +} +///: END:ONLY_INCLUDE_IN diff --git a/yarn.lock b/yarn.lock index a63003e42..88477703f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3872,7 +3872,7 @@ __metadata: languageName: node linkType: hard -"@metamask/key-tree@npm:^6.2.0": +"@metamask/key-tree@npm:^6.2.0, @metamask/key-tree@npm:^6.2.1": version: 6.2.1 resolution: "@metamask/key-tree@npm:6.2.1" dependencies: @@ -24122,6 +24122,7 @@ __metadata: "@metamask/forwarder": ^1.1.0 "@metamask/gas-fee-controller": ^1.0.0 "@metamask/jazzicon": ^2.0.0 + "@metamask/key-tree": ^6.2.1 "@metamask/logo": ^3.1.1 "@metamask/metamask-eth-abis": ^3.0.0 "@metamask/notification-controller": ^1.0.0