@aztec/node-keystore 2.1.0-rc.1 → 2.1.0-rc.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AAiEtC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYvB,CAAC"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG/D,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AACtC,eAAO,MAAM,mBAAmB,kDAGK,CAAC;AAgFtC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYvB,CAAC"}
package/dest/schemas.js CHANGED
@@ -5,6 +5,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
  import { z } from 'zod';
6
6
  // Use Aztec's validation functions but return string types to match our TypeScript interfaces
7
7
  export const ethPrivateKeySchema = z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'Invalid private key (must be 32 bytes with 0x prefix)').transform((s)=>s);
8
+ export const blsPrivateKeySchema = z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'Invalid BLS private key (must be 32 bytes with 0x prefix)').transform((s)=>s);
8
9
  const urlSchema = z.string().url('Invalid URL');
9
10
  // Remote signer config schema
10
11
  const remoteSignerConfigSchema = z.union([
@@ -20,7 +21,7 @@ const remoteSignerAccountSchema = z.union([
20
21
  schemas.EthAddress,
21
22
  z.object({
22
23
  address: schemas.EthAddress,
23
- remoteSignerUrl: optional(urlSchema),
24
+ remoteSignerUrl: urlSchema,
24
25
  certPath: optional(z.string()),
25
26
  certPass: optional(z.string())
26
27
  })
@@ -50,6 +51,25 @@ const ethAccountsSchema = z.union([
50
51
  z.array(ethAccountSchema),
51
52
  mnemonicConfigSchema
52
53
  ]);
54
+ // BLSAccount schema
55
+ const blsAccountSchema = z.union([
56
+ blsPrivateKeySchema,
57
+ jsonKeyFileV3Schema
58
+ ]);
59
+ // AttesterAccount schema: either EthAccount or { eth: EthAccount, bls?: BLSAccount }
60
+ const attesterAccountSchema = z.union([
61
+ ethAccountSchema,
62
+ z.object({
63
+ eth: ethAccountSchema,
64
+ bls: optional(blsAccountSchema)
65
+ })
66
+ ]);
67
+ // AttesterAccounts schema: AttesterAccount | AttesterAccount[] | MnemonicConfig
68
+ const attesterAccountsSchema = z.union([
69
+ attesterAccountSchema,
70
+ z.array(attesterAccountSchema),
71
+ mnemonicConfigSchema
72
+ ]);
53
73
  // Prover keystore schema
54
74
  const proverKeyStoreSchema = z.union([
55
75
  ethAccountSchema,
@@ -60,7 +80,7 @@ const proverKeyStoreSchema = z.union([
60
80
  ]);
61
81
  // Validator keystore schema
62
82
  const validatorKeyStoreSchema = z.object({
63
- attester: ethAccountsSchema,
83
+ attester: attesterAccountsSchema,
64
84
  coinbase: optional(schemas.EthAddress),
65
85
  publisher: optional(ethAccountsSchema),
66
86
  feeRecipient: AztecAddress.schema,
package/dest/types.d.ts CHANGED
@@ -12,12 +12,14 @@ export type Hex<TByteLength extends number> = `0x${string}` & {
12
12
  readonly _length: TByteLength;
13
13
  };
14
14
  /** A json keystore config points to a local file with the encrypted private key, and may require a password for decrypting it */
15
- export type EthJsonKeyFileV3Config = {
15
+ export type JsonKeyFileV3Config = {
16
16
  path: string;
17
17
  password?: string;
18
18
  };
19
19
  /** A private key is a 32-byte 0x-prefixed hex */
20
20
  export type EthPrivateKey = Hex<32>;
21
+ /** A BLS private key is a 32-byte 0x-prefixed hex */
22
+ export type BLSPrivateKey = Hex<32>;
21
23
  /** URL type for remote signers */
22
24
  export type Url = string;
23
25
  /**
@@ -34,14 +36,14 @@ export type EthRemoteSignerConfig = Url | {
34
36
  */
35
37
  export type EthRemoteSignerAccount = EthAddress | {
36
38
  address: EthAddress;
37
- remoteSignerUrl?: Url;
39
+ remoteSignerUrl: Url;
38
40
  certPath?: string;
39
41
  certPass?: string;
40
42
  };
41
43
  /** An L1 account is a private key, a remote signer configuration, or a standard json key store file */
42
- export type EthAccount = EthPrivateKey | EthRemoteSignerAccount | EthJsonKeyFileV3Config;
44
+ export type EthAccount = EthPrivateKey | EthRemoteSignerAccount | JsonKeyFileV3Config;
43
45
  /** A mnemonic can be used to define a set of accounts */
44
- export type EthMnemonicConfig = {
46
+ export type MnemonicConfig = {
45
47
  mnemonic: string;
46
48
  addressIndex?: number;
47
49
  accountIndex?: number;
@@ -49,7 +51,7 @@ export type EthMnemonicConfig = {
49
51
  accountCount?: number;
50
52
  };
51
53
  /** One or more L1 accounts */
52
- export type EthAccounts = EthAccount | EthAccount[] | EthMnemonicConfig;
54
+ export type EthAccounts = EthAccount | EthAccount[] | MnemonicConfig;
53
55
  export type ProverKeyStoreWithId = {
54
56
  /** Address that identifies the prover. This address will receive the rewards. */
55
57
  id: EthAddress;
@@ -57,12 +59,21 @@ export type ProverKeyStoreWithId = {
57
59
  publisher: EthAccounts;
58
60
  };
59
61
  export type ProverKeyStore = ProverKeyStoreWithId | EthAccount;
62
+ /** A BLS account is either a private key, or a standard json key store file */
63
+ export type BLSAccount = BLSPrivateKey | JsonKeyFileV3Config;
64
+ /** An AttesterAccount is a combined EthAccount and optional BLSAccount */
65
+ export type AttesterAccount = {
66
+ eth: EthAccount;
67
+ bls?: BLSAccount;
68
+ } | EthAccount;
69
+ /** One or more attester accounts combining ETH and BLS keys */
70
+ export type AttesterAccounts = AttesterAccount | AttesterAccount[] | MnemonicConfig;
60
71
  export type ValidatorKeyStore = {
61
72
  /**
62
73
  * One or more validator attester keys to handle in this configuration block.
63
74
  * An attester address may only appear once across all configuration blocks across all keystore files.
64
75
  */
65
- attester: EthAccounts;
76
+ attester: AttesterAccounts;
66
77
  /**
67
78
  * Coinbase address to use when proposing an L2 block as any of the validators in this configuration block.
68
79
  * Falls back to the attester address if not set.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,8DAA8D;AAC9D,MAAM,MAAM,GAAG,CAAC,WAAW,SAAS,MAAM,IAAI,KAAK,MAAM,EAAE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AAEhG,iIAAiI;AACjI,MAAM,MAAM,sBAAsB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,iDAAiD;AACjD,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;AAEpC,kCAAkC;AAClC,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC;AAEzB;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,GAAG,GACH;IACE,eAAe,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAC9B,UAAU,GACV;IACE,OAAO,EAAE,UAAU,CAAC;IACpB,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN,uGAAuG;AACvG,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAEzF,yDAAyD;AACzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,UAAU,EAAE,GAAG,iBAAiB,CAAC;AAExE,MAAM,MAAM,oBAAoB,GAAG;IACjC,iFAAiF;IACjF,EAAE,EAAE,UAAU,CAAC;IACf,sDAAsD;IACtD,SAAS,EAAE,WAAW,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,UAAU,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,QAAQ,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B;;OAEG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,8GAA8G;IAC9G,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,sEAAsE;IACtE,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,wHAAwH;IACxH,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/node-keystore",
3
- "version": "2.1.0-rc.1",
3
+ "version": "2.1.0-rc.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -62,9 +62,9 @@
62
62
  ]
63
63
  },
64
64
  "dependencies": {
65
- "@aztec/ethereum": "2.1.0-rc.1",
66
- "@aztec/foundation": "2.1.0-rc.1",
67
- "@aztec/stdlib": "2.1.0-rc.1",
65
+ "@aztec/ethereum": "2.1.0-rc.3",
66
+ "@aztec/foundation": "2.1.0-rc.3",
67
+ "@aztec/stdlib": "2.1.0-rc.3",
68
68
  "@ethersproject/wallet": "^5.7.0",
69
69
  "tslib": "^2.4.0",
70
70
  "viem": "2.23.7",
@@ -18,13 +18,14 @@ import { mnemonicToAccount } from 'viem/accounts';
18
18
  import { ethPrivateKeySchema } from './schemas.js';
19
19
  import { LocalSigner, RemoteSigner } from './signer.js';
20
20
  import type {
21
+ AttesterAccounts,
21
22
  EthAccount,
22
23
  EthAccounts,
23
- EthJsonKeyFileV3Config,
24
- EthMnemonicConfig,
25
24
  EthRemoteSignerAccount,
26
25
  EthRemoteSignerConfig,
26
+ JsonKeyFileV3Config,
27
27
  KeyStore,
28
+ MnemonicConfig,
28
29
  ProverKeyStore,
29
30
  ValidatorKeyStore as ValidatorKeystoreConfig,
30
31
  } from './types.js';
@@ -110,7 +111,7 @@ export class KeystoreManager {
110
111
  const validator = this.getValidator(i);
111
112
  const remoteSigner = validator.remoteSigner || this.keystore.remoteSigner;
112
113
 
113
- collectRemoteSigners(validator.attester, remoteSigner);
114
+ collectRemoteSigners(this.extractEthAccountsFromAttester(validator.attester), remoteSigner);
114
115
  if (validator.publisher) {
115
116
  collectRemoteSigners(validator.publisher, remoteSigner);
116
117
  }
@@ -162,38 +163,38 @@ export class KeystoreManager {
162
163
  * Best-effort address extraction that avoids decryption/derivation (no JSON-V3 or mnemonic processing).
163
164
  * This is used at construction time to check for obvious duplicates without throwing for invalid inputs.
164
165
  */
165
- private extractAddressesWithoutSensitiveOperations(accounts: EthAccounts): EthAddress[] {
166
+ private extractAddressesWithoutSensitiveOperations(accounts: AttesterAccounts): EthAddress[] {
167
+ const ethAccounts = this.extractEthAccountsFromAttester(accounts);
168
+ return this.extractAddressesFromEthAccountsNonSensitive(ethAccounts);
169
+ }
170
+
171
+ /**
172
+ * Extract addresses from EthAccounts without sensitive operations (no decryption/derivation).
173
+ */
174
+ private extractAddressesFromEthAccountsNonSensitive(accounts: EthAccounts): EthAddress[] {
166
175
  const results: EthAddress[] = [];
167
176
 
168
177
  const handleAccount = (account: EthAccount): void => {
169
- // String cases: private key or address or remote signer address
170
178
  if (typeof account === 'string') {
171
179
  if (account.startsWith('0x') && account.length === 66) {
172
- // Private key -> derive address locally without external deps
173
180
  try {
174
181
  const signer = new LocalSigner(Buffer32.fromString(ethPrivateKeySchema.parse(account)));
175
182
  results.push(signer.address);
176
183
  } catch {
177
- // Ignore invalid private key at construction time
184
+ // ignore invalid private key at construction time
178
185
  }
179
- return;
180
186
  }
181
-
182
- // Any other string cannot be confidently resolved here
183
187
  return;
184
188
  }
185
189
 
186
- // JSON V3 keystore: skip (requires decryption)
187
190
  if ('path' in account) {
188
191
  return;
189
192
  }
190
193
 
191
- // Mnemonic: skip (requires derivation and may throw on invalid mnemonics)
192
194
  if ('mnemonic' in (account as any)) {
193
195
  return;
194
196
  }
195
197
 
196
- // Remote signer account. If it contains 'address' then extract, otherwise it IS the address
197
198
  const remoteSigner: EthRemoteSignerAccount = account;
198
199
  if ('address' in remoteSigner) {
199
200
  results.push(remoteSigner.address);
@@ -204,12 +205,15 @@ export class KeystoreManager {
204
205
 
205
206
  if (Array.isArray(accounts)) {
206
207
  for (const account of accounts) {
207
- const subResults = this.extractAddressesWithoutSensitiveOperations(account);
208
- results.push(...subResults);
208
+ handleAccount(account as EthAccount);
209
209
  }
210
210
  return results;
211
211
  }
212
212
 
213
+ if (typeof accounts === 'object' && accounts !== null && 'mnemonic' in (accounts as any)) {
214
+ return results;
215
+ }
216
+
213
217
  handleAccount(accounts as EthAccount);
214
218
  return results;
215
219
  }
@@ -219,7 +223,8 @@ export class KeystoreManager {
219
223
  */
220
224
  createAttesterSigners(validatorIndex: number): EthSigner[] {
221
225
  const validator = this.getValidator(validatorIndex);
222
- return this.createSignersFromEthAccounts(validator.attester, validator.remoteSigner || this.keystore.remoteSigner);
226
+ const ethAccounts = this.extractEthAccountsFromAttester(validator.attester);
227
+ return this.createSignersFromEthAccounts(ethAccounts, validator.remoteSigner || this.keystore.remoteSigner);
223
228
  }
224
229
 
225
230
  /**
@@ -286,7 +291,6 @@ export class KeystoreManager {
286
291
  if ('id' in this.keystore.prover) {
287
292
  const id = this.keystore.prover.id;
288
293
  const signers = this.createSignersFromEthAccounts(this.keystore.prover.publisher, this.keystore.remoteSigner);
289
-
290
294
  return { id, signers };
291
295
  }
292
296
 
@@ -316,22 +320,17 @@ export class KeystoreManager {
316
320
  }
317
321
 
318
322
  /**
319
- * Get coinbase address for validator (falls back to first attester address)
323
+ * Get coinbase address for validator (falls back to the specific attester address)
320
324
  */
321
- getCoinbaseAddress(validatorIndex: number): EthAddress {
325
+ getCoinbaseAddress(validatorIndex: number, attesterAddress: EthAddress): EthAddress {
322
326
  const validator = this.getValidator(validatorIndex);
323
327
 
324
328
  if (validator.coinbase) {
325
329
  return validator.coinbase;
326
330
  }
327
331
 
328
- // Fall back to first attester address
329
- const attesterSigners = this.createAttesterSigners(validatorIndex);
330
- if (attesterSigners.length === 0) {
331
- throw new KeystoreError(`No attester signers found for validator ${validatorIndex}`);
332
- }
333
-
334
- return attesterSigners[0].address;
332
+ // Fall back to the specific attester address
333
+ return attesterAddress;
335
334
  }
336
335
 
337
336
  /**
@@ -368,7 +367,7 @@ export class KeystoreManager {
368
367
  for (let validatorIndex = 0; validatorIndex < validatorCount; validatorIndex++) {
369
368
  const validator = this.getValidator(validatorIndex);
370
369
  const signers = this.createSignersFromEthAccounts(
371
- validator.attester,
370
+ this.extractEthAccountsFromAttester(validator.attester),
372
371
  validator.remoteSigner || this.keystore.remoteSigner,
373
372
  );
374
373
  for (const signer of signers) {
@@ -466,7 +465,7 @@ export class KeystoreManager {
466
465
  /**
467
466
  * Create signer from JSON V3 keystore file or directory
468
467
  */
469
- private createSignerFromJsonV3(config: EthJsonKeyFileV3Config): EthSigner[] {
468
+ private createSignerFromJsonV3(config: JsonKeyFileV3Config): EthSigner[] {
470
469
  try {
471
470
  const stats = statSync(config.path);
472
471
 
@@ -546,7 +545,7 @@ export class KeystoreManager {
546
545
  /**
547
546
  * Create signers from mnemonic configuration using BIP44 derivation
548
547
  */
549
- private createSignersFromMnemonic(config: EthMnemonicConfig): EthSigner[] {
548
+ private createSignersFromMnemonic(config: MnemonicConfig): EthSigner[] {
550
549
  const { mnemonic, addressIndex = 0, accountIndex = 0, addressCount = 1, accountCount = 1 } = config;
551
550
  const signers: EthSigner[] = [];
552
551
 
@@ -677,38 +676,56 @@ export class KeystoreManager {
677
676
  return validator.remoteSigner || this.keystore.remoteSigner;
678
677
  };
679
678
 
680
- // Check the attester configuration
681
- const { attester } = validator;
679
+ // Normalize attester to EthAccounts and search
680
+ const normalized = this.extractEthAccountsFromAttester(validator.attester);
681
+
682
+ const findInEthAccounts = (accs: EthAccounts): EthRemoteSignerConfig | undefined => {
683
+ if (typeof accs === 'string') {
684
+ return checkAccount(accs);
685
+ }
686
+ if (Array.isArray(accs)) {
687
+ for (const a of accs as EthAccount[]) {
688
+ const res = checkAccount(a);
689
+ if (res !== undefined) {
690
+ return res;
691
+ }
692
+ }
693
+ return undefined;
694
+ }
695
+ if (typeof accs === 'object' && accs !== null && 'mnemonic' in accs) {
696
+ // mnemonic-derived keys are local signers; no remote signer config
697
+ return undefined;
698
+ }
699
+ return checkAccount(accs as EthAccount);
700
+ };
701
+
702
+ return findInEthAccounts(normalized);
703
+ }
682
704
 
705
+ /** Extract ETH accounts from AttesterAccounts */
706
+ private extractEthAccountsFromAttester(attester: AttesterAccounts): EthAccounts {
683
707
  if (typeof attester === 'string') {
684
- const result = checkAccount(attester);
685
- return result === undefined ? undefined : result;
708
+ return attester;
686
709
  }
687
-
688
710
  if (Array.isArray(attester)) {
689
- for (const account of attester) {
690
- const result = checkAccount(account);
691
- if (result !== undefined) {
692
- return result;
711
+ const out: EthAccount[] = [];
712
+ for (const item of attester) {
713
+ if (typeof item === 'string') {
714
+ out.push(item);
715
+ } else if ('eth' in (item as any)) {
716
+ out.push((item as any).eth as EthAccount);
717
+ } else if (!('mnemonic' in (item as any))) {
718
+ out.push(item as EthAccount);
693
719
  }
694
720
  }
695
- return undefined;
721
+ return out;
696
722
  }
697
-
698
- // Mnemonic configuration
699
- if ('mnemonic' in attester) {
700
- try {
701
- const signers = this.createSignersFromMnemonic(attester);
702
- const matches = signers.some(s => s.address.equals(attesterAddress));
703
- // Mnemonic-derived keys are local signers
704
- return matches ? undefined : undefined;
705
- } catch {
706
- return undefined;
707
- }
723
+ if ('mnemonic' in (attester as any)) {
724
+ return attester as any;
708
725
  }
709
-
710
- // Single account object
711
- const result = checkAccount(attester);
712
- return result === undefined ? undefined : result;
726
+ if ('eth' in (attester as any)) {
727
+ return (attester as any).eth as EthAccount;
728
+ }
729
+ return attester as any;
713
730
  }
714
731
  }
package/src/loader.ts CHANGED
@@ -285,17 +285,37 @@ export function mergeKeystores(keystores: KeyStore[]): KeyStore {
285
285
  * @returns Array of string keys used to detect duplicates.
286
286
  */
287
287
  function extractAttesterKeys(attester: unknown): string[] {
288
+ // String forms (private key or other) - return as-is for coarse uniqueness
288
289
  if (typeof attester === 'string') {
289
290
  return [attester];
290
291
  }
291
292
 
293
+ // Arrays of attester items
292
294
  if (Array.isArray(attester)) {
293
- return attester.map(a => (typeof a === 'string' ? a : JSON.stringify(a)));
295
+ const keys: string[] = [];
296
+ for (const item of attester) {
297
+ keys.push(...extractAttesterKeys(item));
298
+ }
299
+ return keys;
294
300
  }
295
301
 
296
- if (attester && typeof attester === 'object' && 'address' in attester) {
297
- return [(attester as { address: string }).address];
302
+ if (attester && typeof attester === 'object') {
303
+ const obj = attester as Record<string, unknown>;
304
+
305
+ // New shape: { eth: EthAccount, bls?: BLSAccount }
306
+ if ('eth' in obj) {
307
+ return extractAttesterKeys(obj.eth);
308
+ }
309
+
310
+ // Remote signer account object shape: { address, remoteSignerUrl?, ... }
311
+ if ('address' in obj) {
312
+ return [String((obj as any).address)];
313
+ }
314
+
315
+ // Mnemonic or other object shapes: stringify
316
+ return [JSON.stringify(attester)];
298
317
  }
299
318
 
319
+ // Fallback stringify for anything else (null/undefined)
300
320
  return [JSON.stringify(attester)];
301
321
  }
package/src/schemas.ts CHANGED
@@ -6,13 +6,17 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
6
6
 
7
7
  import { z } from 'zod';
8
8
 
9
- import type { EthPrivateKey } from './types.js';
9
+ import type { BLSPrivateKey, EthPrivateKey } from './types.js';
10
10
 
11
11
  // Use Aztec's validation functions but return string types to match our TypeScript interfaces
12
12
  export const ethPrivateKeySchema = z
13
13
  .string()
14
14
  .regex(/^0x[0-9a-fA-F]{64}$/, 'Invalid private key (must be 32 bytes with 0x prefix)')
15
15
  .transform(s => s as EthPrivateKey);
16
+ export const blsPrivateKeySchema = z
17
+ .string()
18
+ .regex(/^0x[0-9a-fA-F]{64}$/, 'Invalid BLS private key (must be 32 bytes with 0x prefix)')
19
+ .transform(s => s as BLSPrivateKey);
16
20
  const urlSchema = z.string().url('Invalid URL');
17
21
 
18
22
  // Remote signer config schema
@@ -30,7 +34,7 @@ const remoteSignerAccountSchema = z.union([
30
34
  schemas.EthAddress,
31
35
  z.object({
32
36
  address: schemas.EthAddress,
33
- remoteSignerUrl: optional(urlSchema),
37
+ remoteSignerUrl: urlSchema,
34
38
  certPath: optional(z.string()),
35
39
  certPass: optional(z.string()),
36
40
  }),
@@ -57,6 +61,21 @@ const ethAccountSchema = z.union([ethPrivateKeySchema, remoteSignerAccountSchema
57
61
  // EthAccounts schema
58
62
  const ethAccountsSchema = z.union([ethAccountSchema, z.array(ethAccountSchema), mnemonicConfigSchema]);
59
63
 
64
+ // BLSAccount schema
65
+ const blsAccountSchema = z.union([blsPrivateKeySchema, jsonKeyFileV3Schema]);
66
+
67
+ // AttesterAccount schema: either EthAccount or { eth: EthAccount, bls?: BLSAccount }
68
+ const attesterAccountSchema = z.union([
69
+ ethAccountSchema,
70
+ z.object({
71
+ eth: ethAccountSchema,
72
+ bls: optional(blsAccountSchema),
73
+ }),
74
+ ]);
75
+
76
+ // AttesterAccounts schema: AttesterAccount | AttesterAccount[] | MnemonicConfig
77
+ const attesterAccountsSchema = z.union([attesterAccountSchema, z.array(attesterAccountSchema), mnemonicConfigSchema]);
78
+
60
79
  // Prover keystore schema
61
80
  const proverKeyStoreSchema = z.union([
62
81
  ethAccountSchema,
@@ -68,7 +87,7 @@ const proverKeyStoreSchema = z.union([
68
87
 
69
88
  // Validator keystore schema
70
89
  const validatorKeyStoreSchema = z.object({
71
- attester: ethAccountsSchema,
90
+ attester: attesterAccountsSchema,
72
91
  coinbase: optional(schemas.EthAddress),
73
92
  publisher: optional(ethAccountsSchema),
74
93
  feeRecipient: AztecAddress.schema,
package/src/types.ts CHANGED
@@ -12,11 +12,14 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
12
12
  export type Hex<TByteLength extends number> = `0x${string}` & { readonly _length: TByteLength };
13
13
 
14
14
  /** A json keystore config points to a local file with the encrypted private key, and may require a password for decrypting it */
15
- export type EthJsonKeyFileV3Config = { path: string; password?: string };
15
+ export type JsonKeyFileV3Config = { path: string; password?: string };
16
16
 
17
17
  /** A private key is a 32-byte 0x-prefixed hex */
18
18
  export type EthPrivateKey = Hex<32>;
19
19
 
20
+ /** A BLS private key is a 32-byte 0x-prefixed hex */
21
+ export type BLSPrivateKey = Hex<32>;
22
+
20
23
  /** URL type for remote signers */
21
24
  export type Url = string;
22
25
 
@@ -39,16 +42,16 @@ export type EthRemoteSignerAccount =
39
42
  | EthAddress
40
43
  | {
41
44
  address: EthAddress;
42
- remoteSignerUrl?: Url;
45
+ remoteSignerUrl: Url;
43
46
  certPath?: string;
44
47
  certPass?: string;
45
48
  };
46
49
 
47
50
  /** An L1 account is a private key, a remote signer configuration, or a standard json key store file */
48
- export type EthAccount = EthPrivateKey | EthRemoteSignerAccount | EthJsonKeyFileV3Config;
51
+ export type EthAccount = EthPrivateKey | EthRemoteSignerAccount | JsonKeyFileV3Config;
49
52
 
50
53
  /** A mnemonic can be used to define a set of accounts */
51
- export type EthMnemonicConfig = {
54
+ export type MnemonicConfig = {
52
55
  mnemonic: string;
53
56
  addressIndex?: number;
54
57
  accountIndex?: number;
@@ -57,7 +60,7 @@ export type EthMnemonicConfig = {
57
60
  };
58
61
 
59
62
  /** One or more L1 accounts */
60
- export type EthAccounts = EthAccount | EthAccount[] | EthMnemonicConfig;
63
+ export type EthAccounts = EthAccount | EthAccount[] | MnemonicConfig;
61
64
 
62
65
  export type ProverKeyStoreWithId = {
63
66
  /** Address that identifies the prover. This address will receive the rewards. */
@@ -68,12 +71,21 @@ export type ProverKeyStoreWithId = {
68
71
 
69
72
  export type ProverKeyStore = ProverKeyStoreWithId | EthAccount;
70
73
 
74
+ /** A BLS account is either a private key, or a standard json key store file */
75
+ export type BLSAccount = BLSPrivateKey | JsonKeyFileV3Config;
76
+
77
+ /** An AttesterAccount is a combined EthAccount and optional BLSAccount */
78
+ export type AttesterAccount = { eth: EthAccount; bls?: BLSAccount } | EthAccount;
79
+
80
+ /** One or more attester accounts combining ETH and BLS keys */
81
+ export type AttesterAccounts = AttesterAccount | AttesterAccount[] | MnemonicConfig;
82
+
71
83
  export type ValidatorKeyStore = {
72
84
  /**
73
85
  * One or more validator attester keys to handle in this configuration block.
74
86
  * An attester address may only appear once across all configuration blocks across all keystore files.
75
87
  */
76
- attester: EthAccounts;
88
+ attester: AttesterAccounts;
77
89
  /**
78
90
  * Coinbase address to use when proposing an L2 block as any of the validators in this configuration block.
79
91
  * Falls back to the attester address if not set.