@aztec/node-keystore 2.1.0-rc.1 → 2.1.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/keystore_manager.d.ts +9 -3
- package/dest/keystore_manager.d.ts.map +1 -1
- package/dest/keystore_manager.js +59 -43
- package/dest/loader.js +22 -3
- package/dest/schemas.d.ts +391 -94
- package/dest/schemas.d.ts.map +1 -1
- package/dest/schemas.js +22 -2
- package/dest/signer.d.ts +1 -1
- package/dest/signer.d.ts.map +1 -1
- package/dest/signer.js +1 -1
- package/dest/types.d.ts +17 -6
- package/dest/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/keystore_manager.ts +73 -56
- package/src/loader.ts +23 -3
- package/src/schemas.ts +22 -3
- package/src/signer.ts +1 -1
- package/src/types.ts +18 -6
|
@@ -8,7 +8,7 @@ import { Buffer32 } from '@aztec/foundation/buffer';
|
|
|
8
8
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
9
9
|
import type { Signature } from '@aztec/foundation/eth-signature';
|
|
10
10
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
11
|
-
import type { TypedDataDefinition } from 'viem';
|
|
11
|
+
import type { TypedDataDefinition } from '@spalladino/viem';
|
|
12
12
|
import type { EthAccounts, EthRemoteSignerConfig, KeyStore, ProverKeyStore, ValidatorKeyStore as ValidatorKeystoreConfig } from './types.js';
|
|
13
13
|
/**
|
|
14
14
|
* Error thrown when keystore operations fail
|
|
@@ -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
|
|
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;
|
|
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;AAGhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAO5D,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"}
|
package/dest/keystore_manager.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Manages keystore configuration and delegates signing operations to appropriate signers.
|
|
5
5
|
*/ import { Buffer32 } from '@aztec/foundation/buffer';
|
|
6
6
|
import { Wallet } from '@ethersproject/wallet';
|
|
7
|
+
import { mnemonicToAccount } from '@spalladino/viem/accounts';
|
|
7
8
|
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
8
9
|
import { extname, join } from 'path';
|
|
9
|
-
import { mnemonicToAccount } from 'viem/accounts';
|
|
10
10
|
import { ethPrivateKeySchema } from './schemas.js';
|
|
11
11
|
import { LocalSigner, RemoteSigner } from './signer.js';
|
|
12
12
|
/**
|
|
@@ -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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
247
|
-
|
|
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
|
-
//
|
|
534
|
-
const
|
|
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
|
-
|
|
537
|
-
return result === undefined ? undefined : result;
|
|
556
|
+
return attester;
|
|
538
557
|
}
|
|
539
558
|
if (Array.isArray(attester)) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
if (
|
|
543
|
-
|
|
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
|
|
569
|
+
return out;
|
|
547
570
|
}
|
|
548
|
-
// Mnemonic configuration
|
|
549
571
|
if ('mnemonic' in attester) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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'
|
|
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
|
|
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
|
];
|