@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.
@@ -45,6 +45,10 @@ export declare class KeystoreManager {
45
45
  * This is used at construction time to check for obvious duplicates without throwing for invalid inputs.
46
46
  */
47
47
  private extractAddressesWithoutSensitiveOperations;
48
+ /**
49
+ * Extract addresses from EthAccounts without sensitive operations (no decryption/derivation).
50
+ */
51
+ private extractAddressesFromEthAccountsNonSensitive;
48
52
  /**
49
53
  * Create signers for validator attester accounts
50
54
  */
@@ -74,9 +78,9 @@ export declare class KeystoreManager {
74
78
  */
75
79
  getValidatorCount(): number;
76
80
  /**
77
- * Get coinbase address for validator (falls back to first attester address)
81
+ * Get coinbase address for validator (falls back to the specific attester address)
78
82
  */
79
- getCoinbaseAddress(validatorIndex: number): EthAddress;
83
+ getCoinbaseAddress(validatorIndex: number, attesterAddress: EthAddress): EthAddress;
80
84
  /**
81
85
  * Get fee recipient for validator
82
86
  */
@@ -129,5 +133,7 @@ export declare class KeystoreManager {
129
133
  * Precedence: account-level override > validator-level config > file-level default
130
134
  */
131
135
  getEffectiveRemoteSignerConfig(validatorIndex: number, attesterAddress: EthAddress): EthRemoteSignerConfig | undefined;
136
+ /** Extract ETH accounts from AttesterAccounts */
137
+ private extractEthAccountsFromAttester;
132
138
  }
133
139
  //# sourceMappingURL=keystore_manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keystore_manager.d.ts","sourceRoot":"","sources":["../src/keystore_manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAKhD,OAAO,KAAK,EAEV,WAAW,EAIX,qBAAqB,EACrB,QAAQ,EACR,cAAc,EACd,iBAAiB,IAAI,uBAAuB,EAC7C,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAGpB,KAAK,CAAC,EAAE,KAAK;gBAD7B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC;;;;OAIG;gBACS,QAAQ,EAAE,QAAQ;IAK9B;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAwEtC;;;;;OAKG;IACH,OAAO,CAAC,+BAA+B;IAkBvC;;;OAGG;IACH,OAAO,CAAC,0CAA0C;IAoDlD;;OAEG;IACH,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE;IAK1D;;OAEG;IACH,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE;IAc3D,kCAAkC,IAAI,SAAS,EAAE;IAWjD;;OAEG;IACH,oBAAoB,IAAI,SAAS,EAAE;IAQnC;;OAEG;IACH,mBAAmB,IAAI;QAAE,EAAE,EAAE,UAAU,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,SAAS;IAkCvF;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB;IAOpD;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,UAAU;IAgBtD;;OAEG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY;IAKrD;;;OAGG;IACH,kBAAkB,IAAI,WAAW,GAAG,SAAS;IAI7C;;;OAGG;IACH,eAAe,IAAI,cAAc,GAAG,SAAS;IAI7C;;;OAGG;IACH,uCAAuC,IAAI,IAAI;IAqB/C;;OAEG;IACH,OAAO,CAAC,4BAA4B;IA+BpC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA2ClC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkD9B;;OAEG;IACH,OAAO,CAAC,gCAAgC;IAwBxC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA8BjC;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAI3E;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAI1F;;;OAGG;IACH,8BAA8B,CAC5B,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,UAAU,GAC1B,qBAAqB,GAAG,SAAS;CAkHrC"}
1
+ {"version":3,"file":"keystore_manager.d.ts","sourceRoot":"","sources":["../src/keystore_manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAKhD,OAAO,KAAK,EAGV,WAAW,EAEX,qBAAqB,EAErB,QAAQ,EAER,cAAc,EACd,iBAAiB,IAAI,uBAAuB,EAC7C,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAGpB,KAAK,CAAC,EAAE,KAAK;gBAD7B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC;;;;OAIG;gBACS,QAAQ,EAAE,QAAQ;IAK9B;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAwEtC;;;;;OAKG;IACH,OAAO,CAAC,+BAA+B;IAkBvC;;;OAGG;IACH,OAAO,CAAC,0CAA0C;IAKlD;;OAEG;IACH,OAAO,CAAC,2CAA2C;IA+CnD;;OAEG;IACH,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE;IAM1D;;OAEG;IACH,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE;IAc3D,kCAAkC,IAAI,SAAS,EAAE;IAWjD;;OAEG;IACH,oBAAoB,IAAI,SAAS,EAAE;IAQnC;;OAEG;IACH,mBAAmB,IAAI;QAAE,EAAE,EAAE,UAAU,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,SAAS;IAiCvF;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB;IAOpD;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,GAAG,UAAU;IAWnF;;OAEG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY;IAKrD;;;OAGG;IACH,kBAAkB,IAAI,WAAW,GAAG,SAAS;IAI7C;;;OAGG;IACH,eAAe,IAAI,cAAc,GAAG,SAAS;IAI7C;;;OAGG;IACH,uCAAuC,IAAI,IAAI;IAqB/C;;OAEG;IACH,OAAO,CAAC,4BAA4B;IA+BpC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA2ClC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkD9B;;OAEG;IACH,OAAO,CAAC,gCAAgC;IAwBxC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA8BjC;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAI3E;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC;IAI1F;;;OAGG;IACH,8BAA8B,CAC5B,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,UAAU,GAC1B,qBAAqB,GAAG,SAAS;IA0GpC,iDAAiD;IACjD,OAAO,CAAC,8BAA8B;CAyBvC"}
@@ -74,7 +74,7 @@ import { LocalSigner, RemoteSigner } from './signer.js';
74
74
  for(let i = 0; i < validatorCount; i++){
75
75
  const validator = this.getValidator(i);
76
76
  const remoteSigner = validator.remoteSigner || this.keystore.remoteSigner;
77
- collectRemoteSigners(validator.attester, remoteSigner);
77
+ collectRemoteSigners(this.extractEthAccountsFromAttester(validator.attester), remoteSigner);
78
78
  if (validator.publisher) {
79
79
  collectRemoteSigners(validator.publisher, remoteSigner);
80
80
  }
@@ -118,32 +118,31 @@ import { LocalSigner, RemoteSigner } from './signer.js';
118
118
  * Best-effort address extraction that avoids decryption/derivation (no JSON-V3 or mnemonic processing).
119
119
  * This is used at construction time to check for obvious duplicates without throwing for invalid inputs.
120
120
  */ extractAddressesWithoutSensitiveOperations(accounts) {
121
+ const ethAccounts = this.extractEthAccountsFromAttester(accounts);
122
+ return this.extractAddressesFromEthAccountsNonSensitive(ethAccounts);
123
+ }
124
+ /**
125
+ * Extract addresses from EthAccounts without sensitive operations (no decryption/derivation).
126
+ */ extractAddressesFromEthAccountsNonSensitive(accounts) {
121
127
  const results = [];
122
128
  const handleAccount = (account)=>{
123
- // String cases: private key or address or remote signer address
124
129
  if (typeof account === 'string') {
125
130
  if (account.startsWith('0x') && account.length === 66) {
126
- // Private key -> derive address locally without external deps
127
131
  try {
128
132
  const signer = new LocalSigner(Buffer32.fromString(ethPrivateKeySchema.parse(account)));
129
133
  results.push(signer.address);
130
134
  } catch {
131
- // Ignore invalid private key at construction time
135
+ // ignore invalid private key at construction time
132
136
  }
133
- return;
134
137
  }
135
- // Any other string cannot be confidently resolved here
136
138
  return;
137
139
  }
138
- // JSON V3 keystore: skip (requires decryption)
139
140
  if ('path' in account) {
140
141
  return;
141
142
  }
142
- // Mnemonic: skip (requires derivation and may throw on invalid mnemonics)
143
143
  if ('mnemonic' in account) {
144
144
  return;
145
145
  }
146
- // Remote signer account. If it contains 'address' then extract, otherwise it IS the address
147
146
  const remoteSigner = account;
148
147
  if ('address' in remoteSigner) {
149
148
  results.push(remoteSigner.address);
@@ -153,11 +152,13 @@ import { LocalSigner, RemoteSigner } from './signer.js';
153
152
  };
154
153
  if (Array.isArray(accounts)) {
155
154
  for (const account of accounts){
156
- const subResults = this.extractAddressesWithoutSensitiveOperations(account);
157
- results.push(...subResults);
155
+ handleAccount(account);
158
156
  }
159
157
  return results;
160
158
  }
159
+ if (typeof accounts === 'object' && accounts !== null && 'mnemonic' in accounts) {
160
+ return results;
161
+ }
161
162
  handleAccount(accounts);
162
163
  return results;
163
164
  }
@@ -165,7 +166,8 @@ import { LocalSigner, RemoteSigner } from './signer.js';
165
166
  * Create signers for validator attester accounts
166
167
  */ createAttesterSigners(validatorIndex) {
167
168
  const validator = this.getValidator(validatorIndex);
168
- return this.createSignersFromEthAccounts(validator.attester, validator.remoteSigner || this.keystore.remoteSigner);
169
+ const ethAccounts = this.extractEthAccountsFromAttester(validator.attester);
170
+ return this.createSignersFromEthAccounts(ethAccounts, validator.remoteSigner || this.keystore.remoteSigner);
169
171
  }
170
172
  /**
171
173
  * Create signers for validator publisher accounts (falls back to attester if not specified)
@@ -237,18 +239,14 @@ import { LocalSigner, RemoteSigner } from './signer.js';
237
239
  return this.keystore.validators?.length || 0;
238
240
  }
239
241
  /**
240
- * Get coinbase address for validator (falls back to first attester address)
241
- */ getCoinbaseAddress(validatorIndex) {
242
+ * Get coinbase address for validator (falls back to the specific attester address)
243
+ */ getCoinbaseAddress(validatorIndex, attesterAddress) {
242
244
  const validator = this.getValidator(validatorIndex);
243
245
  if (validator.coinbase) {
244
246
  return validator.coinbase;
245
247
  }
246
- // Fall back to first attester address
247
- const attesterSigners = this.createAttesterSigners(validatorIndex);
248
- if (attesterSigners.length === 0) {
249
- throw new KeystoreError(`No attester signers found for validator ${validatorIndex}`);
250
- }
251
- return attesterSigners[0].address;
248
+ // Fall back to the specific attester address
249
+ return attesterAddress;
252
250
  }
253
251
  /**
254
252
  * Get fee recipient for validator
@@ -276,7 +274,7 @@ import { LocalSigner, RemoteSigner } from './signer.js';
276
274
  const validatorCount = this.getValidatorCount();
277
275
  for(let validatorIndex = 0; validatorIndex < validatorCount; validatorIndex++){
278
276
  const validator = this.getValidator(validatorIndex);
279
- const signers = this.createSignersFromEthAccounts(validator.attester, validator.remoteSigner || this.keystore.remoteSigner);
277
+ const signers = this.createSignersFromEthAccounts(this.extractEthAccountsFromAttester(validator.attester), validator.remoteSigner || this.keystore.remoteSigner);
280
278
  for (const signer of signers){
281
279
  const address = signer.address.toString().toLowerCase();
282
280
  if (seenAddresses.has(address)) {
@@ -530,34 +528,52 @@ import { LocalSigner, RemoteSigner } from './signer.js';
530
528
  // Just an address, use defaults
531
529
  return validator.remoteSigner || this.keystore.remoteSigner;
532
530
  };
533
- // Check the attester configuration
534
- const { attester } = validator;
531
+ // Normalize attester to EthAccounts and search
532
+ const normalized = this.extractEthAccountsFromAttester(validator.attester);
533
+ const findInEthAccounts = (accs)=>{
534
+ if (typeof accs === 'string') {
535
+ return checkAccount(accs);
536
+ }
537
+ if (Array.isArray(accs)) {
538
+ for (const a of accs){
539
+ const res = checkAccount(a);
540
+ if (res !== undefined) {
541
+ return res;
542
+ }
543
+ }
544
+ return undefined;
545
+ }
546
+ if (typeof accs === 'object' && accs !== null && 'mnemonic' in accs) {
547
+ // mnemonic-derived keys are local signers; no remote signer config
548
+ return undefined;
549
+ }
550
+ return checkAccount(accs);
551
+ };
552
+ return findInEthAccounts(normalized);
553
+ }
554
+ /** Extract ETH accounts from AttesterAccounts */ extractEthAccountsFromAttester(attester) {
535
555
  if (typeof attester === 'string') {
536
- const result = checkAccount(attester);
537
- return result === undefined ? undefined : result;
556
+ return attester;
538
557
  }
539
558
  if (Array.isArray(attester)) {
540
- for (const account of attester){
541
- const result = checkAccount(account);
542
- if (result !== undefined) {
543
- return result;
559
+ const out = [];
560
+ for (const item of attester){
561
+ if (typeof item === 'string') {
562
+ out.push(item);
563
+ } else if ('eth' in item) {
564
+ out.push(item.eth);
565
+ } else if (!('mnemonic' in item)) {
566
+ out.push(item);
544
567
  }
545
568
  }
546
- return undefined;
569
+ return out;
547
570
  }
548
- // Mnemonic configuration
549
571
  if ('mnemonic' in attester) {
550
- try {
551
- const signers = this.createSignersFromMnemonic(attester);
552
- const matches = signers.some((s)=>s.address.equals(attesterAddress));
553
- // Mnemonic-derived keys are local signers
554
- return matches ? undefined : undefined;
555
- } catch {
556
- return undefined;
557
- }
572
+ return attester;
573
+ }
574
+ if ('eth' in attester) {
575
+ return attester.eth;
558
576
  }
559
- // Single account object
560
- const result = checkAccount(attester);
561
- return result === undefined ? undefined : result;
577
+ return attester;
562
578
  }
563
579
  }
package/dest/loader.js CHANGED
@@ -236,19 +236,38 @@ const logger = createLogger('node-keystore:loader');
236
236
  * @param attester The attester configuration in any supported shape.
237
237
  * @returns Array of string keys used to detect duplicates.
238
238
  */ function extractAttesterKeys(attester) {
239
+ // String forms (private key or other) - return as-is for coarse uniqueness
239
240
  if (typeof attester === 'string') {
240
241
  return [
241
242
  attester
242
243
  ];
243
244
  }
245
+ // Arrays of attester items
244
246
  if (Array.isArray(attester)) {
245
- return attester.map((a)=>typeof a === 'string' ? a : JSON.stringify(a));
247
+ const keys = [];
248
+ for (const item of attester){
249
+ keys.push(...extractAttesterKeys(item));
250
+ }
251
+ return keys;
246
252
  }
247
- if (attester && typeof attester === 'object' && 'address' in attester) {
253
+ if (attester && typeof attester === 'object') {
254
+ const obj = attester;
255
+ // New shape: { eth: EthAccount, bls?: BLSAccount }
256
+ if ('eth' in obj) {
257
+ return extractAttesterKeys(obj.eth);
258
+ }
259
+ // Remote signer account object shape: { address, remoteSignerUrl?, ... }
260
+ if ('address' in obj) {
261
+ return [
262
+ String(obj.address)
263
+ ];
264
+ }
265
+ // Mnemonic or other object shapes: stringify
248
266
  return [
249
- attester.address
267
+ JSON.stringify(attester)
250
268
  ];
251
269
  }
270
+ // Fallback stringify for anything else (null/undefined)
252
271
  return [
253
272
  JSON.stringify(attester)
254
273
  ];