@aztec/aztec 4.0.0-nightly.20260108 → 4.0.0-nightly.20260110

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 CHANGED
@@ -12,6 +12,7 @@ import { injectCommands as injectValidatorKeysCommands } from '@aztec/cli/valida
12
12
  import { getActiveNetworkName } from '@aztec/foundation/config';
13
13
  import { createConsoleLogger, createLogger } from '@aztec/foundation/log';
14
14
  import { Command } from 'commander';
15
+ import { injectMigrateCommand } from '../cli/cmds/migrate_ha_db.js';
15
16
  import { injectAztecCommands } from '../cli/index.js';
16
17
  import { getCliVersion } from '../cli/release_version.js';
17
18
  const NETWORK_FLAG = 'network';
@@ -44,6 +45,7 @@ const debugLogger = createLogger('cli');
44
45
  program = injectAztecNodeCommands(program, userLog, debugLogger);
45
46
  program = injectMiscCommands(program, userLog);
46
47
  program = injectValidatorKeysCommands(program, userLog);
48
+ program = injectMigrateCommand(program, userLog);
47
49
  await program.parseAsync(process.argv);
48
50
  }
49
51
  main().catch((err)=>{
@@ -1,3 +1,3 @@
1
1
  import type { LogFn, Logger } from '@aztec/foundation/log';
2
2
  export declare function aztecStart(options: any, userLog: LogFn, debugLogger: Logger): Promise<void>;
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXp0ZWNfc3RhcnRfYWN0aW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpL2F6dGVjX3N0YXJ0X2FjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFZM0Qsd0JBQXNCLFVBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBeUZqRiJ9
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXp0ZWNfc3RhcnRfYWN0aW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpL2F6dGVjX3N0YXJ0X2FjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFZM0Qsd0JBQXNCLFVBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBOEZqRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"aztec_start_action.d.ts","sourceRoot":"","sources":["../../src/cli/aztec_start_action.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAY3D,wBAAsB,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAyFjF"}
1
+ {"version":3,"file":"aztec_start_action.d.ts","sourceRoot":"","sources":["../../src/cli/aztec_start_action.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAY3D,wBAAsB,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBA8FjF"}
@@ -23,7 +23,12 @@ export async function aztecStart(options, userLog, debugLogger) {
23
23
  l1Mnemonic: localNetwork.l1Mnemonic,
24
24
  l1RpcUrls: options.l1RpcUrls,
25
25
  testAccounts: localNetwork.testAccounts,
26
- realProofs: false
26
+ realProofs: false,
27
+ // Setting the epoch duration to 4 by default for local network. This allows the epoch to be "proven" faster, so
28
+ // the users can consume out hash without having to wait for a long time.
29
+ // Note: We are not proving anything in the local network (realProofs == false). But in `createLocalNetwork`,
30
+ // the EpochTestSettler will set the out hash to the outbox when an epoch is complete.
31
+ aztecEpochDuration: 4
27
32
  }, userLog);
28
33
  // Start Node and PXE JSON-RPC server
29
34
  signalHandlers.push(stop);
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function injectMigrateCommand(program: Command, log: (msg: string) => void): Command;
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0ZV9oYV9kYi5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NsaS9jbWRzL21pZ3JhdGVfaGFfZGIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXpDLHdCQUFnQixvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxNQUFNLEtBQUssSUFBSSxHQUFHLE9BQU8sQ0FzQzFGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate_ha_db.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/migrate_ha_db.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAsC1F"}
@@ -0,0 +1,27 @@
1
+ import { runMigrations } from '@aztec/validator-ha-signer/migrations';
2
+ export function injectMigrateCommand(program, log) {
3
+ const migrateCommand = program.command('migrate-ha-db').description('Run validator-ha-signer database migrations');
4
+ migrateCommand.command('up').description('Apply pending migrations').requiredOption('--database-url <string>', 'PostgreSQL connection string', process.env.DATABASE_URL).option('--verbose', 'Enable verbose output', false).action(async (options)=>{
5
+ const migrations = await runMigrations(options.databaseUrl, {
6
+ direction: 'up',
7
+ verbose: options.verbose
8
+ });
9
+ if (migrations.length > 0) {
10
+ log(`Applied migrations: ${migrations.join(', ')}`);
11
+ } else {
12
+ log('No migrations to apply - schema is up to date');
13
+ }
14
+ });
15
+ migrateCommand.command('down').description('Rollback the last migration').requiredOption('--database-url <string>', 'PostgreSQL connection string', process.env.DATABASE_URL).option('--verbose', 'Enable verbose output', false).action(async (options)=>{
16
+ const migrations = await runMigrations(options.databaseUrl, {
17
+ direction: 'down',
18
+ verbose: options.verbose
19
+ });
20
+ if (migrations.length > 0) {
21
+ log(`Rolled back migrations: ${migrations.join(', ')}`);
22
+ } else {
23
+ log('No migrations to rollback');
24
+ }
25
+ });
26
+ return program;
27
+ }
@@ -69,4 +69,4 @@ export declare function createAztecNode(config?: Partial<AztecNodeConfig>, deps?
69
69
  }, options?: {
70
70
  prefilledPublicData?: PublicDataTreeLeaf[];
71
71
  }): Promise<AztecNodeService>;
72
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwtbmV0d29yay5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xvY2FsLW5ldHdvcmsvbG9jYWwtbmV0d29yay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBRUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLEtBQUssZUFBZSxFQUFvQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsS0FBSyxtQkFBbUIsRUFBb0IsTUFBTSwyQkFBMkIsQ0FBQztBQVN2RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBb0IsTUFBTSx5QkFBeUIsQ0FBQztBQUd6RSxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFHckIsTUFBTSx5QkFBeUIsQ0FBQztBQUlqQyxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQTJELE1BQU0sTUFBTSxDQUFDO0FBY3pGOzs7O0dBSUc7QUFDSCx3QkFBc0IsbUJBQW1CLENBQ3ZDLGVBQWUsRUFBRSxlQUFlLEVBQ2hDLFVBQVUsRUFBRSxHQUFHLEVBQ2YsSUFBSSxHQUFFO0lBQ0osOEJBQThCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDeEMsa0JBQWtCLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDeEIsNEJBQTRCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDbEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JQO0FBRUQsOEJBQThCO0FBQzlCLE1BQU0sTUFBTSxrQkFBa0IsR0FBRyxlQUFlLEdBQUc7SUFDakQsMERBQTBEO0lBQzFELFVBQVUsRUFBRSxNQUFNLENBQUM7SUFDbkIsNkRBQTZEO0lBQzdELFlBQVksRUFBRSxPQUFPLENBQUM7Q0FDdkIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBc0Isa0JBQWtCLENBQUMsTUFBTSx5Q0FBa0MsRUFBRSxPQUFPLEVBQUUsS0FBSzs7O0dBK0doRztBQUVEOzs7R0FHRztBQUNILHdCQUFzQixlQUFlLENBQ25DLE1BQU0sR0FBRSxPQUFPLENBQUMsZUFBZSxDQUFNLEVBQ3JDLElBQUksR0FBRTtJQUFFLFNBQVMsQ0FBQyxFQUFFLGVBQWUsQ0FBQztJQUFDLFVBQVUsQ0FBQyxFQUFFLG1CQUFtQixDQUFDO0lBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFBO0NBQU8sRUFDekcsT0FBTyxHQUFFO0lBQUUsbUJBQW1CLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxDQUFBO0NBQU8sNkJBVzdEIn0=
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwtbmV0d29yay5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xvY2FsLW5ldHdvcmsvbG9jYWwtbmV0d29yay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBRUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDckQsT0FBTyxFQUFFLEtBQUssZUFBZSxFQUFvQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsS0FBSyxtQkFBbUIsRUFBb0IsTUFBTSwyQkFBMkIsQ0FBQztBQVN2RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBb0IsTUFBTSx5QkFBeUIsQ0FBQztBQUd6RSxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlELE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFHckIsTUFBTSx5QkFBeUIsQ0FBQztBQUlqQyxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQTJELE1BQU0sTUFBTSxDQUFDO0FBZXpGOzs7O0dBSUc7QUFDSCx3QkFBc0IsbUJBQW1CLENBQ3ZDLGVBQWUsRUFBRSxlQUFlLEVBQ2hDLFVBQVUsRUFBRSxHQUFHLEVBQ2YsSUFBSSxHQUFFO0lBQ0osOEJBQThCLENBQUMsRUFBRSxNQUFNLENBQUM7SUFDeEMsa0JBQWtCLENBQUMsRUFBRSxFQUFFLENBQUM7SUFDeEIsNEJBQTRCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDbEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JQO0FBRUQsOEJBQThCO0FBQzlCLE1BQU0sTUFBTSxrQkFBa0IsR0FBRyxlQUFlLEdBQUc7SUFDakQsMERBQTBEO0lBQzFELFVBQVUsRUFBRSxNQUFNLENBQUM7SUFDbkIsNkRBQTZEO0lBQzdELFlBQVksRUFBRSxPQUFPLENBQUM7Q0FDdkIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBc0Isa0JBQWtCLENBQUMsTUFBTSx5Q0FBa0MsRUFBRSxPQUFPLEVBQUUsS0FBSzs7O0dBOEhoRztBQUVEOzs7R0FHRztBQUNILHdCQUFzQixlQUFlLENBQ25DLE1BQU0sR0FBRSxPQUFPLENBQUMsZUFBZSxDQUFNLEVBQ3JDLElBQUksR0FBRTtJQUFFLFNBQVMsQ0FBQyxFQUFFLGVBQWUsQ0FBQztJQUFDLFVBQVUsQ0FBQyxFQUFFLG1CQUFtQixDQUFDO0lBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFBO0NBQU8sRUFDekcsT0FBTyxHQUFFO0lBQUUsbUJBQW1CLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxDQUFBO0NBQU8sNkJBVzdEIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"local-network.d.ts","sourceRoot":"","sources":["../../src/local-network/local-network.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAE5C,OAAO,EAAE,KAAK,mBAAmB,EAAoB,MAAM,2BAA2B,CAAC;AASvF,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAoB,MAAM,yBAAyB,CAAC;AAGzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,KAAK,GAAG,EAA2D,MAAM,MAAM,CAAC;AAczF;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,GAAG,EACf,IAAI,GAAE;IACJ,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,EAAE,CAAC;IACxB,4BAA4B,CAAC,EAAE,MAAM,CAAC;CAClC;;;;;;;;;;;;;;;;;;;;;;;GAoBP;AAED,8BAA8B;AAC9B,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG;IACjD,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,yCAAkC,EAAE,OAAO,EAAE,KAAK;;;GA+GhG;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,EACrC,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,eAAe,CAAC;IAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAO,EACzG,OAAO,GAAE;IAAE,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAAO,6BAW7D"}
1
+ {"version":3,"file":"local-network.d.ts","sourceRoot":"","sources":["../../src/local-network/local-network.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAE5C,OAAO,EAAE,KAAK,mBAAmB,EAAoB,MAAM,2BAA2B,CAAC;AASvF,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAoB,MAAM,yBAAyB,CAAC;AAGzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAE,KAAK,GAAG,EAA2D,MAAM,MAAM,CAAC;AAezF;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,GAAG,EACf,IAAI,GAAE;IACJ,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,EAAE,CAAC;IACxB,4BAA4B,CAAC,EAAE,MAAM,CAAC;CAClC;;;;;;;;;;;;;;;;;;;;;;;GAoBP;AAED,8BAA8B;AAC9B,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG;IACjD,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,yCAAkC,EAAE,OAAO,EAAE,KAAK;;;GA8HhG;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,EACrC,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,eAAe,CAAC;IAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAO,EACzG,OAAO,GAAE;IAAE,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAAO,6BAW7D"}
@@ -26,6 +26,7 @@ import { foundry } from 'viem/chains';
26
26
  import { createAccountLogs } from '../cli/util.js';
27
27
  import { DefaultMnemonic } from '../mnemonic.js';
28
28
  import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
29
+ import { EpochTestSettler } from '../testing/epoch_test_settler.js';
29
30
  import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
30
31
  import { getSponsoredFPCAddress } from './sponsored_fpc.js';
31
32
  const logger = createLogger('local-network');
@@ -101,14 +102,16 @@ const localAnvil = foundry;
101
102
  sponsoredFPC
102
103
  ] : [];
103
104
  const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
104
- let watcher = undefined;
105
105
  const dateProvider = new TestDateProvider();
106
+ let cheatcodes;
107
+ let rollupAddress;
108
+ let watcher;
106
109
  if (!aztecNodeConfig.p2pEnabled) {
107
- const l1ContractAddresses = await deployContractsToL1(aztecNodeConfig, aztecNodeConfig.validatorPrivateKeys.getValue()[0], {
110
+ ({ rollupAddress } = await deployContractsToL1(aztecNodeConfig, aztecNodeConfig.validatorPrivateKeys.getValue()[0], {
108
111
  assumeProvenThroughBlockNumber: Number.MAX_SAFE_INTEGER,
109
112
  genesisArchiveRoot,
110
113
  feeJuicePortalInitialBalance: fundingNeeded
111
- });
114
+ }));
112
115
  const chain = aztecNodeConfig.l1RpcUrls.length > 0 ? createEthereumChain([
113
116
  l1RpcUrl
114
117
  ], aztecNodeConfig.l1ChainId) : {
@@ -120,10 +123,12 @@ const localAnvil = foundry;
120
123
  httpViemTransport(l1RpcUrl)
121
124
  ])
122
125
  });
123
- watcher = new AnvilTestWatcher(new EthCheatCodes([
126
+ cheatcodes = new EthCheatCodes([
124
127
  l1RpcUrl
125
- ], dateProvider), l1ContractAddresses.rollupAddress, publicClient, dateProvider);
128
+ ], dateProvider);
129
+ watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
126
130
  watcher.setisLocalNetwork(true);
131
+ watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
127
132
  await watcher.start();
128
133
  }
129
134
  const telemetry = await initTelemetryClient(getTelemetryClientConfig());
@@ -136,6 +141,13 @@ const localAnvil = foundry;
136
141
  }, {
137
142
  prefilledPublicData
138
143
  });
144
+ let epochTestSettler;
145
+ if (!aztecNodeConfig.p2pEnabled) {
146
+ epochTestSettler = new EpochTestSettler(cheatcodes, rollupAddress, node.getBlockSource(), {
147
+ pollingIntervalMs: 200
148
+ });
149
+ await epochTestSettler.start();
150
+ }
139
151
  if (initialAccounts.length) {
140
152
  const PXEConfig = {
141
153
  proverEnabled: aztecNodeConfig.realProofs
@@ -157,6 +169,7 @@ const localAnvil = foundry;
157
169
  const stop = async ()=>{
158
170
  await node.stop();
159
171
  await watcher?.stop();
172
+ await epochTestSettler?.stop();
160
173
  };
161
174
  return {
162
175
  node,
@@ -0,0 +1,17 @@
1
+ import { type EthCheatCodes } from '@aztec/ethereum/test';
2
+ import { type EpochNumber } from '@aztec/foundation/branded-types';
3
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
4
+ export declare class EpochTestSettler {
5
+ private l2BlockSource;
6
+ private options;
7
+ private rollupCheatCodes;
8
+ private epochMonitor?;
9
+ constructor(cheatcodes: EthCheatCodes, rollupAddress: EthAddress, l2BlockSource: L2BlockSource, options: {
10
+ pollingIntervalMs: number;
11
+ provingDelayMs?: number;
12
+ });
13
+ start(): Promise<void>;
14
+ stop(): Promise<void>;
15
+ handleEpochReadyToProve(epoch: EpochNumber): Promise<boolean>;
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfdGVzdF9zZXR0bGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdGluZy9lcG9jaF90ZXN0X3NldHRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssYUFBYSxFQUFvQixNQUFNLHNCQUFzQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxLQUFLLFdBQVcsRUFBYyxNQUFNLGlDQUFpQyxDQUFDO0FBRS9FLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUdyRSxxQkFBYSxnQkFBZ0I7SUFPekIsT0FBTyxDQUFDLGFBQWE7SUFDckIsT0FBTyxDQUFDLE9BQU87SUFQakIsT0FBTyxDQUFDLGdCQUFnQixDQUFtQjtJQUMzQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQWU7SUFFcEMsWUFDRSxVQUFVLEVBQUUsYUFBYSxFQUN6QixhQUFhLEVBQUUsVUFBVSxFQUNqQixhQUFhLEVBQUUsYUFBYSxFQUM1QixPQUFPLEVBQUU7UUFBRSxpQkFBaUIsRUFBRSxNQUFNLENBQUM7UUFBQyxjQUFjLENBQUMsRUFBRSxNQUFNLENBQUE7S0FBRSxFQUd4RTtJQUVLLEtBQUssa0JBSVY7SUFFSyxJQUFJLGtCQUVUO0lBRUssdUJBQXVCLENBQUMsS0FBSyxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBMkJsRTtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epoch_test_settler.d.ts","sourceRoot":"","sources":["../../src/testing/epoch_test_settler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,iCAAiC,CAAC;AAE/E,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGrE,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,OAAO;IAPjB,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,YACE,UAAU,EAAE,aAAa,EACzB,aAAa,EAAE,UAAU,EACjB,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,EAGxE;IAEK,KAAK,kBAIV;IAEK,IAAI,kBAET;IAEK,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CA2BlE;CACF"}
@@ -0,0 +1,52 @@
1
+ import { RollupCheatCodes } from '@aztec/ethereum/test';
2
+ import { SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { EpochMonitor } from '@aztec/prover-node';
4
+ import { computeL2ToL1MembershipWitnessFromMessagesInEpoch } from '@aztec/stdlib/messaging';
5
+ export class EpochTestSettler {
6
+ l2BlockSource;
7
+ options;
8
+ rollupCheatCodes;
9
+ epochMonitor;
10
+ constructor(cheatcodes, rollupAddress, l2BlockSource, options){
11
+ this.l2BlockSource = l2BlockSource;
12
+ this.options = options;
13
+ this.rollupCheatCodes = new RollupCheatCodes(cheatcodes, {
14
+ rollupAddress
15
+ });
16
+ }
17
+ async start() {
18
+ const { epochDuration } = await this.rollupCheatCodes.getConfig();
19
+ this.epochMonitor = new EpochMonitor(this.l2BlockSource, {
20
+ epochDuration: Number(epochDuration)
21
+ }, this.options);
22
+ this.epochMonitor.start(this);
23
+ }
24
+ async stop() {
25
+ await this.epochMonitor?.stop();
26
+ }
27
+ async handleEpochReadyToProve(epoch) {
28
+ const blocks = await this.l2BlockSource.getBlocksForEpoch(epoch);
29
+ const messagesInEpoch = [];
30
+ let previousSlotNumber = SlotNumber.ZERO;
31
+ let checkpointIndex = -1;
32
+ for (const block of blocks){
33
+ const slotNumber = block.header.globalVariables.slotNumber;
34
+ if (slotNumber !== previousSlotNumber) {
35
+ checkpointIndex++;
36
+ messagesInEpoch[checkpointIndex] = [];
37
+ previousSlotNumber = slotNumber;
38
+ }
39
+ messagesInEpoch[checkpointIndex].push(block.body.txEffects.map((txEffect)=>txEffect.l2ToL1Msgs));
40
+ }
41
+ const [firstMessage] = messagesInEpoch.flat(3);
42
+ if (firstMessage) {
43
+ const { root: outHash } = computeL2ToL1MembershipWitnessFromMessagesInEpoch(messagesInEpoch, firstMessage);
44
+ await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
45
+ }
46
+ // Mark the blocks as proven.
47
+ for (const block of blocks){
48
+ await this.rollupCheatCodes.markAsProven(block.number);
49
+ }
50
+ return true;
51
+ }
52
+ }
@@ -1,4 +1,5 @@
1
1
  export { AnvilTestWatcher } from './anvil_test_watcher.js';
2
2
  export { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
3
  export { CheatCodes } from './cheat_codes.js';
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUMifQ==
4
+ export { EpochTestSettler } from './epoch_test_settler.js';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0aW5nL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0seUJBQXlCLENBQUMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { AnvilTestWatcher } from './anvil_test_watcher.js';
2
2
  export { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
3
  export { CheatCodes } from './cheat_codes.js';
4
+ export { EpochTestSettler } from './epoch_test_settler.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/aztec",
3
- "version": "4.0.0-nightly.20260108",
3
+ "version": "4.0.0-nightly.20260110",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -28,38 +28,39 @@
28
28
  "../package.common.json"
29
29
  ],
30
30
  "dependencies": {
31
- "@aztec/accounts": "4.0.0-nightly.20260108",
32
- "@aztec/archiver": "4.0.0-nightly.20260108",
33
- "@aztec/aztec-faucet": "4.0.0-nightly.20260108",
34
- "@aztec/aztec-node": "4.0.0-nightly.20260108",
35
- "@aztec/aztec.js": "4.0.0-nightly.20260108",
36
- "@aztec/bb-prover": "4.0.0-nightly.20260108",
37
- "@aztec/bb.js": "4.0.0-nightly.20260108",
38
- "@aztec/blob-client": "4.0.0-nightly.20260108",
39
- "@aztec/bot": "4.0.0-nightly.20260108",
40
- "@aztec/builder": "4.0.0-nightly.20260108",
41
- "@aztec/cli": "4.0.0-nightly.20260108",
42
- "@aztec/constants": "4.0.0-nightly.20260108",
43
- "@aztec/entrypoints": "4.0.0-nightly.20260108",
44
- "@aztec/ethereum": "4.0.0-nightly.20260108",
45
- "@aztec/foundation": "4.0.0-nightly.20260108",
46
- "@aztec/kv-store": "4.0.0-nightly.20260108",
47
- "@aztec/l1-artifacts": "4.0.0-nightly.20260108",
48
- "@aztec/node-lib": "4.0.0-nightly.20260108",
49
- "@aztec/noir-contracts.js": "4.0.0-nightly.20260108",
50
- "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260108",
51
- "@aztec/p2p": "4.0.0-nightly.20260108",
52
- "@aztec/p2p-bootstrap": "4.0.0-nightly.20260108",
53
- "@aztec/protocol-contracts": "4.0.0-nightly.20260108",
54
- "@aztec/prover-client": "4.0.0-nightly.20260108",
55
- "@aztec/prover-node": "4.0.0-nightly.20260108",
56
- "@aztec/pxe": "4.0.0-nightly.20260108",
57
- "@aztec/sequencer-client": "4.0.0-nightly.20260108",
58
- "@aztec/stdlib": "4.0.0-nightly.20260108",
59
- "@aztec/telemetry-client": "4.0.0-nightly.20260108",
60
- "@aztec/test-wallet": "4.0.0-nightly.20260108",
61
- "@aztec/txe": "4.0.0-nightly.20260108",
62
- "@aztec/world-state": "4.0.0-nightly.20260108",
31
+ "@aztec/accounts": "4.0.0-nightly.20260110",
32
+ "@aztec/archiver": "4.0.0-nightly.20260110",
33
+ "@aztec/aztec-faucet": "4.0.0-nightly.20260110",
34
+ "@aztec/aztec-node": "4.0.0-nightly.20260110",
35
+ "@aztec/aztec.js": "4.0.0-nightly.20260110",
36
+ "@aztec/bb-prover": "4.0.0-nightly.20260110",
37
+ "@aztec/bb.js": "4.0.0-nightly.20260110",
38
+ "@aztec/blob-client": "4.0.0-nightly.20260110",
39
+ "@aztec/bot": "4.0.0-nightly.20260110",
40
+ "@aztec/builder": "4.0.0-nightly.20260110",
41
+ "@aztec/cli": "4.0.0-nightly.20260110",
42
+ "@aztec/constants": "4.0.0-nightly.20260110",
43
+ "@aztec/entrypoints": "4.0.0-nightly.20260110",
44
+ "@aztec/ethereum": "4.0.0-nightly.20260110",
45
+ "@aztec/foundation": "4.0.0-nightly.20260110",
46
+ "@aztec/kv-store": "4.0.0-nightly.20260110",
47
+ "@aztec/l1-artifacts": "4.0.0-nightly.20260110",
48
+ "@aztec/node-lib": "4.0.0-nightly.20260110",
49
+ "@aztec/noir-contracts.js": "4.0.0-nightly.20260110",
50
+ "@aztec/noir-protocol-circuits-types": "4.0.0-nightly.20260110",
51
+ "@aztec/p2p": "4.0.0-nightly.20260110",
52
+ "@aztec/p2p-bootstrap": "4.0.0-nightly.20260110",
53
+ "@aztec/protocol-contracts": "4.0.0-nightly.20260110",
54
+ "@aztec/prover-client": "4.0.0-nightly.20260110",
55
+ "@aztec/prover-node": "4.0.0-nightly.20260110",
56
+ "@aztec/pxe": "4.0.0-nightly.20260110",
57
+ "@aztec/sequencer-client": "4.0.0-nightly.20260110",
58
+ "@aztec/stdlib": "4.0.0-nightly.20260110",
59
+ "@aztec/telemetry-client": "4.0.0-nightly.20260110",
60
+ "@aztec/test-wallet": "4.0.0-nightly.20260110",
61
+ "@aztec/txe": "4.0.0-nightly.20260110",
62
+ "@aztec/validator-ha-signer": "4.0.0-nightly.20260110",
63
+ "@aztec/world-state": "4.0.0-nightly.20260110",
63
64
  "@types/chalk": "^2.2.0",
64
65
  "abitype": "^0.8.11",
65
66
  "chalk": "^5.3.0",
package/src/bin/index.ts CHANGED
@@ -14,6 +14,7 @@ import { createConsoleLogger, createLogger } from '@aztec/foundation/log';
14
14
 
15
15
  import { Command } from 'commander';
16
16
 
17
+ import { injectMigrateCommand } from '../cli/cmds/migrate_ha_db.js';
17
18
  import { injectAztecCommands } from '../cli/index.js';
18
19
  import { getCliVersion } from '../cli/release_version.js';
19
20
 
@@ -55,6 +56,7 @@ async function main() {
55
56
  program = injectAztecNodeCommands(program, userLog, debugLogger);
56
57
  program = injectMiscCommands(program, userLog);
57
58
  program = injectValidatorKeysCommands(program, userLog);
59
+ program = injectMigrateCommand(program, userLog);
58
60
 
59
61
  await program.parseAsync(process.argv);
60
62
  }
@@ -35,6 +35,11 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
35
35
  l1RpcUrls: options.l1RpcUrls,
36
36
  testAccounts: localNetwork.testAccounts,
37
37
  realProofs: false,
38
+ // Setting the epoch duration to 4 by default for local network. This allows the epoch to be "proven" faster, so
39
+ // the users can consume out hash without having to wait for a long time.
40
+ // Note: We are not proving anything in the local network (realProofs == false). But in `createLocalNetwork`,
41
+ // the EpochTestSettler will set the out hash to the outbox when an epoch is complete.
42
+ aztecEpochDuration: 4,
38
43
  },
39
44
  userLog,
40
45
  );
@@ -0,0 +1,43 @@
1
+ import { runMigrations } from '@aztec/validator-ha-signer/migrations';
2
+
3
+ import type { Command } from 'commander';
4
+
5
+ export function injectMigrateCommand(program: Command, log: (msg: string) => void): Command {
6
+ const migrateCommand = program.command('migrate-ha-db').description('Run validator-ha-signer database migrations');
7
+
8
+ migrateCommand
9
+ .command('up')
10
+ .description('Apply pending migrations')
11
+ .requiredOption('--database-url <string>', 'PostgreSQL connection string', process.env.DATABASE_URL)
12
+ .option('--verbose', 'Enable verbose output', false)
13
+ .action(async options => {
14
+ const migrations = await runMigrations(options.databaseUrl, {
15
+ direction: 'up',
16
+ verbose: options.verbose,
17
+ });
18
+ if (migrations.length > 0) {
19
+ log(`Applied migrations: ${migrations.join(', ')}`);
20
+ } else {
21
+ log('No migrations to apply - schema is up to date');
22
+ }
23
+ });
24
+
25
+ migrateCommand
26
+ .command('down')
27
+ .description('Rollback the last migration')
28
+ .requiredOption('--database-url <string>', 'PostgreSQL connection string', process.env.DATABASE_URL)
29
+ .option('--verbose', 'Enable verbose output', false)
30
+ .action(async options => {
31
+ const migrations = await runMigrations(options.databaseUrl, {
32
+ direction: 'down',
33
+ verbose: options.verbose,
34
+ });
35
+ if (migrations.length > 0) {
36
+ log(`Rolled back migrations: ${migrations.join(', ')}`);
37
+ } else {
38
+ log('No migrations to rollback');
39
+ }
40
+ });
41
+
42
+ return program;
43
+ }
@@ -34,6 +34,7 @@ import { foundry } from 'viem/chains';
34
34
  import { createAccountLogs } from '../cli/util.js';
35
35
  import { DefaultMnemonic } from '../mnemonic.js';
36
36
  import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
37
+ import { EpochTestSettler } from '../testing/epoch_test_settler.js';
37
38
  import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
38
39
  import { getSponsoredFPCAddress } from './sponsored_fpc.js';
39
40
 
@@ -97,7 +98,11 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
97
98
  if ((config.l1RpcUrls?.length || 0) > 1) {
98
99
  logger.warn(`Multiple L1 RPC URLs provided. Local networks will only use the first one: ${l1RpcUrl}`);
99
100
  }
100
- const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config };
101
+
102
+ const aztecNodeConfig: AztecNodeConfig = {
103
+ ...getConfigEnvVars(),
104
+ ...config,
105
+ };
101
106
  const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
102
107
  if (
103
108
  aztecNodeConfig.publisherPrivateKeys == undefined ||
@@ -134,10 +139,13 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
134
139
  : [];
135
140
  const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
136
141
 
137
- let watcher: AnvilTestWatcher | undefined = undefined;
138
142
  const dateProvider = new TestDateProvider();
143
+
144
+ let cheatcodes: EthCheatCodes | undefined;
145
+ let rollupAddress: EthAddress | undefined;
146
+ let watcher: AnvilTestWatcher | undefined;
139
147
  if (!aztecNodeConfig.p2pEnabled) {
140
- const l1ContractAddresses = await deployContractsToL1(
148
+ ({ rollupAddress } = await deployContractsToL1(
141
149
  aztecNodeConfig,
142
150
  aztecNodeConfig.validatorPrivateKeys.getValue()[0],
143
151
  {
@@ -145,7 +153,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
145
153
  genesisArchiveRoot,
146
154
  feeJuicePortalInitialBalance: fundingNeeded,
147
155
  },
148
- );
156
+ ));
149
157
 
150
158
  const chain =
151
159
  aztecNodeConfig.l1RpcUrls.length > 0
@@ -157,13 +165,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
157
165
  transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
158
166
  });
159
167
 
160
- watcher = new AnvilTestWatcher(
161
- new EthCheatCodes([l1RpcUrl], dateProvider),
162
- l1ContractAddresses.rollupAddress,
163
- publicClient,
164
- dateProvider,
165
- );
168
+ cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
169
+
170
+ watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
166
171
  watcher.setisLocalNetwork(true);
172
+ watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
173
+
167
174
  await watcher.start();
168
175
  }
169
176
 
@@ -172,6 +179,14 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
172
179
  const blobClient = createBlobClient();
173
180
  const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
174
181
 
182
+ let epochTestSettler: EpochTestSettler | undefined;
183
+ if (!aztecNodeConfig.p2pEnabled) {
184
+ epochTestSettler = new EpochTestSettler(cheatcodes!, rollupAddress!, node.getBlockSource(), {
185
+ pollingIntervalMs: 200,
186
+ });
187
+ await epochTestSettler.start();
188
+ }
189
+
175
190
  if (initialAccounts.length) {
176
191
  const PXEConfig = { proverEnabled: aztecNodeConfig.realProofs };
177
192
  const wallet = await TestWallet.create(node, PXEConfig);
@@ -196,6 +211,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
196
211
  const stop = async () => {
197
212
  await node.stop();
198
213
  await watcher?.stop();
214
+ await epochTestSettler?.stop();
199
215
  };
200
216
 
201
217
  return { node, stop };
@@ -0,0 +1,59 @@
1
+ import { Fr } from '@aztec/aztec.js/fields';
2
+ import { type EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
+ import { type EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
+ import { EpochMonitor } from '@aztec/prover-node';
5
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
6
+ import { computeL2ToL1MembershipWitnessFromMessagesInEpoch } from '@aztec/stdlib/messaging';
7
+
8
+ export class EpochTestSettler {
9
+ private rollupCheatCodes: RollupCheatCodes;
10
+ private epochMonitor?: EpochMonitor;
11
+
12
+ constructor(
13
+ cheatcodes: EthCheatCodes,
14
+ rollupAddress: EthAddress,
15
+ private l2BlockSource: L2BlockSource,
16
+ private options: { pollingIntervalMs: number; provingDelayMs?: number },
17
+ ) {
18
+ this.rollupCheatCodes = new RollupCheatCodes(cheatcodes, { rollupAddress });
19
+ }
20
+
21
+ async start() {
22
+ const { epochDuration } = await this.rollupCheatCodes.getConfig();
23
+ this.epochMonitor = new EpochMonitor(this.l2BlockSource, { epochDuration: Number(epochDuration) }, this.options);
24
+ this.epochMonitor.start(this);
25
+ }
26
+
27
+ async stop() {
28
+ await this.epochMonitor?.stop();
29
+ }
30
+
31
+ async handleEpochReadyToProve(epoch: EpochNumber): Promise<boolean> {
32
+ const blocks = await this.l2BlockSource.getBlocksForEpoch(epoch);
33
+ const messagesInEpoch: Fr[][][][] = [];
34
+ let previousSlotNumber = SlotNumber.ZERO;
35
+ let checkpointIndex = -1;
36
+ for (const block of blocks) {
37
+ const slotNumber = block.header.globalVariables.slotNumber;
38
+ if (slotNumber !== previousSlotNumber) {
39
+ checkpointIndex++;
40
+ messagesInEpoch[checkpointIndex] = [];
41
+ previousSlotNumber = slotNumber;
42
+ }
43
+ messagesInEpoch[checkpointIndex].push(block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs));
44
+ }
45
+
46
+ const [firstMessage] = messagesInEpoch.flat(3);
47
+ if (firstMessage) {
48
+ const { root: outHash } = computeL2ToL1MembershipWitnessFromMessagesInEpoch(messagesInEpoch, firstMessage);
49
+ await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
50
+ }
51
+
52
+ // Mark the blocks as proven.
53
+ for (const block of blocks) {
54
+ await this.rollupCheatCodes.markAsProven(block.number);
55
+ }
56
+
57
+ return true;
58
+ }
59
+ }
@@ -1,3 +1,4 @@
1
1
  export { AnvilTestWatcher } from './anvil_test_watcher.js';
2
2
  export { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
3
3
  export { CheatCodes } from './cheat_codes.js';
4
+ export { EpochTestSettler } from './epoch_test_settler.js';