@aztec/cli 2.1.0-rc.9 → 2.1.2-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/l1/deploy_new_rollup.d.ts +1 -1
- package/dest/cmds/l1/deploy_new_rollup.d.ts.map +1 -1
- package/dest/cmds/l1/deploy_new_rollup.js +2 -2
- package/dest/cmds/l1/index.d.ts.map +1 -1
- package/dest/cmds/l1/index.js +2 -2
- 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 +70 -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 +26 -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 +20 -0
- package/dest/cmds/validator_keys/new.d.ts +26 -0
- package/dest/cmds/validator_keys/new.d.ts.map +1 -0
- package/dest/cmds/validator_keys/new.js +60 -0
- package/dest/cmds/validator_keys/shared.d.ts +68 -0
- package/dest/cmds/validator_keys/shared.d.ts.map +1 -0
- package/dest/cmds/validator_keys/shared.js +271 -0
- package/dest/config/chain_l2_config.d.ts +6 -4
- package/dest/config/chain_l2_config.d.ts.map +1 -1
- package/dest/config/chain_l2_config.js +82 -65
- package/dest/utils/aztec.d.ts +1 -1
- package/dest/utils/aztec.d.ts.map +1 -1
- package/dest/utils/aztec.js +2 -2
- package/dest/utils/commands.d.ts +10 -1
- package/dest/utils/commands.d.ts.map +1 -1
- package/dest/utils/commands.js +30 -3
- package/package.json +28 -24
- package/src/cmds/l1/deploy_new_rollup.ts +2 -0
- package/src/cmds/l1/index.ts +2 -0
- package/src/cmds/validator_keys/add.ts +113 -0
- package/src/cmds/validator_keys/generate_bls_keypair.ts +33 -0
- package/src/cmds/validator_keys/index.ts +96 -0
- package/src/cmds/validator_keys/new.ts +120 -0
- package/src/cmds/validator_keys/shared.ts +321 -0
- package/src/config/chain_l2_config.ts +110 -84
- package/src/utils/aztec.ts +2 -0
- package/src/utils/commands.ts +41 -3
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { prettyPrintJSON } from '@aztec/cli/utils';
|
|
2
|
+
import { computeBn254G1PublicKeyCompressed, deriveBlsPrivateKey } from '@aztec/foundation/crypto';
|
|
3
|
+
import { createBn254Keystore } from '@aztec/foundation/crypto/bls/bn254_keystore';
|
|
4
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
6
|
+
import type { EthAccount, EthPrivateKey, ValidatorKeyStore } from '@aztec/node-keystore/types';
|
|
7
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
|
+
|
|
9
|
+
import { Wallet } from '@ethersproject/wallet';
|
|
10
|
+
import { constants as fsConstants, mkdirSync } from 'fs';
|
|
11
|
+
import { access, writeFile } from 'fs/promises';
|
|
12
|
+
import { homedir } from 'os';
|
|
13
|
+
import { dirname, isAbsolute, join } from 'path';
|
|
14
|
+
import { mnemonicToAccount } from 'viem/accounts';
|
|
15
|
+
|
|
16
|
+
export type ValidatorSummary = { attesterEth?: string; attesterBls?: string; publisherEth?: string[] };
|
|
17
|
+
|
|
18
|
+
export type BuildValidatorsInput = {
|
|
19
|
+
validatorCount: number;
|
|
20
|
+
publisherCount?: number;
|
|
21
|
+
accountIndex: number;
|
|
22
|
+
baseAddressIndex: number;
|
|
23
|
+
mnemonic: string;
|
|
24
|
+
ikm?: string;
|
|
25
|
+
blsPath?: string;
|
|
26
|
+
blsOnly?: boolean;
|
|
27
|
+
feeRecipient: AztecAddress;
|
|
28
|
+
coinbase?: EthAddress;
|
|
29
|
+
remoteSigner?: string;
|
|
30
|
+
fundingAccount?: EthAddress;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function withValidatorIndex(path: string, index: number) {
|
|
34
|
+
const parts = path.split('/');
|
|
35
|
+
if (parts.length >= 4 && parts[0] === 'm' && parts[1] === '12381' && parts[2] === '3600') {
|
|
36
|
+
parts[3] = String(index);
|
|
37
|
+
return parts.join('/');
|
|
38
|
+
}
|
|
39
|
+
return path;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Compute a compressed BN254 G1 public key from a private key.
|
|
44
|
+
* @param privateKeyHex - Private key as 0x-prefixed hex string
|
|
45
|
+
* @returns Compressed G1 point (32 bytes with sign bit in MSB)
|
|
46
|
+
*/
|
|
47
|
+
export async function computeBlsPublicKeyCompressed(privateKeyHex: string): Promise<string> {
|
|
48
|
+
return await computeBn254G1PublicKeyCompressed(privateKeyHex);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function deriveEthAttester(
|
|
52
|
+
mnemonic: string,
|
|
53
|
+
baseAccountIndex: number,
|
|
54
|
+
addressIndex: number,
|
|
55
|
+
remoteSigner?: string,
|
|
56
|
+
): EthAccount | EthPrivateKey {
|
|
57
|
+
const acct = mnemonicToAccount(mnemonic, { accountIndex: baseAccountIndex, addressIndex });
|
|
58
|
+
return remoteSigner
|
|
59
|
+
? ({ address: acct.address as unknown as EthAddress, remoteSignerUrl: remoteSigner } as EthAccount)
|
|
60
|
+
: (('0x' + Buffer.from(acct.getHdKey().privateKey!).toString('hex')) as EthPrivateKey);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function buildValidatorEntries(input: BuildValidatorsInput) {
|
|
64
|
+
const {
|
|
65
|
+
validatorCount,
|
|
66
|
+
publisherCount = 0,
|
|
67
|
+
accountIndex,
|
|
68
|
+
baseAddressIndex,
|
|
69
|
+
mnemonic,
|
|
70
|
+
ikm,
|
|
71
|
+
blsPath,
|
|
72
|
+
blsOnly,
|
|
73
|
+
feeRecipient,
|
|
74
|
+
coinbase,
|
|
75
|
+
remoteSigner,
|
|
76
|
+
fundingAccount,
|
|
77
|
+
} = input;
|
|
78
|
+
|
|
79
|
+
const defaultBlsPath = 'm/12381/3600/0/0/0';
|
|
80
|
+
const summaries: ValidatorSummary[] = [];
|
|
81
|
+
|
|
82
|
+
const validators = await Promise.all(
|
|
83
|
+
Array.from({ length: validatorCount }, async (_unused, i) => {
|
|
84
|
+
const addressIndex = baseAddressIndex + i;
|
|
85
|
+
const basePath = blsPath ?? defaultBlsPath;
|
|
86
|
+
const perValidatorPath = withValidatorIndex(basePath, addressIndex);
|
|
87
|
+
|
|
88
|
+
const blsPrivKey = blsOnly || ikm || mnemonic ? deriveBlsPrivateKey(mnemonic, ikm, perValidatorPath) : undefined;
|
|
89
|
+
const blsPubCompressed = blsPrivKey ? await computeBlsPublicKeyCompressed(blsPrivKey) : undefined;
|
|
90
|
+
|
|
91
|
+
if (blsOnly) {
|
|
92
|
+
const attester = { bls: blsPrivKey! };
|
|
93
|
+
summaries.push({ attesterBls: blsPubCompressed });
|
|
94
|
+
return { attester, feeRecipient } as ValidatorKeyStore;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const ethAttester = deriveEthAttester(mnemonic, accountIndex, addressIndex, remoteSigner);
|
|
98
|
+
const attester = blsPrivKey ? { eth: ethAttester, bls: blsPrivKey } : ethAttester;
|
|
99
|
+
|
|
100
|
+
let publisherField: EthAccount | EthPrivateKey | (EthAccount | EthPrivateKey)[] | undefined;
|
|
101
|
+
const publisherAddresses: string[] = [];
|
|
102
|
+
if (publisherCount > 0) {
|
|
103
|
+
const publishersBaseIndex = baseAddressIndex + validatorCount + i * publisherCount;
|
|
104
|
+
const publisherAccounts = Array.from({ length: publisherCount }, (_unused2, j) => {
|
|
105
|
+
const publisherAddressIndex = publishersBaseIndex + j;
|
|
106
|
+
const pubAcct = mnemonicToAccount(mnemonic, {
|
|
107
|
+
accountIndex,
|
|
108
|
+
addressIndex: publisherAddressIndex,
|
|
109
|
+
});
|
|
110
|
+
publisherAddresses.push(pubAcct.address as unknown as string);
|
|
111
|
+
return remoteSigner
|
|
112
|
+
? ({ address: pubAcct.address as unknown as EthAddress, remoteSignerUrl: remoteSigner } as EthAccount)
|
|
113
|
+
: (('0x' + Buffer.from(pubAcct.getHdKey().privateKey!).toString('hex')) as EthPrivateKey);
|
|
114
|
+
});
|
|
115
|
+
publisherField = publisherCount === 1 ? publisherAccounts[0] : publisherAccounts;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const acct = mnemonicToAccount(mnemonic, {
|
|
119
|
+
accountIndex,
|
|
120
|
+
addressIndex,
|
|
121
|
+
});
|
|
122
|
+
const attesterEthAddress = acct.address as unknown as string;
|
|
123
|
+
summaries.push({
|
|
124
|
+
attesterEth: attesterEthAddress,
|
|
125
|
+
attesterBls: blsPubCompressed,
|
|
126
|
+
publisherEth: publisherAddresses.length > 0 ? publisherAddresses : undefined,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
attester,
|
|
131
|
+
...(publisherField !== undefined ? { publisher: publisherField } : {}),
|
|
132
|
+
feeRecipient,
|
|
133
|
+
coinbase,
|
|
134
|
+
fundingAccount,
|
|
135
|
+
} as ValidatorKeyStore;
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
return { validators, summaries };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export async function resolveKeystoreOutputPath(dataDir?: string, file?: string) {
|
|
143
|
+
const defaultDataDir = join(homedir(), '.aztec', 'keystore');
|
|
144
|
+
const resolvedDir = dataDir && dataDir.length > 0 ? dataDir : defaultDataDir;
|
|
145
|
+
let outputPath: string;
|
|
146
|
+
if (file && file.length > 0) {
|
|
147
|
+
outputPath = isAbsolute(file) ? file : join(resolvedDir, file);
|
|
148
|
+
} else {
|
|
149
|
+
let index = 1;
|
|
150
|
+
while (true) {
|
|
151
|
+
const candidate = join(resolvedDir, `key${index}.json`);
|
|
152
|
+
try {
|
|
153
|
+
await access(candidate, fsConstants.F_OK);
|
|
154
|
+
index += 1;
|
|
155
|
+
} catch {
|
|
156
|
+
outputPath = candidate;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return { resolvedDir, outputPath: outputPath! };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export async function writeKeystoreFile(path: string, keystore: unknown) {
|
|
165
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
166
|
+
await writeFile(path, JSON.stringify(keystore, null, 2), { encoding: 'utf-8' });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function logValidatorSummaries(log: LogFn, summaries: ValidatorSummary[]) {
|
|
170
|
+
const lines: string[] = [];
|
|
171
|
+
for (let i = 0; i < summaries.length; i++) {
|
|
172
|
+
const v = summaries[i];
|
|
173
|
+
lines.push(`acc${i + 1}:`);
|
|
174
|
+
lines.push(` attester:`);
|
|
175
|
+
if (v.attesterEth) {
|
|
176
|
+
lines.push(` eth: ${v.attesterEth}`);
|
|
177
|
+
}
|
|
178
|
+
if (v.attesterBls) {
|
|
179
|
+
lines.push(` bls: ${v.attesterBls}`);
|
|
180
|
+
}
|
|
181
|
+
if (v.publisherEth && v.publisherEth.length > 0) {
|
|
182
|
+
lines.push(` publisher:`);
|
|
183
|
+
for (const addr of v.publisherEth) {
|
|
184
|
+
lines.push(` - ${addr}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (lines.length > 0) {
|
|
189
|
+
log(lines.join('\n'));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function maybePrintJson(log: LogFn, jsonFlag: boolean | undefined, obj: unknown) {
|
|
194
|
+
if (jsonFlag) {
|
|
195
|
+
log(prettyPrintJSON(obj as Record<string, any>));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Writes a BN254 keystore file for a BN254 BLS private key.
|
|
201
|
+
* Returns the absolute path to the written file.
|
|
202
|
+
*
|
|
203
|
+
* @param outDir - Directory to write the keystore file to
|
|
204
|
+
* @param fileNameBase - Base name for the keystore file (will be sanitized)
|
|
205
|
+
* @param password - Password for encrypting the private key
|
|
206
|
+
* @param privateKeyHex - Private key as 0x-prefixed hex string (32 bytes)
|
|
207
|
+
* @param pubkeyHex - Public key as hex string
|
|
208
|
+
* @param derivationPath - BIP-44 style derivation path
|
|
209
|
+
* @returns Absolute path to the written keystore file
|
|
210
|
+
*/
|
|
211
|
+
export async function writeBn254BlsKeystore(
|
|
212
|
+
outDir: string,
|
|
213
|
+
fileNameBase: string,
|
|
214
|
+
password: string,
|
|
215
|
+
privateKeyHex: string,
|
|
216
|
+
pubkeyHex: string,
|
|
217
|
+
derivationPath: string,
|
|
218
|
+
): Promise<string> {
|
|
219
|
+
mkdirSync(outDir, { recursive: true });
|
|
220
|
+
|
|
221
|
+
const keystore = createBn254Keystore(password, privateKeyHex, pubkeyHex, derivationPath);
|
|
222
|
+
|
|
223
|
+
const safeBase = fileNameBase.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
224
|
+
const outPath = join(outDir, `keystore-${safeBase}.json`);
|
|
225
|
+
await writeFile(outPath, JSON.stringify(keystore, null, 2), { encoding: 'utf-8' });
|
|
226
|
+
return outPath;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Replace plaintext BLS keys in validators with { path, password } pointing to BN254 keystore files. */
|
|
230
|
+
export async function writeBlsBn254ToFile(
|
|
231
|
+
validators: ValidatorKeyStore[],
|
|
232
|
+
options: { outDir: string; password: string },
|
|
233
|
+
): Promise<void> {
|
|
234
|
+
for (let i = 0; i < validators.length; i++) {
|
|
235
|
+
const v = validators[i];
|
|
236
|
+
if (!v || typeof v !== 'object' || !('attester' in v)) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const att = (v as any).attester;
|
|
240
|
+
|
|
241
|
+
// Shapes: { bls: <hex> } or { eth: <ethAccount>, bls?: <hex> } or plain EthAccount
|
|
242
|
+
const blsKey: string | undefined = typeof att === 'object' && 'bls' in att ? (att as any).bls : undefined;
|
|
243
|
+
if (!blsKey || typeof blsKey !== 'string') {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const pub = await computeBlsPublicKeyCompressed(blsKey);
|
|
248
|
+
const path = 'm/12381/3600/0/0/0';
|
|
249
|
+
const fileBase = `${String(i + 1)}_${pub.slice(2, 18)}`;
|
|
250
|
+
const keystorePath = await writeBn254BlsKeystore(options.outDir, fileBase, options.password, blsKey, pub, path);
|
|
251
|
+
|
|
252
|
+
if (typeof att === 'object') {
|
|
253
|
+
(att as any).bls = { path: keystorePath, password: options.password };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** Writes an Ethereum JSON V3 keystore using ethers, returns absolute path */
|
|
259
|
+
export async function writeEthJsonV3Keystore(
|
|
260
|
+
outDir: string,
|
|
261
|
+
fileNameBase: string,
|
|
262
|
+
password: string,
|
|
263
|
+
privateKeyHex: string,
|
|
264
|
+
): Promise<string> {
|
|
265
|
+
const safeBase = fileNameBase.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
266
|
+
mkdirSync(outDir, { recursive: true });
|
|
267
|
+
const wallet = new Wallet(privateKeyHex);
|
|
268
|
+
const json = await wallet.encrypt(password);
|
|
269
|
+
const outPath = join(outDir, `keystore-eth-${safeBase}.json`);
|
|
270
|
+
await writeFile(outPath, json, { encoding: 'utf-8' });
|
|
271
|
+
return outPath;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Replace plaintext ETH keys in validators with { path, password } pointing to JSON V3 files. */
|
|
275
|
+
export async function writeEthJsonV3ToFile(
|
|
276
|
+
validators: ValidatorKeyStore[],
|
|
277
|
+
options: { outDir: string; password: string },
|
|
278
|
+
): Promise<void> {
|
|
279
|
+
const maybeEncryptEth = async (account: any, label: string) => {
|
|
280
|
+
if (typeof account === 'string' && account.startsWith('0x') && account.length === 66) {
|
|
281
|
+
const fileBase = `${label}_${account.slice(2, 10)}`;
|
|
282
|
+
const p = await writeEthJsonV3Keystore(options.outDir, fileBase, options.password, account);
|
|
283
|
+
return { path: p, password: options.password };
|
|
284
|
+
}
|
|
285
|
+
return account;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
for (let i = 0; i < validators.length; i++) {
|
|
289
|
+
const v = validators[i];
|
|
290
|
+
if (!v || typeof v !== 'object') {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// attester may be string (eth), object with eth, or remote signer
|
|
295
|
+
const att = (v as any).attester;
|
|
296
|
+
if (typeof att === 'string') {
|
|
297
|
+
(v as any).attester = await maybeEncryptEth(att, `attester_${i + 1}`);
|
|
298
|
+
} else if (att && typeof att === 'object' && 'eth' in att) {
|
|
299
|
+
(att as any).eth = await maybeEncryptEth((att as any).eth, `attester_${i + 1}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// publisher can be single or array
|
|
303
|
+
if ('publisher' in v) {
|
|
304
|
+
const pub = (v as any).publisher;
|
|
305
|
+
if (Array.isArray(pub)) {
|
|
306
|
+
const out: any[] = [];
|
|
307
|
+
for (let j = 0; j < pub.length; j++) {
|
|
308
|
+
out.push(await maybeEncryptEth(pub[j], `publisher_${i + 1}_${j + 1}`));
|
|
309
|
+
}
|
|
310
|
+
(v as any).publisher = out;
|
|
311
|
+
} else if (pub !== undefined) {
|
|
312
|
+
(v as any).publisher = await maybeEncryptEth(pub, `publisher_${i + 1}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Optional fundingAccount within validator
|
|
317
|
+
if ('fundingAccount' in v) {
|
|
318
|
+
(v as any).fundingAccount = await maybeEncryptEth((v as any).fundingAccount, `funding_${i + 1}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { DefaultL1ContractsConfig, type L1ContractsConfig } from '@aztec/ethereum';
|
|
2
|
-
import type {
|
|
2
|
+
import type { NetworkNames } from '@aztec/foundation/config';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import type { SharedNodeConfig } from '@aztec/node-lib/config';
|
|
5
5
|
import type { P2PConfig } from '@aztec/p2p/config';
|
|
6
6
|
import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
|
|
7
7
|
|
|
8
|
-
import path
|
|
8
|
+
import path from 'path';
|
|
9
9
|
|
|
10
10
|
import publicIncludeMetrics from '../../public_include_metric_prefixes.json' with { type: 'json' };
|
|
11
|
-
import { cachedFetch } from './cached_fetch.js';
|
|
12
11
|
import { enrichEthAddressVar, enrichVar } from './enrich_env.js';
|
|
13
12
|
|
|
14
13
|
const SNAPSHOTS_URL = 'https://aztec-labs-snapshots.com';
|
|
@@ -34,6 +33,8 @@ export type L2ChainConfig = L1ContractsConfig &
|
|
|
34
33
|
publicIncludeMetrics?: string[];
|
|
35
34
|
publicMetricsCollectorUrl?: string;
|
|
36
35
|
publicMetricsCollectFrom?: string[];
|
|
36
|
+
skipArchiverInitialSync?: boolean;
|
|
37
|
+
blobAllowEmptySources?: boolean;
|
|
37
38
|
|
|
38
39
|
// Setting the dbMapSize provides the default for every DB in the node.
|
|
39
40
|
// Then we explicitly override the sizes for the archiver and the larger trees.
|
|
@@ -45,6 +46,7 @@ export type L2ChainConfig = L1ContractsConfig &
|
|
|
45
46
|
|
|
46
47
|
// Control whether sentinel is enabled or not. Needed for slashing
|
|
47
48
|
sentinelEnabled: boolean;
|
|
49
|
+
disableTransactions: boolean;
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
const DefaultSlashConfig = {
|
|
@@ -96,6 +98,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
|
|
|
96
98
|
l1ChainId: 11155111,
|
|
97
99
|
testAccounts: false,
|
|
98
100
|
sponsoredFPC: false,
|
|
101
|
+
disableTransactions: true,
|
|
99
102
|
p2pEnabled: true,
|
|
100
103
|
p2pBootstrapNodes: [],
|
|
101
104
|
seqMinTxsPerBlock: 0,
|
|
@@ -109,6 +112,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
|
|
|
109
112
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
110
113
|
publicMetricsCollectFrom: ['sequencer'],
|
|
111
114
|
txPoolDeleteTxsAfterReorg: false,
|
|
115
|
+
blobAllowEmptySources: true,
|
|
112
116
|
|
|
113
117
|
/** How many seconds an L1 slot lasts. */
|
|
114
118
|
ethereumSlotDuration: 12,
|
|
@@ -148,11 +152,10 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
|
|
|
148
152
|
activationThreshold: 200_000n * 10n ** 18n,
|
|
149
153
|
localEjectionThreshold: 196_000n * 10n ** 18n,
|
|
150
154
|
|
|
151
|
-
governanceProposerRoundSize: 300,
|
|
152
|
-
governanceProposerQuorum: 151,
|
|
155
|
+
governanceProposerRoundSize: 300,
|
|
156
|
+
governanceProposerQuorum: 151,
|
|
153
157
|
|
|
154
158
|
// Node slashing config
|
|
155
|
-
// TODO TMNT-330
|
|
156
159
|
slashMinPenaltyPercentage: 0.5,
|
|
157
160
|
slashMaxPenaltyPercentage: 2.0,
|
|
158
161
|
slashInactivityTargetPercentage: 0.7,
|
|
@@ -177,6 +180,7 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
|
|
|
177
180
|
l1ChainId: 11155111,
|
|
178
181
|
testAccounts: false,
|
|
179
182
|
sponsoredFPC: true,
|
|
183
|
+
disableTransactions: false,
|
|
180
184
|
p2pEnabled: true,
|
|
181
185
|
p2pBootstrapNodes: [],
|
|
182
186
|
seqMinTxsPerBlock: 0,
|
|
@@ -231,9 +235,10 @@ export const testnetL2ChainConfig: L2ChainConfig = {
|
|
|
231
235
|
testAccounts: false,
|
|
232
236
|
sponsoredFPC: true,
|
|
233
237
|
p2pEnabled: true,
|
|
238
|
+
disableTransactions: true,
|
|
234
239
|
p2pBootstrapNodes: [],
|
|
235
240
|
seqMinTxsPerBlock: 0,
|
|
236
|
-
seqMaxTxsPerBlock:
|
|
241
|
+
seqMaxTxsPerBlock: 0,
|
|
237
242
|
realProofs: true,
|
|
238
243
|
snapshotsUrls: [`${SNAPSHOTS_URL}/testnet/`],
|
|
239
244
|
autoUpdate: 'config-and-version',
|
|
@@ -243,46 +248,80 @@ export const testnetL2ChainConfig: L2ChainConfig = {
|
|
|
243
248
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
244
249
|
publicMetricsCollectFrom: ['sequencer'],
|
|
245
250
|
txPoolDeleteTxsAfterReorg: true,
|
|
251
|
+
skipArchiverInitialSync: true,
|
|
252
|
+
blobAllowEmptySources: true,
|
|
246
253
|
|
|
247
|
-
// Deployment stuff
|
|
248
254
|
/** How many seconds an L1 slot lasts. */
|
|
249
255
|
ethereumSlotDuration: 12,
|
|
250
256
|
/** How many seconds an L2 slots lasts (must be multiple of ethereum slot duration). */
|
|
251
|
-
aztecSlotDuration:
|
|
257
|
+
aztecSlotDuration: 72,
|
|
252
258
|
/** How many L2 slots an epoch lasts. */
|
|
253
259
|
aztecEpochDuration: 32,
|
|
254
260
|
/** The target validator committee size. */
|
|
255
|
-
aztecTargetCommitteeSize:
|
|
261
|
+
aztecTargetCommitteeSize: 24,
|
|
256
262
|
/** The number of epochs to lag behind the current epoch for validator selection. */
|
|
257
263
|
lagInEpochs: 2,
|
|
258
264
|
/** The number of epochs after an epoch ends that proofs are still accepted. */
|
|
259
265
|
aztecProofSubmissionEpochs: 1,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
266
|
+
|
|
267
|
+
// This is a diff from mainnet: we have 2-strikes you're out, rather than 3 on mainnet.
|
|
268
|
+
localEjectionThreshold: 198_000n * 10n ** 18n,
|
|
269
|
+
/** How many sequencers must agree with a slash for it to be executed. */
|
|
270
|
+
slashingQuorum: 65,
|
|
271
|
+
slashingRoundSizeInEpochs: 4,
|
|
272
|
+
slashingExecutionDelayInRounds: 28,
|
|
273
|
+
slashingLifetimeInRounds: 34,
|
|
274
|
+
slashingVetoer: EthAddress.fromString('0xBbB4aF368d02827945748b28CD4b2D42e4A37480'),
|
|
275
|
+
slashingOffsetInRounds: 2,
|
|
276
|
+
|
|
277
|
+
slashingDisableDuration: 259_200, // 3 days
|
|
278
|
+
slasherFlavor: 'tally',
|
|
279
|
+
|
|
280
|
+
slashAmountSmall: 2_000n * 10n ** 18n,
|
|
281
|
+
slashAmountMedium: 2_000n * 10n ** 18n,
|
|
282
|
+
slashAmountLarge: 2_000n * 10n ** 18n,
|
|
283
|
+
|
|
270
284
|
/** The mana target for the rollup */
|
|
271
|
-
manaTarget:
|
|
285
|
+
manaTarget: 0n,
|
|
286
|
+
|
|
272
287
|
/** The proving cost per mana */
|
|
273
|
-
provingCostPerMana:
|
|
274
|
-
/** Exit delay for stakers */
|
|
275
|
-
exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
|
|
288
|
+
provingCostPerMana: 0n,
|
|
276
289
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
290
|
+
exitDelaySeconds: 4 * 24 * 60 * 60, // 4 days
|
|
291
|
+
|
|
292
|
+
activationThreshold: 200_000n * 10n ** 18n,
|
|
293
|
+
ejectionThreshold: 100_000n * 10n ** 18n,
|
|
294
|
+
|
|
295
|
+
governanceProposerRoundSize: 300,
|
|
296
|
+
governanceProposerQuorum: 151,
|
|
297
|
+
|
|
298
|
+
// Node slashing config
|
|
299
|
+
slashInactivityTargetPercentage: 0.8,
|
|
300
|
+
slashInactivityConsecutiveEpochThreshold: 2,
|
|
301
|
+
slashInactivityPenalty: 2_000n * 10n ** 18n,
|
|
302
|
+
slashPrunePenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for prune offenses right now
|
|
303
|
+
slashDataWithholdingPenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for data withholding offenses right now
|
|
304
|
+
slashProposeInvalidAttestationsPenalty: 2_000n * 10n ** 18n,
|
|
305
|
+
slashAttestDescendantOfInvalidPenalty: 2_000n * 10n ** 18n,
|
|
306
|
+
slashUnknownPenalty: 2_000n * 10n ** 18n,
|
|
307
|
+
slashBroadcastedInvalidBlockPenalty: 2_000n * 10n ** 18n, // 10_000n * 10n ** 18n, Disabled for now until further testing
|
|
308
|
+
slashGracePeriodL2Slots: 1_200, // One day from deployment
|
|
309
|
+
slashOffenseExpirationRounds: 8,
|
|
310
|
+
|
|
311
|
+
slashMinPenaltyPercentage: 0.5,
|
|
312
|
+
slashMaxPenaltyPercentage: 2.0,
|
|
313
|
+
slashMaxPayloadSize: 50,
|
|
314
|
+
slashExecuteRoundsLookBack: 4,
|
|
315
|
+
|
|
316
|
+
sentinelEnabled: true,
|
|
281
317
|
|
|
282
318
|
...DefaultNetworkDBMapSizeConfig,
|
|
283
319
|
};
|
|
284
320
|
|
|
285
|
-
export const
|
|
321
|
+
export const mainnetL2ChainConfig: L2ChainConfig = {
|
|
322
|
+
txPoolDeleteTxsAfterReorg: true,
|
|
323
|
+
disableTransactions: true,
|
|
324
|
+
|
|
286
325
|
l1ChainId: 1,
|
|
287
326
|
testAccounts: false,
|
|
288
327
|
sponsoredFPC: false,
|
|
@@ -291,14 +330,13 @@ export const ignitionL2ChainConfig: L2ChainConfig = {
|
|
|
291
330
|
seqMinTxsPerBlock: 0,
|
|
292
331
|
seqMaxTxsPerBlock: 0,
|
|
293
332
|
realProofs: true,
|
|
294
|
-
snapshotsUrls: [`${SNAPSHOTS_URL}/
|
|
333
|
+
snapshotsUrls: [`${SNAPSHOTS_URL}/mainnet/`],
|
|
295
334
|
autoUpdate: 'notify',
|
|
296
|
-
autoUpdateUrl: 'https://storage.googleapis.com/aztec-
|
|
335
|
+
autoUpdateUrl: 'https://storage.googleapis.com/aztec-mainnet/auto-update/mainnet.json',
|
|
297
336
|
maxTxPoolSize: 100_000_000, // 100MB
|
|
298
337
|
publicIncludeMetrics,
|
|
299
338
|
publicMetricsCollectorUrl: 'https://telemetry.alpha-testnet.aztec-labs.com/v1/metrics',
|
|
300
339
|
publicMetricsCollectFrom: ['sequencer'],
|
|
301
|
-
txPoolDeleteTxsAfterReorg: false,
|
|
302
340
|
|
|
303
341
|
/** How many seconds an L1 slot lasts. */
|
|
304
342
|
ethereumSlotDuration: 12,
|
|
@@ -312,73 +350,61 @@ export const ignitionL2ChainConfig: L2ChainConfig = {
|
|
|
312
350
|
lagInEpochs: 2,
|
|
313
351
|
/** The number of epochs after an epoch ends that proofs are still accepted. */
|
|
314
352
|
aztecProofSubmissionEpochs: 1,
|
|
353
|
+
|
|
354
|
+
localEjectionThreshold: 196_000n * 10n ** 18n,
|
|
315
355
|
/** How many sequencers must agree with a slash for it to be executed. */
|
|
316
356
|
slashingQuorum: 65,
|
|
317
|
-
|
|
318
357
|
slashingRoundSizeInEpochs: 4,
|
|
319
|
-
slashingLifetimeInRounds: 40,
|
|
320
358
|
slashingExecutionDelayInRounds: 28,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
slashAmountMedium: 10_000n * 10n ** 18n,
|
|
324
|
-
slashAmountLarge: 50_000n * 10n ** 18n,
|
|
359
|
+
slashingLifetimeInRounds: 34,
|
|
360
|
+
slashingVetoer: EthAddress.ZERO, // TODO TMNT-329
|
|
325
361
|
slashingOffsetInRounds: 2,
|
|
362
|
+
|
|
363
|
+
slashingDisableDuration: 259_200, // 3 days
|
|
326
364
|
slasherFlavor: 'tally',
|
|
327
|
-
|
|
365
|
+
|
|
366
|
+
slashAmountSmall: 2_000n * 10n ** 18n,
|
|
367
|
+
slashAmountMedium: 2_000n * 10n ** 18n,
|
|
368
|
+
slashAmountLarge: 2_000n * 10n ** 18n,
|
|
328
369
|
|
|
329
370
|
/** The mana target for the rollup */
|
|
330
371
|
manaTarget: 0n,
|
|
331
372
|
|
|
332
|
-
exitDelaySeconds: 5 * 24 * 60 * 60,
|
|
333
|
-
|
|
334
373
|
/** The proving cost per mana */
|
|
335
374
|
provingCostPerMana: 0n,
|
|
336
375
|
|
|
337
|
-
|
|
376
|
+
exitDelaySeconds: 4 * 24 * 60 * 60, // 4 days
|
|
377
|
+
|
|
338
378
|
activationThreshold: 200_000n * 10n ** 18n,
|
|
339
|
-
|
|
379
|
+
ejectionThreshold: 100_000n * 10n ** 18n,
|
|
340
380
|
|
|
341
|
-
governanceProposerRoundSize:
|
|
342
|
-
governanceProposerQuorum:
|
|
381
|
+
governanceProposerRoundSize: 1000,
|
|
382
|
+
governanceProposerQuorum: 600,
|
|
343
383
|
|
|
344
384
|
// Node slashing config
|
|
345
|
-
|
|
346
|
-
slashMinPenaltyPercentage: 0.5,
|
|
347
|
-
slashMaxPenaltyPercentage: 2.0,
|
|
348
|
-
slashInactivityTargetPercentage: 0.7,
|
|
385
|
+
slashInactivityTargetPercentage: 0.8,
|
|
349
386
|
slashInactivityConsecutiveEpochThreshold: 2,
|
|
350
387
|
slashInactivityPenalty: 2_000n * 10n ** 18n,
|
|
351
388
|
slashPrunePenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for prune offenses right now
|
|
352
389
|
slashDataWithholdingPenalty: 0n, // 2_000n * 10n ** 18n, We disable slashing for data withholding offenses right now
|
|
353
|
-
slashProposeInvalidAttestationsPenalty:
|
|
354
|
-
slashAttestDescendantOfInvalidPenalty:
|
|
390
|
+
slashProposeInvalidAttestationsPenalty: 2_000n * 10n ** 18n,
|
|
391
|
+
slashAttestDescendantOfInvalidPenalty: 2_000n * 10n ** 18n,
|
|
355
392
|
slashUnknownPenalty: 2_000n * 10n ** 18n,
|
|
356
|
-
slashBroadcastedInvalidBlockPenalty:
|
|
357
|
-
|
|
358
|
-
slashGracePeriodL2Slots: 32 * 4, // One round from genesis
|
|
393
|
+
slashBroadcastedInvalidBlockPenalty: 2_000n * 10n ** 18n, // 10_000n * 10n ** 18n, Disabled for now until further testing
|
|
394
|
+
slashGracePeriodL2Slots: 1_200, // One day from deployment
|
|
359
395
|
slashOffenseExpirationRounds: 8,
|
|
360
|
-
|
|
396
|
+
|
|
397
|
+
slashMinPenaltyPercentage: 0.5,
|
|
398
|
+
slashMaxPenaltyPercentage: 2.0,
|
|
399
|
+
slashMaxPayloadSize: 50,
|
|
361
400
|
slashExecuteRoundsLookBack: 4,
|
|
362
401
|
|
|
402
|
+
sentinelEnabled: true,
|
|
403
|
+
|
|
363
404
|
...DefaultNetworkDBMapSizeConfig,
|
|
364
405
|
};
|
|
365
406
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
export async function getBootnodes(networkName: NetworkNames, cacheDir?: string) {
|
|
369
|
-
const url = `http://static.aztec.network/${networkName}/bootnodes.json`;
|
|
370
|
-
const data = await cachedFetch(url, {
|
|
371
|
-
cacheDurationMs: BOOTNODE_CACHE_DURATION_MS,
|
|
372
|
-
cacheFile: cacheDir ? join(cacheDir, networkName, 'bootnodes.json') : undefined,
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
return data?.bootnodes;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export async function getL2ChainConfig(
|
|
379
|
-
networkName: NetworkNames,
|
|
380
|
-
cacheDir?: string,
|
|
381
|
-
): Promise<L2ChainConfig | undefined> {
|
|
407
|
+
export function getL2ChainConfig(networkName: NetworkNames): L2ChainConfig | undefined {
|
|
382
408
|
let config: L2ChainConfig | undefined;
|
|
383
409
|
if (networkName === 'staging-public') {
|
|
384
410
|
config = { ...stagingPublicL2ChainConfig };
|
|
@@ -386,16 +412,8 @@ export async function getL2ChainConfig(
|
|
|
386
412
|
config = { ...testnetL2ChainConfig };
|
|
387
413
|
} else if (networkName === 'staging-ignition') {
|
|
388
414
|
config = { ...stagingIgnitionL2ChainConfig };
|
|
389
|
-
} else if (networkName === '
|
|
390
|
-
config = { ...
|
|
391
|
-
}
|
|
392
|
-
if (!config) {
|
|
393
|
-
return undefined;
|
|
394
|
-
}
|
|
395
|
-
// If the bootnodes are not set, get them from the network
|
|
396
|
-
const bootnodeKey: EnvVar = 'BOOTSTRAP_NODES';
|
|
397
|
-
if (!process.env[bootnodeKey]) {
|
|
398
|
-
config.p2pBootstrapNodes = await getBootnodes(networkName, cacheDir);
|
|
415
|
+
} else if (networkName === 'mainnet') {
|
|
416
|
+
config = { ...mainnetL2ChainConfig };
|
|
399
417
|
}
|
|
400
418
|
return config;
|
|
401
419
|
}
|
|
@@ -404,14 +422,13 @@ function getDefaultDataDir(networkName: NetworkNames): string {
|
|
|
404
422
|
return path.join(process.env.HOME || '~', '.aztec', networkName, 'data');
|
|
405
423
|
}
|
|
406
424
|
|
|
407
|
-
export
|
|
425
|
+
export function enrichEnvironmentWithChainConfig(networkName: NetworkNames) {
|
|
408
426
|
if (networkName === 'local') {
|
|
409
427
|
return;
|
|
410
428
|
}
|
|
411
429
|
|
|
412
430
|
enrichVar('DATA_DIRECTORY', getDefaultDataDir(networkName));
|
|
413
|
-
const
|
|
414
|
-
const config = await getL2ChainConfig(networkName, cacheDir);
|
|
431
|
+
const config = getL2ChainConfig(networkName);
|
|
415
432
|
|
|
416
433
|
if (!config) {
|
|
417
434
|
throw new Error(`Unknown network name: ${networkName}`);
|
|
@@ -435,6 +452,14 @@ export async function enrichEnvironmentWithChainConfig(networkName: NetworkNames
|
|
|
435
452
|
enrichVar('NULLIFIER_TREE_MAP_SIZE_KB', config.nullifierTreeMapSizeKb.toString());
|
|
436
453
|
enrichVar('PUBLIC_DATA_TREE_MAP_SIZE_KB', config.publicDataTreeMapSizeKb.toString());
|
|
437
454
|
|
|
455
|
+
if (config.skipArchiverInitialSync !== undefined) {
|
|
456
|
+
enrichVar('SKIP_ARCHIVER_INITIAL_SYNC', config.skipArchiverInitialSync.toString());
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (config.blobAllowEmptySources !== undefined) {
|
|
460
|
+
enrichVar('BLOB_ALLOW_EMPTY_SOURCES', config.blobAllowEmptySources.toString());
|
|
461
|
+
}
|
|
462
|
+
|
|
438
463
|
if (config.autoUpdate) {
|
|
439
464
|
enrichVar('AUTO_UPDATE', config.autoUpdate?.toString());
|
|
440
465
|
}
|
|
@@ -496,4 +521,5 @@ export async function enrichEnvironmentWithChainConfig(networkName: NetworkNames
|
|
|
496
521
|
enrichVar('SLASH_MAX_PAYLOAD_SIZE', config.slashMaxPayloadSize.toString());
|
|
497
522
|
|
|
498
523
|
enrichVar('SENTINEL_ENABLED', config.sentinelEnabled.toString());
|
|
524
|
+
enrichVar('TRANSACTIONS_DISABLED', config.disableTransactions.toString());
|
|
499
525
|
}
|