@aztec/node-keystore 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107
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/config.d.ts +1 -1
- package/dest/index.d.ts +1 -1
- package/dest/keystore_manager.d.ts +19 -7
- package/dest/keystore_manager.d.ts.map +1 -1
- package/dest/keystore_manager.js +198 -125
- package/dest/loader.d.ts +1 -1
- package/dest/loader.d.ts.map +1 -1
- package/dest/loader.js +93 -18
- package/dest/schemas.d.ts +2893 -990
- package/dest/schemas.d.ts.map +1 -1
- package/dest/schemas.js +102 -40
- package/dest/signer.d.ts +10 -17
- package/dest/signer.d.ts.map +1 -1
- package/dest/signer.js +58 -6
- package/dest/types.d.ts +46 -27
- package/dest/types.d.ts.map +1 -1
- package/dest/types.js +1 -1
- package/package.json +10 -7
- package/src/keystore_manager.ts +242 -145
- package/src/loader.ts +95 -11
- package/src/schemas.ts +135 -58
- package/src/signer.ts +84 -11
- package/src/types.ts +50 -32
package/dest/loader.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* Keystore File Loader
|
|
3
3
|
*
|
|
4
4
|
* Handles loading and parsing keystore configuration files.
|
|
5
|
-
*/ import {
|
|
5
|
+
*/ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
6
7
|
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
7
8
|
import { extname, join } from 'path';
|
|
9
|
+
import { privateKeyToAddress } from 'viem/accounts';
|
|
8
10
|
import { keystoreSchema } from './schemas.js';
|
|
9
11
|
const logger = createLogger('node-keystore:loader');
|
|
10
12
|
/**
|
|
@@ -166,12 +168,17 @@ const logger = createLogger('node-keystore:loader');
|
|
|
166
168
|
}
|
|
167
169
|
// Track attester addresses to prevent duplicates
|
|
168
170
|
const attesterAddresses = new Set();
|
|
171
|
+
// Determine schema version: use v2 if any input is v2
|
|
172
|
+
const schemaVersion = keystores.some((ks)=>ks.schemaVersion === 2) ? 2 : 1;
|
|
169
173
|
const merged = {
|
|
170
|
-
schemaVersion
|
|
174
|
+
schemaVersion,
|
|
171
175
|
validators: [],
|
|
172
176
|
slasher: undefined,
|
|
173
177
|
remoteSigner: undefined,
|
|
174
|
-
prover: undefined
|
|
178
|
+
prover: undefined,
|
|
179
|
+
publisher: undefined,
|
|
180
|
+
coinbase: undefined,
|
|
181
|
+
feeRecipient: undefined
|
|
175
182
|
};
|
|
176
183
|
for(let i = 0; i < keystores.length; i++){
|
|
177
184
|
const keystore = keystores[i];
|
|
@@ -179,15 +186,22 @@ const logger = createLogger('node-keystore:loader');
|
|
|
179
186
|
if (keystore.validators) {
|
|
180
187
|
for (const validator of keystore.validators){
|
|
181
188
|
// Check for duplicate attester addresses
|
|
182
|
-
const attesterKeys =
|
|
183
|
-
for (
|
|
189
|
+
const attesterKeys = extractAttesterAddresses(validator.attester);
|
|
190
|
+
for (let key of attesterKeys){
|
|
191
|
+
key = key.toLowerCase();
|
|
184
192
|
if (attesterAddresses.has(key)) {
|
|
185
193
|
throw new KeyStoreLoadError(`Duplicate attester address ${key} found across keystore files`, `keystores[${i}].validators`);
|
|
186
194
|
}
|
|
187
195
|
attesterAddresses.add(key);
|
|
188
196
|
}
|
|
197
|
+
// When merging v1 validators into a v2+ result, preserve original fallback behavior
|
|
198
|
+
// by explicitly setting publisher/coinbase/feeRecipient if they're missing
|
|
199
|
+
if (keystore.schemaVersion !== schemaVersion) {
|
|
200
|
+
throw new KeyStoreLoadError(`Cannot merge keystores with different schema versions: ${keystore.schemaVersion} and ${schemaVersion}`, `keystores[${i}].schemaVersion`);
|
|
201
|
+
} else {
|
|
202
|
+
merged.validators.push(validator);
|
|
203
|
+
}
|
|
189
204
|
}
|
|
190
|
-
merged.validators.push(...keystore.validators);
|
|
191
205
|
}
|
|
192
206
|
// Merge slasher (accumulate all)
|
|
193
207
|
if (keystore.slasher) {
|
|
@@ -219,6 +233,43 @@ const logger = createLogger('node-keystore:loader');
|
|
|
219
233
|
}
|
|
220
234
|
merged.prover = keystore.prover;
|
|
221
235
|
}
|
|
236
|
+
// Merge top-level publisher (accumulate all, unless conflicting MnemonicConfigs)
|
|
237
|
+
if (keystore.publisher) {
|
|
238
|
+
if (!merged.publisher) {
|
|
239
|
+
merged.publisher = keystore.publisher;
|
|
240
|
+
} else {
|
|
241
|
+
const isMnemonic = (accounts)=>typeof accounts === 'object' && accounts !== null && 'mnemonic' in accounts;
|
|
242
|
+
// If either is a mnemonic, warn and use last one (can't merge mnemonics)
|
|
243
|
+
if (isMnemonic(merged.publisher) || isMnemonic(keystore.publisher)) {
|
|
244
|
+
logger.warn('Multiple default publisher configurations found with mnemonic, using the last one (cannot merge mnemonics)');
|
|
245
|
+
merged.publisher = keystore.publisher;
|
|
246
|
+
} else {
|
|
247
|
+
// Both are non-mnemonic, accumulate them
|
|
248
|
+
const toArray = (accounts)=>Array.isArray(accounts) ? accounts : [
|
|
249
|
+
accounts
|
|
250
|
+
];
|
|
251
|
+
const combined = [
|
|
252
|
+
...toArray(merged.publisher),
|
|
253
|
+
...toArray(keystore.publisher)
|
|
254
|
+
];
|
|
255
|
+
merged.publisher = combined;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Merge top-level coinbase (last one wins, but warn about conflicts)
|
|
260
|
+
if (keystore.coinbase) {
|
|
261
|
+
if (merged.coinbase) {
|
|
262
|
+
logger.warn('Multiple default coinbase addresses found, using the last one');
|
|
263
|
+
}
|
|
264
|
+
merged.coinbase = keystore.coinbase;
|
|
265
|
+
}
|
|
266
|
+
// Merge top-level feeRecipient (last one wins, but warn about conflicts)
|
|
267
|
+
if (keystore.feeRecipient) {
|
|
268
|
+
if (merged.feeRecipient) {
|
|
269
|
+
logger.warn('Multiple default feeRecipient addresses found, using the last one');
|
|
270
|
+
}
|
|
271
|
+
merged.feeRecipient = keystore.feeRecipient;
|
|
272
|
+
}
|
|
222
273
|
}
|
|
223
274
|
// Clean up empty arrays
|
|
224
275
|
if (merged.validators.length === 0) {
|
|
@@ -235,21 +286,45 @@ const logger = createLogger('node-keystore:loader');
|
|
|
235
286
|
*
|
|
236
287
|
* @param attester The attester configuration in any supported shape.
|
|
237
288
|
* @returns Array of string keys used to detect duplicates.
|
|
238
|
-
*/ function
|
|
289
|
+
*/ function extractAttesterAddresses(attester) {
|
|
290
|
+
// String forms (private key or other) - return as-is for coarse uniqueness
|
|
239
291
|
if (typeof attester === 'string') {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
292
|
+
if (attester.length === 66) {
|
|
293
|
+
return [
|
|
294
|
+
privateKeyToAddress(attester)
|
|
295
|
+
];
|
|
296
|
+
} else {
|
|
297
|
+
return [
|
|
298
|
+
attester
|
|
299
|
+
];
|
|
300
|
+
}
|
|
243
301
|
}
|
|
302
|
+
// Arrays of attester items
|
|
244
303
|
if (Array.isArray(attester)) {
|
|
245
|
-
|
|
304
|
+
const keys = [];
|
|
305
|
+
for (const item of attester){
|
|
306
|
+
keys.push(...extractAttesterAddresses(item));
|
|
307
|
+
}
|
|
308
|
+
return keys;
|
|
246
309
|
}
|
|
247
|
-
if (attester && typeof attester === 'object'
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
310
|
+
if (attester && typeof attester === 'object') {
|
|
311
|
+
if (attester instanceof EthAddress) {
|
|
312
|
+
return [
|
|
313
|
+
attester.toString()
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
const obj = attester;
|
|
317
|
+
// New shape: { eth: EthAccount, bls?: BLSAccount }
|
|
318
|
+
if ('eth' in obj) {
|
|
319
|
+
return extractAttesterAddresses(obj.eth);
|
|
320
|
+
}
|
|
321
|
+
// Remote signer account object shape: { address, remoteSignerUrl?, ... }
|
|
322
|
+
if ('address' in obj) {
|
|
323
|
+
return [
|
|
324
|
+
String(obj.address)
|
|
325
|
+
];
|
|
326
|
+
}
|
|
251
327
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
];
|
|
328
|
+
// mnemonic, encrypted file just disable early duplicates checking
|
|
329
|
+
return [];
|
|
255
330
|
}
|