@aztec/aztec 5.0.0-private.20260319 → 5.0.0-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.
Files changed (108) hide show
  1. package/dest/bin/index.js +1 -1
  2. package/dest/cli/aztec_start_action.d.ts +1 -1
  3. package/dest/cli/aztec_start_action.d.ts.map +1 -1
  4. package/dest/cli/aztec_start_action.js +16 -24
  5. package/dest/cli/aztec_start_options.d.ts +2 -2
  6. package/dest/cli/aztec_start_options.d.ts.map +1 -1
  7. package/dest/cli/aztec_start_options.js +14 -14
  8. package/dest/cli/cmds/compile.d.ts +1 -1
  9. package/dest/cli/cmds/compile.d.ts.map +1 -1
  10. package/dest/cli/cmds/compile.js +8 -8
  11. package/dest/cli/cmds/profile.d.ts +1 -1
  12. package/dest/cli/cmds/profile.d.ts.map +1 -1
  13. package/dest/cli/cmds/profile.js +1 -1
  14. package/dest/cli/cmds/profile_gates.d.ts +2 -2
  15. package/dest/cli/cmds/profile_gates.d.ts.map +1 -1
  16. package/dest/cli/cmds/profile_gates.js +21 -3
  17. package/dest/cli/cmds/standby.d.ts +3 -5
  18. package/dest/cli/cmds/standby.d.ts.map +1 -1
  19. package/dest/cli/cmds/standby.js +3 -3
  20. package/dest/cli/cmds/start_bot.d.ts +1 -1
  21. package/dest/cli/cmds/start_bot.d.ts.map +1 -1
  22. package/dest/cli/cmds/start_bot.js +8 -4
  23. package/dest/cli/cmds/start_node.d.ts +1 -1
  24. package/dest/cli/cmds/start_node.d.ts.map +1 -1
  25. package/dest/cli/cmds/start_node.js +13 -40
  26. package/dest/cli/cmds/start_prover_agent.d.ts +1 -1
  27. package/dest/cli/cmds/start_prover_agent.d.ts.map +1 -1
  28. package/dest/cli/cmds/start_prover_agent.js +5 -17
  29. package/dest/cli/cmds/start_prover_broker.d.ts +1 -1
  30. package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
  31. package/dest/cli/cmds/start_prover_broker.js +11 -8
  32. package/dest/cli/cmds/start_txe.d.ts +2 -2
  33. package/dest/cli/cmds/start_txe.d.ts.map +1 -1
  34. package/dest/cli/cmds/start_txe.js +6 -5
  35. package/dest/cli/cmds/utils/collect_crate_dirs.d.ts +21 -0
  36. package/dest/cli/cmds/utils/collect_crate_dirs.d.ts.map +1 -0
  37. package/dest/cli/cmds/utils/collect_crate_dirs.js +114 -0
  38. package/dest/cli/cmds/utils/needs_recompile.d.ts +1 -1
  39. package/dest/cli/cmds/utils/needs_recompile.d.ts.map +1 -1
  40. package/dest/cli/cmds/utils/needs_recompile.js +9 -53
  41. package/dest/cli/cmds/utils/warn_if_aztec_version_mismatch.d.ts +4 -0
  42. package/dest/cli/cmds/utils/warn_if_aztec_version_mismatch.d.ts.map +1 -0
  43. package/dest/cli/cmds/utils/warn_if_aztec_version_mismatch.js +61 -0
  44. package/dest/cli/util.js +7 -5
  45. package/dest/examples/token.js +3 -3
  46. package/dest/local-network/auth_registry.d.ts +5 -0
  47. package/dest/local-network/auth_registry.d.ts.map +1 -0
  48. package/dest/local-network/auth_registry.js +17 -0
  49. package/dest/local-network/banana_fpc.d.ts +3 -2
  50. package/dest/local-network/banana_fpc.d.ts.map +1 -1
  51. package/dest/local-network/banana_fpc.js +11 -7
  52. package/dest/local-network/local-network.d.ts +6 -29
  53. package/dest/local-network/local-network.d.ts.map +1 -1
  54. package/dest/local-network/local-network.js +45 -70
  55. package/dest/testing/cheat_codes.d.ts +18 -17
  56. package/dest/testing/cheat_codes.d.ts.map +1 -1
  57. package/dest/testing/cheat_codes.js +70 -36
  58. package/dest/testing/epoch_test_settler.d.ts +2 -2
  59. package/dest/testing/epoch_test_settler.d.ts.map +1 -1
  60. package/dest/testing/epoch_test_settler.js +6 -25
  61. package/dest/testing/index.d.ts +1 -2
  62. package/dest/testing/index.d.ts.map +1 -1
  63. package/dest/testing/index.js +0 -1
  64. package/package.json +34 -33
  65. package/scripts/add_crate.sh +11 -60
  66. package/scripts/aztec.sh +6 -2
  67. package/scripts/init.sh +5 -5
  68. package/scripts/new.sh +2 -2
  69. package/scripts/setup_workspace.sh +3 -2
  70. package/scripts/templates/blank/contract/Nargo.toml +6 -0
  71. package/scripts/templates/blank/contract/src/main.nr +10 -0
  72. package/scripts/templates/blank/test/Nargo.toml +7 -0
  73. package/scripts/templates/blank/test/src/lib.nr +11 -0
  74. package/scripts/templates/counter/contract/Nargo.toml +7 -0
  75. package/scripts/templates/counter/contract/src/main.nr +48 -0
  76. package/scripts/templates/counter/test/Nargo.toml +7 -0
  77. package/scripts/templates/counter/test/src/lib.nr +32 -0
  78. package/src/bin/index.ts +1 -1
  79. package/src/cli/aztec_start_action.ts +14 -17
  80. package/src/cli/aztec_start_options.ts +21 -22
  81. package/src/cli/cmds/compile.ts +10 -9
  82. package/src/cli/cmds/profile.ts +2 -1
  83. package/src/cli/cmds/profile_gates.ts +20 -4
  84. package/src/cli/cmds/standby.ts +4 -4
  85. package/src/cli/cmds/start_bot.ts +9 -6
  86. package/src/cli/cmds/start_node.ts +20 -23
  87. package/src/cli/cmds/start_prover_agent.ts +5 -8
  88. package/src/cli/cmds/start_prover_broker.ts +10 -11
  89. package/src/cli/cmds/start_txe.ts +7 -5
  90. package/src/cli/cmds/utils/collect_crate_dirs.ts +118 -0
  91. package/src/cli/cmds/utils/needs_recompile.ts +8 -61
  92. package/src/cli/cmds/utils/warn_if_aztec_version_mismatch.ts +76 -0
  93. package/src/cli/util.ts +7 -7
  94. package/src/examples/token.ts +3 -3
  95. package/src/local-network/auth_registry.ts +19 -0
  96. package/src/local-network/banana_fpc.ts +12 -8
  97. package/src/local-network/local-network.ts +49 -80
  98. package/src/testing/cheat_codes.ts +89 -39
  99. package/src/testing/epoch_test_settler.ts +8 -31
  100. package/src/testing/index.ts +0 -1
  101. package/dest/cli/cmds/start_archiver.d.ts +0 -9
  102. package/dest/cli/cmds/start_archiver.d.ts.map +0 -1
  103. package/dest/cli/cmds/start_archiver.js +0 -48
  104. package/dest/testing/anvil_test_watcher.d.ts +0 -42
  105. package/dest/testing/anvil_test_watcher.d.ts.map +0 -1
  106. package/dest/testing/anvil_test_watcher.js +0 -181
  107. package/src/cli/cmds/start_archiver.ts +0 -50
  108. package/src/testing/anvil_test_watcher.ts +0 -210
@@ -21,10 +21,10 @@ async function main() {
21
21
 
22
22
  const wallet = await EmbeddedWallet.create(node);
23
23
 
24
- // During local network setup we deploy a few accounts. Below we add them to our wallet.
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.createSchnorrAccount(aliceInitialAccountData.secret, aliceInitialAccountData.salt);
27
- await wallet.createSchnorrAccount(bobInitialAccountData.secret, bobInitialAccountData.salt);
26
+ await wallet.createSchnorrInitializerlessAccount(aliceInitialAccountData.secret, aliceInitialAccountData.salt);
27
+ await wallet.createSchnorrInitializerlessAccount(bobInitialAccountData.secret, bobInitialAccountData.salt);
28
28
 
29
29
  const alice = aliceInitialAccountData.address;
30
30
  const bob = bobInitialAccountData.address;
@@ -0,0 +1,19 @@
1
+ import type { WaitOpts } from '@aztec/aztec.js/contracts';
2
+ import { publishContractClass, publishInstance } from '@aztec/aztec.js/deployment';
3
+ import type { Wallet } from '@aztec/aztec.js/wallet';
4
+ import { AuthRegistryArtifact, getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
5
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
6
+
7
+ export async function publishStandardAuthRegistry(
8
+ wallet: Wallet,
9
+ from: AztecAddress,
10
+ waitOpts?: WaitOpts,
11
+ ): Promise<void> {
12
+ const { instance, contractClass } = await getStandardAuthRegistry();
13
+ if (!(await wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) {
14
+ await (await publishContractClass(wallet, AuthRegistryArtifact)).send({ from, wait: waitOpts });
15
+ }
16
+ if (!(await wallet.getContractMetadata(instance.address)).isContractPublished) {
17
+ await publishInstance(wallet, instance).send({ from, wait: waitOpts });
18
+ }
19
+ }
@@ -1,4 +1,5 @@
1
1
  import { type InitialAccountData, getInitialTestAccountsData } from '@aztec/accounts/testing';
2
+ import type { WaitOpts } from '@aztec/aztec.js/contracts';
2
3
  import type { Wallet } from '@aztec/aztec.js/wallet';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import type { LogFn } from '@aztec/foundation/log';
@@ -45,19 +46,22 @@ export async function getBananaFPCAddress(initialAccounts: InitialAccountData[])
45
46
  return (await getBananaFPCInstance(initialAccounts)).address;
46
47
  }
47
48
 
48
- export async function setupBananaFPC(initialAccounts: InitialAccountData[], wallet: Wallet, log: LogFn) {
49
+ export async function setupBananaFPC(
50
+ initialAccounts: InitialAccountData[],
51
+ wallet: Wallet,
52
+ log: LogFn,
53
+ waitOpts?: WaitOpts,
54
+ ) {
49
55
  const bananaCoinAddress = await getBananaCoinAddress(initialAccounts);
50
56
  const admin = getBananaAdmin(initialAccounts);
51
57
  const [{ contract: bananaCoin }, { contract: fpc }] = await Promise.all([
52
- TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal).send({
53
- from: admin,
54
- contractAddressSalt: BANANA_COIN_SALT,
58
+ TokenContract.deploy(wallet, admin, bananaCoinArgs.name, bananaCoinArgs.symbol, bananaCoinArgs.decimal, {
59
+ salt: BANANA_COIN_SALT,
55
60
  universalDeploy: true,
56
- }),
57
- FPCContract.deploy(wallet, bananaCoinAddress, admin).send({
61
+ }).send({ from: admin, wait: waitOpts }),
62
+ FPCContract.deploy(wallet, bananaCoinAddress, admin, { salt: BANANA_FPC_SALT, universalDeploy: true }).send({
58
63
  from: admin,
59
- contractAddressSalt: BANANA_FPC_SALT,
60
- universalDeploy: true,
64
+ wait: waitOpts,
61
65
  }),
62
66
  ]);
63
67
 
@@ -6,46 +6,48 @@ 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
- import { EthCheatCodes } from '@aztec/ethereum/test';
13
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
15
14
  import { SecretValue } from '@aztec/foundation/config';
16
15
  import { EthAddress } from '@aztec/foundation/eth-address';
17
16
  import type { LogFn } from '@aztec/foundation/log';
18
17
  import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
19
18
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
20
19
  import { protocolContractsHash } from '@aztec/protocol-contracts';
21
- import { SequencerState } from '@aztec/sequencer-client';
22
20
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
23
21
  import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
24
- import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
22
+ import { TxStatus } from '@aztec/stdlib/tx';
23
+ import type { GenesisData } from '@aztec/stdlib/world-state';
25
24
  import {
26
25
  type TelemetryClient,
27
26
  getConfigEnvVars as getTelemetryClientConfig,
28
27
  initTelemetryClient,
29
28
  } from '@aztec/telemetry-client';
30
29
  import { EmbeddedWallet } from '@aztec/wallets/embedded';
31
- import { deployFundedSchnorrAccounts } from '@aztec/wallets/testing';
30
+ import { createFundedInitializerlessAccounts } from '@aztec/wallets/testing';
32
31
  import { getGenesisValues } from '@aztec/world-state/testing';
33
32
 
34
- import { type Hex, createPublicClient, fallback, http as httpViemTransport } from 'viem';
33
+ import type { Hex } from 'viem';
35
34
  import { mnemonicToAccount, privateKeyToAddress } from 'viem/accounts';
36
35
  import { foundry } from 'viem/chains';
37
36
 
38
37
  import { createAccountLogs } from '../cli/util.js';
39
38
  import { DefaultMnemonic } from '../mnemonic.js';
40
- import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
41
- import { EpochTestSettler } from '../testing/epoch_test_settler.js';
42
39
  import { getTokenAllowedSetupFunctions } from '../testing/token_allowed_setup.js';
40
+ import { publishStandardAuthRegistry } from './auth_registry.js';
43
41
  import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
44
42
  import { getSponsoredFPCAddress } from './sponsored_fpc.js';
45
43
 
46
44
  const logger = createLogger('local-network');
47
45
 
48
- const localAnvil = foundry;
46
+ // The embedded wallet defaults to waiting for PROPOSED, which returns as soon as a tx lands in a
47
+ // proposed L2 block. That is flaky for the serial sandbox setup below: a proposed block can be
48
+ // pruned before its checkpoint is published, dropping a tx we already moved on from ("Tx dropped by
49
+ // P2P node"). Wait for the checkpoint so each setup tx is durably included before the next is sent.
50
+ const setupWaitOpts = { waitForStatus: TxStatus.CHECKPOINTED };
49
51
 
50
52
  /**
51
53
  * Function to deploy our L1 contracts to the local network L1
@@ -59,7 +61,7 @@ export async function deployContractsToL1(
59
61
  genesisArchiveRoot?: Fr;
60
62
  feeJuicePortalInitialBalance?: bigint;
61
63
  } = {},
62
- ) {
64
+ ): Promise<L1ContractAddresses> {
63
65
  await waitForPublicClient(aztecNodeConfig);
64
66
 
65
67
  const l1Contracts = await deployAztecL1Contracts(aztecNodeConfig.l1RpcUrls[0], privateKey, foundry.id, {
@@ -70,14 +72,14 @@ export async function deployContractsToL1(
70
72
  genesisArchiveRoot: opts.genesisArchiveRoot ?? new Fr(GENESIS_ARCHIVE_ROOT),
71
73
  feeJuicePortalInitialBalance: opts.feeJuicePortalInitialBalance,
72
74
  aztecTargetCommitteeSize: 0, // no committee in local network
73
- slasherFlavor: 'none', // no slashing in local network
75
+ slasherEnabled: false, // no slashing in local network
74
76
  realVerifier: false,
75
77
  });
76
78
 
77
- aztecNodeConfig.l1Contracts = l1Contracts.l1ContractAddresses;
79
+ Object.assign(aztecNodeConfig, l1Contracts.l1ContractAddresses);
78
80
  aztecNodeConfig.rollupVersion = l1Contracts.rollupVersion;
79
81
 
80
- return aztecNodeConfig.l1Contracts;
82
+ return l1Contracts.l1ContractAddresses;
81
83
  }
82
84
 
83
85
  /** Local network settings. */
@@ -107,10 +109,29 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
107
109
  // in the setup allowlist so FPC-based fee payments work out of the box.
108
110
  const tokenAllowList = await getTokenAllowedSetupFunctions();
109
111
 
112
+ const envConfig = getConfigEnvVars();
110
113
  const aztecNodeConfig: AztecNodeConfig = {
111
- ...getConfigEnvVars(),
114
+ ...envConfig,
112
115
  ...config,
116
+ skipOrphanProposedBlockPruning: true,
113
117
  txPublicSetupAllowListExtend: [...tokenAllowList, ...(config.txPublicSetupAllowListExtend ?? [])],
118
+ // The local network runs against anvil with no committee, so it defaults to the deterministic
119
+ // AutomineSequencer, which owns L1 time control (warps the dateProvider and L1 timestamps to slot
120
+ // boundaries as it builds), replacing the deleted AnvilTestWatcher. This remains true when p2p is
121
+ // enabled for local peer testing; local-network is not a mode for connecting to an existing network.
122
+ useAutomineSequencer: config.useAutomineSequencer ?? true,
123
+ // The AutomineSequencer owns epoch proving in the local network — it writes epoch out hashes to
124
+ // the L1 Outbox and advances the proven tip as checkpoints land, through the same serial queue as
125
+ // its builds — replacing the standalone EpochTestSettler that used to race the build loop.
126
+ automineEnableProveEpoch: config.automineEnableProveEpoch ?? true,
127
+ // Defaults for the local network / sandbox; callers (e.g. the CLI) may override. No real proving
128
+ // happens here — the AutomineSequencer synthetically settles epochs. Short epochs let it write out
129
+ // hashes quickly (so users can consume L2-to-L1 messages without a long wait), with a wider
130
+ // proof-submission window so the synthetic settler has headroom before the rollup would prune an
131
+ // unproven checkpoint.
132
+ realProofs: config.realProofs ?? false,
133
+ aztecEpochDuration: config.aztecEpochDuration ?? 4,
134
+ aztecProofSubmissionEpochs: config.aztecProofSubmissionEpochs ?? 2,
114
135
  };
115
136
  const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
116
137
  if (
@@ -134,7 +155,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
134
155
  const initialAccounts = await (async () => {
135
156
  if (config.testAccounts === true || config.testAccounts === undefined) {
136
157
  if (aztecNodeConfig.p2pEnabled) {
137
- userLog(`Not setting up test accounts as we are connecting to a network`);
158
+ userLog(`Not setting up test accounts when p2p is enabled`);
138
159
  } else {
139
160
  userLog(`Setting up test accounts`);
140
161
  return await getInitialTestAccountsData();
@@ -151,73 +172,21 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
151
172
  ...(initialAccounts.length ? [bananaFPC, sponsoredFPC] : []),
152
173
  ...prefundAddresses,
153
174
  ];
154
- const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
175
+ const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(fundedAddresses);
155
176
 
156
177
  const dateProvider = new TestDateProvider();
157
178
 
158
- let cheatcodes: EthCheatCodes | undefined;
159
- let rollupAddress: EthAddress | undefined;
160
- let watcher: AnvilTestWatcher | undefined;
161
179
  if (!aztecNodeConfig.p2pEnabled) {
162
- ({ rollupAddress } = await deployContractsToL1(
163
- aztecNodeConfig,
164
- aztecNodeConfig.validatorPrivateKeys.getValue()[0],
165
- {
166
- genesisArchiveRoot,
167
- feeJuicePortalInitialBalance: fundingNeeded,
168
- },
169
- ));
170
-
171
- const chain =
172
- aztecNodeConfig.l1RpcUrls.length > 0
173
- ? createEthereumChain([l1RpcUrl], aztecNodeConfig.l1ChainId)
174
- : { chainInfo: localAnvil };
175
-
176
- const publicClient = createPublicClient({
177
- chain: chain.chainInfo,
178
- transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
180
+ await deployContractsToL1(aztecNodeConfig, aztecNodeConfig.validatorPrivateKeys.getValue()[0], {
181
+ genesisArchiveRoot,
182
+ feeJuicePortalInitialBalance: fundingNeeded,
179
183
  });
180
-
181
- cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
182
-
183
- watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
184
- watcher.setisLocalNetwork(true);
185
- watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
186
-
187
- await watcher.start();
188
184
  }
189
185
 
190
186
  const telemetry = await initTelemetryClient(getTelemetryClientConfig());
191
187
  // Create a local blob client client inside the local network, no http connectivity
192
188
  const blobClient = createBlobClient();
193
- const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
194
-
195
- // Now that the node is up, let the watcher check for pending txs so it can skip unfilled slots faster when
196
- // transactions are waiting in the mempool. Also let it check if the sequencer is actively building, to avoid
197
- // warping time out from under an in-progress block.
198
- watcher?.setGetPendingTxCount(() => node.getPendingTxCount());
199
- const sequencer = node.getSequencer()?.getSequencer();
200
- if (sequencer) {
201
- const idleStates: Set<string> = new Set([
202
- SequencerState.STOPPED,
203
- SequencerState.STOPPING,
204
- SequencerState.IDLE,
205
- SequencerState.SYNCHRONIZING,
206
- ]);
207
- watcher?.setIsSequencerBuilding(() => !idleStates.has(sequencer.getState()));
208
- }
209
-
210
- let epochTestSettler: EpochTestSettler | undefined;
211
- if (!aztecNodeConfig.p2pEnabled) {
212
- epochTestSettler = new EpochTestSettler(
213
- cheatcodes!,
214
- rollupAddress!,
215
- node.getBlockSource(),
216
- logger.createChild('epoch-settler'),
217
- { pollingIntervalMs: 200 },
218
- );
219
- await epochTestSettler.start();
220
- }
189
+ const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { genesis });
221
190
 
222
191
  if (initialAccounts.length) {
223
192
  const wallet = await EmbeddedWallet.create(node, {
@@ -226,11 +195,14 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
226
195
  });
227
196
 
228
197
  userLog('Setting up funded test accounts...');
229
- const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
198
+ const accountManagers = await createFundedInitializerlessAccounts(wallet, initialAccounts);
230
199
  const accLogs = await createAccountLogs(accountManagers, wallet);
231
200
  userLog(accLogs.join(''));
232
201
 
233
- await setupBananaFPC(initialAccounts, wallet, userLog);
202
+ userLog('Publishing standard AuthRegistry contract...');
203
+ await publishStandardAuthRegistry(wallet, initialAccounts[0].address, setupWaitOpts);
204
+
205
+ await setupBananaFPC(initialAccounts, wallet, userLog, setupWaitOpts);
234
206
 
235
207
  userLog(`SponsoredFPC: ${await getSponsoredFPCAddress()}`);
236
208
 
@@ -240,8 +212,6 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
240
212
 
241
213
  const stop = async () => {
242
214
  await node.stop();
243
- await watcher?.stop();
244
- await epochTestSettler?.stop();
245
215
  };
246
216
 
247
217
  return { node, stop };
@@ -259,14 +229,13 @@ export async function createAztecNode(
259
229
  dateProvider?: DateProvider;
260
230
  proverBroker?: ProvingJobBroker;
261
231
  } = {},
262
- options: { prefilledPublicData?: PublicDataTreeLeaf[] } = {},
232
+ options: { genesis?: GenesisData } = {},
263
233
  ) {
264
234
  // TODO(#12272): will clean this up. This is criminal.
265
- const { l1Contracts, ...rest } = getConfigEnvVars();
235
+ // Not sure why this was ever done. Will be fixed in A-989, A-991, A-990.
266
236
  const aztecNodeConfig: AztecNodeConfig = {
267
- ...rest,
237
+ ...getConfigEnvVars(),
268
238
  ...config,
269
- l1Contracts: { ...l1Contracts, ...config.l1Contracts },
270
239
  };
271
240
  const node = await AztecNodeService.createAndSync(
272
241
  aztecNodeConfig,
@@ -1,9 +1,9 @@
1
1
  import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
2
- import { BlockNumber } from '@aztec/foundation/branded-types';
3
- import { retryUntil } from '@aztec/foundation/retry';
2
+ import { SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { createLogger } from '@aztec/foundation/log';
4
4
  import type { DateProvider } from '@aztec/foundation/timer';
5
- import type { SequencerClient } from '@aztec/sequencer-client';
6
- import type { AztecNode } from '@aztec/stdlib/interfaces/client';
5
+ import type { AutomineSequencer } from '@aztec/sequencer-client/automine';
6
+ import type { AztecNode, AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
7
7
 
8
8
  /**
9
9
  * A class that provides utility functions for interacting with the chain.
@@ -12,68 +12,118 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
12
12
  * codes, please consider whether it makes sense to just introduce new utils in your tests instead.
13
13
  */
14
14
  export class CheatCodes {
15
+ private logger = createLogger('aztecjs:cheat_codes');
16
+
15
17
  constructor(
16
18
  /** Cheat codes for L1.*/
17
19
  public eth: EthCheatCodes,
18
20
  /** Cheat codes for the Aztec Rollup contract on L1. */
19
21
  public rollup: RollupCheatCodes,
22
+ /** When wired, redirects time-warps through the AutomineSequencer queue (test-only). */
23
+ private automine?: AutomineSequencer,
20
24
  ) {}
21
25
 
22
- static async create(rpcUrls: string[], node: AztecNode, dateProvider: DateProvider): Promise<CheatCodes> {
26
+ static async create(
27
+ rpcUrls: string[],
28
+ node: AztecNode,
29
+ dateProvider: DateProvider,
30
+ automine?: AutomineSequencer,
31
+ ): Promise<CheatCodes> {
23
32
  const ethCheatCodes = new EthCheatCodes(rpcUrls, dateProvider);
24
33
  const rollupCheatCodes = new RollupCheatCodes(
25
34
  ethCheatCodes,
26
35
  await node.getNodeInfo().then(n => n.l1ContractAddresses),
27
36
  );
28
- return new CheatCodes(ethCheatCodes, rollupCheatCodes);
37
+ return new CheatCodes(ethCheatCodes, rollupCheatCodes, automine);
29
38
  }
30
39
 
31
40
  /**
32
41
  * Warps the L1 timestamp to a target timestamp and mines an L2 block that advances the L2 timestamp to at least
33
- * the target timestamp. L2 timestamp is not advanced exactly to the target timestamp because it is determined
34
- * by the slot number, which advances in fixed intervals.
35
- * This is useful for testing time-dependent contract behavior.
36
- * @param sequencerClient - The sequencer client to use to force an empty block to be mined.
37
- * @param node - The Aztec node used to query if a new block has been mined.
42
+ * the target timestamp. If the target timestamp falls within the current L2 slot (which already has a block),
43
+ * the timestamp is automatically adjusted forward to the start of the next slot so that `mineBlock()` succeeds.
44
+ * @param node - The Aztec node used to force an empty block to be mined.
38
45
  * @param targetTimestamp - The target timestamp to warp to (in seconds)
39
46
  */
40
- async warpL2TimeAtLeastTo(sequencerClient: SequencerClient, node: AztecNode, targetTimestamp: bigint | number) {
41
- const currentL2BlockNumber: BlockNumber = await node.getBlockNumber();
47
+ async warpL2TimeAtLeastTo(node: AztecNode & AztecNodeDebug, targetTimestamp: bigint | number) {
48
+ const targetBigInt = BigInt(targetTimestamp);
49
+ const currentTimestamp = BigInt(await this.eth.lastBlockTimestamp());
42
50
 
43
- // We warp the L1 timestamp
44
- await this.eth.warp(targetTimestamp, { resetBlockInterval: true });
51
+ if (targetBigInt <= currentTimestamp) {
52
+ throw new Error(
53
+ `warpL2TimeAtLeastTo: target timestamp ${targetBigInt} is not in the future (current L1 timestamp is ${currentTimestamp}).`,
54
+ );
55
+ }
45
56
 
46
- // Wait until an L2 block is mined
47
- const sequencer = sequencerClient.getSequencer();
48
- const minTxsPerBlock = sequencer.getConfig().minTxsPerBlock;
49
- sequencer.updateConfig({ minTxsPerBlock: 0 });
57
+ // AutomineSequencer owns time control through its serial queue — delegate to keep warps atomic
58
+ // with respect to any in-flight build, and avoid the mineBlock-loop hack below.
59
+ // `warpTo` internally builds an empty L2 checkpoint, which auto-mines exactly one L1 block at
60
+ // the target slot boundary, so no separate `node.mineBlock()` is needed here.
61
+ if (this.automine) {
62
+ await this.automine.warpTo(Number(targetBigInt));
63
+ return;
64
+ }
50
65
 
51
- await retryUntil(
52
- async () => {
53
- const newL2BlockNumber: BlockNumber = await node.getBlockNumber();
54
- return newL2BlockNumber > currentL2BlockNumber;
55
- },
56
- 'new block after warping L2 time',
57
- 36,
58
- 1,
59
- );
66
+ const currentSlot = await this.rollup.getSlot();
67
+ let effectiveTargetSlot = await this.rollup.getSlotAt(targetBigInt);
68
+ let effectiveTimestamp = await this.rollup.getTimestampForSlot(effectiveTargetSlot);
69
+
70
+ if (effectiveTimestamp < targetBigInt || effectiveTargetSlot <= currentSlot) {
71
+ const adjustedSlot = SlotNumber(Math.max(effectiveTargetSlot + 1, currentSlot + 1));
72
+ const adjustedTimestamp = await this.rollup.getTimestampForSlot(adjustedSlot);
73
+ this.logger.warn(
74
+ `warpL2TimeAtLeastTo: target timestamp ${targetBigInt} does not align with a future L2 slot boundary. ` +
75
+ `Auto-adjusting to start of slot ${adjustedSlot} at timestamp ${adjustedTimestamp}.`,
76
+ );
77
+ effectiveTimestamp = adjustedTimestamp;
78
+ effectiveTargetSlot = adjustedSlot;
79
+ }
60
80
 
61
- // Restore original minTxsPerBlock
62
- sequencer.updateConfig({ minTxsPerBlock });
81
+ await this.eth.warp(effectiveTimestamp, { resetBlockInterval: true });
82
+
83
+ // The sequencer's polling loop may have a `work()` cycle in flight that captured pre-warp slot/timestamp values
84
+ // just before our warp landed. That cycle would mine an L2 block at the stale slot — the L1 sync prunes such a
85
+ // block from the canonical chain, but it lingers in local world state and the PXE will use it as the anchor for
86
+ // subsequent txs, leading to `expiration_timestamp` values that are already in the past relative to L1. Mine
87
+ // until we observe an L2 block at (or past) the post-warp slot, ensuring the next tx anchors to a fresh block.
88
+ const maxAttempts = 5;
89
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
90
+ await node.mineBlock();
91
+ const blockData = await node.getBlockData('latest');
92
+ const blockSlot = blockData?.header.globalVariables.slotNumber;
93
+ if (blockSlot !== undefined && BigInt(blockSlot) >= BigInt(effectiveTargetSlot)) {
94
+ return;
95
+ }
96
+ this.logger.warn(
97
+ `warpL2TimeAtLeastTo: mined L2 block at slot ${blockSlot}, expected at least ${effectiveTargetSlot}. ` +
98
+ `Retrying mineBlock (attempt ${attempt}/${maxAttempts}).`,
99
+ );
100
+ }
101
+ throw new Error(
102
+ `warpL2TimeAtLeastTo: failed to mine an L2 block at or past slot ${effectiveTargetSlot} after ${maxAttempts} attempts.`,
103
+ );
63
104
  }
64
105
 
65
106
  /**
66
107
  * Warps the L1 timestamp forward by a specified duration and mines an L2 block that advances the L2 timestamp at
67
- * least by the duration. L2 timestamp is not advanced exactly by the duration because it is determined by the slot
68
- * number, which advances in fixed intervals.
69
- * This is useful for testing time-dependent contract behavior.
70
- * @param sequencerClient - The sequencer client to use to force an empty block to be mined.
71
- * @param node - The Aztec node used to query if a new block has been mined.
108
+ * least by the duration. If the duration is too short to cross an L2 slot boundary, the warp is automatically
109
+ * extended to the start of the next slot so that `mineBlock()` succeeds.
110
+ * @param node - The Aztec node used to force an empty block to be mined.
72
111
  * @param duration - The duration to advance time by (in seconds)
73
112
  */
74
- async warpL2TimeAtLeastBy(sequencerClient: SequencerClient, node: AztecNode, duration: bigint | number) {
75
- const currentTimestamp = await this.eth.timestamp();
76
- const targetTimestamp = BigInt(currentTimestamp) + BigInt(duration);
77
- await this.warpL2TimeAtLeastTo(sequencerClient, node, targetTimestamp);
113
+ async warpL2TimeAtLeastBy(node: AztecNode & AztecNodeDebug, duration: bigint | number) {
114
+ if (BigInt(duration) <= 0n) {
115
+ throw new Error(`warpL2TimeAtLeastBy: duration must be positive, got ${duration} seconds.`);
116
+ }
117
+
118
+ // Advance relative to whichever clock leads. A live sequencer mines L2 blocks at slot boundaries that can run
119
+ // ahead of anvil's L1 timestamp, so basing the target on L1 alone would advance the L2 timestamp by less than
120
+ // `duration`. Anchoring to the latest L2 block timestamp when it leads guarantees the post-warp L2 block is at
121
+ // least `duration` ahead of the current one.
122
+ const currentL1Timestamp = BigInt(await this.eth.lastBlockTimestamp());
123
+ const latestBlockData = await node.getBlockData('latest');
124
+ const latestL2Timestamp = latestBlockData ? BigInt(latestBlockData.header.globalVariables.timestamp) : 0n;
125
+ const baseTimestamp = latestL2Timestamp > currentL1Timestamp ? latestL2Timestamp : currentL1Timestamp;
126
+ const targetTimestamp = baseTimestamp + BigInt(duration);
127
+ await this.warpL2TimeAtLeastTo(node, targetTimestamp);
78
128
  }
79
129
  }
@@ -1,10 +1,9 @@
1
- import { Fr } from '@aztec/aztec.js/fields';
2
1
  import { type EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
- import { type EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import type { EpochNumber } from '@aztec/foundation/branded-types';
4
3
  import type { Logger } from '@aztec/foundation/log';
4
+ import { settleEpochOutbox } from '@aztec/prover-client/test';
5
5
  import { EpochMonitor } from '@aztec/prover-node';
6
6
  import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
7
- import { computeEpochOutHash } from '@aztec/stdlib/messaging';
8
7
 
9
8
  export class EpochTestSettler {
10
9
  private rollupCheatCodes: RollupCheatCodes;
@@ -31,34 +30,12 @@ export class EpochTestSettler {
31
30
  }
32
31
 
33
32
  async handleEpochReadyToProve(epoch: EpochNumber): Promise<boolean> {
34
- const checkpointedBlocks = await this.l2BlockSource.getCheckpointedBlocksForEpoch(epoch);
35
- const blocks = checkpointedBlocks.map(b => b.block);
36
- this.log.info(
37
- `Settling epoch ${epoch} with blocks ${blocks[0]?.header.getBlockNumber()} to ${blocks.at(-1)?.header.getBlockNumber()}`,
38
- { blocks: blocks.map(b => b.toBlockInfo()) },
39
- );
40
- const messagesInEpoch: Fr[][][][] = [];
41
- let previousSlotNumber = SlotNumber.ZERO;
42
- let checkpointIndex = -1;
43
-
44
- for (const block of blocks) {
45
- const slotNumber = block.header.globalVariables.slotNumber;
46
- if (slotNumber !== previousSlotNumber) {
47
- checkpointIndex++;
48
- messagesInEpoch[checkpointIndex] = [];
49
- previousSlotNumber = slotNumber;
50
- }
51
- messagesInEpoch[checkpointIndex].push(block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs));
52
- }
53
-
54
- const outHash = computeEpochOutHash(messagesInEpoch);
55
- if (!outHash.isZero()) {
56
- await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
57
- } else {
58
- this.log.info(`No L2 to L1 messages in epoch ${epoch}`);
59
- }
60
-
61
- const lastCheckpoint = checkpointedBlocks.at(-1)?.checkpointNumber;
33
+ const lastCheckpoint = await settleEpochOutbox({
34
+ rollupCheatCodes: this.rollupCheatCodes,
35
+ l2BlockSource: this.l2BlockSource,
36
+ epoch,
37
+ log: this.log,
38
+ });
62
39
  if (lastCheckpoint !== undefined) {
63
40
  await this.rollupCheatCodes.markAsProven(lastCheckpoint);
64
41
  } else {
@@ -1,4 +1,3 @@
1
- export { AnvilTestWatcher } from './anvil_test_watcher.js';
2
1
  export { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
2
  export { CheatCodes } from './cheat_codes.js';
4
3
  export { EpochTestSettler } from './epoch_test_settler.js';
@@ -1,9 +0,0 @@
1
- import { type ArchiverConfig } from '@aztec/archiver';
2
- import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
3
- import { type DataStoreConfig } from '@aztec/stdlib/kv-store';
4
- export type { ArchiverConfig, DataStoreConfig };
5
- /** Starts a standalone archiver. */
6
- export declare function startArchiver(options: any, signalHandlers: (() => Promise<void>)[], services: NamespacedApiHandlers): Promise<{
7
- config: ArchiverConfig & DataStoreConfig;
8
- }>;
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfYXJjaGl2ZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvY21kcy9zdGFydF9hcmNoaXZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQW9FLE1BQU0saUJBQWlCLENBQUM7QUFJeEgsT0FBTyxLQUFLLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUUvRSxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0sd0JBQXdCLENBQUM7QUFLbEYsWUFBWSxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsQ0FBQztBQUVoRCxvQ0FBb0M7QUFDcEMsd0JBQXNCLGFBQWEsQ0FDakMsT0FBTyxFQUFFLEdBQUcsRUFDWixjQUFjLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQ3ZDLFFBQVEsRUFBRSxxQkFBcUIsR0FDOUIsT0FBTyxDQUFDO0lBQUUsTUFBTSxFQUFFLGNBQWMsR0FBRyxlQUFlLENBQUE7Q0FBRSxDQUFDLENBK0J2RCJ9
@@ -1 +0,0 @@
1
- {"version":3,"file":"start_archiver.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/start_archiver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAoE,MAAM,iBAAiB,CAAC;AAIxH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,wBAAwB,CAAC;AAKlF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AAEhD,oCAAoC;AACpC,wBAAsB,aAAa,CACjC,OAAO,EAAE,GAAG,EACZ,cAAc,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EACvC,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,GAAG,eAAe,CAAA;CAAE,CAAC,CA+BvD"}
@@ -1,48 +0,0 @@
1
- import { archiverConfigMappings, createArchiver, getArchiverConfigFromEnv } from '@aztec/archiver';
2
- import { createLogger } from '@aztec/aztec.js/log';
3
- import { blobClientConfigMapping, createBlobClient } from '@aztec/blob-client/client';
4
- import { getL1Config } from '@aztec/cli/config';
5
- import { ArchiverApiSchema } from '@aztec/stdlib/interfaces/server';
6
- import { dataConfigMappings } from '@aztec/stdlib/kv-store';
7
- import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
8
- import { extractRelevantOptions } from '../util.js';
9
- /** Starts a standalone archiver. */ export async function startArchiver(options, signalHandlers, services) {
10
- const envConfig = getArchiverConfigFromEnv();
11
- const cliOptions = extractRelevantOptions(options, {
12
- ...archiverConfigMappings,
13
- ...dataConfigMappings,
14
- ...blobClientConfigMapping
15
- }, 'archiver');
16
- let archiverConfig = {
17
- ...envConfig,
18
- ...cliOptions
19
- };
20
- archiverConfig.dataStoreMapSizeKb = archiverConfig.archiverStoreMapSizeKb ?? archiverConfig.dataStoreMapSizeKb;
21
- if (!archiverConfig.l1Contracts.registryAddress || archiverConfig.l1Contracts.registryAddress.isZero()) {
22
- throw new Error('L1 registry address is required to start an Archiver');
23
- }
24
- const { addresses, config: l1Config } = await getL1Config(archiverConfig.l1Contracts.registryAddress, archiverConfig.l1RpcUrls, archiverConfig.l1ChainId);
25
- archiverConfig.l1Contracts = addresses;
26
- archiverConfig = {
27
- ...archiverConfig,
28
- ...l1Config
29
- };
30
- const telemetry = await initTelemetryClient(getTelemetryClientConfig());
31
- const blobClient = createBlobClient(archiverConfig, {
32
- logger: createLogger('archiver:blob-client:client')
33
- });
34
- const archiver = await createArchiver(archiverConfig, {
35
- telemetry,
36
- blobClient
37
- }, {
38
- blockUntilSync: true
39
- });
40
- services.archiver = [
41
- archiver,
42
- ArchiverApiSchema
43
- ];
44
- signalHandlers.push(archiver.stop);
45
- return {
46
- config: archiverConfig
47
- };
48
- }