11import { prettyPrintJSON } from '@aztec/cli/utils' ;
2+ import { times , timesParallel } from '@aztec/foundation/collection' ;
23import { deriveBlsPrivateKey } from '@aztec/foundation/crypto/bls' ;
34import { createBn254Keystore } from '@aztec/foundation/crypto/bls/bn254_keystore' ;
45import { computeBn254G1PublicKeyCompressed } from '@aztec/foundation/crypto/bn254' ;
@@ -91,62 +92,57 @@ export async function buildValidatorEntries(input: BuildValidatorsInput) {
9192 remoteSigner,
9293 } = input ;
9394
94- const summaries : ValidatorSummary [ ] = [ ] ;
95-
96- const validators = await Promise . all (
97- Array . from ( { length : validatorCount } , async ( _unused , i ) => {
98- const addressIndex = baseAddressIndex + i ;
99- const basePath = blsPath ?? defaultBlsPath ;
100- const perValidatorPath = withValidatorIndex ( basePath , accountIndex , addressIndex ) ;
101-
102- const blsPrivKey = ikm || mnemonic ? deriveBlsPrivateKey ( mnemonic , ikm , perValidatorPath ) : undefined ;
103- const blsPubCompressed = blsPrivKey ? await computeBlsPublicKeyCompressed ( blsPrivKey ) : undefined ;
104-
105- const ethAttester = deriveEthAttester ( mnemonic , accountIndex , addressIndex , remoteSigner ) ;
106- const attester = blsPrivKey ? { eth : ethAttester , bls : blsPrivKey } : ethAttester ;
107-
108- let publisherField : EthAccount | EthPrivateKey | ( EthAccount | EthPrivateKey ) [ ] | undefined ;
109- const publisherAddresses : string [ ] = [ ] ;
110- if ( publishers && publishers . length > 0 ) {
111- publisherAddresses . push ( ...publishers ) ;
112- publisherField = publishers . length === 1 ? ( publishers [ 0 ] as EthPrivateKey ) : ( publishers as EthPrivateKey [ ] ) ;
113- } else if ( publisherCount > 0 ) {
114- const publishersBaseIndex = baseAddressIndex + validatorCount + i * publisherCount ;
115- const publisherAccounts = Array . from ( { length : publisherCount } , ( _unused2 , j ) => {
116- const publisherAddressIndex = publishersBaseIndex + j ;
117- const pubAcct = mnemonicToAccount ( mnemonic , {
118- accountIndex,
119- addressIndex : publisherAddressIndex ,
120- } ) ;
121- publisherAddresses . push ( pubAcct . address as unknown as string ) ;
122- return remoteSigner
123- ? ( { address : pubAcct . address as unknown as EthAddress , remoteSignerUrl : remoteSigner } as EthAccount )
124- : ( ( '0x' + Buffer . from ( pubAcct . getHdKey ( ) . privateKey ! ) . toString ( 'hex' ) ) as EthPrivateKey ) ;
95+ const entries = await timesParallel ( validatorCount , async i => {
96+ const addressIndex = baseAddressIndex + i ;
97+ const basePath = blsPath ?? defaultBlsPath ;
98+ const perValidatorPath = withValidatorIndex ( basePath , accountIndex , addressIndex ) ;
99+
100+ const blsPrivKey = ikm || mnemonic ? deriveBlsPrivateKey ( mnemonic , ikm , perValidatorPath ) : undefined ;
101+ const blsPubCompressed = blsPrivKey ? await computeBlsPublicKeyCompressed ( blsPrivKey ) : undefined ;
102+ const attesterAccount = mnemonicToAccount ( mnemonic , { accountIndex, addressIndex } ) ;
103+ const attesterEthAddress = attesterAccount . address as unknown as string ;
104+ const ethAttester = remoteSigner
105+ ? ( { address : attesterAccount . address as unknown as EthAddress , remoteSignerUrl : remoteSigner } as EthAccount )
106+ : ( ( '0x' + Buffer . from ( attesterAccount . getHdKey ( ) . privateKey ! ) . toString ( 'hex' ) ) as EthPrivateKey ) ;
107+ const attester = blsPrivKey ? { eth : ethAttester , bls : blsPrivKey } : ethAttester ;
108+
109+ let publisherField : EthAccount | EthPrivateKey | ( EthAccount | EthPrivateKey ) [ ] | undefined ;
110+ const publisherAddresses : string [ ] = [ ] ;
111+ if ( publishers && publishers . length > 0 ) {
112+ publisherAddresses . push ( ...publishers ) ;
113+ publisherField = publishers . length === 1 ? ( publishers [ 0 ] as EthPrivateKey ) : ( publishers as EthPrivateKey [ ] ) ;
114+ } else if ( publisherCount > 0 ) {
115+ const publishersBaseIndex = baseAddressIndex + validatorCount + i * publisherCount ;
116+ const publisherAccounts = times ( publisherCount , j => {
117+ const publisherAddressIndex = publishersBaseIndex + j ;
118+ const pubAcct = mnemonicToAccount ( mnemonic , {
119+ accountIndex,
120+ addressIndex : publisherAddressIndex ,
125121 } ) ;
126- publisherField = publisherCount === 1 ? publisherAccounts [ 0 ] : publisherAccounts ;
127- }
128-
129- const acct = mnemonicToAccount ( mnemonic , {
130- accountIndex,
131- addressIndex,
132- } ) ;
133- const attesterEthAddress = acct . address as unknown as string ;
134- summaries . push ( {
135- attesterEth : attesterEthAddress ,
136- attesterBls : blsPubCompressed ,
137- publisherEth : publisherAddresses . length > 0 ? publisherAddresses : undefined ,
122+ publisherAddresses . push ( pubAcct . address as unknown as string ) ;
123+ return remoteSigner
124+ ? ( { address : pubAcct . address as unknown as EthAddress , remoteSignerUrl : remoteSigner } as EthAccount )
125+ : ( ( '0x' + Buffer . from ( pubAcct . getHdKey ( ) . privateKey ! ) . toString ( 'hex' ) ) as EthPrivateKey ) ;
138126 } ) ;
127+ publisherField = publisherCount === 1 ? publisherAccounts [ 0 ] : publisherAccounts ;
128+ }
139129
140- return {
130+ return {
131+ validator : {
141132 attester,
142133 ...( publisherField !== undefined ? { publisher : publisherField } : { } ) ,
143134 feeRecipient,
144135 coinbase : coinbase ?? attesterEthAddress ,
145- } as ValidatorKeyStore ;
146- } ) ,
147- ) ;
136+ } as ValidatorKeyStore ,
137+ summary : {
138+ attesterEth : attesterEthAddress ,
139+ attesterBls : blsPubCompressed ,
140+ publisherEth : publisherAddresses . length > 0 ? publisherAddresses : undefined ,
141+ } as ValidatorSummary ,
142+ } ;
143+ } ) ;
148144
149- return { validators, summaries } ;
145+ return { validators : entries . map ( entry => entry . validator ) , summaries : entries . map ( entry => entry . summary ) } ;
150146}
151147
152148export async function resolveKeystoreOutputPath ( dataDir ?: string , file ?: string ) {
@@ -228,7 +224,7 @@ export async function writeBn254BlsKeystore(
228224) : Promise < string > {
229225 mkdirSync ( outDir , { recursive : true } ) ;
230226
231- const keystore = createBn254Keystore ( password , privateKeyHex , pubkeyHex , derivationPath ) ;
227+ const keystore = await createBn254Keystore ( password , privateKeyHex , pubkeyHex , derivationPath ) ;
232228
233229 const safeBase = fileNameBase . replace ( / [ ^ a - z A - Z 0 - 9 _ - ] / g, '_' ) ;
234230 const outPath = join ( outDir , `keystore-${ safeBase } .json` ) ;
@@ -241,28 +237,29 @@ export async function writeBlsBn254ToFile(
241237 validators : ValidatorKeyStore [ ] ,
242238 options : { outDir : string ; password : string ; blsPath ?: string } ,
243239) : Promise < void > {
244- for ( let i = 0 ; i < validators . length ; i ++ ) {
245- const v = validators [ i ] ;
246- if ( ! v || typeof v !== 'object' || ! ( 'attester' in v ) ) {
247- continue ;
248- }
249- const att = ( v as any ) . attester ;
240+ await Promise . all (
241+ validators . map ( async ( v , i ) => {
242+ if ( ! v || typeof v !== 'object' || ! ( 'attester' in v ) ) {
243+ return ;
244+ }
245+ const att = ( v as any ) . attester ;
250246
251- // Shapes: { bls: <hex> } or { eth: <ethAccount>, bls?: <hex> } or plain EthAccount
252- const blsKey : string | undefined = typeof att === 'object' && 'bls' in att ? ( att as any ) . bls : undefined ;
253- if ( ! blsKey || typeof blsKey !== 'string' ) {
254- continue ;
255- }
247+ // Shapes: { bls: <hex> } or { eth: <ethAccount>, bls?: <hex> } or plain EthAccount
248+ const blsKey : string | undefined = typeof att === 'object' && 'bls' in att ? ( att as any ) . bls : undefined ;
249+ if ( ! blsKey || typeof blsKey !== 'string' ) {
250+ return ;
251+ }
256252
257- const pub = await computeBlsPublicKeyCompressed ( blsKey ) ;
258- const path = options . blsPath ?? defaultBlsPath ;
259- const fileBase = `${ String ( i + 1 ) } _${ pub . slice ( 2 , 18 ) } ` ;
260- const keystorePath = await writeBn254BlsKeystore ( options . outDir , fileBase , options . password , blsKey , pub , path ) ;
253+ const pub = await computeBlsPublicKeyCompressed ( blsKey ) ;
254+ const path = options . blsPath ?? defaultBlsPath ;
255+ const fileBase = `${ String ( i + 1 ) } _${ pub . slice ( 2 , 18 ) } ` ;
256+ const keystorePath = await writeBn254BlsKeystore ( options . outDir , fileBase , options . password , blsKey , pub , path ) ;
261257
262- if ( typeof att === 'object' ) {
263- ( att as any ) . bls = { path : keystorePath , password : options . password } ;
264- }
265- }
258+ if ( typeof att === 'object' ) {
259+ ( att as any ) . bls = { path : keystorePath , password : options . password } ;
260+ }
261+ } ) ,
262+ ) ;
266263}
267264
268265/** Writes an Ethereum JSON V3 keystore using ethers, returns absolute path */
@@ -295,32 +292,31 @@ export async function writeEthJsonV3ToFile(
295292 return account ;
296293 } ;
297294
298- for ( let i = 0 ; i < validators . length ; i ++ ) {
299- const v = validators [ i ] ;
300- if ( ! v || typeof v !== 'object' ) {
301- continue ;
302- }
295+ await Promise . all (
296+ validators . map ( async ( v , i ) => {
297+ if ( ! v || typeof v !== 'object' ) {
298+ return ;
299+ }
303300
304- // attester may be string (eth), object with eth, or remote signer
305- const att = ( v as any ) . attester ;
306- if ( typeof att === 'string' ) {
307- ( v as any ) . attester = await maybeEncryptEth ( att , `attester_${ i + 1 } ` ) ;
308- } else if ( att && typeof att === 'object' && 'eth' in att ) {
309- ( att as any ) . eth = await maybeEncryptEth ( ( att as any ) . eth , `attester_${ i + 1 } ` ) ;
310- }
301+ // attester may be string (eth), object with eth, or remote signer
302+ const att = ( v as any ) . attester ;
303+ if ( typeof att === 'string' ) {
304+ ( v as any ) . attester = await maybeEncryptEth ( att , `attester_${ i + 1 } ` ) ;
305+ } else if ( att && typeof att === 'object' && 'eth' in att ) {
306+ ( att as any ) . eth = await maybeEncryptEth ( ( att as any ) . eth , `attester_${ i + 1 } ` ) ;
307+ }
311308
312- // publisher can be single or array
313- if ( 'publisher' in v ) {
314- const pub = ( v as any ) . publisher ;
315- if ( Array . isArray ( pub ) ) {
316- const out : any [ ] = [ ] ;
317- for ( let j = 0 ; j < pub . length ; j ++ ) {
318- out . push ( await maybeEncryptEth ( pub [ j ] , `publisher_${ i + 1 } _${ j + 1 } ` ) ) ;
309+ // publisher can be single or array
310+ if ( 'publisher' in v ) {
311+ const pub = ( v as any ) . publisher ;
312+ if ( Array . isArray ( pub ) ) {
313+ ( v as any ) . publisher = await Promise . all (
314+ pub . map ( ( account , j ) => maybeEncryptEth ( account , `publisher_${ i + 1 } _${ j + 1 } ` ) ) ,
315+ ) ;
316+ } else if ( pub !== undefined ) {
317+ ( v as any ) . publisher = await maybeEncryptEth ( pub , `publisher_${ i + 1 } ` ) ;
319318 }
320- ( v as any ) . publisher = out ;
321- } else if ( pub !== undefined ) {
322- ( v as any ) . publisher = await maybeEncryptEth ( pub , `publisher_${ i + 1 } ` ) ;
323319 }
324- }
325- }
320+ } ) ,
321+ ) ;
326322}
0 commit comments