@aztec/key-store 5.0.0-private.20260319 → 5.0.0-rc.1

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.
@@ -84,13 +84,13 @@ export declare class KeyStore {
84
84
  */
85
85
  getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise<Fr>;
86
86
  /**
87
- * Retrieves the sk_m corresponding to the pk_m.
88
- * @throws If the provided public key is not associated with any of the registered accounts.
89
- * @param pkM - The master public key to get secret key for.
87
+ * Retrieves the sk_m corresponding to the given pk_m hash.
88
+ * @throws If the provided hash is not associated with any of the registered accounts.
89
+ * @param pkMHash - The master public key hash to get secret key for.
90
90
  * @returns A Promise that resolves to sk_m.
91
91
  * @dev Used when feeding the sk_m to the kernel circuit for keys verification.
92
92
  */
93
- getMasterSecretKey(pkM: PublicKey): Promise<GrumpkinScalar>;
93
+ getMasterSecretKey(pkMHash: Fr): Promise<GrumpkinScalar>;
94
94
  /**
95
95
  * Checks whether a given account has a key matching the provided master public key hash.
96
96
  * @param account - The account address to check.
@@ -106,4 +106,4 @@ export declare class KeyStore {
106
106
  */
107
107
  getKeyPrefixAndAccount(value: Bufferable): Promise<[KeyPrefix, AztecAddress]>;
108
108
  }
109
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMva2V5X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0sbUNBQW1DLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUFxQixNQUFNLDZCQUE2QixDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUVMLEtBQUssU0FBUyxFQUNkLEtBQUssU0FBUyxFQUlmLE1BQU0sb0JBQW9CLENBQUM7QUFPNUI7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQUNuQixnQkFBdUIsY0FBYyxLQUFLO0lBSTFDLFlBQVksUUFBUSxFQUFFLGlCQUFpQixFQUd0QztJQUVEOzs7T0FHRztJQUNJLGFBQWEsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDLENBSS9DO0lBRUQ7Ozs7O09BS0c7SUFDVSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0F3Q3hGO0lBRUQ7OztPQUdHO0lBQ1UsV0FBVyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUtsRDtJQUVELGdFQUFnRTtJQUNuRCxVQUFVLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRS9EO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsdUJBQXVCLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQXNDOUc7SUFFRDs7Ozs7T0FLRztJQUNVLDJCQUEyQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFsRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBUXhGO0lBRUQ7Ozs7O09BS0c7SUFDVSxpQ0FBaUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FReEY7SUFFRDs7Ozs7T0FLRztJQUNVLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFoRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBUTdGO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsOEJBQThCLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0Fhakc7SUFFRDs7Ozs7O09BTUc7SUFDVSxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsU0FBUyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FrQnZFO0lBRUQ7Ozs7O09BS0c7SUFDVSxhQUFhLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FTL0U7SUFFRDs7Ozs7T0FLRztJQUNVLHNCQUFzQixDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBY3pGO0NBQ0YifQ==
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMva2V5X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0sbUNBQW1DLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUFxQixNQUFNLDZCQUE2QixDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUVMLEtBQUssU0FBUyxFQUNkLEtBQUssU0FBUyxFQUtmLE1BQU0sb0JBQW9CLENBQUM7QUFPNUI7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQUNuQixnQkFBdUIsY0FBYyxLQUFLO0lBSTFDLFlBQVksUUFBUSxFQUFFLGlCQUFpQixFQUd0QztJQUVEOzs7T0FHRztJQUNJLGFBQWEsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDLENBSS9DO0lBRUQ7Ozs7O09BS0c7SUFDVSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0ErQ3hGO0lBRUQ7OztPQUdHO0lBQ1UsV0FBVyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUtsRDtJQUVELGdFQUFnRTtJQUNuRCxVQUFVLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRS9EO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksdUJBQXVCLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQTBDeEc7SUFFRDs7Ozs7T0FLRztJQUNVLDJCQUEyQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFsRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBUXhGO0lBRUQ7Ozs7O09BS0c7SUFDVSxpQ0FBaUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FReEY7SUFFRDs7Ozs7T0FLRztJQUNVLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFoRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBUTdGO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsOEJBQThCLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0Fhakc7SUFFRDs7Ozs7O09BTUc7SUFDSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0E2QjlEO0lBRUQ7Ozs7O09BS0c7SUFDSSxhQUFhLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FXekU7SUFFRDs7Ozs7T0FLRztJQUNVLHNCQUFzQixDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBY3pGO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"key_store.d.ts","sourceRoot":"","sources":["../src/key_store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,cAAc,EAAS,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,SAAS,EAIf,MAAM,oBAAoB,CAAC;AAO5B;;GAEG;AACH,qBAAa,QAAQ;;IACnB,gBAAuB,cAAc,KAAK;IAI1C,YAAY,QAAQ,EAAE,iBAAiB,EAGtC;IAED;;;OAGG;IACI,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAI/C;IAED;;;;;OAKG;IACU,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAwCxF;IAED;;;OAGG;IACU,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAKlD;IAED,gEAAgE;IACnD,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/D;IAED;;;;;;OAMG;IACU,uBAAuB,CAAC,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAsC9G;IAED;;;;;OAKG;IACU,2BAA2B,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQlF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,yBAAyB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQhF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAQ7F;IAED;;;;;;OAMG;IACU,8BAA8B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,CAajG;IAED;;;;;;OAMG;IACU,kBAAkB,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAkBvE;IAED;;;;;OAKG;IACU,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAS/E;IAED;;;;;OAKG;IACU,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAczF;CACF"}
1
+ {"version":3,"file":"key_store.d.ts","sourceRoot":"","sources":["../src/key_store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,cAAc,EAAS,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,SAAS,EAKf,MAAM,oBAAoB,CAAC;AAO5B;;GAEG;AACH,qBAAa,QAAQ;;IACnB,gBAAuB,cAAc,KAAK;IAI1C,YAAY,QAAQ,EAAE,iBAAiB,EAGtC;IAED;;;OAGG;IACI,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAI/C;IAED;;;;;OAKG;IACU,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CA+CxF;IAED;;;OAGG;IACU,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAKlD;IAED,gEAAgE;IACnD,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/D;IAED;;;;;;OAMG;IACI,uBAAuB,CAAC,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0CxG;IAED;;;;;OAKG;IACU,2BAA2B,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQlF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,yBAAyB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQhF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAQ7F;IAED;;;;;;OAMG;IACU,8BAA8B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,CAajG;IAED;;;;;;OAMG;IACI,kBAAkB,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CA6B9D;IAED;;;;;OAKG;IACI,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAWzE;IAED;;;;;OAKG;IACU,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAczF;CACF"}
package/dest/key_store.js CHANGED
@@ -7,7 +7,7 @@ import { serializeToBuffer } from '@aztec/foundation/serialize';
7
7
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
8
8
  import { CompleteAddress } from '@aztec/stdlib/contract';
9
9
  import { KeyValidationRequest } from '@aztec/stdlib/kernel';
10
- import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecretKey } from '@aztec/stdlib/keys';
10
+ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecretKey, hashPublicKey } from '@aztec/stdlib/keys';
11
11
  /** Maps a key prefix to the storage suffix for the corresponding master secret key. */ function secretKeyStorageSuffix(prefix) {
12
12
  return prefix === 'n' ? 'nhk_m' : `${prefix}sk_m`;
13
13
  }
@@ -35,30 +35,32 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
35
35
  * @param partialAddress - The partial address of the account.
36
36
  * @returns The account's complete address.
37
37
  */ async addAccount(sk, partialAddress) {
38
- const { masterNullifierHidingKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, publicKeys } = await deriveKeys(sk);
39
- const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress);
38
+ const { masterNullifierHidingKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, masterNullifierPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, publicKeys } = await deriveKeys(sk);
39
+ const completeAddress = await CompleteAddress.fromPublicKeysAndPartialAddress(publicKeys, partialAddress);
40
40
  const { address: account } = completeAddress;
41
- // Compute hashes before transaction
42
- const masterNullifierPublicKeyHash = await publicKeys.masterNullifierPublicKey.hash();
43
- const masterIncomingViewingPublicKeyHash = await publicKeys.masterIncomingViewingPublicKey.hash();
44
- const masterOutgoingViewingPublicKeyHash = await publicKeys.masterOutgoingViewingPublicKey.hash();
45
- const masterTaggingPublicKeyHash = await publicKeys.masterTaggingPublicKey.hash();
41
+ // The kernel cannot check that nhpk/ovpk/tpk are on-curve or non-infinity, so the PXE/key-store
42
+ // must guarantee it before persistence. By design, the above derivation produces points that are on
43
+ // the curve and not at infinity.
44
+ // The npk/ovpk/tpk hashes are already in publicKeys; ivpk_m_hash is computed for indexing.
45
+ const masterIncomingViewingPublicKeyHash = await hashPublicKey(publicKeys.ivpkM);
46
+ // The Message Signing and Fallback Keys don't have a derivation path yet, so we just use the default values for their hashes.
47
+ // So we avoid storing them persistently. The default hash is still required for address derivation
46
48
  await this.#db.transactionAsync(async ()=>{
47
49
  // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
48
50
  await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
49
51
  await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
50
52
  await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
51
53
  await this.#keys.set(`${account.toString()}-nhk_m`, masterNullifierHidingKey.toBuffer());
52
- await this.#keys.set(`${account.toString()}-npk_m`, publicKeys.masterNullifierPublicKey.toBuffer());
53
- await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.masterIncomingViewingPublicKey.toBuffer());
54
- await this.#keys.set(`${account.toString()}-ovpk_m`, publicKeys.masterOutgoingViewingPublicKey.toBuffer());
55
- await this.#keys.set(`${account.toString()}-tpk_m`, publicKeys.masterTaggingPublicKey.toBuffer());
54
+ await this.#keys.set(`${account.toString()}-npk_m`, masterNullifierPublicKey.toBuffer());
55
+ await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.ivpkM.toBuffer());
56
+ await this.#keys.set(`${account.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer());
57
+ await this.#keys.set(`${account.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer());
56
58
  // We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
57
59
  // using the #getKeyPrefixAndAccount function later on
58
- await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
60
+ await this.#keys.set(`${account.toString()}-npk_m_hash`, publicKeys.npkMHash.toBuffer());
59
61
  await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
60
- await this.#keys.set(`${account.toString()}-ovpk_m_hash`, masterOutgoingViewingPublicKeyHash.toBuffer());
61
- await this.#keys.set(`${account.toString()}-tpk_m_hash`, masterTaggingPublicKeyHash.toBuffer());
62
+ await this.#keys.set(`${account.toString()}-ovpk_m_hash`, publicKeys.ovpkMHash.toBuffer());
63
+ await this.#keys.set(`${account.toString()}-tpk_m_hash`, publicKeys.tpkMHash.toBuffer());
62
64
  });
63
65
  // At last, we return the newly derived account address
64
66
  return completeAddress;
@@ -81,33 +83,36 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
81
83
  * @param pkMHash - The master public key hash.
82
84
  * @param contractAddress - The contract address to silo the secret key in the key validation request with.
83
85
  * @returns The key validation request.
84
- */ async getKeyValidationRequest(pkMHash, contractAddress) {
85
- const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
86
- // Now we find the master public key for the account
87
- const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
88
- if (!pkMBuffer) {
89
- throw new Error(`Could not find ${keyPrefix}pk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
90
- }
91
- const pkM = Point.fromBuffer(pkMBuffer);
92
- const computedPkMHash = await pkM.hash();
93
- if (!computedPkMHash.equals(pkMHash)) {
94
- throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
95
- }
96
- // Now we find the secret key for the public key
97
- const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
98
- const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
99
- if (!skMBuffer) {
100
- throw new Error(`Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
101
- }
102
- const skM = GrumpkinScalar.fromBuffer(skMBuffer);
103
- // We sanity check that it's possible to derive the public key from the secret key
104
- const derivedPkM = await derivePublicKeyFromSecretKey(skM);
105
- if (!derivedPkM.equals(pkM)) {
106
- throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`);
107
- }
108
- // At last we silo the secret key and return the key validation request
109
- const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix);
110
- return new KeyValidationRequest(pkM, skApp);
86
+ */ getKeyValidationRequest(pkMHash, contractAddress) {
87
+ return this.#db.transactionAsync(async ()=>{
88
+ const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
89
+ // Load the stored master public key point. The returned KVR carries only the hash, but we
90
+ // use the point here as a witness for two integrity checks below: (1) it matches the supplied
91
+ // hash, and (2) it matches the value derived from the stored secret key.
92
+ const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
93
+ if (!pkMBuffer) {
94
+ throw new Error(`Could not find ${keyPrefix}pk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
95
+ }
96
+ const pkM = Point.fromBuffer(pkMBuffer);
97
+ // Now we find the secret key for the public key
98
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
99
+ const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
100
+ if (!skMBuffer) {
101
+ throw new Error(`Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
102
+ }
103
+ const skM = GrumpkinScalar.fromBuffer(skMBuffer);
104
+ // The remaining awaits are non-DB computations. They are safe because no further IDB operations follow them.
105
+ const computedPkMHash = await hashPublicKey(pkM);
106
+ if (!computedPkMHash.equals(pkMHash)) {
107
+ throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
108
+ }
109
+ const derivedPkM = await derivePublicKeyFromSecretKey(skM);
110
+ if (!derivedPkM.equals(pkM)) {
111
+ throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`);
112
+ }
113
+ const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix);
114
+ return new KeyValidationRequest(pkMHash, skApp);
115
+ });
111
116
  }
112
117
  /**
113
118
  * Gets the master nullifier public key for a given account.
@@ -188,39 +193,49 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
188
193
  ], DomainSeparator.OVSK_M);
189
194
  }
190
195
  /**
191
- * Retrieves the sk_m corresponding to the pk_m.
192
- * @throws If the provided public key is not associated with any of the registered accounts.
193
- * @param pkM - The master public key to get secret key for.
196
+ * Retrieves the sk_m corresponding to the given pk_m hash.
197
+ * @throws If the provided hash is not associated with any of the registered accounts.
198
+ * @param pkMHash - The master public key hash to get secret key for.
194
199
  * @returns A Promise that resolves to sk_m.
195
200
  * @dev Used when feeding the sk_m to the kernel circuit for keys verification.
196
- */ async getMasterSecretKey(pkM) {
197
- const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkM);
198
- const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
199
- const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
200
- if (!secretKeyBuffer) {
201
- throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`);
202
- }
203
- const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
204
- const derivedpkM = await derivePublicKeyFromSecretKey(skM);
205
- if (!derivedpkM.equals(pkM)) {
206
- throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
207
- }
208
- return Promise.resolve(skM);
201
+ */ getMasterSecretKey(pkMHash) {
202
+ return this.#db.transactionAsync(async ()=>{
203
+ const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
204
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
205
+ const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
206
+ if (!secretKeyBuffer) {
207
+ throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()}. This should not happen.`);
208
+ }
209
+ const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
210
+ // Non-DB computation — safe because no further IDB operations follow.
211
+ // Integrity check: confirm the stored secret key still derives the requested hash. The check
212
+ // is hash-based rather than point-equal because the on-disk identifier is `pk_m_hash`;
213
+ // cryptographic collision resistance of `hashPublicKey` makes this equivalent to a
214
+ // direct point comparison in practice.
215
+ const derivedPkM = await derivePublicKeyFromSecretKey(skM);
216
+ const derivedPkMHash = await hashPublicKey(derivedPkM);
217
+ if (!derivedPkMHash.equals(pkMHash)) {
218
+ throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()} in secret keys buffer.`);
219
+ }
220
+ return skM;
221
+ });
209
222
  }
210
223
  /**
211
224
  * Checks whether a given account has a key matching the provided master public key hash.
212
225
  * @param account - The account address to check.
213
226
  * @param pkMHash - The master public key hash to look for.
214
227
  * @returns True if the account has a key with the given hash.
215
- */ async accountHasKey(account, pkMHash) {
216
- const pkMHashBuffer = serializeToBuffer(pkMHash);
217
- for (const prefix of KEY_PREFIXES){
218
- const stored = await this.#keys.getAsync(`${account.toString()}-${prefix}pk_m_hash`);
219
- if (stored && Buffer.from(stored).equals(pkMHashBuffer)) {
220
- return true;
228
+ */ accountHasKey(account, pkMHash) {
229
+ return this.#db.transactionAsync(async ()=>{
230
+ const pkMHashBuffer = serializeToBuffer(pkMHash);
231
+ for (const prefix of KEY_PREFIXES){
232
+ const stored = await this.#keys.getAsync(`${account.toString()}-${prefix}pk_m_hash`);
233
+ if (stored && Buffer.from(stored).equals(pkMHashBuffer)) {
234
+ return true;
235
+ }
221
236
  }
222
- }
223
- return false;
237
+ return false;
238
+ });
224
239
  }
225
240
  /**
226
241
  * Gets the key prefix and account address for a given value.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/key-store",
3
- "version": "5.0.0-private.20260319",
3
+ "version": "5.0.0-rc.1",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "typedocOptions": {
@@ -57,10 +57,10 @@
57
57
  ]
58
58
  },
59
59
  "dependencies": {
60
- "@aztec/constants": "5.0.0-private.20260319",
61
- "@aztec/foundation": "5.0.0-private.20260319",
62
- "@aztec/kv-store": "5.0.0-private.20260319",
63
- "@aztec/stdlib": "5.0.0-private.20260319",
60
+ "@aztec/constants": "5.0.0-rc.1",
61
+ "@aztec/foundation": "5.0.0-rc.1",
62
+ "@aztec/kv-store": "5.0.0-rc.1",
63
+ "@aztec/stdlib": "5.0.0-rc.1",
64
64
  "tslib": "^2.4.0"
65
65
  },
66
66
  "devDependencies": {
package/src/key_store.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  computeAppSecretKey,
16
16
  deriveKeys,
17
17
  derivePublicKeyFromSecretKey,
18
+ hashPublicKey,
18
19
  } from '@aztec/stdlib/keys';
19
20
 
20
21
  /** Maps a key prefix to the storage suffix for the corresponding master secret key. */
@@ -57,17 +58,24 @@ export class KeyStore {
57
58
  masterIncomingViewingSecretKey,
58
59
  masterOutgoingViewingSecretKey,
59
60
  masterTaggingSecretKey,
61
+ masterNullifierPublicKey,
62
+ masterOutgoingViewingPublicKey,
63
+ masterTaggingPublicKey,
60
64
  publicKeys,
61
65
  } = await deriveKeys(sk);
62
66
 
63
- const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress);
67
+ const completeAddress = await CompleteAddress.fromPublicKeysAndPartialAddress(publicKeys, partialAddress);
64
68
  const { address: account } = completeAddress;
65
69
 
66
- // Compute hashes before transaction
67
- const masterNullifierPublicKeyHash = await publicKeys.masterNullifierPublicKey.hash();
68
- const masterIncomingViewingPublicKeyHash = await publicKeys.masterIncomingViewingPublicKey.hash();
69
- const masterOutgoingViewingPublicKeyHash = await publicKeys.masterOutgoingViewingPublicKey.hash();
70
- const masterTaggingPublicKeyHash = await publicKeys.masterTaggingPublicKey.hash();
70
+ // The kernel cannot check that nhpk/ovpk/tpk are on-curve or non-infinity, so the PXE/key-store
71
+ // must guarantee it before persistence. By design, the above derivation produces points that are on
72
+ // the curve and not at infinity.
73
+
74
+ // The npk/ovpk/tpk hashes are already in publicKeys; ivpk_m_hash is computed for indexing.
75
+ const masterIncomingViewingPublicKeyHash = await hashPublicKey(publicKeys.ivpkM);
76
+
77
+ // The Message Signing and Fallback Keys don't have a derivation path yet, so we just use the default values for their hashes.
78
+ // So we avoid storing them persistently. The default hash is still required for address derivation
71
79
 
72
80
  await this.#db.transactionAsync(async () => {
73
81
  // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
@@ -76,17 +84,17 @@ export class KeyStore {
76
84
  await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
77
85
  await this.#keys.set(`${account.toString()}-nhk_m`, masterNullifierHidingKey.toBuffer());
78
86
 
79
- await this.#keys.set(`${account.toString()}-npk_m`, publicKeys.masterNullifierPublicKey.toBuffer());
80
- await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.masterIncomingViewingPublicKey.toBuffer());
81
- await this.#keys.set(`${account.toString()}-ovpk_m`, publicKeys.masterOutgoingViewingPublicKey.toBuffer());
82
- await this.#keys.set(`${account.toString()}-tpk_m`, publicKeys.masterTaggingPublicKey.toBuffer());
87
+ await this.#keys.set(`${account.toString()}-npk_m`, masterNullifierPublicKey.toBuffer());
88
+ await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.ivpkM.toBuffer());
89
+ await this.#keys.set(`${account.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer());
90
+ await this.#keys.set(`${account.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer());
83
91
 
84
92
  // We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
85
93
  // using the #getKeyPrefixAndAccount function later on
86
- await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
94
+ await this.#keys.set(`${account.toString()}-npk_m_hash`, publicKeys.npkMHash.toBuffer());
87
95
  await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
88
- await this.#keys.set(`${account.toString()}-ovpk_m_hash`, masterOutgoingViewingPublicKeyHash.toBuffer());
89
- await this.#keys.set(`${account.toString()}-tpk_m_hash`, masterTaggingPublicKeyHash.toBuffer());
96
+ await this.#keys.set(`${account.toString()}-ovpk_m_hash`, publicKeys.ovpkMHash.toBuffer());
97
+ await this.#keys.set(`${account.toString()}-tpk_m_hash`, publicKeys.tpkMHash.toBuffer());
90
98
  });
91
99
 
92
100
  // At last, we return the newly derived account address
@@ -116,44 +124,48 @@ export class KeyStore {
116
124
  * @param contractAddress - The contract address to silo the secret key in the key validation request with.
117
125
  * @returns The key validation request.
118
126
  */
119
- public async getKeyValidationRequest(pkMHash: Fr, contractAddress: AztecAddress): Promise<KeyValidationRequest> {
120
- const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
127
+ public getKeyValidationRequest(pkMHash: Fr, contractAddress: AztecAddress): Promise<KeyValidationRequest> {
128
+ return this.#db.transactionAsync(async () => {
129
+ const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
130
+
131
+ // Load the stored master public key point. The returned KVR carries only the hash, but we
132
+ // use the point here as a witness for two integrity checks below: (1) it matches the supplied
133
+ // hash, and (2) it matches the value derived from the stored secret key.
134
+ const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
135
+ if (!pkMBuffer) {
136
+ throw new Error(
137
+ `Could not find ${keyPrefix}pk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
138
+ );
139
+ }
121
140
 
122
- // Now we find the master public key for the account
123
- const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
124
- if (!pkMBuffer) {
125
- throw new Error(
126
- `Could not find ${keyPrefix}pk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
127
- );
128
- }
141
+ const pkM = Point.fromBuffer(pkMBuffer);
129
142
 
130
- const pkM = Point.fromBuffer(pkMBuffer);
131
- const computedPkMHash = await pkM.hash();
132
- if (!computedPkMHash.equals(pkMHash)) {
133
- throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
134
- }
143
+ // Now we find the secret key for the public key
144
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
145
+ const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
146
+ if (!skMBuffer) {
147
+ throw new Error(
148
+ `Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
149
+ );
150
+ }
135
151
 
136
- // Now we find the secret key for the public key
137
- const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
138
- const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
139
- if (!skMBuffer) {
140
- throw new Error(
141
- `Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
142
- );
143
- }
152
+ const skM = GrumpkinScalar.fromBuffer(skMBuffer);
144
153
 
145
- const skM = GrumpkinScalar.fromBuffer(skMBuffer);
154
+ // The remaining awaits are non-DB computations. They are safe because no further IDB operations follow them.
155
+ const computedPkMHash = await hashPublicKey(pkM);
156
+ if (!computedPkMHash.equals(pkMHash)) {
157
+ throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
158
+ }
146
159
 
147
- // We sanity check that it's possible to derive the public key from the secret key
148
- const derivedPkM = await derivePublicKeyFromSecretKey(skM);
149
- if (!derivedPkM.equals(pkM)) {
150
- throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`);
151
- }
160
+ const derivedPkM = await derivePublicKeyFromSecretKey(skM);
161
+ if (!derivedPkM.equals(pkM)) {
162
+ throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`);
163
+ }
152
164
 
153
- // At last we silo the secret key and return the key validation request
154
- const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix!);
165
+ const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix!);
155
166
 
156
- return new KeyValidationRequest(pkM, skApp);
167
+ return new KeyValidationRequest(pkMHash, skApp);
168
+ });
157
169
  }
158
170
 
159
171
  /**
@@ -259,30 +271,41 @@ export class KeyStore {
259
271
  }
260
272
 
261
273
  /**
262
- * Retrieves the sk_m corresponding to the pk_m.
263
- * @throws If the provided public key is not associated with any of the registered accounts.
264
- * @param pkM - The master public key to get secret key for.
274
+ * Retrieves the sk_m corresponding to the given pk_m hash.
275
+ * @throws If the provided hash is not associated with any of the registered accounts.
276
+ * @param pkMHash - The master public key hash to get secret key for.
265
277
  * @returns A Promise that resolves to sk_m.
266
278
  * @dev Used when feeding the sk_m to the kernel circuit for keys verification.
267
279
  */
268
- public async getMasterSecretKey(pkM: PublicKey): Promise<GrumpkinScalar> {
269
- const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkM);
270
-
271
- const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
272
- const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
273
- if (!secretKeyBuffer) {
274
- throw new Error(
275
- `Could not find ${skStorageSuffix} for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`,
276
- );
277
- }
280
+ public getMasterSecretKey(pkMHash: Fr): Promise<GrumpkinScalar> {
281
+ return this.#db.transactionAsync(async () => {
282
+ const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
283
+
284
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
285
+ const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
286
+ if (!secretKeyBuffer) {
287
+ throw new Error(
288
+ `Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()}. This should not happen.`,
289
+ );
290
+ }
278
291
 
279
- const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
280
- const derivedpkM = await derivePublicKeyFromSecretKey(skM);
281
- if (!derivedpkM.equals(pkM)) {
282
- throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
283
- }
292
+ const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
293
+
294
+ // Non-DB computation — safe because no further IDB operations follow.
295
+ // Integrity check: confirm the stored secret key still derives the requested hash. The check
296
+ // is hash-based rather than point-equal because the on-disk identifier is `pk_m_hash`;
297
+ // cryptographic collision resistance of `hashPublicKey` makes this equivalent to a
298
+ // direct point comparison in practice.
299
+ const derivedPkM = await derivePublicKeyFromSecretKey(skM);
300
+ const derivedPkMHash = await hashPublicKey(derivedPkM);
301
+ if (!derivedPkMHash.equals(pkMHash)) {
302
+ throw new Error(
303
+ `Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()} in secret keys buffer.`,
304
+ );
305
+ }
284
306
 
285
- return Promise.resolve(skM);
307
+ return skM;
308
+ });
286
309
  }
287
310
 
288
311
  /**
@@ -291,15 +314,17 @@ export class KeyStore {
291
314
  * @param pkMHash - The master public key hash to look for.
292
315
  * @returns True if the account has a key with the given hash.
293
316
  */
294
- public async accountHasKey(account: AztecAddress, pkMHash: Fr): Promise<boolean> {
295
- const pkMHashBuffer = serializeToBuffer(pkMHash);
296
- for (const prefix of KEY_PREFIXES) {
297
- const stored = await this.#keys.getAsync(`${account.toString()}-${prefix}pk_m_hash`);
298
- if (stored && Buffer.from(stored).equals(pkMHashBuffer)) {
299
- return true;
317
+ public accountHasKey(account: AztecAddress, pkMHash: Fr): Promise<boolean> {
318
+ return this.#db.transactionAsync(async () => {
319
+ const pkMHashBuffer = serializeToBuffer(pkMHash);
320
+ for (const prefix of KEY_PREFIXES) {
321
+ const stored = await this.#keys.getAsync(`${account.toString()}-${prefix}pk_m_hash`);
322
+ if (stored && Buffer.from(stored).equals(pkMHashBuffer)) {
323
+ return true;
324
+ }
300
325
  }
301
- }
302
- return false;
326
+ return false;
327
+ });
303
328
  }
304
329
 
305
330
  /**