@aztec/key-store 0.0.1-commit.03f7ef2 → 0.0.1-commit.08c5969dc

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.
@@ -11,7 +11,7 @@ import { type KeyPrefix, type PublicKey } from '@aztec/stdlib/keys';
11
11
  */
12
12
  export declare class KeyStore {
13
13
  #private;
14
- static readonly SCHEMA_VERSION: number;
14
+ static readonly SCHEMA_VERSION = 1;
15
15
  constructor(database: AztecAsyncKVStore);
16
16
  /**
17
17
  * Creates a new account from a randomly generated secret key.
@@ -30,6 +30,8 @@ export declare class KeyStore {
30
30
  * @returns A Promise that resolves to an array of account addresses.
31
31
  */
32
32
  getAccounts(): Promise<AztecAddress[]>;
33
+ /** Checks whether an account is registered in the key store. */
34
+ hasAccount(account: AztecAddress): Promise<boolean>;
33
35
  /**
34
36
  * Gets the key validation request for a given master public key hash and contract address.
35
37
  * @throws If the account corresponding to the master public key hash does not exist in the key store.
@@ -89,6 +91,13 @@ export declare class KeyStore {
89
91
  * @dev Used when feeding the sk_m to the kernel circuit for keys verification.
90
92
  */
91
93
  getMasterSecretKey(pkM: PublicKey): Promise<GrumpkinScalar>;
94
+ /**
95
+ * Checks whether a given account has a key matching the provided master public key hash.
96
+ * @param account - The account address to check.
97
+ * @param pkMHash - The master public key hash to look for.
98
+ * @returns True if the account has a key with the given hash.
99
+ */
100
+ accountHasKey(account: AztecAddress, pkMHash: Fr): Promise<boolean>;
92
101
  /**
93
102
  * Gets the key prefix and account address for a given value.
94
103
  * @returns A tuple containing the key prefix and account address.
@@ -97,4 +106,4 @@ export declare class KeyStore {
97
106
  */
98
107
  getKeyPrefixAndAccount(value: Bufferable): Promise<[KeyPrefix, AztecAddress]>;
99
108
  }
100
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMva2V5X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0sbUNBQW1DLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUFxQixNQUFNLDZCQUE2QixDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUVMLEtBQUssU0FBUyxFQUNkLEtBQUssU0FBUyxFQUlmLE1BQU0sb0JBQW9CLENBQUM7QUFFNUI7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQUNuQixnQkFBdUIsY0FBYyxTQUFLO0lBRzFDLFlBQVksUUFBUSxFQUFFLGlCQUFpQixFQUV0QztJQUVEOzs7T0FHRztJQUNJLGFBQWEsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDLENBSS9DO0lBRUQ7Ozs7O09BS0c7SUFDVSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FvQ3hGO0lBRUQ7OztPQUdHO0lBQ1UsV0FBVyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUtsRDtJQUVEOzs7Ozs7T0FNRztJQUNVLHVCQUF1QixDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsZUFBZSxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FxQzlHO0lBRUQ7Ozs7O09BS0c7SUFDVSwyQkFBMkIsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FRbEY7SUFFRDs7Ozs7T0FLRztJQUNVLGlDQUFpQyxDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVF4RjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBUXhGO0lBRUQ7Ozs7O09BS0c7SUFDVSx5QkFBeUIsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FRaEY7SUFFRDs7Ozs7T0FLRztJQUNVLGlDQUFpQyxDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQVE3RjtJQUVEOzs7Ozs7T0FNRztJQUNVLDhCQUE4QixDQUFDLE9BQU8sRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLENBYWpHO0lBRUQ7Ozs7OztPQU1HO0lBQ1Usa0JBQWtCLENBQUMsR0FBRyxFQUFFLFNBQVMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBaUJ2RTtJQUVEOzs7OztPQUtHO0lBQ1Usc0JBQXNCLENBQUMsS0FBSyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FjekY7Q0FDRiJ9
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMva2V5X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0sbUNBQW1DLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUFxQixNQUFNLDZCQUE2QixDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUVMLEtBQUssU0FBUyxFQUNkLEtBQUssU0FBUyxFQUlmLE1BQU0sb0JBQW9CLENBQUM7QUFPNUI7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQUNuQixnQkFBdUIsY0FBYyxLQUFLO0lBSTFDLFlBQVksUUFBUSxFQUFFLGlCQUFpQixFQUd0QztJQUVEOzs7T0FHRztJQUNJLGFBQWEsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDLENBSS9DO0lBRUQ7Ozs7O09BS0c7SUFDVSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0F3Q3hGO0lBRUQ7OztPQUdHO0lBQ1UsV0FBVyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUtsRDtJQUVELGdFQUFnRTtJQUNuRCxVQUFVLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRS9EO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsdUJBQXVCLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQXNDOUc7SUFFRDs7Ozs7T0FLRztJQUNVLDJCQUEyQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFsRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBUXhGO0lBRUQ7Ozs7O09BS0c7SUFDVSxpQ0FBaUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FReEY7SUFFRDs7Ozs7T0FLRztJQUNVLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFoRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBUTdGO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsOEJBQThCLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0Fhakc7SUFFRDs7Ozs7O09BTUc7SUFDVSxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsU0FBUyxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FrQnZFO0lBRUQ7Ozs7O09BS0c7SUFDVSxhQUFhLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FTL0U7SUFFRDs7Ozs7T0FLRztJQUNVLHNCQUFzQixDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBY3pGO0NBQ0YifQ==
@@ -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;AAE5B;;GAEG;AACH,qBAAa,QAAQ;;IACnB,gBAAuB,cAAc,SAAK;IAG1C,YAAY,QAAQ,EAAE,iBAAiB,EAEtC;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,CAoCxF;IAED;;;OAGG;IACU,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAKlD;IAED;;;;;;OAMG;IACU,uBAAuB,CAAC,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqC9G;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,CAiBvE;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,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"}
package/dest/key_store.js CHANGED
@@ -8,12 +8,17 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
8
8
  import { CompleteAddress } from '@aztec/stdlib/contract';
9
9
  import { KeyValidationRequest } from '@aztec/stdlib/kernel';
10
10
  import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecretKey } from '@aztec/stdlib/keys';
11
+ /** Maps a key prefix to the storage suffix for the corresponding master secret key. */ function secretKeyStorageSuffix(prefix) {
12
+ return prefix === 'n' ? 'nhk_m' : `${prefix}sk_m`;
13
+ }
11
14
  /**
12
15
  * Used for managing keys. Can hold keys of multiple accounts.
13
16
  */ export class KeyStore {
14
17
  static SCHEMA_VERSION = 1;
18
+ #db;
15
19
  #keys;
16
20
  constructor(database){
21
+ this.#db = database;
17
22
  this.#keys = database.openMap('key_store');
18
23
  }
19
24
  /**
@@ -30,28 +35,31 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
30
35
  * @param partialAddress - The partial address of the account.
31
36
  * @returns The account's complete address.
32
37
  */ async addAccount(sk, partialAddress) {
33
- const { masterNullifierSecretKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, publicKeys } = await deriveKeys(sk);
38
+ const { masterNullifierHidingKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, publicKeys } = await deriveKeys(sk);
34
39
  const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress);
35
40
  const { address: account } = completeAddress;
36
- // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
37
- await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
38
- await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
39
- await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
40
- await this.#keys.set(`${account.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer());
41
- await this.#keys.set(`${account.toString()}-npk_m`, publicKeys.masterNullifierPublicKey.toBuffer());
42
- await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.masterIncomingViewingPublicKey.toBuffer());
43
- await this.#keys.set(`${account.toString()}-ovpk_m`, publicKeys.masterOutgoingViewingPublicKey.toBuffer());
44
- await this.#keys.set(`${account.toString()}-tpk_m`, publicKeys.masterTaggingPublicKey.toBuffer());
45
- // We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
46
- // using the #getKeyPrefixAndAccount function later on
41
+ // Compute hashes before transaction
47
42
  const masterNullifierPublicKeyHash = await publicKeys.masterNullifierPublicKey.hash();
48
- await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
49
43
  const masterIncomingViewingPublicKeyHash = await publicKeys.masterIncomingViewingPublicKey.hash();
50
- await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
51
44
  const masterOutgoingViewingPublicKeyHash = await publicKeys.masterOutgoingViewingPublicKey.hash();
52
- await this.#keys.set(`${account.toString()}-ovpk_m_hash`, masterOutgoingViewingPublicKeyHash.toBuffer());
53
45
  const masterTaggingPublicKeyHash = await publicKeys.masterTaggingPublicKey.hash();
54
- await this.#keys.set(`${account.toString()}-tpk_m_hash`, masterTaggingPublicKeyHash.toBuffer());
46
+ await this.#db.transactionAsync(async ()=>{
47
+ // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
48
+ await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
49
+ await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
50
+ await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
51
+ 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());
56
+ // 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
+ // using the #getKeyPrefixAndAccount function later on
58
+ await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
59
+ 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
+ });
55
63
  // At last, we return the newly derived account address
56
64
  return completeAddress;
57
65
  }
@@ -64,6 +72,9 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
64
72
  const accounts = allMapKeys.filter((key)=>key.endsWith('-ivsk_m')).map((key)=>key.split('-')[0]);
65
73
  return accounts.map((account)=>AztecAddress.fromString(account));
66
74
  }
75
+ /** Checks whether an account is registered in the key store. */ async hasAccount(account) {
76
+ return !!await this.#keys.getAsync(`${account.toString()}-ivsk_m`);
77
+ }
67
78
  /**
68
79
  * Gets the key validation request for a given master public key hash and contract address.
69
80
  * @throws If the account corresponding to the master public key hash does not exist in the key store.
@@ -83,9 +94,10 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
83
94
  throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
84
95
  }
85
96
  // Now we find the secret key for the public key
86
- const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}sk_m`);
97
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
98
+ const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
87
99
  if (!skMBuffer) {
88
- throw new Error(`Could not find ${keyPrefix}sk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
100
+ throw new Error(`Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
89
101
  }
90
102
  const skM = GrumpkinScalar.fromBuffer(skMBuffer);
91
103
  // We sanity check that it's possible to derive the public key from the secret key
@@ -183,18 +195,34 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
183
195
  * @dev Used when feeding the sk_m to the kernel circuit for keys verification.
184
196
  */ async getMasterSecretKey(pkM) {
185
197
  const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkM);
186
- const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}sk_m`);
198
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
199
+ const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
187
200
  if (!secretKeyBuffer) {
188
- throw new Error(`Could not find ${keyPrefix}sk_m for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`);
201
+ throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`);
189
202
  }
190
203
  const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
191
204
  const derivedpkM = await derivePublicKeyFromSecretKey(skM);
192
205
  if (!derivedpkM.equals(pkM)) {
193
- throw new Error(`Could not find ${keyPrefix}skM for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
206
+ throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
194
207
  }
195
208
  return Promise.resolve(skM);
196
209
  }
197
210
  /**
211
+ * Checks whether a given account has a key matching the provided master public key hash.
212
+ * @param account - The account address to check.
213
+ * @param pkMHash - The master public key hash to look for.
214
+ * @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;
221
+ }
222
+ }
223
+ return false;
224
+ }
225
+ /**
198
226
  * Gets the key prefix and account address for a given value.
199
227
  * @returns A tuple containing the key prefix and account address.
200
228
  * @dev Note that this is quite inefficient but it should not matter because there should never be too many keys
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/key-store",
3
- "version": "0.0.1-commit.03f7ef2",
3
+ "version": "0.0.1-commit.08c5969dc",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "typedocOptions": {
@@ -57,17 +57,17 @@
57
57
  ]
58
58
  },
59
59
  "dependencies": {
60
- "@aztec/constants": "0.0.1-commit.03f7ef2",
61
- "@aztec/foundation": "0.0.1-commit.03f7ef2",
62
- "@aztec/kv-store": "0.0.1-commit.03f7ef2",
63
- "@aztec/stdlib": "0.0.1-commit.03f7ef2",
60
+ "@aztec/constants": "0.0.1-commit.08c5969dc",
61
+ "@aztec/foundation": "0.0.1-commit.08c5969dc",
62
+ "@aztec/kv-store": "0.0.1-commit.08c5969dc",
63
+ "@aztec/stdlib": "0.0.1-commit.08c5969dc",
64
64
  "tslib": "^2.4.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@jest/globals": "^30.0.0",
68
68
  "@types/jest": "^30.0.0",
69
69
  "@types/node": "^22.15.17",
70
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
70
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
71
71
  "jest": "^30.0.0",
72
72
  "ts-node": "^10.9.1",
73
73
  "typescript": "^5.3.3"
package/src/key_store.ts CHANGED
@@ -17,14 +17,21 @@ import {
17
17
  derivePublicKeyFromSecretKey,
18
18
  } from '@aztec/stdlib/keys';
19
19
 
20
+ /** Maps a key prefix to the storage suffix for the corresponding master secret key. */
21
+ function secretKeyStorageSuffix(prefix: KeyPrefix): string {
22
+ return prefix === 'n' ? 'nhk_m' : `${prefix}sk_m`;
23
+ }
24
+
20
25
  /**
21
26
  * Used for managing keys. Can hold keys of multiple accounts.
22
27
  */
23
28
  export class KeyStore {
24
29
  public static readonly SCHEMA_VERSION = 1;
30
+ #db: AztecAsyncKVStore;
25
31
  #keys: AztecAsyncMap<string, Buffer>;
26
32
 
27
33
  constructor(database: AztecAsyncKVStore) {
34
+ this.#db = database;
28
35
  this.#keys = database.openMap('key_store');
29
36
  }
30
37
 
@@ -46,7 +53,7 @@ export class KeyStore {
46
53
  */
47
54
  public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise<CompleteAddress> {
48
55
  const {
49
- masterNullifierSecretKey,
56
+ masterNullifierHidingKey,
50
57
  masterIncomingViewingSecretKey,
51
58
  masterOutgoingViewingSecretKey,
52
59
  masterTaggingSecretKey,
@@ -56,27 +63,31 @@ export class KeyStore {
56
63
  const completeAddress = await CompleteAddress.fromSecretKeyAndPartialAddress(sk, partialAddress);
57
64
  const { address: account } = completeAddress;
58
65
 
59
- // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
60
- await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
61
- await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
62
- await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
63
- await this.#keys.set(`${account.toString()}-nsk_m`, masterNullifierSecretKey.toBuffer());
64
-
65
- await this.#keys.set(`${account.toString()}-npk_m`, publicKeys.masterNullifierPublicKey.toBuffer());
66
- await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.masterIncomingViewingPublicKey.toBuffer());
67
- await this.#keys.set(`${account.toString()}-ovpk_m`, publicKeys.masterOutgoingViewingPublicKey.toBuffer());
68
- await this.#keys.set(`${account.toString()}-tpk_m`, publicKeys.masterTaggingPublicKey.toBuffer());
69
-
70
- // We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
71
- // using the #getKeyPrefixAndAccount function later on
66
+ // Compute hashes before transaction
72
67
  const masterNullifierPublicKeyHash = await publicKeys.masterNullifierPublicKey.hash();
73
- await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
74
68
  const masterIncomingViewingPublicKeyHash = await publicKeys.masterIncomingViewingPublicKey.hash();
75
- await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
76
69
  const masterOutgoingViewingPublicKeyHash = await publicKeys.masterOutgoingViewingPublicKey.hash();
77
- await this.#keys.set(`${account.toString()}-ovpk_m_hash`, masterOutgoingViewingPublicKeyHash.toBuffer());
78
70
  const masterTaggingPublicKeyHash = await publicKeys.masterTaggingPublicKey.hash();
79
- await this.#keys.set(`${account.toString()}-tpk_m_hash`, masterTaggingPublicKeyHash.toBuffer());
71
+
72
+ await this.#db.transactionAsync(async () => {
73
+ // Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
74
+ await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
75
+ await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
76
+ await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
77
+ await this.#keys.set(`${account.toString()}-nhk_m`, masterNullifierHidingKey.toBuffer());
78
+
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());
83
+
84
+ // 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
+ // using the #getKeyPrefixAndAccount function later on
86
+ await this.#keys.set(`${account.toString()}-npk_m_hash`, masterNullifierPublicKeyHash.toBuffer());
87
+ 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());
90
+ });
80
91
 
81
92
  // At last, we return the newly derived account address
82
93
  return completeAddress;
@@ -93,6 +104,11 @@ export class KeyStore {
93
104
  return accounts.map(account => AztecAddress.fromString(account));
94
105
  }
95
106
 
107
+ /** Checks whether an account is registered in the key store. */
108
+ public async hasAccount(account: AztecAddress): Promise<boolean> {
109
+ return !!(await this.#keys.getAsync(`${account.toString()}-ivsk_m`));
110
+ }
111
+
96
112
  /**
97
113
  * Gets the key validation request for a given master public key hash and contract address.
98
114
  * @throws If the account corresponding to the master public key hash does not exist in the key store.
@@ -118,10 +134,11 @@ export class KeyStore {
118
134
  }
119
135
 
120
136
  // Now we find the secret key for the public key
121
- const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}sk_m`);
137
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
138
+ const skMBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
122
139
  if (!skMBuffer) {
123
140
  throw new Error(
124
- `Could not find ${keyPrefix}sk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
141
+ `Could not find ${skStorageSuffix} for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`,
125
142
  );
126
143
  }
127
144
 
@@ -251,22 +268,40 @@ export class KeyStore {
251
268
  public async getMasterSecretKey(pkM: PublicKey): Promise<GrumpkinScalar> {
252
269
  const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkM);
253
270
 
254
- const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}sk_m`);
271
+ const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
272
+ const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
255
273
  if (!secretKeyBuffer) {
256
274
  throw new Error(
257
- `Could not find ${keyPrefix}sk_m for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`,
275
+ `Could not find ${skStorageSuffix} for ${keyPrefix}pk_m ${pkM.toString()}. This should not happen.`,
258
276
  );
259
277
  }
260
278
 
261
279
  const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
262
280
  const derivedpkM = await derivePublicKeyFromSecretKey(skM);
263
281
  if (!derivedpkM.equals(pkM)) {
264
- throw new Error(`Could not find ${keyPrefix}skM for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
282
+ throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pkM ${pkM.toString()} in secret keys buffer.`);
265
283
  }
266
284
 
267
285
  return Promise.resolve(skM);
268
286
  }
269
287
 
288
+ /**
289
+ * Checks whether a given account has a key matching the provided master public key hash.
290
+ * @param account - The account address to check.
291
+ * @param pkMHash - The master public key hash to look for.
292
+ * @returns True if the account has a key with the given hash.
293
+ */
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;
300
+ }
301
+ }
302
+ return false;
303
+ }
304
+
270
305
  /**
271
306
  * Gets the key prefix and account address for a given value.
272
307
  * @returns A tuple containing the key prefix and account address.