@aztec/cli 2.1.2 → 2.1.3-rc.1
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/cmds/validator_keys/add.d.ts.map +1 -1
- package/dest/cmds/validator_keys/add.js +1 -2
- package/dest/cmds/validator_keys/index.d.ts.map +1 -1
- package/dest/cmds/validator_keys/index.js +10 -3
- package/dest/cmds/validator_keys/new.d.ts +4 -1
- package/dest/cmds/validator_keys/new.d.ts.map +1 -1
- package/dest/cmds/validator_keys/new.js +82 -8
- package/dest/cmds/validator_keys/shared.d.ts +0 -1
- package/dest/cmds/validator_keys/shared.d.ts.map +1 -1
- package/dest/cmds/validator_keys/shared.js +2 -14
- 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 +206 -0
- package/dest/config/chain_l2_config.d.ts +3 -0
- package/dest/config/chain_l2_config.d.ts.map +1 -1
- package/dest/config/chain_l2_config.js +87 -3
- package/package.json +24 -24
- package/src/cmds/validator_keys/add.ts +0 -2
- package/src/cmds/validator_keys/index.ts +31 -3
- package/src/cmds/validator_keys/new.ts +97 -9
- package/src/cmds/validator_keys/shared.ts +1 -9
- package/src/cmds/validator_keys/staker.ts +298 -0
- package/src/config/chain_l2_config.ts +122 -4
|
@@ -58,7 +58,8 @@ export const stagingIgnitionL2ChainConfig = {
|
|
|
58
58
|
],
|
|
59
59
|
autoUpdate: 'config-and-version',
|
|
60
60
|
autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/staging-ignition.json',
|
|
61
|
-
maxTxPoolSize:
|
|
61
|
+
maxTxPoolSize: 0,
|
|
62
|
+
publicMetricsOptOut: false,
|
|
62
63
|
publicIncludeMetrics,
|
|
63
64
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
64
65
|
publicMetricsCollectFrom: [
|
|
@@ -125,6 +126,7 @@ export const stagingPublicL2ChainConfig = {
|
|
|
125
126
|
],
|
|
126
127
|
autoUpdate: 'config-and-version',
|
|
127
128
|
autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/staging-public.json',
|
|
129
|
+
publicMetricsOptOut: false,
|
|
128
130
|
publicIncludeMetrics,
|
|
129
131
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
130
132
|
publicMetricsCollectFrom: [
|
|
@@ -150,6 +152,45 @@ export const stagingPublicL2ChainConfig = {
|
|
|
150
152
|
...DefaultSlashConfig,
|
|
151
153
|
...DefaultNetworkDBMapSizeConfig
|
|
152
154
|
};
|
|
155
|
+
export const nextNetL2ChainConfig = {
|
|
156
|
+
l1ChainId: 11155111,
|
|
157
|
+
testAccounts: true,
|
|
158
|
+
sponsoredFPC: true,
|
|
159
|
+
p2pEnabled: true,
|
|
160
|
+
disableTransactions: false,
|
|
161
|
+
p2pBootstrapNodes: [],
|
|
162
|
+
seqMinTxsPerBlock: 0,
|
|
163
|
+
seqMaxTxsPerBlock: 8,
|
|
164
|
+
realProofs: true,
|
|
165
|
+
snapshotsUrls: [],
|
|
166
|
+
autoUpdate: 'config-and-version',
|
|
167
|
+
autoUpdateUrl: '',
|
|
168
|
+
publicMetricsOptOut: true,
|
|
169
|
+
publicIncludeMetrics,
|
|
170
|
+
publicMetricsCollectorUrl: '',
|
|
171
|
+
publicMetricsCollectFrom: [
|
|
172
|
+
''
|
|
173
|
+
],
|
|
174
|
+
maxTxPoolSize: 100_000_000,
|
|
175
|
+
txPoolDeleteTxsAfterReorg: false,
|
|
176
|
+
// Deployment stuff
|
|
177
|
+
/** How many seconds an L1 slot lasts. */ ethereumSlotDuration: 12,
|
|
178
|
+
/** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 36,
|
|
179
|
+
/** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
|
|
180
|
+
/** The target validator committee size. */ aztecTargetCommitteeSize: 48,
|
|
181
|
+
/** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: DefaultL1ContractsConfig.lagInEpochs,
|
|
182
|
+
/** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
|
|
183
|
+
/** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
|
|
184
|
+
/** The deposit amount for a validator */ activationThreshold: DefaultL1ContractsConfig.activationThreshold,
|
|
185
|
+
/** The minimum stake for a validator. */ ejectionThreshold: DefaultL1ContractsConfig.ejectionThreshold,
|
|
186
|
+
/** The slashing round size */ slashingRoundSizeInEpochs: DefaultL1ContractsConfig.slashingRoundSizeInEpochs,
|
|
187
|
+
/** Governance proposing round size */ governanceProposerRoundSize: DefaultL1ContractsConfig.governanceProposerRoundSize,
|
|
188
|
+
/** The mana target for the rollup */ manaTarget: DefaultL1ContractsConfig.manaTarget,
|
|
189
|
+
/** The proving cost per mana */ provingCostPerMana: DefaultL1ContractsConfig.provingCostPerMana,
|
|
190
|
+
/** Exit delay for stakers */ exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
|
|
191
|
+
...DefaultSlashConfig,
|
|
192
|
+
...DefaultNetworkDBMapSizeConfig
|
|
193
|
+
};
|
|
153
194
|
export const testnetL2ChainConfig = {
|
|
154
195
|
l1ChainId: 11155111,
|
|
155
196
|
testAccounts: false,
|
|
@@ -166,6 +207,7 @@ export const testnetL2ChainConfig = {
|
|
|
166
207
|
autoUpdate: 'config-and-version',
|
|
167
208
|
autoUpdateUrl: 'https://storage.googleapis.com/aztec-testnet/auto-update/testnet.json',
|
|
168
209
|
maxTxPoolSize: 100_000_000,
|
|
210
|
+
publicMetricsOptOut: false,
|
|
169
211
|
publicIncludeMetrics,
|
|
170
212
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
171
213
|
publicMetricsCollectFrom: [
|
|
@@ -235,12 +277,14 @@ export const mainnetL2ChainConfig = {
|
|
|
235
277
|
],
|
|
236
278
|
autoUpdate: 'notify',
|
|
237
279
|
autoUpdateUrl: 'https://storage.googleapis.com/aztec-mainnet/auto-update/mainnet.json',
|
|
238
|
-
maxTxPoolSize:
|
|
280
|
+
maxTxPoolSize: 0,
|
|
281
|
+
publicMetricsOptOut: true,
|
|
239
282
|
publicIncludeMetrics,
|
|
240
283
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
241
284
|
publicMetricsCollectFrom: [
|
|
242
285
|
'sequencer'
|
|
243
286
|
],
|
|
287
|
+
blobAllowEmptySources: true,
|
|
244
288
|
/** How many seconds an L1 slot lasts. */ ethereumSlotDuration: 12,
|
|
245
289
|
/** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 72,
|
|
246
290
|
/** How many L2 slots an epoch lasts. */ aztecEpochDuration: 32,
|
|
@@ -252,7 +296,7 @@ export const mainnetL2ChainConfig = {
|
|
|
252
296
|
slashingRoundSizeInEpochs: 4,
|
|
253
297
|
slashingExecutionDelayInRounds: 28,
|
|
254
298
|
slashingLifetimeInRounds: 34,
|
|
255
|
-
slashingVetoer: EthAddress.
|
|
299
|
+
slashingVetoer: EthAddress.fromString('0xBbB4aF368d02827945748b28CD4b2D42e4A37480'),
|
|
256
300
|
slashingOffsetInRounds: 2,
|
|
257
301
|
slashingDisableDuration: 259_200,
|
|
258
302
|
slasherFlavor: 'tally',
|
|
@@ -285,6 +329,45 @@ export const mainnetL2ChainConfig = {
|
|
|
285
329
|
sentinelEnabled: true,
|
|
286
330
|
...DefaultNetworkDBMapSizeConfig
|
|
287
331
|
};
|
|
332
|
+
export const devnetL2ChainConfig = {
|
|
333
|
+
l1ChainId: 11155111,
|
|
334
|
+
testAccounts: true,
|
|
335
|
+
sponsoredFPC: true,
|
|
336
|
+
p2pEnabled: true,
|
|
337
|
+
disableTransactions: false,
|
|
338
|
+
p2pBootstrapNodes: [],
|
|
339
|
+
seqMinTxsPerBlock: 0,
|
|
340
|
+
seqMaxTxsPerBlock: 8,
|
|
341
|
+
realProofs: false,
|
|
342
|
+
snapshotsUrls: [],
|
|
343
|
+
autoUpdate: 'config-and-version',
|
|
344
|
+
autoUpdateUrl: '',
|
|
345
|
+
publicMetricsOptOut: true,
|
|
346
|
+
publicIncludeMetrics,
|
|
347
|
+
publicMetricsCollectorUrl: '',
|
|
348
|
+
publicMetricsCollectFrom: [
|
|
349
|
+
''
|
|
350
|
+
],
|
|
351
|
+
maxTxPoolSize: 100_000_000,
|
|
352
|
+
txPoolDeleteTxsAfterReorg: true,
|
|
353
|
+
// Deployment stuff
|
|
354
|
+
/** How many seconds an L1 slot lasts. */ ethereumSlotDuration: 12,
|
|
355
|
+
/** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */ aztecSlotDuration: 36,
|
|
356
|
+
/** How many L2 slots an epoch lasts. */ aztecEpochDuration: 8,
|
|
357
|
+
/** The target validator committee size. */ aztecTargetCommitteeSize: 1,
|
|
358
|
+
/** The number of epochs to lag behind the current epoch for validator selection. */ lagInEpochs: 1,
|
|
359
|
+
/** The local ejection threshold for a validator. Stricter than ejectionThreshold but local to a specific rollup */ localEjectionThreshold: DefaultL1ContractsConfig.localEjectionThreshold,
|
|
360
|
+
/** The number of epochs after an epoch ends that proofs are still accepted. */ aztecProofSubmissionEpochs: 1,
|
|
361
|
+
/** The deposit amount for a validator */ activationThreshold: DefaultL1ContractsConfig.activationThreshold,
|
|
362
|
+
/** The minimum stake for a validator. */ ejectionThreshold: DefaultL1ContractsConfig.ejectionThreshold,
|
|
363
|
+
/** The slashing round size */ slashingRoundSizeInEpochs: DefaultL1ContractsConfig.slashingRoundSizeInEpochs,
|
|
364
|
+
/** Governance proposing round size */ governanceProposerRoundSize: DefaultL1ContractsConfig.governanceProposerRoundSize,
|
|
365
|
+
/** The mana target for the rollup */ manaTarget: DefaultL1ContractsConfig.manaTarget,
|
|
366
|
+
/** The proving cost per mana */ provingCostPerMana: DefaultL1ContractsConfig.provingCostPerMana,
|
|
367
|
+
/** Exit delay for stakers */ exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
|
|
368
|
+
...DefaultSlashConfig,
|
|
369
|
+
...DefaultNetworkDBMapSizeConfig
|
|
370
|
+
};
|
|
288
371
|
export function getL2ChainConfig(networkName) {
|
|
289
372
|
let config;
|
|
290
373
|
if (networkName === 'staging-public') {
|
|
@@ -355,6 +438,7 @@ export function enrichEnvironmentWithChainConfig(networkName) {
|
|
|
355
438
|
if (config.publicMetricsCollectFrom) {
|
|
356
439
|
enrichVar('PUBLIC_OTEL_COLLECT_FROM', config.publicMetricsCollectFrom.join(','));
|
|
357
440
|
}
|
|
441
|
+
enrichVar('PUBLIC_OTEL_OPT_OUT', config.publicMetricsOptOut.toString());
|
|
358
442
|
// Deployment stuff
|
|
359
443
|
enrichVar('ETHEREUM_SLOT_DURATION', config.ethereumSlotDuration.toString());
|
|
360
444
|
enrichVar('AZTEC_SLOT_DURATION', config.aztecSlotDuration.toString());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3-rc.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./contracts": "./dest/cmds/contracts/index.js",
|
|
@@ -71,18 +71,18 @@
|
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@aztec/archiver": "2.1.
|
|
75
|
-
"@aztec/aztec.js": "2.1.
|
|
76
|
-
"@aztec/constants": "2.1.
|
|
77
|
-
"@aztec/entrypoints": "2.1.
|
|
78
|
-
"@aztec/ethereum": "2.1.
|
|
79
|
-
"@aztec/foundation": "2.1.
|
|
80
|
-
"@aztec/l1-artifacts": "2.1.
|
|
81
|
-
"@aztec/node-keystore": "2.1.
|
|
82
|
-
"@aztec/node-lib": "2.1.
|
|
83
|
-
"@aztec/p2p": "2.1.
|
|
84
|
-
"@aztec/stdlib": "2.1.
|
|
85
|
-
"@aztec/world-state": "2.1.
|
|
74
|
+
"@aztec/archiver": "2.1.3-rc.1",
|
|
75
|
+
"@aztec/aztec.js": "2.1.3-rc.1",
|
|
76
|
+
"@aztec/constants": "2.1.3-rc.1",
|
|
77
|
+
"@aztec/entrypoints": "2.1.3-rc.1",
|
|
78
|
+
"@aztec/ethereum": "2.1.3-rc.1",
|
|
79
|
+
"@aztec/foundation": "2.1.3-rc.1",
|
|
80
|
+
"@aztec/l1-artifacts": "2.1.3-rc.1",
|
|
81
|
+
"@aztec/node-keystore": "2.1.3-rc.1",
|
|
82
|
+
"@aztec/node-lib": "2.1.3-rc.1",
|
|
83
|
+
"@aztec/p2p": "2.1.3-rc.1",
|
|
84
|
+
"@aztec/stdlib": "2.1.3-rc.1",
|
|
85
|
+
"@aztec/world-state": "2.1.3-rc.1",
|
|
86
86
|
"@ethersproject/wallet": "^5.8.0",
|
|
87
87
|
"@iarna/toml": "^2.2.5",
|
|
88
88
|
"@libp2p/peer-id-factory": "^3.0.4",
|
|
@@ -96,8 +96,8 @@
|
|
|
96
96
|
"viem": "npm:@spalladino/viem@2.38.2-eip7594.0"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
-
"@aztec/accounts": "2.1.
|
|
100
|
-
"@aztec/protocol-contracts": "2.1.
|
|
99
|
+
"@aztec/accounts": "2.1.3-rc.1",
|
|
100
|
+
"@aztec/protocol-contracts": "2.1.3-rc.1",
|
|
101
101
|
"@jest/globals": "^30.0.0",
|
|
102
102
|
"@types/jest": "^30.0.0",
|
|
103
103
|
"@types/lodash.chunk": "^4.2.9",
|
|
@@ -113,15 +113,15 @@
|
|
|
113
113
|
"typescript": "^5.3.3"
|
|
114
114
|
},
|
|
115
115
|
"peerDependencies": {
|
|
116
|
-
"@aztec/accounts": "2.1.
|
|
117
|
-
"@aztec/bb-prover": "2.1.
|
|
118
|
-
"@aztec/ethereum": "2.1.
|
|
119
|
-
"@aztec/l1-artifacts": "2.1.
|
|
120
|
-
"@aztec/noir-contracts.js": "2.1.
|
|
121
|
-
"@aztec/noir-protocol-circuits-types": "2.1.
|
|
122
|
-
"@aztec/noir-test-contracts.js": "2.1.
|
|
123
|
-
"@aztec/protocol-contracts": "2.1.
|
|
124
|
-
"@aztec/stdlib": "2.1.
|
|
116
|
+
"@aztec/accounts": "2.1.3-rc.1",
|
|
117
|
+
"@aztec/bb-prover": "2.1.3-rc.1",
|
|
118
|
+
"@aztec/ethereum": "2.1.3-rc.1",
|
|
119
|
+
"@aztec/l1-artifacts": "2.1.3-rc.1",
|
|
120
|
+
"@aztec/noir-contracts.js": "2.1.3-rc.1",
|
|
121
|
+
"@aztec/noir-protocol-circuits-types": "2.1.3-rc.1",
|
|
122
|
+
"@aztec/noir-test-contracts.js": "2.1.3-rc.1",
|
|
123
|
+
"@aztec/protocol-contracts": "2.1.3-rc.1",
|
|
124
|
+
"@aztec/stdlib": "2.1.3-rc.1"
|
|
125
125
|
},
|
|
126
126
|
"files": [
|
|
127
127
|
"dest",
|
|
@@ -30,7 +30,6 @@ export async function addValidatorKeys(existing: string, options: AddValidatorKe
|
|
|
30
30
|
addressIndex,
|
|
31
31
|
ikm,
|
|
32
32
|
blsPath,
|
|
33
|
-
blsOnly,
|
|
34
33
|
json,
|
|
35
34
|
feeRecipient: feeRecipientOpt,
|
|
36
35
|
coinbase: coinbaseOpt,
|
|
@@ -75,7 +74,6 @@ export async function addValidatorKeys(existing: string, options: AddValidatorKe
|
|
|
75
74
|
mnemonic: mnemonicToUse,
|
|
76
75
|
ikm,
|
|
77
76
|
blsPath,
|
|
78
|
-
blsOnly,
|
|
79
77
|
feeRecipient,
|
|
80
78
|
coinbase,
|
|
81
79
|
remoteSigner,
|
|
@@ -7,7 +7,7 @@ import { parseAztecAddress, parseEthereumAddress, parseHex, parseOptionalInteger
|
|
|
7
7
|
export function injectCommands(program: Command, log: LogFn) {
|
|
8
8
|
const group = program
|
|
9
9
|
.command('validator-keys')
|
|
10
|
-
.aliases(['valKeys'])
|
|
10
|
+
.aliases(['valKeys', 'valkeys'])
|
|
11
11
|
.description('Manage validator keystores for node operators');
|
|
12
12
|
|
|
13
13
|
group
|
|
@@ -29,13 +29,23 @@ export function injectCommands(program: Command, log: LogFn) {
|
|
|
29
29
|
.option('--remote-signer <url>', 'Default remote signer URL for accounts in this file')
|
|
30
30
|
.option('--ikm <hex>', 'Initial keying material for BLS (alternative to mnemonic)', value => parseHex(value, 32))
|
|
31
31
|
.option('--bls-path <path>', 'EIP-2334 path (default m/12381/3600/0/0/0)')
|
|
32
|
-
.option('--bls-only', 'Generate only BLS keys')
|
|
33
32
|
.option(
|
|
34
33
|
'--password <str>',
|
|
35
34
|
'Password for writing keystore files (ETH JSON V3 and BLS EIP-2335). Empty string allowed',
|
|
36
35
|
)
|
|
37
36
|
.option('--out-dir <dir>', 'Output directory for generated keystore file(s)')
|
|
38
37
|
.option('--json', 'Echo resulting JSON to stdout')
|
|
38
|
+
.option('--staker-output', 'Generate staker output JSON files for each attester')
|
|
39
|
+
.option('--gse-address <address>', 'GSE contract address (required with --staker-output)', parseEthereumAddress)
|
|
40
|
+
.option('--l1-rpc-urls <urls>', 'L1 RPC URLs (comma-separated, required with --staker-output)', value =>
|
|
41
|
+
value.split(','),
|
|
42
|
+
)
|
|
43
|
+
.option(
|
|
44
|
+
'-c, --l1-chain-id <number>',
|
|
45
|
+
'L1 chain ID (required with --staker-output)',
|
|
46
|
+
value => parseInt(value),
|
|
47
|
+
31337,
|
|
48
|
+
)
|
|
39
49
|
.requiredOption('--fee-recipient <address>', 'Aztec address that will receive fees', parseAztecAddress)
|
|
40
50
|
.action(async options => {
|
|
41
51
|
const { newValidatorKeystore } = await import('./new.js');
|
|
@@ -62,7 +72,6 @@ export function injectCommands(program: Command, log: LogFn) {
|
|
|
62
72
|
.option('--remote-signer <url>', 'Default remote signer URL for accounts in this file')
|
|
63
73
|
.option('--ikm <hex>', 'Initial keying material for BLS (alternative to mnemonic)', value => parseHex(value, 32))
|
|
64
74
|
.option('--bls-path <path>', 'EIP-2334 path (default m/12381/3600/0/0/0)')
|
|
65
|
-
.option('--bls-only', 'Generate only BLS keys')
|
|
66
75
|
.option('--empty', 'Generate an empty skeleton without keys')
|
|
67
76
|
.option(
|
|
68
77
|
'--password <str>',
|
|
@@ -76,6 +85,25 @@ export function injectCommands(program: Command, log: LogFn) {
|
|
|
76
85
|
await addValidatorKeys(existing, options, log);
|
|
77
86
|
});
|
|
78
87
|
|
|
88
|
+
group
|
|
89
|
+
.command('staker')
|
|
90
|
+
.summary('Generate staking JSON from keystore')
|
|
91
|
+
.description(
|
|
92
|
+
'Reads a validator keystore and outputs staking data with BLS public keys for each attester (skips mnemonics)',
|
|
93
|
+
)
|
|
94
|
+
.requiredOption('--from <keystore>', 'Path to keystore JSON file')
|
|
95
|
+
.option('--password <password>', 'Password for decrypting encrypted keystores (if not specified in keystore file)')
|
|
96
|
+
.requiredOption('--gse-address <address>', 'GSE contract address', parseEthereumAddress)
|
|
97
|
+
.option('--l1-rpc-urls <urls>', 'L1 RPC URLs (comma-separated)', value => value.split(','), [
|
|
98
|
+
'http://localhost:8545',
|
|
99
|
+
])
|
|
100
|
+
.option('-c, --l1-chain-id <number>', 'L1 chain ID', value => parseInt(value), 31337)
|
|
101
|
+
.option('--output <file>', 'Output file path (if not specified, JSON is written to stdout)')
|
|
102
|
+
.action(async options => {
|
|
103
|
+
const { generateStakerJson } = await import('./staker.js');
|
|
104
|
+
await generateStakerJson(options, log);
|
|
105
|
+
});
|
|
106
|
+
|
|
79
107
|
// top-level convenience: aztec generate-bls-keypair
|
|
80
108
|
program
|
|
81
109
|
.command('generate-bls-keypair')
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { prettyPrintJSON } from '@aztec/cli/utils';
|
|
2
|
+
import { GSEContract, createEthereumChain } from '@aztec/ethereum';
|
|
1
3
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
4
|
import type { LogFn } from '@aztec/foundation/log';
|
|
3
5
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
6
|
|
|
5
7
|
import { wordlist } from '@scure/bip39/wordlists/english.js';
|
|
6
|
-
import {
|
|
8
|
+
import { writeFile } from 'fs/promises';
|
|
9
|
+
import { basename, dirname, join } from 'path';
|
|
10
|
+
import { createPublicClient, fallback, http } from 'viem';
|
|
7
11
|
import { generateMnemonic, mnemonicToAccount } from 'viem/accounts';
|
|
8
12
|
|
|
9
13
|
import {
|
|
@@ -15,6 +19,7 @@ import {
|
|
|
15
19
|
writeEthJsonV3ToFile,
|
|
16
20
|
writeKeystoreFile,
|
|
17
21
|
} from './shared.js';
|
|
22
|
+
import { processAttesterAccounts } from './staker.js';
|
|
18
23
|
|
|
19
24
|
export type NewValidatorKeystoreOptions = {
|
|
20
25
|
dataDir?: string;
|
|
@@ -28,7 +33,6 @@ export type NewValidatorKeystoreOptions = {
|
|
|
28
33
|
separatePublisher?: boolean;
|
|
29
34
|
ikm?: string;
|
|
30
35
|
blsPath?: string;
|
|
31
|
-
blsOnly?: boolean;
|
|
32
36
|
password?: string;
|
|
33
37
|
outDir?: string;
|
|
34
38
|
json?: boolean;
|
|
@@ -36,6 +40,10 @@ export type NewValidatorKeystoreOptions = {
|
|
|
36
40
|
coinbase?: EthAddress;
|
|
37
41
|
remoteSigner?: string;
|
|
38
42
|
fundingAccount?: EthAddress;
|
|
43
|
+
stakerOutput?: boolean;
|
|
44
|
+
gseAddress?: EthAddress;
|
|
45
|
+
l1RpcUrls?: string[];
|
|
46
|
+
l1ChainId?: number;
|
|
39
47
|
};
|
|
40
48
|
|
|
41
49
|
export async function newValidatorKeystore(options: NewValidatorKeystoreOptions, log: LogFn) {
|
|
@@ -51,14 +59,30 @@ export async function newValidatorKeystore(options: NewValidatorKeystoreOptions,
|
|
|
51
59
|
feeRecipient,
|
|
52
60
|
remoteSigner,
|
|
53
61
|
fundingAccount,
|
|
54
|
-
blsOnly,
|
|
55
62
|
blsPath,
|
|
56
63
|
ikm,
|
|
57
64
|
mnemonic: _mnemonic,
|
|
58
65
|
password,
|
|
59
66
|
outDir,
|
|
67
|
+
stakerOutput,
|
|
68
|
+
gseAddress,
|
|
69
|
+
l1RpcUrls,
|
|
70
|
+
l1ChainId,
|
|
60
71
|
} = options;
|
|
61
72
|
|
|
73
|
+
// Validate staker output requirements
|
|
74
|
+
if (stakerOutput) {
|
|
75
|
+
if (!gseAddress) {
|
|
76
|
+
throw new Error('--gse-address is required when using --staker-output');
|
|
77
|
+
}
|
|
78
|
+
if (!l1RpcUrls || l1RpcUrls.length === 0) {
|
|
79
|
+
throw new Error('--l1-rpc-urls is required when using --staker-output');
|
|
80
|
+
}
|
|
81
|
+
if (l1ChainId === undefined) {
|
|
82
|
+
throw new Error('--l1-chain-id is required when using --staker-output');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
62
86
|
if (remoteSigner && !_mnemonic) {
|
|
63
87
|
throw new Error(
|
|
64
88
|
'Using --remote-signer requires a deterministic key source. Provide --mnemonic to derive keys, or omit --remote-signer to write new private keys to keystore.',
|
|
@@ -67,6 +91,14 @@ export async function newValidatorKeystore(options: NewValidatorKeystoreOptions,
|
|
|
67
91
|
|
|
68
92
|
const mnemonic = _mnemonic ?? generateMnemonic(wordlist);
|
|
69
93
|
|
|
94
|
+
if (!_mnemonic && !json) {
|
|
95
|
+
log('No mnemonic provided, generating new one...');
|
|
96
|
+
log(`Using new mnemonic:`);
|
|
97
|
+
log('');
|
|
98
|
+
log(mnemonic);
|
|
99
|
+
log('');
|
|
100
|
+
}
|
|
101
|
+
|
|
70
102
|
const validatorCount = typeof count === 'number' && Number.isFinite(count) && count > 0 ? Math.floor(count) : 1;
|
|
71
103
|
const { outputPath } = await resolveKeystoreOutputPath(dataDir, file);
|
|
72
104
|
|
|
@@ -78,7 +110,6 @@ export async function newValidatorKeystore(options: NewValidatorKeystoreOptions,
|
|
|
78
110
|
mnemonic,
|
|
79
111
|
ikm,
|
|
80
112
|
blsPath,
|
|
81
|
-
blsOnly,
|
|
82
113
|
feeRecipient,
|
|
83
114
|
coinbase,
|
|
84
115
|
remoteSigner,
|
|
@@ -99,15 +130,66 @@ export async function newValidatorKeystore(options: NewValidatorKeystoreOptions,
|
|
|
99
130
|
|
|
100
131
|
await writeKeystoreFile(outputPath, keystore);
|
|
101
132
|
|
|
102
|
-
|
|
103
|
-
|
|
133
|
+
// Generate staker outputs if requested
|
|
134
|
+
const allStakerOutputs: any[] = [];
|
|
135
|
+
if (stakerOutput && gseAddress && l1RpcUrls && l1ChainId !== undefined) {
|
|
136
|
+
const chain = createEthereumChain(l1RpcUrls, l1ChainId);
|
|
137
|
+
const publicClient = createPublicClient({
|
|
138
|
+
chain: chain.chainInfo,
|
|
139
|
+
transport: fallback(l1RpcUrls.map(url => http(url))),
|
|
140
|
+
});
|
|
141
|
+
const gse = new GSEContract(publicClient, gseAddress);
|
|
142
|
+
|
|
143
|
+
const keystoreOutDir = outDir && outDir.length > 0 ? outDir : dirname(outputPath);
|
|
144
|
+
// Extract keystore base name without extension for unique staker output filenames
|
|
145
|
+
const keystoreBaseName = basename(outputPath, '.json');
|
|
146
|
+
|
|
147
|
+
// Process each validator
|
|
148
|
+
for (let i = 0; i < validators.length; i++) {
|
|
149
|
+
const validator = validators[i];
|
|
150
|
+
const outputs = await processAttesterAccounts(validator.attester, gse, password);
|
|
151
|
+
|
|
152
|
+
// Save each attester's staker output
|
|
153
|
+
for (let j = 0; j < outputs.length; j++) {
|
|
154
|
+
const attesterIndex = i + 1;
|
|
155
|
+
const stakerOutputPath = join(
|
|
156
|
+
keystoreOutDir,
|
|
157
|
+
`${keystoreBaseName}_attester${attesterIndex}_staker_output.json`,
|
|
158
|
+
);
|
|
159
|
+
await writeFile(stakerOutputPath, prettyPrintJSON(outputs[j]), 'utf-8');
|
|
160
|
+
allStakerOutputs.push(outputs[j]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const outputData = !_mnemonic ? { ...keystore, generatedMnemonic: mnemonic } : keystore;
|
|
166
|
+
|
|
167
|
+
// Handle JSON output
|
|
168
|
+
if (json) {
|
|
169
|
+
if (stakerOutput && allStakerOutputs.length > 0) {
|
|
170
|
+
const combinedOutput = {
|
|
171
|
+
keystore: outputData,
|
|
172
|
+
staker: allStakerOutputs,
|
|
173
|
+
};
|
|
174
|
+
maybePrintJson(log, json, combinedOutput as unknown as Record<string, any>);
|
|
175
|
+
} else {
|
|
176
|
+
maybePrintJson(log, json, outputData as unknown as Record<string, any>);
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
104
179
|
log(`Wrote validator keystore to ${outputPath}`);
|
|
180
|
+
if (stakerOutput && allStakerOutputs.length > 0) {
|
|
181
|
+
const keystoreOutDir = outDir && outDir.length > 0 ? outDir : dirname(outputPath);
|
|
182
|
+
log(`Wrote ${allStakerOutputs.length} staker output file(s) to ${keystoreOutDir}`);
|
|
183
|
+
log('');
|
|
184
|
+
}
|
|
105
185
|
}
|
|
106
186
|
|
|
107
|
-
//
|
|
108
|
-
|
|
187
|
+
// print a concise summary of public keys (addresses and BLS pubkeys) if no --json options was selected
|
|
188
|
+
if (!json) {
|
|
189
|
+
logValidatorSummaries(log, summaries);
|
|
190
|
+
}
|
|
109
191
|
|
|
110
|
-
if (
|
|
192
|
+
if (mnemonic && remoteSigner && !json) {
|
|
111
193
|
for (let i = 0; i < validatorCount; i++) {
|
|
112
194
|
const addrIdx = addressIndex + i;
|
|
113
195
|
const acct = mnemonicToAccount(mnemonic, {
|
|
@@ -117,4 +199,10 @@ export async function newValidatorKeystore(options: NewValidatorKeystoreOptions,
|
|
|
117
199
|
log(`attester address: ${acct.address} remoteSignerUrl: ${remoteSigner}`);
|
|
118
200
|
}
|
|
119
201
|
}
|
|
202
|
+
|
|
203
|
+
// Log staker outputs if not in JSON mode
|
|
204
|
+
if (!json && stakerOutput && allStakerOutputs.length > 0) {
|
|
205
|
+
log('\nStaker outputs:');
|
|
206
|
+
log(prettyPrintJSON(allStakerOutputs));
|
|
207
|
+
}
|
|
120
208
|
}
|
|
@@ -23,7 +23,6 @@ export type BuildValidatorsInput = {
|
|
|
23
23
|
mnemonic: string;
|
|
24
24
|
ikm?: string;
|
|
25
25
|
blsPath?: string;
|
|
26
|
-
blsOnly?: boolean;
|
|
27
26
|
feeRecipient: AztecAddress;
|
|
28
27
|
coinbase?: EthAddress;
|
|
29
28
|
remoteSigner?: string;
|
|
@@ -69,7 +68,6 @@ export async function buildValidatorEntries(input: BuildValidatorsInput) {
|
|
|
69
68
|
mnemonic,
|
|
70
69
|
ikm,
|
|
71
70
|
blsPath,
|
|
72
|
-
blsOnly,
|
|
73
71
|
feeRecipient,
|
|
74
72
|
coinbase,
|
|
75
73
|
remoteSigner,
|
|
@@ -85,15 +83,9 @@ export async function buildValidatorEntries(input: BuildValidatorsInput) {
|
|
|
85
83
|
const basePath = blsPath ?? defaultBlsPath;
|
|
86
84
|
const perValidatorPath = withValidatorIndex(basePath, addressIndex);
|
|
87
85
|
|
|
88
|
-
const blsPrivKey =
|
|
86
|
+
const blsPrivKey = ikm || mnemonic ? deriveBlsPrivateKey(mnemonic, ikm, perValidatorPath) : undefined;
|
|
89
87
|
const blsPubCompressed = blsPrivKey ? await computeBlsPublicKeyCompressed(blsPrivKey) : undefined;
|
|
90
88
|
|
|
91
|
-
if (blsOnly) {
|
|
92
|
-
const attester = { bls: blsPrivKey! };
|
|
93
|
-
summaries.push({ attesterBls: blsPubCompressed });
|
|
94
|
-
return { attester, feeRecipient } as ValidatorKeyStore;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
89
|
const ethAttester = deriveEthAttester(mnemonic, accountIndex, addressIndex, remoteSigner);
|
|
98
90
|
const attester = blsPrivKey ? { eth: ethAttester, bls: blsPrivKey } : ethAttester;
|
|
99
91
|
|