@aztec/aztec 0.0.1-commit.b9865e97 → 0.0.1-commit.be03c316
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/bin/index.js +2 -0
- package/dest/cli/aztec_start_action.d.ts +1 -1
- package/dest/cli/aztec_start_action.d.ts.map +1 -1
- package/dest/cli/aztec_start_action.js +6 -27
- package/dest/cli/aztec_start_options.js +1 -1
- package/dest/cli/cmds/compile.d.ts +1 -1
- package/dest/cli/cmds/compile.d.ts.map +1 -1
- package/dest/cli/cmds/compile.js +25 -17
- package/dest/cli/cmds/prover.d.ts +4 -0
- package/dest/cli/cmds/prover.d.ts.map +1 -0
- package/dest/cli/cmds/prover.js +24 -0
- package/dest/cli/cmds/standby.d.ts +28 -2
- package/dest/cli/cmds/standby.d.ts.map +1 -1
- package/dest/cli/cmds/standby.js +45 -2
- package/dest/cli/cmds/start_bot.d.ts +1 -1
- package/dest/cli/cmds/start_bot.d.ts.map +1 -1
- package/dest/cli/cmds/start_bot.js +5 -1
- package/dest/cli/cmds/start_node.d.ts +1 -1
- package/dest/cli/cmds/start_node.d.ts.map +1 -1
- package/dest/cli/cmds/start_node.js +14 -23
- package/dest/cli/cmds/utils/artifacts.d.ts +6 -1
- package/dest/cli/cmds/utils/artifacts.d.ts.map +1 -1
- package/dest/cli/util.d.ts +10 -5
- package/dest/cli/util.d.ts.map +1 -1
- package/dest/cli/util.js +20 -49
- package/dest/examples/token.js +3 -3
- package/dest/local-network/local-network.d.ts +6 -5
- package/dest/local-network/local-network.d.ts.map +1 -1
- package/dest/local-network/local-network.js +33 -76
- package/dest/testing/cheat_codes.d.ts +16 -23
- package/dest/testing/cheat_codes.d.ts.map +1 -1
- package/dest/testing/cheat_codes.js +20 -82
- package/dest/testing/epoch_test_settler.d.ts +2 -2
- package/dest/testing/epoch_test_settler.d.ts.map +1 -1
- package/dest/testing/epoch_test_settler.js +5 -26
- package/dest/testing/index.d.ts +2 -2
- package/dest/testing/index.d.ts.map +1 -1
- package/dest/testing/index.js +1 -1
- package/dest/testing/local-network.d.ts +51 -0
- package/dest/testing/local-network.d.ts.map +1 -0
- package/dest/testing/local-network.js +60 -0
- package/dest/testing/token_allowed_setup.d.ts +9 -4
- package/dest/testing/token_allowed_setup.d.ts.map +1 -1
- package/dest/testing/token_allowed_setup.js +12 -8
- package/package.json +34 -34
- package/scripts/templates/counter/contract/src/main.nr +4 -4
- package/src/bin/index.ts +2 -0
- package/src/cli/aztec_start_action.ts +3 -14
- package/src/cli/aztec_start_options.ts +1 -1
- package/src/cli/cmds/compile.ts +29 -16
- package/src/cli/cmds/prover.ts +42 -0
- package/src/cli/cmds/standby.ts +55 -3
- package/src/cli/cmds/start_bot.ts +6 -1
- package/src/cli/cmds/start_node.ts +17 -23
- package/src/cli/cmds/utils/artifacts.ts +5 -0
- package/src/cli/util.ts +21 -62
- package/src/examples/token.ts +11 -3
- package/src/local-network/local-network.ts +40 -88
- package/src/testing/cheat_codes.ts +19 -103
- package/src/testing/epoch_test_settler.ts +8 -30
- package/src/testing/index.ts +1 -1
- package/src/testing/local-network.ts +97 -0
- package/src/testing/token_allowed_setup.ts +15 -8
- package/dest/testing/anvil_test_watcher.d.ts +0 -54
- package/dest/testing/anvil_test_watcher.d.ts.map +0 -1
- package/dest/testing/anvil_test_watcher.js +0 -235
- package/src/testing/anvil_test_watcher.ts +0 -273
package/src/cli/cmds/standby.ts
CHANGED
|
@@ -6,13 +6,16 @@ import type { GenesisStateConfig } from '@aztec/ethereum/config';
|
|
|
6
6
|
import { RegistryContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
7
7
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
8
8
|
import { startHttpRpcServer } from '@aztec/foundation/json-rpc/server';
|
|
9
|
-
import type
|
|
9
|
+
import { type LogFn, createLogger } from '@aztec/foundation/log';
|
|
10
10
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
11
11
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
|
+
import type { VersionCheck } from '@aztec/stdlib/update-checker';
|
|
12
13
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
13
14
|
|
|
14
15
|
import Koa from 'koa';
|
|
15
16
|
|
|
17
|
+
import { isShuttingDown, softShutdown } from '../util.js';
|
|
18
|
+
|
|
16
19
|
const ROLLUP_POLL_INTERVAL_S = 60;
|
|
17
20
|
|
|
18
21
|
/**
|
|
@@ -23,7 +26,7 @@ const ROLLUP_POLL_INTERVAL_S = 60;
|
|
|
23
26
|
export async function computeExpectedGenesisRoot(config: GenesisStateConfig, userLog: LogFn) {
|
|
24
27
|
const testAccounts = config.testAccounts ? (await getInitialTestAccountsData()).map(a => a.address) : [];
|
|
25
28
|
const sponsoredFPCAccounts = config.sponsoredFPC ? [await getSponsoredFPCAddress()] : [];
|
|
26
|
-
const prefundAddresses = (config.prefundAddresses ?? []).map(a => AztecAddress.
|
|
29
|
+
const prefundAddresses = (config.prefundAddresses ?? []).map(a => AztecAddress.fromStringUnsafe(a));
|
|
27
30
|
const initialFundedAccounts = testAccounts.concat(sponsoredFPCAccounts).concat(prefundAddresses);
|
|
28
31
|
|
|
29
32
|
userLog(`Initial funded accounts: ${initialFundedAccounts.map(a => a.toString()).join(', ')}`);
|
|
@@ -35,7 +38,12 @@ export async function computeExpectedGenesisRoot(config: GenesisStateConfig, use
|
|
|
35
38
|
return { genesisArchiveRoot, genesis };
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Compares the rollup's on-chain protocol constants (genesis archive root, VK tree root, protocol
|
|
43
|
+
* contracts hash) against the node's expected local values. Returns a list of human-readable mismatch
|
|
44
|
+
* descriptions, empty if the rollup is compatible.
|
|
45
|
+
*/
|
|
46
|
+
export async function checkRollupCompatibility(
|
|
39
47
|
rollup: RollupContract,
|
|
40
48
|
expected: { genesisArchiveRoot: Fr; vkTreeRoot: Fr; protocolContractsHash: Fr },
|
|
41
49
|
): Promise<string[]> {
|
|
@@ -130,3 +138,47 @@ export async function waitForCompatibleRollup(
|
|
|
130
138
|
await new Promise<void>((resolve, reject) => standbyServer.close(err => (err ? reject(err) : resolve())));
|
|
131
139
|
}
|
|
132
140
|
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Polls the canonical rollup's protocol constants every 10 minutes and soft-shuts-down the node once they
|
|
144
|
+
* diverge from the node's expected local values (i.e. an incompatible rollup has become canonical on L1).
|
|
145
|
+
* The HTTP health server is left running so K8s probes keep passing on the wound-down pod. This is the
|
|
146
|
+
* inverse of {@link waitForCompatibleRollup}; it should only be set up for nodes following the canonical
|
|
147
|
+
* rollup. Reuses the {@link checkRollupCompatibility} diff and the generic VersionChecker poll primitive.
|
|
148
|
+
*/
|
|
149
|
+
export async function setupAutoShutdown(
|
|
150
|
+
config: { l1RpcUrls: string[]; l1ChainId: number },
|
|
151
|
+
registryAddress: EthAddress,
|
|
152
|
+
rollupVersion: number | 'canonical',
|
|
153
|
+
expected: { genesisArchiveRoot: Fr; vkTreeRoot: Fr; protocolContractsHash: Fr },
|
|
154
|
+
signalHandlers: Array<() => Promise<void>>,
|
|
155
|
+
): Promise<void> {
|
|
156
|
+
const { VersionChecker } = await import('@aztec/stdlib/update-checker');
|
|
157
|
+
|
|
158
|
+
const logger = createLogger('auto_shutdown');
|
|
159
|
+
const publicClient = getPublicClient(config);
|
|
160
|
+
const registry = new RegistryContract(publicClient, registryAddress);
|
|
161
|
+
|
|
162
|
+
const check: VersionCheck = {
|
|
163
|
+
name: 'rollup',
|
|
164
|
+
currentVersion: 'compatible',
|
|
165
|
+
getLatestVersion: async () => {
|
|
166
|
+
const rollupAddress = await registry.getRollupAddress(rollupVersion);
|
|
167
|
+
const rollup = new RollupContract(publicClient, rollupAddress.toString());
|
|
168
|
+
const mismatches = await checkRollupCompatibility(rollup, expected);
|
|
169
|
+
return mismatches.length === 0 ? 'compatible' : `incompatible: ${mismatches.join('; ')}`;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const checker = new VersionChecker([check], 600_000, logger);
|
|
174
|
+
checker.on('newVersion', ({ latestVersion }) => {
|
|
175
|
+
if (isShuttingDown()) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
logger.warn('Canonical rollup is no longer compatible; auto-shutting down node', { latestVersion });
|
|
179
|
+
// softShutdown never rejects (it awaits handlers via allSettled); fire-and-forget from the listener.
|
|
180
|
+
void softShutdown(logger.info.bind(logger), signalHandlers);
|
|
181
|
+
});
|
|
182
|
+
checker.start();
|
|
183
|
+
signalHandlers.push(() => checker.stop());
|
|
184
|
+
}
|
|
@@ -56,6 +56,11 @@ export async function addBot(
|
|
|
56
56
|
const config = extractRelevantOptions<BotConfig>(options, botConfigMappings, 'bot');
|
|
57
57
|
userLog?.(`Starting bot with config ${stringifyConfig(config)}`);
|
|
58
58
|
|
|
59
|
+
// The bot wallet's embedded PXE syncs to this tip (see start_bot.ts/start_node.ts which build the wallet from the
|
|
60
|
+
// same options). L1-to-L2 readiness checks must be evaluated at this tip rather than at 'latest', or the bot can
|
|
61
|
+
// consider a message ready while the PXE simulation anchors to an older block that cannot prove its membership yet.
|
|
62
|
+
const { syncChainTip } = extractRelevantOptions<PXEConfig & CliPXEOptions>(options, allPxeConfigMappings, 'pxe');
|
|
63
|
+
|
|
59
64
|
const db = await (config.dataDirectory
|
|
60
65
|
? createStore('bot', BotStore.SCHEMA_VERSION, config)
|
|
61
66
|
: openTmpStore('bot', true, config.dataStoreMapSizeKb));
|
|
@@ -63,7 +68,7 @@ export async function addBot(
|
|
|
63
68
|
const store = new BotStore(db);
|
|
64
69
|
await store.cleanupOldClaims();
|
|
65
70
|
|
|
66
|
-
const botRunner = new BotRunner(config, wallet, aztecNode, telemetry, aztecNodeAdmin, store);
|
|
71
|
+
const botRunner = new BotRunner(config, wallet, aztecNode, telemetry, aztecNodeAdmin, store, syncChainTip);
|
|
67
72
|
if (!config.noStart) {
|
|
68
73
|
void botRunner.start(); // Do not block since bot setup takes time
|
|
69
74
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AztecNodeConfig,
|
|
3
|
+
aztecNodeConfigMappings,
|
|
4
|
+
getConfigEnvVars,
|
|
5
|
+
registerAztecNodeRpcHandlers,
|
|
6
|
+
} from '@aztec/aztec-node';
|
|
2
7
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
8
|
import { getL1Config } from '@aztec/cli/config';
|
|
4
|
-
import { getPublicClient } from '@aztec/ethereum/client';
|
|
5
9
|
import { getGenesisStateConfigEnvVars } from '@aztec/ethereum/config';
|
|
6
10
|
import { type NetworkNames, SecretValue } from '@aztec/foundation/config';
|
|
7
11
|
import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
|
|
@@ -15,8 +19,7 @@ import {
|
|
|
15
19
|
proverBrokerBackoff,
|
|
16
20
|
} from '@aztec/prover-client/broker';
|
|
17
21
|
import { type CliPXEOptions, type PXEConfig, allPxeConfigMappings } from '@aztec/pxe/config';
|
|
18
|
-
import {
|
|
19
|
-
import { P2PApiSchema, ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
|
|
22
|
+
import { ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
|
|
20
23
|
import {
|
|
21
24
|
type TelemetryClientConfig,
|
|
22
25
|
initTelemetryClient,
|
|
@@ -26,14 +29,9 @@ import {
|
|
|
26
29
|
import { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
27
30
|
|
|
28
31
|
import { createAztecNode } from '../../local-network/index.js';
|
|
29
|
-
import {
|
|
30
|
-
extractNamespacedOptions,
|
|
31
|
-
extractRelevantOptions,
|
|
32
|
-
preloadCrsDataForVerifying,
|
|
33
|
-
setupVersionChecker,
|
|
34
|
-
} from '../util.js';
|
|
32
|
+
import { extractNamespacedOptions, extractRelevantOptions, preloadCrsDataForVerifying } from '../util.js';
|
|
35
33
|
import { getVersions } from '../versioning.js';
|
|
36
|
-
import { computeExpectedGenesisRoot, waitForCompatibleRollup } from './standby.js';
|
|
34
|
+
import { computeExpectedGenesisRoot, setupAutoShutdown, waitForCompatibleRollup } from './standby.js';
|
|
37
35
|
import { startProverBroker } from './start_prover_broker.js';
|
|
38
36
|
|
|
39
37
|
export async function startNode(
|
|
@@ -156,15 +154,12 @@ export async function startNode(
|
|
|
156
154
|
// Create and start Aztec Node
|
|
157
155
|
const node = await createAztecNode(nodeConfig, { telemetry, proverBroker: broker }, { genesis });
|
|
158
156
|
|
|
159
|
-
|
|
160
|
-
services.node = [node, AztecNodeApiSchema];
|
|
161
|
-
services.p2p = [node.getP2P(), P2PApiSchema];
|
|
162
|
-
adminServices.nodeAdmin = [node, AztecNodeAdminApiSchema];
|
|
157
|
+
registerAztecNodeRpcHandlers(node, services, adminServices, { debug: options.nodeDebug });
|
|
163
158
|
|
|
164
159
|
// Register prover-node services if the prover node subsystem is running
|
|
165
160
|
const proverNode = node.getProverNode();
|
|
166
161
|
if (proverNode) {
|
|
167
|
-
|
|
162
|
+
adminServices.prover = [proverNode, ProverNodeApiSchema];
|
|
168
163
|
if (!nodeConfig.proverBrokerUrl) {
|
|
169
164
|
services.provingJobSource = [proverNode.getProver().getProvingJobSource(), ProvingJobConsumerSchema];
|
|
170
165
|
}
|
|
@@ -183,15 +178,14 @@ export async function startNode(
|
|
|
183
178
|
await addBot(options, signalHandlers, services, wallet, node, telemetry, undefined);
|
|
184
179
|
}
|
|
185
180
|
|
|
186
|
-
if (nodeConfig.
|
|
187
|
-
const cacheDir = process.env.DATA_DIRECTORY ? `${process.env.DATA_DIRECTORY}/cache` : undefined;
|
|
181
|
+
if (nodeConfig.enableAutoShutdown && networkName !== 'local' && followsCanonicalRollup) {
|
|
188
182
|
try {
|
|
189
|
-
await
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
183
|
+
await setupAutoShutdown(
|
|
184
|
+
nodeConfig,
|
|
185
|
+
nodeConfig.registryAddress,
|
|
186
|
+
(nodeConfig.rollupVersion as number | 'canonical') ?? 'canonical',
|
|
187
|
+
{ genesisArchiveRoot, vkTreeRoot: getVKTreeRoot(), protocolContractsHash },
|
|
193
188
|
signalHandlers,
|
|
194
|
-
cacheDir,
|
|
195
189
|
);
|
|
196
190
|
} catch {
|
|
197
191
|
/* no-op */
|
|
@@ -6,6 +6,11 @@ export interface CompiledArtifact {
|
|
|
6
6
|
file_map: unknown;
|
|
7
7
|
functions: ContractFunction[];
|
|
8
8
|
bytecode?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Set to true by the AVM transpiler (invoked via `bb aztec_process`) once the contract has been transpiled and its
|
|
11
|
+
* verification keys generated. Absent on raw `nargo compile` output, hence optional.
|
|
12
|
+
*/
|
|
13
|
+
transpiled?: boolean;
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
export interface ContractFunction {
|
package/src/cli/util.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import type { AztecNodeConfig } from '@aztec/aztec-node';
|
|
2
2
|
import type { AccountManager } from '@aztec/aztec.js/wallet';
|
|
3
|
-
import {
|
|
4
|
-
import { RegistryContract } from '@aztec/ethereum/contracts';
|
|
5
|
-
import type { ViemClient } from '@aztec/ethereum/types';
|
|
6
|
-
import type { ConfigMappingsType, NetworkNames } from '@aztec/foundation/config';
|
|
3
|
+
import type { ConfigMappingsType } from '@aztec/foundation/config';
|
|
7
4
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
8
|
-
import {
|
|
5
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
9
6
|
import type { ProverConfig } from '@aztec/stdlib/interfaces/server';
|
|
10
|
-
import { type VersionCheck, getPackageVersion } from '@aztec/stdlib/update-checker';
|
|
11
7
|
import type { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
12
8
|
|
|
13
9
|
import chalk from 'chalk';
|
|
14
10
|
import type { Command } from 'commander';
|
|
15
|
-
import type { Hex } from 'viem';
|
|
16
11
|
|
|
17
12
|
import { type AztecStartOption, aztecStartOptions } from './aztec_start_options.js';
|
|
18
13
|
|
|
@@ -51,6 +46,24 @@ export function isShuttingDown(): boolean {
|
|
|
51
46
|
return shutdownPromise !== undefined;
|
|
52
47
|
}
|
|
53
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Stops the node's subsystems (via the registered signal handlers) without exiting the process, leaving
|
|
51
|
+
* the HTTP health server listening so K8s liveness/readiness probes keep passing. Unlike {@link shutdown}
|
|
52
|
+
* this deliberately does not latch `shutdownPromise` or call `process.exit`; instead it re-arms
|
|
53
|
+
* SIGTERM/SIGINT so a later K8s pod deletion still terminates the wound-down pod with a clean exit.
|
|
54
|
+
*/
|
|
55
|
+
export async function softShutdown(logFn: LogFn, signalHandlers: Array<() => Promise<void>>): Promise<void> {
|
|
56
|
+
logFn('Canonical rollup upgrade detected: stopping subsystems, health server stays up.', {
|
|
57
|
+
exitCode: ExitCode.ROLLUP_UPGRADE,
|
|
58
|
+
});
|
|
59
|
+
await Promise.allSettled(signalHandlers.map(fn => fn()));
|
|
60
|
+
for (const sig of ['SIGTERM', 'SIGINT'] as const) {
|
|
61
|
+
process.removeAllListeners(sig);
|
|
62
|
+
process.once(sig, () => process.exit(ExitCode.ROLLUP_UPGRADE));
|
|
63
|
+
}
|
|
64
|
+
logFn('Subsystems stopped due to rollup upgrade. Health server remains active.');
|
|
65
|
+
}
|
|
66
|
+
|
|
54
67
|
export const installSignalHandlers = (logFn: LogFn, cb?: Array<() => Promise<void>>) => {
|
|
55
68
|
const signals = [
|
|
56
69
|
['SIGINT', ExitCode.SIGINT],
|
|
@@ -81,7 +94,7 @@ export async function createAccountLogs(accountManagers: AccountManager[], walle
|
|
|
81
94
|
if (registeredAccounts.find(a => a.item.equals(completeAddress.address))) {
|
|
82
95
|
accountLogStrings.push(` Address: ${completeAddress.address.toString()}\n`);
|
|
83
96
|
accountLogStrings.push(` Partial Address: ${completeAddress.partialAddress.toString()}\n`);
|
|
84
|
-
accountLogStrings.push(` Secret Key: ${
|
|
97
|
+
accountLogStrings.push(` Secret Key: ${accountManager.getSecretKey().toString()}\n`);
|
|
85
98
|
accountLogStrings.push(` Master nullifier public key hash: ${completeAddress.publicKeys.npkMHash.toString()}\n`);
|
|
86
99
|
accountLogStrings.push(` Master incoming viewing public key: ${completeAddress.publicKeys.ivpkM.toString()}\n\n`);
|
|
87
100
|
accountLogStrings.push(
|
|
@@ -291,60 +304,6 @@ export async function preloadCrsDataForServerSideProving(
|
|
|
291
304
|
}
|
|
292
305
|
}
|
|
293
306
|
|
|
294
|
-
export async function setupVersionChecker(
|
|
295
|
-
network: NetworkNames,
|
|
296
|
-
followsCanonicalRollup: boolean,
|
|
297
|
-
publicClient: ViemClient,
|
|
298
|
-
signalHandlers: Array<() => Promise<void>>,
|
|
299
|
-
cacheDir?: string,
|
|
300
|
-
): Promise<void> {
|
|
301
|
-
const networkConfig = await getNetworkConfig(network, cacheDir);
|
|
302
|
-
if (!networkConfig) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const { VersionChecker } = await import('@aztec/stdlib/update-checker');
|
|
307
|
-
|
|
308
|
-
const logger = createLogger('version_check');
|
|
309
|
-
const registry = new RegistryContract(publicClient, networkConfig.registryAddress as Hex);
|
|
310
|
-
|
|
311
|
-
const checks: Array<VersionCheck> = [];
|
|
312
|
-
checks.push({
|
|
313
|
-
name: 'node',
|
|
314
|
-
currentVersion: getPackageVersion(),
|
|
315
|
-
getLatestVersion: async () => {
|
|
316
|
-
const cfg = await getNetworkConfig(network, cacheDir);
|
|
317
|
-
return cfg?.nodeVersion;
|
|
318
|
-
},
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
if (followsCanonicalRollup) {
|
|
322
|
-
const getLatestVersion = async () => {
|
|
323
|
-
const version = (await registry.getRollupVersions()).at(-1);
|
|
324
|
-
return version !== undefined ? String(version) : undefined;
|
|
325
|
-
};
|
|
326
|
-
const currentVersion = await getLatestVersion();
|
|
327
|
-
if (currentVersion !== undefined) {
|
|
328
|
-
checks.push({
|
|
329
|
-
name: 'rollup',
|
|
330
|
-
currentVersion,
|
|
331
|
-
getLatestVersion,
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const checker = new VersionChecker(checks, 600_000, logger);
|
|
337
|
-
checker.on('newVersion', ({ name, latestVersion, currentVersion }) => {
|
|
338
|
-
if (isShuttingDown()) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
logger.warn(`New ${name} version available`, { latestVersion, currentVersion });
|
|
343
|
-
});
|
|
344
|
-
checker.start();
|
|
345
|
-
signalHandlers.push(() => checker.stop());
|
|
346
|
-
}
|
|
347
|
-
|
|
348
307
|
export function stringifyConfig(config: object): string {
|
|
349
308
|
return Object.entries(config)
|
|
350
309
|
.map(([key, value]) => `${key}=${jsonStringify(value)}`)
|
package/src/examples/token.ts
CHANGED
|
@@ -21,10 +21,18 @@ async function main() {
|
|
|
21
21
|
|
|
22
22
|
const wallet = await EmbeddedWallet.create(node);
|
|
23
23
|
|
|
24
|
-
// During local network setup we
|
|
24
|
+
// During local network setup we create a few initializerless accounts. Below we add them to our wallet.
|
|
25
25
|
const [aliceInitialAccountData, bobInitialAccountData] = await getInitialTestAccountsData();
|
|
26
|
-
await wallet.
|
|
27
|
-
|
|
26
|
+
await wallet.createSchnorrInitializerlessAccount(
|
|
27
|
+
aliceInitialAccountData.secret,
|
|
28
|
+
aliceInitialAccountData.salt,
|
|
29
|
+
aliceInitialAccountData.signingKey,
|
|
30
|
+
);
|
|
31
|
+
await wallet.createSchnorrInitializerlessAccount(
|
|
32
|
+
bobInitialAccountData.secret,
|
|
33
|
+
bobInitialAccountData.salt,
|
|
34
|
+
bobInitialAccountData.signingKey,
|
|
35
|
+
);
|
|
28
36
|
|
|
29
37
|
const alice = aliceInitialAccountData.address;
|
|
30
38
|
const bob = bobInitialAccountData.address;
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-warnings
|
|
2
2
|
import { getInitialTestAccountsData } from '@aztec/accounts/testing';
|
|
3
|
-
import {
|
|
3
|
+
import { createAztecNodeService } from '@aztec/aztec-node';
|
|
4
4
|
import { type AztecNodeConfig, getConfigEnvVars } from '@aztec/aztec-node/config';
|
|
5
5
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
6
6
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
7
7
|
import { type BlobClientInterface, createBlobClient } from '@aztec/blob-client/client';
|
|
8
8
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
9
|
-
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
10
9
|
import { waitForPublicClient } from '@aztec/ethereum/client';
|
|
11
10
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
12
11
|
import { NULL_KEY } from '@aztec/ethereum/constants';
|
|
13
12
|
import { deployAztecL1Contracts } from '@aztec/ethereum/deploy-aztec-l1-contracts';
|
|
14
13
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
15
|
-
import { EthCheatCodes } from '@aztec/ethereum/test';
|
|
16
14
|
import { SecretValue } from '@aztec/foundation/config';
|
|
17
15
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
18
16
|
import type { LogFn } from '@aztec/foundation/log';
|
|
19
17
|
import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
|
|
20
18
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
21
19
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
22
|
-
import { SequencerState } from '@aztec/sequencer-client';
|
|
23
20
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
24
21
|
import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
|
|
25
22
|
import { TxStatus } from '@aztec/stdlib/tx';
|
|
@@ -30,17 +27,15 @@ import {
|
|
|
30
27
|
initTelemetryClient,
|
|
31
28
|
} from '@aztec/telemetry-client';
|
|
32
29
|
import { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
33
|
-
import {
|
|
30
|
+
import { createFundedInitializerlessAccounts } from '@aztec/wallets/testing';
|
|
34
31
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
35
32
|
|
|
36
|
-
import {
|
|
33
|
+
import type { Hex } from 'viem';
|
|
37
34
|
import { mnemonicToAccount, privateKeyToAddress } from 'viem/accounts';
|
|
38
35
|
import { foundry } from 'viem/chains';
|
|
39
36
|
|
|
40
37
|
import { createAccountLogs } from '../cli/util.js';
|
|
41
38
|
import { DefaultMnemonic } from '../mnemonic.js';
|
|
42
|
-
import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
|
|
43
|
-
import { EpochTestSettler } from '../testing/epoch_test_settler.js';
|
|
44
39
|
import { getTokenAllowedSetupFunctions } from '../testing/token_allowed_setup.js';
|
|
45
40
|
import { publishStandardAuthRegistry } from './auth_registry.js';
|
|
46
41
|
import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
|
|
@@ -54,8 +49,6 @@ const logger = createLogger('local-network');
|
|
|
54
49
|
// P2P node"). Wait for the checkpoint so each setup tx is durably included before the next is sent.
|
|
55
50
|
const setupWaitOpts = { waitForStatus: TxStatus.CHECKPOINTED };
|
|
56
51
|
|
|
57
|
-
const localAnvil = foundry;
|
|
58
|
-
|
|
59
52
|
/**
|
|
60
53
|
* Function to deploy our L1 contracts to the local network L1
|
|
61
54
|
* @param aztecNodeConfig - The Aztec Node Config
|
|
@@ -95,6 +88,8 @@ export type LocalNetworkConfig = AztecNodeConfig & {
|
|
|
95
88
|
l1Mnemonic: string;
|
|
96
89
|
/** Whether to deploy test accounts on local network start.*/
|
|
97
90
|
testAccounts: boolean;
|
|
91
|
+
/** Override the default per-address fee juice granted at genesis to funded addresses. */
|
|
92
|
+
initialAccountFeeJuice?: Fr;
|
|
98
93
|
};
|
|
99
94
|
|
|
100
95
|
/**
|
|
@@ -116,10 +111,33 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
116
111
|
// in the setup allowlist so FPC-based fee payments work out of the box.
|
|
117
112
|
const tokenAllowList = await getTokenAllowedSetupFunctions();
|
|
118
113
|
|
|
114
|
+
const envConfig = getConfigEnvVars();
|
|
119
115
|
const aztecNodeConfig: AztecNodeConfig = {
|
|
120
|
-
...
|
|
116
|
+
...envConfig,
|
|
121
117
|
...config,
|
|
118
|
+
skipOrphanProposedBlockPruning: true,
|
|
119
|
+
// The local network builds node config from env without a DATA_DIRECTORY, so the validator's
|
|
120
|
+
// local signing protection runs against an ephemeral store. That is acceptable for this dev
|
|
121
|
+
// network; production validators must persist it and fail-fast when the data directory is unset.
|
|
122
|
+
allowEphemeralSigningProtection: config.allowEphemeralSigningProtection ?? true,
|
|
122
123
|
txPublicSetupAllowListExtend: [...tokenAllowList, ...(config.txPublicSetupAllowListExtend ?? [])],
|
|
124
|
+
// The local network runs against anvil with no committee, so it defaults to the deterministic
|
|
125
|
+
// AutomineSequencer, which owns L1 time control (warps the dateProvider and L1 timestamps to slot
|
|
126
|
+
// boundaries as it builds), replacing the deleted AnvilTestWatcher. This remains true when p2p is
|
|
127
|
+
// enabled for local peer testing; local-network is not a mode for connecting to an existing network.
|
|
128
|
+
useAutomineSequencer: config.useAutomineSequencer ?? true,
|
|
129
|
+
// The AutomineSequencer owns epoch proving in the local network — it writes epoch out hashes to
|
|
130
|
+
// the L1 Outbox and advances the proven tip as checkpoints land, through the same serial queue as
|
|
131
|
+
// its builds — replacing the standalone EpochTestSettler that used to race the build loop.
|
|
132
|
+
automineEnableProveEpoch: config.automineEnableProveEpoch ?? true,
|
|
133
|
+
// Defaults for the local network / sandbox; callers (e.g. the CLI) may override. No real proving
|
|
134
|
+
// happens here — the AutomineSequencer synthetically settles epochs. Short epochs let it write out
|
|
135
|
+
// hashes quickly (so users can consume L2-to-L1 messages without a long wait), with a wider
|
|
136
|
+
// proof-submission window so the synthetic settler has headroom before the rollup would prune an
|
|
137
|
+
// unproven checkpoint.
|
|
138
|
+
realProofs: config.realProofs ?? false,
|
|
139
|
+
aztecEpochDuration: config.aztecEpochDuration ?? 4,
|
|
140
|
+
aztecProofSubmissionEpochs: config.aztecProofSubmissionEpochs ?? 2,
|
|
123
141
|
};
|
|
124
142
|
const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
|
|
125
143
|
if (
|
|
@@ -143,7 +161,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
143
161
|
const initialAccounts = await (async () => {
|
|
144
162
|
if (config.testAccounts === true || config.testAccounts === undefined) {
|
|
145
163
|
if (aztecNodeConfig.p2pEnabled) {
|
|
146
|
-
userLog(`Not setting up test accounts
|
|
164
|
+
userLog(`Not setting up test accounts when p2p is enabled`);
|
|
147
165
|
} else {
|
|
148
166
|
userLog(`Setting up test accounts`);
|
|
149
167
|
return await getInitialTestAccountsData();
|
|
@@ -154,46 +172,24 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
154
172
|
|
|
155
173
|
const bananaFPC = await getBananaFPCAddress(initialAccounts);
|
|
156
174
|
const sponsoredFPC = await getSponsoredFPCAddress();
|
|
157
|
-
const prefundAddresses = (aztecNodeConfig.prefundAddresses ?? []).map(a => AztecAddress.
|
|
175
|
+
const prefundAddresses = (aztecNodeConfig.prefundAddresses ?? []).map(a => AztecAddress.fromStringUnsafe(a));
|
|
158
176
|
const fundedAddresses = [
|
|
159
177
|
...initialAccounts.map(a => a.address),
|
|
160
178
|
...(initialAccounts.length ? [bananaFPC, sponsoredFPC] : []),
|
|
161
179
|
...prefundAddresses,
|
|
162
180
|
];
|
|
163
|
-
const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
|
|
181
|
+
const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
|
|
182
|
+
fundedAddresses,
|
|
183
|
+
config.initialAccountFeeJuice,
|
|
184
|
+
);
|
|
164
185
|
|
|
165
186
|
const dateProvider = new TestDateProvider();
|
|
166
187
|
|
|
167
|
-
let cheatcodes: EthCheatCodes | undefined;
|
|
168
|
-
let rollupAddress: EthAddress | undefined;
|
|
169
|
-
let watcher: AnvilTestWatcher | undefined;
|
|
170
188
|
if (!aztecNodeConfig.p2pEnabled) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
{
|
|
175
|
-
genesisArchiveRoot,
|
|
176
|
-
feeJuicePortalInitialBalance: fundingNeeded,
|
|
177
|
-
},
|
|
178
|
-
));
|
|
179
|
-
|
|
180
|
-
const chain =
|
|
181
|
-
aztecNodeConfig.l1RpcUrls.length > 0
|
|
182
|
-
? createEthereumChain([l1RpcUrl], aztecNodeConfig.l1ChainId)
|
|
183
|
-
: { chainInfo: localAnvil };
|
|
184
|
-
|
|
185
|
-
const publicClient = createPublicClient({
|
|
186
|
-
chain: chain.chainInfo,
|
|
187
|
-
transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
|
|
189
|
+
await deployContractsToL1(aztecNodeConfig, aztecNodeConfig.validatorPrivateKeys.getValue()[0], {
|
|
190
|
+
genesisArchiveRoot,
|
|
191
|
+
feeJuicePortalInitialBalance: fundingNeeded,
|
|
188
192
|
});
|
|
189
|
-
|
|
190
|
-
cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
|
|
191
|
-
|
|
192
|
-
watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
|
|
193
|
-
watcher.setisLocalNetwork(true);
|
|
194
|
-
watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
|
|
195
|
-
|
|
196
|
-
await watcher.start();
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
const telemetry = await initTelemetryClient(getTelemetryClientConfig());
|
|
@@ -201,48 +197,6 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
201
197
|
const blobClient = createBlobClient();
|
|
202
198
|
const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { genesis });
|
|
203
199
|
|
|
204
|
-
// Now that the node is up, let the watcher check for pending txs so it can skip unfilled slots faster when
|
|
205
|
-
// transactions are waiting in the mempool. Also let it check if the sequencer is actively building, to avoid
|
|
206
|
-
// warping time out from under an in-progress block.
|
|
207
|
-
watcher?.setGetPendingTxCount(() => node.getPendingTxCount());
|
|
208
|
-
const sequencer = node.getSequencer()?.getSequencer();
|
|
209
|
-
if (sequencer) {
|
|
210
|
-
const idleStates: Set<string> = new Set([
|
|
211
|
-
SequencerState.STOPPED,
|
|
212
|
-
SequencerState.STOPPING,
|
|
213
|
-
SequencerState.IDLE,
|
|
214
|
-
SequencerState.SYNCHRONIZING,
|
|
215
|
-
]);
|
|
216
|
-
watcher?.setIsSequencerBuilding(() => !idleStates.has(sequencer.getState()));
|
|
217
|
-
// Under proposer pipelining the L1 publish for slot N happens during wall-clock slot N,
|
|
218
|
-
// but the proposer for slot N has already built the checkpoint during slot N-1 and is
|
|
219
|
-
// waiting for L1 to advance. We need to fast-forward L1 to wake that wait — and the wait
|
|
220
|
-
// we have to break first is `waitForValidParentCheckpointOnL1`, which blocks the
|
|
221
|
-
// checkpoint_proposal_job's background submission task until the archiver has synced past
|
|
222
|
-
// the build slot. That wait happens *before* `PUBLISHING_CHECKPOINT` is set, so a hook on
|
|
223
|
-
// that state transition would be circular (L1 has to advance before the state we'd use to
|
|
224
|
-
// advance L1 fires). The earliest pre-wait signal is `block-proposed`, which the sequencer
|
|
225
|
-
// emits once each block is built. In sandbox single-block-per-slot mode this is
|
|
226
|
-
// effectively "checkpoint built", and the watcher warp is harmless if a subsequent
|
|
227
|
-
// assembly/validation/parent-wait step aborts: L1 just sits one slot ahead, which the
|
|
228
|
-
// cascade absorbs.
|
|
229
|
-
if (watcher) {
|
|
230
|
-
sequencer.on('block-proposed', ({ slot }) => watcher!.setProposedTargetSlot(Number(slot)));
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
let epochTestSettler: EpochTestSettler | undefined;
|
|
235
|
-
if (!aztecNodeConfig.p2pEnabled) {
|
|
236
|
-
epochTestSettler = new EpochTestSettler(
|
|
237
|
-
cheatcodes!,
|
|
238
|
-
rollupAddress!,
|
|
239
|
-
node.getBlockSource(),
|
|
240
|
-
logger.createChild('epoch-settler'),
|
|
241
|
-
{ pollingIntervalMs: 200 },
|
|
242
|
-
);
|
|
243
|
-
await epochTestSettler.start();
|
|
244
|
-
}
|
|
245
|
-
|
|
246
200
|
if (initialAccounts.length) {
|
|
247
201
|
const wallet = await EmbeddedWallet.create(node, {
|
|
248
202
|
pxeConfig: { proverEnabled: aztecNodeConfig.realProofs },
|
|
@@ -250,7 +204,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
250
204
|
});
|
|
251
205
|
|
|
252
206
|
userLog('Setting up funded test accounts...');
|
|
253
|
-
const accountManagers = await
|
|
207
|
+
const accountManagers = await createFundedInitializerlessAccounts(wallet, initialAccounts);
|
|
254
208
|
const accLogs = await createAccountLogs(accountManagers, wallet);
|
|
255
209
|
userLog(accLogs.join(''));
|
|
256
210
|
|
|
@@ -267,8 +221,6 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
267
221
|
|
|
268
222
|
const stop = async () => {
|
|
269
223
|
await node.stop();
|
|
270
|
-
await watcher?.stop();
|
|
271
|
-
await epochTestSettler?.stop();
|
|
272
224
|
};
|
|
273
225
|
|
|
274
226
|
return { node, stop };
|
|
@@ -294,7 +246,7 @@ export async function createAztecNode(
|
|
|
294
246
|
...getConfigEnvVars(),
|
|
295
247
|
...config,
|
|
296
248
|
};
|
|
297
|
-
const node = await
|
|
249
|
+
const node = await createAztecNodeService(
|
|
298
250
|
aztecNodeConfig,
|
|
299
251
|
{ ...deps, proverNodeDeps: { broker: deps.proverBroker } },
|
|
300
252
|
options,
|