@metamask-previews/keyring-controller 22.0.2-preview-2873423 → 22.0.2-preview-a272c5e1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Add support for envelope encryption ([#5940](https://github.com/MetaMask/core/pull/5940))
13
+
14
+ ### Changed
15
+
16
+ - Upgrade mock encryptor to support multiple ciphertexts ([#5943](https://github.com/MetaMask/core/pull/5943))
17
+
10
18
  ## [22.0.2]
11
19
 
12
20
  ### Fixed
@@ -36,7 +36,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
36
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
- var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_createKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_assertNoDuplicateAccounts, _KeyringController_setUnlocked, _KeyringController_assertIsUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
39
+ var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_updateCachedEncryptionKey, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _KeyringController_isEnvelopeEncryptionEnabled, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_createKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_assertNoDuplicateAccounts, _KeyringController_setUnlocked, _KeyringController_assertIsUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.KeyringController = exports.getDefaultKeyringState = exports.keyringBuilderFactory = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.isCustodyKeyring = exports.KeyringTypes = void 0;
42
42
  const util_1 = require("@ethereumjs/util");
@@ -168,6 +168,17 @@ function assertIsValidPassword(password) {
168
168
  throw new Error(constants_1.KeyringControllerError.InvalidEmptyPassword);
169
169
  }
170
170
  }
171
+ /**
172
+ * Assert that the provided cacheEncryptionKey is true.
173
+ *
174
+ * @param cacheEncryptionKey - The cacheEncryptionKey to check.
175
+ * @throws If the cacheEncryptionKey is not true.
176
+ */
177
+ function assertIsCacheEncryptionKeyTrue(cacheEncryptionKey) {
178
+ if (!cacheEncryptionKey) {
179
+ throw new Error(constants_1.KeyringControllerError.CacheEncryptionKeyDisabled);
180
+ }
181
+ }
171
182
  /**
172
183
  * Checks if the provided value is a serialized keyrings array.
173
184
  *
@@ -258,6 +269,7 @@ class KeyringController extends base_controller_1.BaseController {
258
269
  keyrings: { persist: false, anonymous: false },
259
270
  encryptionKey: { persist: false, anonymous: false },
260
271
  encryptionSalt: { persist: false, anonymous: false },
272
+ encryptedEncryptionKey: { persist: true, anonymous: false },
261
273
  },
262
274
  messenger,
263
275
  state: {
@@ -274,6 +286,7 @@ class KeyringController extends base_controller_1.BaseController {
274
286
  _KeyringController_keyrings.set(this, void 0);
275
287
  _KeyringController_unsupportedKeyrings.set(this, void 0);
276
288
  _KeyringController_password.set(this, void 0);
289
+ _KeyringController_encryptionKey.set(this, void 0);
277
290
  _KeyringController_qrKeyringStateListener.set(this, void 0);
278
291
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
279
292
  ? keyringBuilders.concat(defaultKeyringBuilders)
@@ -373,19 +386,22 @@ class KeyringController extends base_controller_1.BaseController {
373
386
  /**
374
387
  * Create a new vault and primary keyring.
375
388
  *
376
- * This only works if keyrings are empty. If there is a pre-existing unlocked vault, calling this will have no effect.
377
- * If there is a pre-existing locked vault, it will be replaced.
389
+ * This only works if keyrings are empty. If there is a pre-existing unlocked
390
+ * vault, calling this will have no effect. If there is a pre-existing locked
391
+ * vault, it will be replaced.
378
392
  *
379
393
  * @param password - Password to unlock the new vault.
394
+ * @param encryptionKey - Optional encryption key to encrypt the new vault. If
395
+ * set, envelope encryption will be used.
380
396
  * @returns Promise resolving when the operation ends successfully.
381
397
  */
382
- async createNewVaultAndKeychain(password) {
398
+ async createNewVaultAndKeychain(password, encryptionKey) {
383
399
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
384
400
  const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
385
401
  if (!accounts.length) {
386
402
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
387
403
  type: KeyringTypes.hd,
388
- });
404
+ }, encryptionKey);
389
405
  }
390
406
  });
391
407
  }
@@ -414,7 +430,16 @@ class KeyringController extends base_controller_1.BaseController {
414
430
  if (!this.state.vault) {
415
431
  throw new Error(constants_1.KeyringControllerError.VaultError);
416
432
  }
417
- await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
433
+ if (this.state.encryptedEncryptionKey) {
434
+ // Envelope encryption mode.
435
+ assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
436
+ const key = (await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.encryptedEncryptionKey));
437
+ const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(key);
438
+ await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(importedKey, this.state.vault);
439
+ }
440
+ else {
441
+ await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
442
+ }
418
443
  }
419
444
  /**
420
445
  * Returns the status of the vault.
@@ -603,7 +628,7 @@ class KeyringController extends base_controller_1.BaseController {
603
628
  try {
604
629
  wallet = ethereumjs_wallet_1.thirdparty.fromEtherWallet(input, password);
605
630
  }
606
- catch (e) {
631
+ catch {
607
632
  wallet = wallet || (await ethereumjs_wallet_1.default.fromV3(input, password, true));
608
633
  }
609
634
  privateKey = (0, utils_1.bytesToHex)(wallet.getPrivateKey());
@@ -662,6 +687,7 @@ class KeyringController extends base_controller_1.BaseController {
662
687
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
663
688
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
664
689
  __classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
690
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
665
691
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
666
692
  this.update((state) => {
667
693
  state.isUnlocked = false;
@@ -842,10 +868,24 @@ class KeyringController extends base_controller_1.BaseController {
842
868
  * @returns Promise resolving when the operation completes.
843
869
  */
844
870
  changePassword(password) {
871
+ return this.changePasswordAndEncryptionKey(password);
872
+ }
873
+ /**
874
+ * Changes the password and encryption key used to encrypt the vault.
875
+ *
876
+ * @param password - The new password.
877
+ * @param encryptionKey - The new encryption key. If omitted, the encryption
878
+ * key will not be changed.
879
+ * @returns Promise resolving when the operation completes.
880
+ */
881
+ changePasswordAndEncryptionKey(password, encryptionKey) {
845
882
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
846
883
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
847
884
  assertIsValidPassword(password);
885
+ // Update password.
848
886
  __classPrivateFieldSet(this, _KeyringController_password, password, "f");
887
+ // Update encryption key.
888
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateCachedEncryptionKey).call(this, encryptionKey);
849
889
  // We need to clear encryption key and salt from state
850
890
  // to force the controller to re-encrypt the vault using
851
891
  // the new password.
@@ -1159,7 +1199,7 @@ class KeyringController extends base_controller_1.BaseController {
1159
1199
  }
1160
1200
  }
1161
1201
  exports.KeyringController = KeyringController;
1162
- _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1202
+ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_encryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1163
1203
  this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1164
1204
  this.messagingSystem.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
1165
1205
  this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
@@ -1228,9 +1268,10 @@ async function _KeyringController_addQRKeyring() {
1228
1268
  * @param keyring - A object containing the params to instantiate a new keyring.
1229
1269
  * @param keyring.type - The keyring type.
1230
1270
  * @param keyring.opts - Optional parameters required to instantiate the keyring.
1271
+ * @param encryptionKey - Optional encryption key to encrypt the vault.
1231
1272
  * @returns A promise that resolves to the state.
1232
1273
  */
1233
- async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1274
+ async function _KeyringController_createNewVaultWithKeyring(password, keyring, encryptionKey) {
1234
1275
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1235
1276
  if (typeof password !== 'string') {
1236
1277
  throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
@@ -1240,9 +1281,17 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1240
1281
  delete state.encryptionSalt;
1241
1282
  });
1242
1283
  __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1284
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateCachedEncryptionKey).call(this, encryptionKey);
1243
1285
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1244
1286
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1245
1287
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1288
+ }, _KeyringController_updateCachedEncryptionKey = function _KeyringController_updateCachedEncryptionKey(encryptionKey) {
1289
+ if (!encryptionKey && this.state.encryptedEncryptionKey) {
1290
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, this.state.encryptionKey, "f");
1291
+ }
1292
+ else {
1293
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, encryptionKey, "f");
1294
+ }
1246
1295
  }, _KeyringController_verifySeedPhrase =
1247
1296
  /**
1248
1297
  * Internal non-exclusive method to verify the seed phrase.
@@ -1332,6 +1381,7 @@ async function _KeyringController_getSessionState() {
1332
1381
  return {
1333
1382
  keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
1334
1383
  password: __classPrivateFieldGet(this, _KeyringController_password, "f"),
1384
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
1335
1385
  };
1336
1386
  }, _KeyringController_restoreSerializedKeyrings =
1337
1387
  /**
@@ -1367,7 +1417,7 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
1367
1417
  */
1368
1418
  async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
1369
1419
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1370
- const encryptedVault = this.state.vault;
1420
+ const { vault: encryptedVault, encryptedEncryptionKey } = this.state;
1371
1421
  if (!encryptedVault) {
1372
1422
  throw new Error(constants_1.KeyringControllerError.VaultError);
1373
1423
  }
@@ -1376,11 +1426,20 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1376
1426
  if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1377
1427
  assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1378
1428
  if (password) {
1379
- const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1380
- vault = result.vault;
1381
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1382
- updatedState.encryptionKey = result.exportedKeyString;
1383
- updatedState.encryptionSalt = result.salt;
1429
+ if (encryptedEncryptionKey) {
1430
+ const key = (await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedEncryptionKey));
1431
+ const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(key);
1432
+ vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(importedKey, encryptedVault);
1433
+ __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1434
+ updatedState.encryptionKey = key;
1435
+ }
1436
+ else {
1437
+ const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1438
+ vault = result.vault;
1439
+ __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1440
+ updatedState.encryptionKey = result.exportedKeyString;
1441
+ updatedState.encryptionSalt = result.salt;
1442
+ }
1384
1443
  }
1385
1444
  else {
1386
1445
  const parsedEncryptedVault = JSON.parse(encryptedVault);
@@ -1451,15 +1510,31 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1451
1510
  updatedState.vault = JSON.stringify(vaultJSON);
1452
1511
  }
1453
1512
  else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
1454
- const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1455
- updatedState.vault = newVault;
1456
- updatedState.encryptionKey = exportedKeyString;
1513
+ if (__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
1514
+ // Update cached key.
1515
+ updatedState.encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f");
1516
+ // Encrypt key and update encrypted key.
1517
+ const encryptedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
1518
+ updatedState.encryptedEncryptionKey = encryptedKey;
1519
+ // Encrypt and update vault.
1520
+ const importedKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
1521
+ const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(importedKey, serializedKeyrings);
1522
+ updatedState.vault = JSON.stringify(vaultJSON);
1523
+ }
1524
+ else {
1525
+ const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1526
+ updatedState.vault = newVault;
1527
+ updatedState.encryptionKey = exportedKeyString;
1528
+ }
1457
1529
  }
1458
1530
  }
1459
1531
  else {
1460
1532
  assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
1461
1533
  updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1462
1534
  }
1535
+ if (__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isEnvelopeEncryptionEnabled).call(this)) {
1536
+ assertIsCacheEncryptionKeyTrue(__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f"));
1537
+ }
1463
1538
  if (!updatedState.vault) {
1464
1539
  throw new Error(constants_1.KeyringControllerError.MissingVaultData);
1465
1540
  }
@@ -1471,6 +1546,9 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1471
1546
  state.encryptionKey = updatedState.encryptionKey;
1472
1547
  state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1473
1548
  }
1549
+ if (updatedState.encryptedEncryptionKey) {
1550
+ state.encryptedEncryptionKey = updatedState.encryptedEncryptionKey;
1551
+ }
1474
1552
  });
1475
1553
  return true;
1476
1554
  });
@@ -1480,6 +1558,8 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1480
1558
  return false;
1481
1559
  }
1482
1560
  return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
1561
+ }, _KeyringController_isEnvelopeEncryptionEnabled = function _KeyringController_isEnvelopeEncryptionEnabled() {
1562
+ return this.state.encryptedEncryptionKey || __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f");
1483
1563
  }, _KeyringController_getAccountsFromKeyrings =
1484
1564
  /**
1485
1565
  * Retrieves all the accounts from keyrings instances
@@ -1564,7 +1644,8 @@ async function _KeyringController_createKeyring(type, data) {
1564
1644
  if (keyring.init) {
1565
1645
  await keyring.init();
1566
1646
  }
1567
- if (type === KeyringTypes.hd && (!(0, utils_1.isObject)(data) || !data.mnemonic)) {
1647
+ if (type === KeyringTypes.hd &&
1648
+ (!(0, utils_1.isObject)(data) || !data.mnemonic)) {
1568
1649
  if (!keyring.generateRandomMnemonic) {
1569
1650
  throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic);
1570
1651
  }
@@ -1686,11 +1767,16 @@ async function _KeyringController_assertNoDuplicateAccounts(additionalKeyrings =
1686
1767
  }
1687
1768
  }, _KeyringController_persistOrRollback =
1688
1769
  /**
1689
- * Execute the given function after acquiring the controller lock
1690
- * and save the vault to state after it (only if needed), or rollback to their
1691
- * previous state in case of error.
1770
+ * Execute the given function after acquiring the controller lock and save the
1771
+ * vault to state after it (only if needed), or rollback to their previous
1772
+ * state in case of error.
1773
+ *
1774
+ * ATTENTION: The callback must **not** alter `controller.state`. Any state
1775
+ * change performed by the callback will not be rolled back on error.
1692
1776
  *
1693
- * @param callback - The function to execute.
1777
+ * @param callback - The function to execute. This callback must **not** alter
1778
+ * `controller.state`. Any state change performed by the callback will not be
1779
+ * rolled back on error.
1694
1780
  * @returns The result of the function.
1695
1781
  */
1696
1782
  async function _KeyringController_persistOrRollback(callback) {