@aztec-labs/cli 6.0.0-nightly.20260829
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/README.md +23 -0
- package/dest/cmds/aztec_node/block_number.d.ts +3 -0
- package/dest/cmds/aztec_node/block_number.d.ts.map +1 -0
- package/dest/cmds/aztec_node/block_number.js +10 -0
- package/dest/cmds/aztec_node/get_block.d.ts +3 -0
- package/dest/cmds/aztec_node/get_block.d.ts.map +1 -0
- package/dest/cmds/aztec_node/get_block.js +10 -0
- package/dest/cmds/aztec_node/get_current_min_fee.d.ts +3 -0
- package/dest/cmds/aztec_node/get_current_min_fee.d.ts.map +1 -0
- package/dest/cmds/aztec_node/get_current_min_fee.js +7 -0
- package/dest/cmds/aztec_node/get_l1_to_l2_message_witness.d.ts +5 -0
- package/dest/cmds/aztec_node/get_l1_to_l2_message_witness.d.ts.map +1 -0
- package/dest/cmds/aztec_node/get_l1_to_l2_message_witness.js +12 -0
- package/dest/cmds/aztec_node/get_logs.d.ts +33 -0
- package/dest/cmds/aztec_node/get_logs.d.ts.map +1 -0
- package/dest/cmds/aztec_node/get_logs.js +61 -0
- package/dest/cmds/aztec_node/get_node_info.d.ts +3 -0
- package/dest/cmds/aztec_node/get_node_info.d.ts.map +1 -0
- package/dest/cmds/aztec_node/get_node_info.js +58 -0
- package/dest/cmds/aztec_node/index.d.ts +4 -0
- package/dest/cmds/aztec_node/index.d.ts.map +1 -0
- package/dest/cmds/aztec_node/index.js +38 -0
- package/dest/cmds/infrastructure/index.d.ts +4 -0
- package/dest/cmds/infrastructure/index.d.ts.map +1 -0
- package/dest/cmds/infrastructure/index.js +22 -0
- package/dest/cmds/infrastructure/sequencers.d.ts +12 -0
- package/dest/cmds/infrastructure/sequencers.d.ts.map +1 -0
- package/dest/cmds/infrastructure/sequencers.js +113 -0
- package/dest/cmds/infrastructure/setup_l2_contract.d.ts +3 -0
- package/dest/cmds/infrastructure/setup_l2_contract.d.ts.map +1 -0
- package/dest/cmds/infrastructure/setup_l2_contract.js +35 -0
- package/dest/cmds/l1/advance_epoch.d.ts +3 -0
- package/dest/cmds/l1/advance_epoch.d.ts.map +1 -0
- package/dest/cmds/l1/advance_epoch.js +12 -0
- package/dest/cmds/l1/assume_proven_through.d.ts +4 -0
- package/dest/cmds/l1/assume_proven_through.d.ts.map +1 -0
- package/dest/cmds/l1/assume_proven_through.js +12 -0
- package/dest/cmds/l1/compute_genesis_values.d.ts +4 -0
- package/dest/cmds/l1/compute_genesis_values.d.ts.map +1 -0
- package/dest/cmds/l1/compute_genesis_values.js +17 -0
- package/dest/cmds/l1/create_l1_account.d.ts +3 -0
- package/dest/cmds/l1/create_l1_account.d.ts.map +1 -0
- package/dest/cmds/l1/create_l1_account.js +15 -0
- package/dest/cmds/l1/deploy_l1_contracts_cmd.d.ts +4 -0
- package/dest/cmds/l1/deploy_l1_contracts_cmd.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_l1_contracts_cmd.js +80 -0
- package/dest/cmds/l1/deploy_new_rollup.d.ts +5 -0
- package/dest/cmds/l1/deploy_new_rollup.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_new_rollup.js +26 -0
- package/dest/cmds/l1/get_l1_addresses.d.ts +4 -0
- package/dest/cmds/l1/get_l1_addresses.d.ts.map +1 -0
- package/dest/cmds/l1/get_l1_addresses.js +21 -0
- package/dest/cmds/l1/get_l1_balance.d.ts +4 -0
- package/dest/cmds/l1/get_l1_balance.d.ts.map +1 -0
- package/dest/cmds/l1/get_l1_balance.js +35 -0
- package/dest/cmds/l1/governance_utils.d.ts +50 -0
- package/dest/cmds/l1/governance_utils.d.ts.map +1 -0
- package/dest/cmds/l1/governance_utils.js +87 -0
- package/dest/cmds/l1/index.d.ts +4 -0
- package/dest/cmds/l1/index.d.ts.map +1 -0
- package/dest/cmds/l1/index.js +201 -0
- package/dest/cmds/l1/prover_stats.d.ts +14 -0
- package/dest/cmds/l1/prover_stats.d.ts.map +1 -0
- package/dest/cmds/l1/prover_stats.js +147 -0
- package/dest/cmds/l1/trigger_seed_snapshot.d.ts +6 -0
- package/dest/cmds/l1/trigger_seed_snapshot.d.ts.map +1 -0
- package/dest/cmds/l1/trigger_seed_snapshot.js +20 -0
- package/dest/cmds/l1/update_l1_validators.d.ts +45 -0
- package/dest/cmds/l1/update_l1_validators.d.ts.map +1 -0
- package/dest/cmds/l1/update_l1_validators.js +280 -0
- package/dest/cmds/misc/generate_bootnode_enr.d.ts +3 -0
- package/dest/cmds/misc/generate_bootnode_enr.d.ts.map +1 -0
- package/dest/cmds/misc/generate_bootnode_enr.js +5 -0
- package/dest/cmds/misc/generate_p2p_private_key.d.ts +3 -0
- package/dest/cmds/misc/generate_p2p_private_key.d.ts.map +1 -0
- package/dest/cmds/misc/generate_p2p_private_key.js +7 -0
- package/dest/cmds/misc/generate_secret_key.d.ts +5 -0
- package/dest/cmds/misc/generate_secret_key.d.ts.map +1 -0
- package/dest/cmds/misc/generate_secret_key.js +6 -0
- package/dest/cmds/misc/index.d.ts +4 -0
- package/dest/cmds/misc/index.d.ts.map +1 -0
- package/dest/cmds/misc/index.js +32 -0
- package/dest/cmds/misc/update/common.d.ts +17 -0
- package/dest/cmds/misc/update/common.d.ts.map +1 -0
- package/dest/cmds/misc/update/common.js +3 -0
- package/dest/cmds/misc/update/github.d.ts +3 -0
- package/dest/cmds/misc/update/github.d.ts.map +1 -0
- package/dest/cmds/misc/update/github.js +2 -0
- package/dest/cmds/misc/update/noir.d.ts +10 -0
- package/dest/cmds/misc/update/noir.d.ts.map +1 -0
- package/dest/cmds/misc/update/noir.js +45 -0
- package/dest/cmds/misc/update/npm.d.ts +34 -0
- package/dest/cmds/misc/update/npm.d.ts.map +1 -0
- package/dest/cmds/misc/update/npm.js +123 -0
- package/dest/cmds/misc/update/utils.d.ts +14 -0
- package/dest/cmds/misc/update/utils.d.ts.map +1 -0
- package/dest/cmds/misc/update/utils.js +38 -0
- package/dest/cmds/misc/update.d.ts +3 -0
- package/dest/cmds/misc/update.d.ts.map +1 -0
- package/dest/cmds/misc/update.js +51 -0
- package/dest/cmds/validator_keys/add.d.ts +5 -0
- package/dest/cmds/validator_keys/add.d.ts.map +1 -0
- package/dest/cmds/validator_keys/add.js +83 -0
- package/dest/cmds/validator_keys/eth_json_v3_worker.d.ts +2 -0
- package/dest/cmds/validator_keys/eth_json_v3_worker.d.ts.map +1 -0
- package/dest/cmds/validator_keys/eth_json_v3_worker.js +27 -0
- package/dest/cmds/validator_keys/generate_bls_keypair.d.ts +12 -0
- package/dest/cmds/validator_keys/generate_bls_keypair.d.ts.map +1 -0
- package/dest/cmds/validator_keys/generate_bls_keypair.js +27 -0
- package/dest/cmds/validator_keys/index.d.ts +4 -0
- package/dest/cmds/validator_keys/index.d.ts.map +1 -0
- package/dest/cmds/validator_keys/index.js +33 -0
- package/dest/cmds/validator_keys/new.d.ts +35 -0
- package/dest/cmds/validator_keys/new.d.ts.map +1 -0
- package/dest/cmds/validator_keys/new.js +220 -0
- package/dest/cmds/validator_keys/set_funding_account.d.ts +14 -0
- package/dest/cmds/validator_keys/set_funding_account.d.ts.map +1 -0
- package/dest/cmds/validator_keys/set_funding_account.js +37 -0
- package/dest/cmds/validator_keys/shared.d.ts +81 -0
- package/dest/cmds/validator_keys/shared.d.ts.map +1 -0
- package/dest/cmds/validator_keys/shared.js +352 -0
- package/dest/cmds/validator_keys/staker.d.ts +38 -0
- package/dest/cmds/validator_keys/staker.d.ts.map +1 -0
- package/dest/cmds/validator_keys/staker.js +210 -0
- package/dest/cmds/validator_keys/utils.d.ts +35 -0
- package/dest/cmds/validator_keys/utils.d.ts.map +1 -0
- package/dest/cmds/validator_keys/utils.js +86 -0
- package/dest/config/cached_fetch.d.ts +27 -0
- package/dest/config/cached_fetch.d.ts.map +1 -0
- package/dest/config/cached_fetch.js +132 -0
- package/dest/config/chain_l2_config.d.ts +19 -0
- package/dest/config/chain_l2_config.d.ts.map +1 -0
- package/dest/config/chain_l2_config.js +60 -0
- package/dest/config/enrich_env.d.ts +4 -0
- package/dest/config/enrich_env.d.ts.map +1 -0
- package/dest/config/enrich_env.js +12 -0
- package/dest/config/generated/networks.d.ts +236 -0
- package/dest/config/generated/networks.d.ts.map +1 -0
- package/dest/config/generated/networks.js +237 -0
- package/dest/config/get_l1_config.d.ts +9 -0
- package/dest/config/get_l1_config.d.ts.map +1 -0
- package/dest/config/get_l1_config.js +24 -0
- package/dest/config/index.d.ts +5 -0
- package/dest/config/index.d.ts.map +1 -0
- package/dest/config/index.js +4 -0
- package/dest/config/network_config.d.ts +22 -0
- package/dest/config/network_config.d.ts.map +1 -0
- package/dest/config/network_config.js +119 -0
- package/dest/utils/aztec.d.ts +56 -0
- package/dest/utils/aztec.d.ts.map +1 -0
- package/dest/utils/aztec.js +161 -0
- package/dest/utils/commands.d.ts +161 -0
- package/dest/utils/commands.d.ts.map +1 -0
- package/dest/utils/commands.js +341 -0
- package/dest/utils/encoding.d.ts +15 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/utils/encoding.js +103 -0
- package/dest/utils/github.d.ts +3 -0
- package/dest/utils/github.d.ts.map +1 -0
- package/dest/utils/github.js +2 -0
- package/dest/utils/index.d.ts +6 -0
- package/dest/utils/index.d.ts.map +1 -0
- package/dest/utils/index.js +5 -0
- package/dest/utils/inspect.d.ts +11 -0
- package/dest/utils/inspect.d.ts.map +1 -0
- package/dest/utils/inspect.js +90 -0
- package/dest/utils/setup_contracts.d.ts +3 -0
- package/dest/utils/setup_contracts.d.ts.map +1 -0
- package/dest/utils/setup_contracts.js +16 -0
- package/package.json +141 -0
- package/public_include_metric_prefixes.json +1 -0
- package/src/cmds/aztec_node/block_number.ts +9 -0
- package/src/cmds/aztec_node/get_block.ts +11 -0
- package/src/cmds/aztec_node/get_current_min_fee.ts +9 -0
- package/src/cmds/aztec_node/get_l1_to_l2_message_witness.ts +27 -0
- package/src/cmds/aztec_node/get_logs.ts +100 -0
- package/src/cmds/aztec_node/get_node_info.ts +61 -0
- package/src/cmds/aztec_node/index.ts +91 -0
- package/src/cmds/infrastructure/index.ts +51 -0
- package/src/cmds/infrastructure/sequencers.ts +122 -0
- package/src/cmds/infrastructure/setup_l2_contract.ts +40 -0
- package/src/cmds/l1/advance_epoch.ts +14 -0
- package/src/cmds/l1/assume_proven_through.ts +20 -0
- package/src/cmds/l1/compute_genesis_values.ts +29 -0
- package/src/cmds/l1/create_l1_account.ts +16 -0
- package/src/cmds/l1/deploy_l1_contracts_cmd.ts +105 -0
- package/src/cmds/l1/deploy_new_rollup.ts +65 -0
- package/src/cmds/l1/get_l1_addresses.ts +31 -0
- package/src/cmds/l1/get_l1_balance.ts +44 -0
- package/src/cmds/l1/governance_utils.ts +183 -0
- package/src/cmds/l1/index.ts +499 -0
- package/src/cmds/l1/prover_stats.ts +213 -0
- package/src/cmds/l1/trigger_seed_snapshot.ts +32 -0
- package/src/cmds/l1/update_l1_validators.ts +358 -0
- package/src/cmds/misc/generate_bootnode_enr.ts +13 -0
- package/src/cmds/misc/generate_p2p_private_key.ts +9 -0
- package/src/cmds/misc/generate_secret_key.ts +5 -0
- package/src/cmds/misc/index.ts +67 -0
- package/src/cmds/misc/update/common.ts +16 -0
- package/src/cmds/misc/update/github.ts +2 -0
- package/src/cmds/misc/update/noir.ts +56 -0
- package/src/cmds/misc/update/npm.ts +148 -0
- package/src/cmds/misc/update/utils.ts +49 -0
- package/src/cmds/misc/update.ts +71 -0
- package/src/cmds/validator_keys/add.ts +122 -0
- package/src/cmds/validator_keys/eth_json_v3_worker.ts +30 -0
- package/src/cmds/validator_keys/generate_bls_keypair.ts +33 -0
- package/src/cmds/validator_keys/index.ts +181 -0
- package/src/cmds/validator_keys/new.ts +326 -0
- package/src/cmds/validator_keys/set_funding_account.ts +54 -0
- package/src/cmds/validator_keys/shared.ts +414 -0
- package/src/cmds/validator_keys/staker.ts +300 -0
- package/src/cmds/validator_keys/utils.ts +124 -0
- package/src/config/cached_fetch.ts +154 -0
- package/src/config/chain_l2_config.ts +71 -0
- package/src/config/enrich_env.ts +15 -0
- package/src/config/generated/networks.ts +241 -0
- package/src/config/get_l1_config.ts +31 -0
- package/src/config/index.ts +4 -0
- package/src/config/network_config.ts +150 -0
- package/src/utils/aztec.ts +203 -0
- package/src/utils/commands.ts +434 -0
- package/src/utils/encoding.ts +117 -0
- package/src/utils/github.ts +2 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/inspect.ts +111 -0
- package/src/utils/setup_contracts.ts +19 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { prettyPrintJSON } from '@aztec-labs/cli/utils';
|
|
2
|
+
import { asyncPool } from '@aztec-labs/foundation/async-pool';
|
|
3
|
+
import { deriveBlsPrivateKey } from '@aztec-labs/foundation/crypto/bls';
|
|
4
|
+
import { createBn254Keystore } from '@aztec-labs/foundation/crypto/bls/bn254_keystore';
|
|
5
|
+
import { computeBn254G1PublicKeyCompressed } from '@aztec-labs/foundation/crypto/bn254';
|
|
6
|
+
import { EthAddress } from '@aztec-labs/foundation/eth-address';
|
|
7
|
+
import type { LogFn } from '@aztec-labs/foundation/log';
|
|
8
|
+
import type { EthAccount, EthPrivateKey, ValidatorKeyStore } from '@aztec-labs/node-keystore/types';
|
|
9
|
+
import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
10
|
+
import { Wallet } from '@ethersproject/wallet';
|
|
11
|
+
import { constants as fsConstants, mkdirSync } from 'fs';
|
|
12
|
+
import { access, writeFile } from 'fs/promises';
|
|
13
|
+
import { availableParallelism, homedir } from 'os';
|
|
14
|
+
import { dirname, isAbsolute, join } from 'path';
|
|
15
|
+
import { mnemonicToAccount } from 'viem/accounts';
|
|
16
|
+
import { Worker } from 'worker_threads';
|
|
17
|
+
|
|
18
|
+
import { defaultBlsPath } from './utils.js';
|
|
19
|
+
|
|
20
|
+
type EthJsonV3WorkerResult = { json: string } | { error: { message: string; name?: string; stack?: string } };
|
|
21
|
+
|
|
22
|
+
// ethers' default scrypt parameters use substantial memory, so keep worker fan-out bounded.
|
|
23
|
+
const maxEthKeystoreWorkers = Math.max(1, Math.min(4, availableParallelism()));
|
|
24
|
+
|
|
25
|
+
function deserializeWorkerError(error: { message: string; name?: string; stack?: string }) {
|
|
26
|
+
const result = new Error(error.message);
|
|
27
|
+
result.name = error.name ?? result.name;
|
|
28
|
+
result.stack = error.stack;
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function encryptEthJsonV3InWorker(privateKeyHex: string, password: string): Promise<string> {
|
|
33
|
+
return new Promise<string>((resolve, reject) => {
|
|
34
|
+
// @dependency ./eth_json_v3_worker.ts
|
|
35
|
+
const worker = new Worker(new URL('./eth_json_v3_worker.js', import.meta.url), {
|
|
36
|
+
workerData: { privateKeyHex, password },
|
|
37
|
+
});
|
|
38
|
+
let settled = false;
|
|
39
|
+
|
|
40
|
+
worker.once('message', (result: EthJsonV3WorkerResult) => {
|
|
41
|
+
settled = true;
|
|
42
|
+
|
|
43
|
+
if ('json' in result) {
|
|
44
|
+
resolve(result.json);
|
|
45
|
+
} else {
|
|
46
|
+
reject(deserializeWorkerError(result.error));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
worker.once('error', error => {
|
|
50
|
+
settled = true;
|
|
51
|
+
reject(error);
|
|
52
|
+
});
|
|
53
|
+
worker.once('exit', code => {
|
|
54
|
+
if (!settled) {
|
|
55
|
+
reject(new Error(`ETH JSON V3 worker stopped with exit code ${code}`));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function encryptEthJsonV3(privateKeyHex: string, password: string): Promise<string> {
|
|
62
|
+
if (process.env.JEST_WORKER_ID !== undefined) {
|
|
63
|
+
return await new Wallet(privateKeyHex).encrypt(password);
|
|
64
|
+
}
|
|
65
|
+
return await encryptEthJsonV3InWorker(privateKeyHex, password);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type ValidatorSummary = { attesterEth?: string; attesterBls?: string; publisherEth?: string[] };
|
|
69
|
+
|
|
70
|
+
export type BuildValidatorsInput = {
|
|
71
|
+
validatorCount: number;
|
|
72
|
+
publisherCount?: number;
|
|
73
|
+
publishers?: string[];
|
|
74
|
+
accountIndex: number;
|
|
75
|
+
baseAddressIndex: number;
|
|
76
|
+
mnemonic: string;
|
|
77
|
+
ikm?: string;
|
|
78
|
+
blsPath?: string;
|
|
79
|
+
feeRecipient: AztecAddress;
|
|
80
|
+
coinbase?: EthAddress;
|
|
81
|
+
remoteSigner?: string;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export function withValidatorIndex(path: string, accountIndex: number = 0, addressIndex: number = 0) {
|
|
85
|
+
// NOTE: The legacy BLS CLI is to allow users who generated keys in 2.1.4 to be able to use the same command
|
|
86
|
+
// to re-generate their keys. In 2.1.5 we switched how we append addresses to the path so this is to maintain backwards compatibility.
|
|
87
|
+
const useLegacyBlsCli = ['true', '1', 'yes', 'y'].includes(process.env.LEGACY_BLS_CLI ?? '');
|
|
88
|
+
|
|
89
|
+
const defaultBlsPathParts = defaultBlsPath.split('/');
|
|
90
|
+
|
|
91
|
+
const parts = path.split('/');
|
|
92
|
+
if (parts.length == defaultBlsPathParts.length && parts.every((part, index) => part === defaultBlsPathParts[index])) {
|
|
93
|
+
if (useLegacyBlsCli) {
|
|
94
|
+
// In 2.1.4, we were using address-index in parts[3] and did NOT use account-index, check lines 32 & 84
|
|
95
|
+
// https://github.com/AztecProtocol/aztec-packages/blob/v2.1.4/yarn-project/cli/src/cmds/validator_keys/shared.ts
|
|
96
|
+
|
|
97
|
+
parts[3] = String(addressIndex);
|
|
98
|
+
} else {
|
|
99
|
+
parts[3] = String(accountIndex);
|
|
100
|
+
parts[5] = String(addressIndex);
|
|
101
|
+
}
|
|
102
|
+
return parts.join('/');
|
|
103
|
+
}
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Compute a compressed BN254 G1 public key from a private key.
|
|
109
|
+
* @param privateKeyHex - Private key as 0x-prefixed hex string
|
|
110
|
+
* @returns Compressed G1 point (32 bytes with sign bit in MSB)
|
|
111
|
+
*/
|
|
112
|
+
export async function computeBlsPublicKeyCompressed(privateKeyHex: string): Promise<string> {
|
|
113
|
+
return await computeBn254G1PublicKeyCompressed(privateKeyHex);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function deriveEthAttester(
|
|
117
|
+
mnemonic: string,
|
|
118
|
+
baseAccountIndex: number,
|
|
119
|
+
addressIndex: number,
|
|
120
|
+
remoteSigner?: string,
|
|
121
|
+
): EthAccount | EthPrivateKey {
|
|
122
|
+
const acct = mnemonicToAccount(mnemonic, { accountIndex: baseAccountIndex, addressIndex });
|
|
123
|
+
return remoteSigner
|
|
124
|
+
? ({ address: acct.address as unknown as EthAddress, remoteSignerUrl: remoteSigner } as EthAccount)
|
|
125
|
+
: (('0x' + Buffer.from(acct.getHdKey().privateKey!).toString('hex')) as EthPrivateKey);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolve a `--funding-account` value into a keystore `EthAccount`. A 66-char value is a private key
|
|
130
|
+
* (used verbatim). A 42-char value is an address: with an explicit `remoteSigner` URL it becomes an
|
|
131
|
+
* `{ address, remoteSignerUrl }` pair; without one it is stored as a bare address that falls back to
|
|
132
|
+
* the keystore-level remote signer at runtime. Callers must validate the value first (see
|
|
133
|
+
* `validateFundingAccountOptions`).
|
|
134
|
+
*/
|
|
135
|
+
export function resolveFundingAccount(fundingAccount: string, remoteSigner?: string): EthAccount {
|
|
136
|
+
if (fundingAccount.length === 66) {
|
|
137
|
+
return fundingAccount as EthPrivateKey;
|
|
138
|
+
}
|
|
139
|
+
const address = EthAddress.fromString(fundingAccount);
|
|
140
|
+
return remoteSigner ? ({ address, remoteSignerUrl: remoteSigner } as EthAccount) : address;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export async function buildValidatorEntries(input: BuildValidatorsInput) {
|
|
144
|
+
const {
|
|
145
|
+
validatorCount,
|
|
146
|
+
publisherCount = 0,
|
|
147
|
+
publishers,
|
|
148
|
+
accountIndex,
|
|
149
|
+
baseAddressIndex,
|
|
150
|
+
mnemonic,
|
|
151
|
+
ikm,
|
|
152
|
+
blsPath,
|
|
153
|
+
feeRecipient,
|
|
154
|
+
coinbase,
|
|
155
|
+
remoteSigner,
|
|
156
|
+
} = input;
|
|
157
|
+
|
|
158
|
+
const summaries: ValidatorSummary[] = [];
|
|
159
|
+
|
|
160
|
+
const validators = await Promise.all(
|
|
161
|
+
Array.from({ length: validatorCount }, async (_unused, i) => {
|
|
162
|
+
const addressIndex = baseAddressIndex + i;
|
|
163
|
+
const basePath = blsPath ?? defaultBlsPath;
|
|
164
|
+
const perValidatorPath = withValidatorIndex(basePath, accountIndex, addressIndex);
|
|
165
|
+
|
|
166
|
+
const blsPrivKey = ikm || mnemonic ? deriveBlsPrivateKey(mnemonic, ikm, perValidatorPath) : undefined;
|
|
167
|
+
const blsPubCompressed = blsPrivKey ? await computeBlsPublicKeyCompressed(blsPrivKey) : undefined;
|
|
168
|
+
|
|
169
|
+
const ethAttester = deriveEthAttester(mnemonic, accountIndex, addressIndex, remoteSigner);
|
|
170
|
+
const attester = blsPrivKey ? { eth: ethAttester, bls: blsPrivKey } : ethAttester;
|
|
171
|
+
|
|
172
|
+
let publisherField: EthAccount | EthPrivateKey | (EthAccount | EthPrivateKey)[] | undefined;
|
|
173
|
+
const publisherAddresses: string[] = [];
|
|
174
|
+
if (publishers && publishers.length > 0) {
|
|
175
|
+
publisherAddresses.push(...publishers);
|
|
176
|
+
publisherField = publishers.length === 1 ? (publishers[0] as EthPrivateKey) : (publishers as EthPrivateKey[]);
|
|
177
|
+
} else if (publisherCount > 0) {
|
|
178
|
+
const publishersBaseIndex = baseAddressIndex + validatorCount + i * publisherCount;
|
|
179
|
+
const publisherAccounts = Array.from({ length: publisherCount }, (_unused2, j) => {
|
|
180
|
+
const publisherAddressIndex = publishersBaseIndex + j;
|
|
181
|
+
const pubAcct = mnemonicToAccount(mnemonic, {
|
|
182
|
+
accountIndex,
|
|
183
|
+
addressIndex: publisherAddressIndex,
|
|
184
|
+
});
|
|
185
|
+
publisherAddresses.push(pubAcct.address as unknown as string);
|
|
186
|
+
return remoteSigner
|
|
187
|
+
? ({ address: pubAcct.address as unknown as EthAddress, remoteSignerUrl: remoteSigner } as EthAccount)
|
|
188
|
+
: (('0x' + Buffer.from(pubAcct.getHdKey().privateKey!).toString('hex')) as EthPrivateKey);
|
|
189
|
+
});
|
|
190
|
+
publisherField = publisherCount === 1 ? publisherAccounts[0] : publisherAccounts;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const acct = mnemonicToAccount(mnemonic, {
|
|
194
|
+
accountIndex,
|
|
195
|
+
addressIndex,
|
|
196
|
+
});
|
|
197
|
+
const attesterEthAddress = acct.address as unknown as string;
|
|
198
|
+
summaries.push({
|
|
199
|
+
attesterEth: attesterEthAddress,
|
|
200
|
+
attesterBls: blsPubCompressed,
|
|
201
|
+
publisherEth: publisherAddresses.length > 0 ? publisherAddresses : undefined,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
attester,
|
|
206
|
+
...(publisherField !== undefined ? { publisher: publisherField } : {}),
|
|
207
|
+
feeRecipient,
|
|
208
|
+
coinbase: coinbase ?? attesterEthAddress,
|
|
209
|
+
} as ValidatorKeyStore;
|
|
210
|
+
}),
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
return { validators, summaries };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export async function resolveKeystoreOutputPath(dataDir?: string, file?: string) {
|
|
217
|
+
const defaultDataDir = join(homedir(), '.aztec', 'keystore');
|
|
218
|
+
const resolvedDir = dataDir && dataDir.length > 0 ? dataDir : defaultDataDir;
|
|
219
|
+
let outputPath: string;
|
|
220
|
+
if (file && file.length > 0) {
|
|
221
|
+
outputPath = isAbsolute(file) ? file : join(resolvedDir, file);
|
|
222
|
+
} else {
|
|
223
|
+
let index = 1;
|
|
224
|
+
while (true) {
|
|
225
|
+
const candidate = join(resolvedDir, `key${index}.json`);
|
|
226
|
+
try {
|
|
227
|
+
await access(candidate, fsConstants.F_OK);
|
|
228
|
+
index += 1;
|
|
229
|
+
} catch {
|
|
230
|
+
outputPath = candidate;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { resolvedDir, outputPath: outputPath! };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export async function writeKeystoreFile(path: string, keystore: unknown) {
|
|
239
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
240
|
+
await writeFile(path, JSON.stringify(keystore, null, 2), { encoding: 'utf-8' });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function logValidatorSummaries(log: LogFn, summaries: ValidatorSummary[]) {
|
|
244
|
+
const lines: string[] = [];
|
|
245
|
+
for (let i = 0; i < summaries.length; i++) {
|
|
246
|
+
const v = summaries[i];
|
|
247
|
+
lines.push(`acc${i + 1}:`);
|
|
248
|
+
lines.push(` attester:`);
|
|
249
|
+
if (v.attesterEth) {
|
|
250
|
+
lines.push(` eth: ${v.attesterEth}`);
|
|
251
|
+
}
|
|
252
|
+
if (v.attesterBls) {
|
|
253
|
+
lines.push(` bls: ${v.attesterBls}`);
|
|
254
|
+
}
|
|
255
|
+
if (v.publisherEth && v.publisherEth.length > 0) {
|
|
256
|
+
lines.push(` publisher:`);
|
|
257
|
+
for (const addr of v.publisherEth) {
|
|
258
|
+
lines.push(` - ${addr}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (lines.length > 0) {
|
|
263
|
+
log(lines.join('\n'));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function maybePrintJson(log: LogFn, jsonFlag: boolean | undefined, obj: unknown) {
|
|
268
|
+
if (jsonFlag) {
|
|
269
|
+
log(prettyPrintJSON(obj as Record<string, any>));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Writes a BN254 keystore file for a BN254 BLS private key.
|
|
275
|
+
* Returns the absolute path to the written file.
|
|
276
|
+
*
|
|
277
|
+
* @param outDir - Directory to write the keystore file to
|
|
278
|
+
* @param fileNameBase - Base name for the keystore file (will be sanitized)
|
|
279
|
+
* @param password - Password for encrypting the private key
|
|
280
|
+
* @param privateKeyHex - Private key as 0x-prefixed hex string (32 bytes)
|
|
281
|
+
* @param pubkeyHex - Public key as hex string
|
|
282
|
+
* @param derivationPath - BIP-44 style derivation path
|
|
283
|
+
* @returns Absolute path to the written keystore file
|
|
284
|
+
*/
|
|
285
|
+
export async function writeBn254BlsKeystore(
|
|
286
|
+
outDir: string,
|
|
287
|
+
fileNameBase: string,
|
|
288
|
+
password: string,
|
|
289
|
+
privateKeyHex: string,
|
|
290
|
+
pubkeyHex: string,
|
|
291
|
+
derivationPath: string,
|
|
292
|
+
): Promise<string> {
|
|
293
|
+
mkdirSync(outDir, { recursive: true });
|
|
294
|
+
|
|
295
|
+
const keystore = await createBn254Keystore(password, privateKeyHex, pubkeyHex, derivationPath);
|
|
296
|
+
|
|
297
|
+
const safeBase = fileNameBase.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
298
|
+
const outPath = join(outDir, `keystore-${safeBase}.json`);
|
|
299
|
+
await writeFile(outPath, JSON.stringify(keystore, null, 2), { encoding: 'utf-8' });
|
|
300
|
+
return outPath;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Replace plaintext BLS keys in validators with { path, password } pointing to BN254 keystore files. */
|
|
304
|
+
export async function writeBlsBn254ToFile(
|
|
305
|
+
validators: ValidatorKeyStore[],
|
|
306
|
+
options: { outDir: string; password: string; blsPath?: string },
|
|
307
|
+
): Promise<void> {
|
|
308
|
+
await Promise.all(
|
|
309
|
+
validators.map(async (v, i) => {
|
|
310
|
+
if (!v || typeof v !== 'object' || !('attester' in v)) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const att = (v as any).attester;
|
|
314
|
+
|
|
315
|
+
// Shapes: { bls: <hex> } or { eth: <ethAccount>, bls?: <hex> } or plain EthAccount
|
|
316
|
+
const blsKey: string | undefined = typeof att === 'object' && 'bls' in att ? (att as any).bls : undefined;
|
|
317
|
+
if (!blsKey || typeof blsKey !== 'string') {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const pub = await computeBlsPublicKeyCompressed(blsKey);
|
|
322
|
+
const path = options.blsPath ?? defaultBlsPath;
|
|
323
|
+
const fileBase = `${String(i + 1)}_${pub.slice(2, 18)}`;
|
|
324
|
+
const keystorePath = await writeBn254BlsKeystore(options.outDir, fileBase, options.password, blsKey, pub, path);
|
|
325
|
+
|
|
326
|
+
if (typeof att === 'object') {
|
|
327
|
+
(att as any).bls = { path: keystorePath, password: options.password };
|
|
328
|
+
}
|
|
329
|
+
}),
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Writes an Ethereum JSON V3 keystore using ethers, returns absolute path */
|
|
334
|
+
export async function writeEthJsonV3Keystore(
|
|
335
|
+
outDir: string,
|
|
336
|
+
fileNameBase: string,
|
|
337
|
+
password: string,
|
|
338
|
+
privateKeyHex: string,
|
|
339
|
+
): Promise<string> {
|
|
340
|
+
const safeBase = fileNameBase.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
341
|
+
mkdirSync(outDir, { recursive: true });
|
|
342
|
+
const json = await encryptEthJsonV3(privateKeyHex, password);
|
|
343
|
+
const outPath = join(outDir, `keystore-eth-${safeBase}.json`);
|
|
344
|
+
await writeFile(outPath, json, { encoding: 'utf-8' });
|
|
345
|
+
return outPath;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* If `account` is a plaintext ETH private key, encrypt it to a JSON V3 file and return a
|
|
350
|
+
* { path, password } reference; otherwise return it unchanged.
|
|
351
|
+
*/
|
|
352
|
+
async function maybeEncryptEthAccount(account: any, label: string, options: { outDir: string; password: string }) {
|
|
353
|
+
if (typeof account === 'string' && account.startsWith('0x') && account.length === 66) {
|
|
354
|
+
const fileBase = `${label}_${account.slice(2, 10)}`;
|
|
355
|
+
const p = await writeEthJsonV3Keystore(options.outDir, fileBase, options.password, account);
|
|
356
|
+
return { path: p, password: options.password };
|
|
357
|
+
}
|
|
358
|
+
return account;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Encrypt a plaintext funding-account key to a JSON V3 file, replacing it with a { path, password } reference. */
|
|
362
|
+
export async function encryptFundingAccountToFile(
|
|
363
|
+
account: EthAccount,
|
|
364
|
+
options: { outDir: string; password: string },
|
|
365
|
+
): Promise<EthAccount> {
|
|
366
|
+
return (await maybeEncryptEthAccount(account, 'funding', options)) as EthAccount;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/** Replace plaintext ETH keys in validators with { path, password } pointing to JSON V3 files. */
|
|
370
|
+
export async function writeEthJsonV3ToFile(
|
|
371
|
+
validators: ValidatorKeyStore[],
|
|
372
|
+
options: { outDir: string; password: string },
|
|
373
|
+
): Promise<void> {
|
|
374
|
+
const tasks: (() => Promise<void>)[] = [];
|
|
375
|
+
|
|
376
|
+
const maybeQueueEncryptEth = (account: any, label: string, setEncryptedAccount: (account: any) => void) => {
|
|
377
|
+
if (typeof account === 'string' && account.startsWith('0x') && account.length === 66) {
|
|
378
|
+
tasks.push(async () => {
|
|
379
|
+
const fileBase = `${label}_${account.slice(2, 10)}`;
|
|
380
|
+
const path = await writeEthJsonV3Keystore(options.outDir, fileBase, options.password, account);
|
|
381
|
+
setEncryptedAccount({ path, password: options.password });
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
for (let i = 0; i < validators.length; i++) {
|
|
387
|
+
const v = validators[i];
|
|
388
|
+
if (!v || typeof v !== 'object') {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// attester may be string (eth), object with eth, or remote signer
|
|
393
|
+
const att = (v as any).attester;
|
|
394
|
+
if (typeof att === 'string') {
|
|
395
|
+
maybeQueueEncryptEth(att, `attester_${i + 1}`, account => ((v as any).attester = account));
|
|
396
|
+
} else if (att && typeof att === 'object' && 'eth' in att) {
|
|
397
|
+
maybeQueueEncryptEth((att as any).eth, `attester_${i + 1}`, account => ((att as any).eth = account));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// publisher can be single or array
|
|
401
|
+
if ('publisher' in v) {
|
|
402
|
+
const pub = (v as any).publisher;
|
|
403
|
+
if (Array.isArray(pub)) {
|
|
404
|
+
for (let j = 0; j < pub.length; j++) {
|
|
405
|
+
maybeQueueEncryptEth(pub[j], `publisher_${i + 1}_${j + 1}`, account => (pub[j] = account));
|
|
406
|
+
}
|
|
407
|
+
} else if (pub !== undefined) {
|
|
408
|
+
maybeQueueEncryptEth(pub, `publisher_${i + 1}`, account => ((v as any).publisher = account));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
await asyncPool(maxEthKeystoreWorkers, tasks, task => task());
|
|
414
|
+
}
|