@aztec/end-to-end 2.0.0-nightly.20250825 → 2.0.0-nightly.20250827

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 (42) hide show
  1. package/dest/e2e_epochs/epochs_test.d.ts +1 -1
  2. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  3. package/dest/e2e_epochs/epochs_test.js +8 -3
  4. package/dest/e2e_fees/fees_test.d.ts.map +1 -1
  5. package/dest/e2e_fees/fees_test.js +1 -5
  6. package/dest/e2e_multi_validator/utils.d.ts +12 -0
  7. package/dest/e2e_multi_validator/utils.d.ts.map +1 -0
  8. package/dest/e2e_multi_validator/utils.js +220 -0
  9. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  10. package/dest/e2e_p2p/p2p_network.js +2 -2
  11. package/dest/fixtures/e2e_prover_test.js +4 -2
  12. package/dest/fixtures/setup_p2p_test.js +3 -1
  13. package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
  14. package/dest/fixtures/snapshot_manager.js +9 -6
  15. package/dest/fixtures/utils.d.ts +6 -1
  16. package/dest/fixtures/utils.d.ts.map +1 -1
  17. package/dest/fixtures/utils.js +27 -9
  18. package/package.json +36 -35
  19. package/src/e2e_epochs/epochs_test.ts +11 -4
  20. package/src/e2e_fees/fees_test.ts +1 -2
  21. package/src/e2e_multi_validator/utils.ts +264 -0
  22. package/src/e2e_p2p/p2p_network.ts +2 -2
  23. package/src/fixtures/e2e_prover_test.ts +2 -2
  24. package/src/fixtures/setup_p2p_test.ts +1 -1
  25. package/src/fixtures/snapshot_manager.ts +6 -3
  26. package/src/fixtures/utils.ts +39 -9
  27. package/dest/sample-dapp/connect.d.mts +0 -2
  28. package/dest/sample-dapp/connect.d.mts.map +0 -1
  29. package/dest/sample-dapp/connect.js +0 -12
  30. package/dest/sample-dapp/contracts.d.mts +0 -3
  31. package/dest/sample-dapp/contracts.d.mts.map +0 -1
  32. package/dest/sample-dapp/contracts.js +0 -10
  33. package/dest/sample-dapp/deploy.d.mts +0 -3
  34. package/dest/sample-dapp/deploy.d.mts.map +0 -1
  35. package/dest/sample-dapp/deploy.js +0 -39
  36. package/dest/sample-dapp/index.d.mts +0 -2
  37. package/dest/sample-dapp/index.d.mts.map +0 -1
  38. package/dest/sample-dapp/index.js +0 -108
  39. package/src/sample-dapp/connect.mjs +0 -16
  40. package/src/sample-dapp/contracts.mjs +0 -14
  41. package/src/sample-dapp/deploy.mjs +0 -42
  42. package/src/sample-dapp/index.mjs +0 -131
@@ -9,7 +9,7 @@ import { createBlobSinkClient } from '@aztec/blob-sink/client';
9
9
  import { createBlobSinkServer } from '@aztec/blob-sink/server';
10
10
  import { GENESIS_ARCHIVE_ROOT, SPONSORED_FPC_SALT } from '@aztec/constants';
11
11
  import { FeeAssetArtifact, NULL_KEY, RollupContract, createExtendedL1Client, deployL1Contracts, deployMulticall3, getL1ContractsConfigEnvVars, isAnvilTestChain } from '@aztec/ethereum';
12
- import { DelayedTxUtils, EthCheatCodesWithState, startAnvil } from '@aztec/ethereum/test';
12
+ import { DelayedTxUtils, EthCheatCodes, EthCheatCodesWithState, createDelayedL1TxUtilsFromViemWallet, startAnvil } from '@aztec/ethereum/test';
13
13
  import { SecretValue } from '@aztec/foundation/config';
14
14
  import { randomBytes } from '@aztec/foundation/crypto';
15
15
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -36,7 +36,7 @@ import getPort from 'get-port';
36
36
  import { tmpdir } from 'os';
37
37
  import * as path from 'path';
38
38
  import { getContract } from 'viem';
39
- import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
39
+ import { generatePrivateKey, mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
40
40
  import { foundry } from 'viem/chains';
41
41
  import { MNEMONIC, TEST_PEER_CHECK_INTERVAL_MS } from './fixtures.js';
42
42
  import { getACVMConfig } from './get_acvm_config.js';
@@ -143,6 +143,7 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
143
143
  l1Client,
144
144
  rollupVersion
145
145
  };
146
+ const ethCheatCodes = new EthCheatCodes(config.l1RpcUrls);
146
147
  const cheatCodes = await CheatCodes.create(config.l1RpcUrls, pxeClient);
147
148
  const teardown = ()=>Promise.resolve();
148
149
  logger.verbose('Constructing available wallets from already registered accounts...');
@@ -166,6 +167,7 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
166
167
  accounts: wallets.slice(0, numberOfAccounts).map((w)=>w.getAddress()),
167
168
  logger,
168
169
  cheatCodes,
170
+ ethCheatCodes,
169
171
  prefilledPublicData: undefined,
170
172
  mockGossipSubNetwork: undefined,
171
173
  watcher: undefined,
@@ -240,8 +242,10 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
240
242
  }
241
243
  let publisherPrivKey = undefined;
242
244
  let publisherHdAccount = undefined;
243
- if (config.publisherPrivateKey && config.publisherPrivateKey.getValue() != NULL_KEY) {
244
- publisherHdAccount = privateKeyToAccount(config.publisherPrivateKey.getValue());
245
+ if (opts.l1PublisherKey && opts.l1PublisherKey.getValue() && opts.l1PublisherKey.getValue() != NULL_KEY) {
246
+ publisherHdAccount = privateKeyToAccount(opts.l1PublisherKey.getValue());
247
+ } else if (config.publisherPrivateKeys && config.publisherPrivateKeys.length > 0 && config.publisherPrivateKeys[0].getValue() != NULL_KEY) {
248
+ publisherHdAccount = privateKeyToAccount(config.publisherPrivateKeys[0].getValue());
245
249
  } else if (!MNEMONIC) {
246
250
  throw new Error(`Mnemonic not provided and no publisher private key`);
247
251
  } else {
@@ -250,8 +254,11 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
250
254
  });
251
255
  const publisherPrivKeyRaw = publisherHdAccount.getHdKey().privateKey;
252
256
  publisherPrivKey = publisherPrivKeyRaw === null ? null : Buffer.from(publisherPrivKeyRaw);
253
- config.publisherPrivateKey = new SecretValue(`0x${publisherPrivKey.toString('hex')}`);
257
+ config.publisherPrivateKeys = [
258
+ new SecretValue(`0x${publisherPrivKey.toString('hex')}`)
259
+ ];
254
260
  }
261
+ config.coinbase = EthAddress.fromString(publisherHdAccount.address);
255
262
  if (PXE_URL) {
256
263
  // we are setting up against a remote environment, l1 contracts are assumed to already be deployed
257
264
  return await setupWithRemoteEnvironment(publisherHdAccount, config, logger, numberOfAccounts);
@@ -365,6 +372,13 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
365
372
  config.minTxsPerBlock = numberOfAccounts === 0 ? 0 : 1;
366
373
  config.p2pEnabled = opts.mockGossipSubNetwork || config.p2pEnabled;
367
374
  config.p2pIp = opts.p2pIp ?? config.p2pIp ?? '127.0.0.1';
375
+ if (!config.disableValidator) {
376
+ if ((config.validatorPrivateKeys?.getValue().length ?? 0) === 0) {
377
+ config.validatorPrivateKeys = new SecretValue([
378
+ generatePrivateKey()
379
+ ]);
380
+ }
381
+ }
368
382
  const aztecNode = await AztecNodeService.createAndSync(config, {
369
383
  dateProvider,
370
384
  blobSinkClient,
@@ -377,7 +391,7 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
377
391
  const sequencerClient = aztecNode.getSequencer();
378
392
  if (sequencerClient) {
379
393
  const publisher = sequencerClient.sequencer.publisher;
380
- publisher.l1TxUtils = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, config.ethereumSlotDuration);
394
+ publisher.l1TxUtils = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, config.ethereumSlotDuration, l1Client);
381
395
  }
382
396
  let proverNode = undefined;
383
397
  if (opts.startProverNode) {
@@ -434,8 +448,8 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
434
448
  if (bbConfig?.cleanup) {
435
449
  await bbConfig.cleanup();
436
450
  }
437
- await tryStop(anvil, logger);
438
451
  await tryStop(watcher, logger);
452
+ await tryStop(anvil, logger);
439
453
  await tryStop(blobSink, logger);
440
454
  await tryRmDir(directoryToCleanup, logger);
441
455
  } catch (err) {
@@ -447,6 +461,7 @@ export const setupL1Contracts = async (l1RpcUrls, account, logger, args = {}, ch
447
461
  aztecNodeAdmin: aztecNode,
448
462
  blobSink,
449
463
  cheatCodes,
464
+ ethCheatCodes,
450
465
  config,
451
466
  dateProvider,
452
467
  deployL1ContractsValues,
@@ -620,7 +635,9 @@ export function createAndSyncProverNode(proverNodePrivateKey, aztecNodeConfig, p
620
635
  txCollectionNodeRpcUrls: [],
621
636
  realProofs: false,
622
637
  proverAgentCount: 2,
623
- publisherPrivateKey: new SecretValue(proverNodePrivateKey),
638
+ publisherPrivateKeys: [
639
+ new SecretValue(proverNodePrivateKey)
640
+ ],
624
641
  proverNodeMaxPendingJobs: 10,
625
642
  proverNodeMaxParallelBlocksPerEpoch: 32,
626
643
  proverNodePollingIntervalMs: 200,
@@ -629,6 +646,7 @@ export function createAndSyncProverNode(proverNodePrivateKey, aztecNodeConfig, p
629
646
  txGatheringMaxParallelRequestsPerNode: 10,
630
647
  txGatheringTimeoutMs: 24_000,
631
648
  proverNodeFailedEpochStore: undefined,
649
+ proverId: EthAddress.fromNumber(1),
632
650
  ...proverNodeConfig
633
651
  };
634
652
  const l1TxUtils = createDelayedL1TxUtils(aztecNodeConfig, proverNodePrivateKey, 'prover-node', proverNodeDeps.dateProvider);
@@ -650,7 +668,7 @@ export function createAndSyncProverNode(proverNodePrivateKey, aztecNodeConfig, p
650
668
  function createDelayedL1TxUtils(aztecNodeConfig, privateKey, logName, dateProvider) {
651
669
  const l1Client = createExtendedL1Client(aztecNodeConfig.l1RpcUrls, privateKey, foundry);
652
670
  const log = createLogger(logName);
653
- const l1TxUtils = new DelayedTxUtils(l1Client, log, dateProvider, aztecNodeConfig);
671
+ const l1TxUtils = createDelayedL1TxUtilsFromViemWallet(l1Client, log, dateProvider, aztecNodeConfig);
654
672
  l1TxUtils.enableDelayer(aztecNodeConfig.ethereumSlotDuration);
655
673
  return l1TxUtils;
656
674
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/end-to-end",
3
- "version": "2.0.0-nightly.20250825",
3
+ "version": "2.0.0-nightly.20250827",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "inherits": [
@@ -25,40 +25,41 @@
25
25
  "formatting": "run -T prettier --check ./src && run -T eslint ./src"
26
26
  },
27
27
  "dependencies": {
28
- "@aztec/accounts": "2.0.0-nightly.20250825",
29
- "@aztec/archiver": "2.0.0-nightly.20250825",
30
- "@aztec/aztec": "2.0.0-nightly.20250825",
31
- "@aztec/aztec-node": "2.0.0-nightly.20250825",
32
- "@aztec/aztec.js": "2.0.0-nightly.20250825",
33
- "@aztec/bb-prover": "2.0.0-nightly.20250825",
34
- "@aztec/blob-lib": "2.0.0-nightly.20250825",
35
- "@aztec/blob-sink": "2.0.0-nightly.20250825",
36
- "@aztec/bot": "2.0.0-nightly.20250825",
37
- "@aztec/cli": "2.0.0-nightly.20250825",
38
- "@aztec/constants": "2.0.0-nightly.20250825",
39
- "@aztec/entrypoints": "2.0.0-nightly.20250825",
40
- "@aztec/epoch-cache": "2.0.0-nightly.20250825",
41
- "@aztec/ethereum": "2.0.0-nightly.20250825",
42
- "@aztec/foundation": "2.0.0-nightly.20250825",
43
- "@aztec/kv-store": "2.0.0-nightly.20250825",
44
- "@aztec/l1-artifacts": "2.0.0-nightly.20250825",
45
- "@aztec/merkle-tree": "2.0.0-nightly.20250825",
46
- "@aztec/noir-contracts.js": "2.0.0-nightly.20250825",
47
- "@aztec/noir-noirc_abi": "2.0.0-nightly.20250825",
48
- "@aztec/noir-protocol-circuits-types": "2.0.0-nightly.20250825",
49
- "@aztec/noir-test-contracts.js": "2.0.0-nightly.20250825",
50
- "@aztec/p2p": "2.0.0-nightly.20250825",
51
- "@aztec/protocol-contracts": "2.0.0-nightly.20250825",
52
- "@aztec/prover-client": "2.0.0-nightly.20250825",
53
- "@aztec/prover-node": "2.0.0-nightly.20250825",
54
- "@aztec/pxe": "2.0.0-nightly.20250825",
55
- "@aztec/sequencer-client": "2.0.0-nightly.20250825",
56
- "@aztec/simulator": "2.0.0-nightly.20250825",
57
- "@aztec/slasher": "2.0.0-nightly.20250825",
58
- "@aztec/stdlib": "2.0.0-nightly.20250825",
59
- "@aztec/telemetry-client": "2.0.0-nightly.20250825",
60
- "@aztec/validator-client": "2.0.0-nightly.20250825",
61
- "@aztec/world-state": "2.0.0-nightly.20250825",
28
+ "@aztec/accounts": "2.0.0-nightly.20250827",
29
+ "@aztec/archiver": "2.0.0-nightly.20250827",
30
+ "@aztec/aztec": "2.0.0-nightly.20250827",
31
+ "@aztec/aztec-node": "2.0.0-nightly.20250827",
32
+ "@aztec/aztec.js": "2.0.0-nightly.20250827",
33
+ "@aztec/bb-prover": "2.0.0-nightly.20250827",
34
+ "@aztec/blob-lib": "2.0.0-nightly.20250827",
35
+ "@aztec/blob-sink": "2.0.0-nightly.20250827",
36
+ "@aztec/bot": "2.0.0-nightly.20250827",
37
+ "@aztec/cli": "2.0.0-nightly.20250827",
38
+ "@aztec/constants": "2.0.0-nightly.20250827",
39
+ "@aztec/entrypoints": "2.0.0-nightly.20250827",
40
+ "@aztec/epoch-cache": "2.0.0-nightly.20250827",
41
+ "@aztec/ethereum": "2.0.0-nightly.20250827",
42
+ "@aztec/foundation": "2.0.0-nightly.20250827",
43
+ "@aztec/kv-store": "2.0.0-nightly.20250827",
44
+ "@aztec/l1-artifacts": "2.0.0-nightly.20250827",
45
+ "@aztec/merkle-tree": "2.0.0-nightly.20250827",
46
+ "@aztec/node-keystore": "2.0.0-nightly.20250827",
47
+ "@aztec/noir-contracts.js": "2.0.0-nightly.20250827",
48
+ "@aztec/noir-noirc_abi": "2.0.0-nightly.20250827",
49
+ "@aztec/noir-protocol-circuits-types": "2.0.0-nightly.20250827",
50
+ "@aztec/noir-test-contracts.js": "2.0.0-nightly.20250827",
51
+ "@aztec/p2p": "2.0.0-nightly.20250827",
52
+ "@aztec/protocol-contracts": "2.0.0-nightly.20250827",
53
+ "@aztec/prover-client": "2.0.0-nightly.20250827",
54
+ "@aztec/prover-node": "2.0.0-nightly.20250827",
55
+ "@aztec/pxe": "2.0.0-nightly.20250827",
56
+ "@aztec/sequencer-client": "2.0.0-nightly.20250827",
57
+ "@aztec/simulator": "2.0.0-nightly.20250827",
58
+ "@aztec/slasher": "2.0.0-nightly.20250827",
59
+ "@aztec/stdlib": "2.0.0-nightly.20250827",
60
+ "@aztec/telemetry-client": "2.0.0-nightly.20250827",
61
+ "@aztec/validator-client": "2.0.0-nightly.20250827",
62
+ "@aztec/world-state": "2.0.0-nightly.20250827",
62
63
  "@iarna/toml": "^2.2.5",
63
64
  "@jest/globals": "^30.0.0",
64
65
  "@noble/curves": "=1.0.0",
@@ -26,7 +26,7 @@ import {
26
26
  SequencerState,
27
27
  } from '@aztec/sequencer-client';
28
28
  import type { TestSequencerClient } from '@aztec/sequencer-client/test';
29
- import type { EthAddress, L2BlockNumber } from '@aztec/stdlib/block';
29
+ import { EthAddress, type L2BlockNumber } from '@aztec/stdlib/block';
30
30
  import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
31
31
  import { tryStop } from '@aztec/stdlib/interfaces/server';
32
32
 
@@ -124,7 +124,8 @@ export class EpochsTestContext {
124
124
  proverTestDelayMs: opts.proverTestDelayMs ?? 0,
125
125
  // We use numeric incremental prover ids for simplicity, but we can switch to
126
126
  // using the prover's eth address if the proverId is used for something in the rollup contract
127
- proverId: Fr.fromString('1'),
127
+ // Use numeric EthAddress for deterministic prover id
128
+ proverId: EthAddress.fromNumber(1),
128
129
  // This must be enough so that the tx from the prover is delayed properly,
129
130
  // but not so much to hang the sequencer and timeout the teardown
130
131
  txPropagationMaxQueryAttempts: opts.txPropagationMaxQueryAttempts ?? 12,
@@ -189,7 +190,7 @@ export class EpochsTestContext {
189
190
  const proverNode = await withLogNameSuffix(suffix, () =>
190
191
  createAndSyncProverNode(
191
192
  proverNodePrivateKey,
192
- { ...this.context.config, proverId: Fr.fromString(suffix) },
193
+ { ...this.context.config, proverId: EthAddress.fromNumber(parseInt(suffix, 10)) },
193
194
  { dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')) },
194
195
  this.context.aztecNode,
195
196
  undefined,
@@ -250,9 +251,15 @@ export class EpochsTestContext {
250
251
  this.logger.info(
251
252
  `Setting tx delayer max inclusion time into slot to ${opts.txDelayerMaxInclusionTimeIntoSlot} seconds`,
252
253
  );
254
+ // Here we reach into the sequencer and hook in a tx delayer. The problem is that the sequencer's l1 utils only uses a public client, not a wallet.
255
+ // The delayer needs a wallet (a client that can sign), so we have to create one here.
256
+ const l1Client = createExtendedL1Client(
257
+ resolvedConfig.l1RpcUrls!,
258
+ resolvedConfig.publisherPrivateKeys![0]!.getValue(),
259
+ );
253
260
  const sequencer = node.getSequencer() as TestSequencerClient;
254
261
  const publisher = sequencer.sequencer.publisher;
255
- const delayed = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, this.L1_BLOCK_TIME_IN_S);
262
+ const delayed = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, this.L1_BLOCK_TIME_IN_S, l1Client);
256
263
  delayed.delayer!.setMaxInclusionTimeIntoSlot(opts.txDelayerMaxInclusionTimeIntoSlot);
257
264
  publisher.l1TxUtils = delayed;
258
265
  }
@@ -108,6 +108,7 @@ export class FeesTest {
108
108
  if (!numberOfAccounts) {
109
109
  throw new Error('There must be at least 1 initial account.');
110
110
  }
111
+ this.coinbase = setupOptions.coinbase ?? EthAddress.random();
111
112
  this.logger = createLogger(`e2e:e2e_fees:${testName}`);
112
113
  this.snapshotManager = createSnapshotManager(
113
114
  `e2e_fees/${testName}-${numberOfAccounts}`,
@@ -119,7 +120,6 @@ export class FeesTest {
119
120
 
120
121
  async setup() {
121
122
  const context = await this.snapshotManager.setup();
122
- await context.aztecNode.setConfig({ feeRecipient: this.sequencerAddress, coinbase: this.coinbase });
123
123
 
124
124
  this.rollupContract = RollupContract.getFromConfig(context.aztecNodeConfig);
125
125
  this.chainMonitor = new ChainMonitor(this.rollupContract, context.dateProvider, this.logger, 200).start();
@@ -205,7 +205,6 @@ export class FeesTest {
205
205
 
206
206
  const canonicalFeeJuice = await getCanonicalFeeJuice();
207
207
  this.feeJuiceContract = await FeeJuiceContract.at(canonicalFeeJuice.address, this.aliceWallet);
208
- this.coinbase = EthAddress.random();
209
208
  },
210
209
  );
211
210
  }
@@ -0,0 +1,264 @@
1
+ import type { AztecAddress } from '@aztec/aztec.js';
2
+ import { getAddressFromPrivateKey } from '@aztec/ethereum';
3
+ import { EthAddress } from '@aztec/foundation/eth-address';
4
+ import type { EthPrivateKey } from '@aztec/node-keystore';
5
+
6
+ import { writeFile } from 'fs/promises';
7
+ import { createServer } from 'http';
8
+ import { signMessage, signTypedData } from 'viem/accounts';
9
+
10
+ // Create a mock JSON RPC signer
11
+ // Only supports signing messages and type data
12
+
13
+ const SUPPORTED_METHODS = ['eth_sign', 'eth_signTypedData_v4'];
14
+
15
+ export function createJSONRPCSigner(keyLookup: Map<string, EthPrivateKey>, stats: Map<string, number>) {
16
+ return createServer((req, res) => {
17
+ if (req.method === 'POST') {
18
+ let body = '';
19
+ req.on('data', chunk => {
20
+ body += chunk.toString();
21
+ });
22
+ req.on('end', () => {
23
+ try {
24
+ const jsonRequest = JSON.parse(body);
25
+ res.writeHead(200, { 'Content-Type': 'application/json' });
26
+
27
+ if (!SUPPORTED_METHODS.includes(jsonRequest.method)) {
28
+ res.end(
29
+ JSON.stringify({
30
+ jsonrpc: '2.0',
31
+ id: jsonRequest.id,
32
+ error: { code: -32601, message: 'Method not supported' },
33
+ }),
34
+ );
35
+ return;
36
+ }
37
+
38
+ // Get the address sending the transaction
39
+ const [address, data] = jsonRequest.params;
40
+
41
+ const lowerCaseAddress = address.toLowerCase();
42
+ stats.set(lowerCaseAddress, (stats.get(lowerCaseAddress) ?? 0) + 1);
43
+
44
+ // Find the private key for the address
45
+ const privateKey = keyLookup.get(address.toLowerCase());
46
+ if (!privateKey) {
47
+ res.end(
48
+ JSON.stringify({
49
+ jsonrpc: '2.0',
50
+ id: jsonRequest.id,
51
+ error: { code: -32602, message: `No private key found for address ${address}` },
52
+ }),
53
+ );
54
+ return;
55
+ }
56
+
57
+ const promise =
58
+ jsonRequest.method === 'eth_sign'
59
+ ? signMessage({ message: { raw: data as `0x${string}` }, privateKey })
60
+ : signTypedData({
61
+ privateKey,
62
+ ...data,
63
+ });
64
+
65
+ void promise.then(signature => {
66
+ res.end(
67
+ JSON.stringify({
68
+ jsonrpc: '2.0',
69
+ id: jsonRequest.id,
70
+ result: signature,
71
+ }),
72
+ );
73
+ });
74
+ } catch (err) {
75
+ res.end(
76
+ JSON.stringify({
77
+ jsonrpc: '2.0',
78
+ id: 1,
79
+ error: { code: -32603, message: `${err}` },
80
+ }),
81
+ );
82
+ }
83
+ });
84
+ } else {
85
+ res.writeHead(405);
86
+ res.end('Method not allowed');
87
+ }
88
+ });
89
+ }
90
+
91
+ // Functions for creating file based key stores for the e2e_multi_validator_node_key_store test
92
+ export async function createKeyFile1(
93
+ fileName: string,
94
+ mnemonic: string,
95
+ validatorIndex: number,
96
+ publisher1Key: EthPrivateKey,
97
+ publisher2Key: EthPrivateKey,
98
+ coinbase: EthAddress,
99
+ feeRecipient: AztecAddress,
100
+ ) {
101
+ const obj = {
102
+ schemaVersion: 1,
103
+ validators: [
104
+ {
105
+ attester: {
106
+ mnemonic: mnemonic,
107
+ accountIndex: 0,
108
+ addressIndex: validatorIndex,
109
+ addressCount: 1,
110
+ },
111
+ coinbase: coinbase.toChecksumString(),
112
+ publisher: [publisher1Key, publisher2Key],
113
+ feeRecipient: feeRecipient.toString(),
114
+ },
115
+ ],
116
+ };
117
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
118
+ }
119
+
120
+ export async function createKeyFile2(
121
+ fileName: string,
122
+ validatorKey: EthPrivateKey,
123
+ publisherMnemonic: string,
124
+ publisher1Index: number,
125
+ coinbase: EthAddress,
126
+ feeRecipient: AztecAddress,
127
+ ) {
128
+ const obj = {
129
+ schemaVersion: 1,
130
+ validators: [
131
+ {
132
+ attester: validatorKey,
133
+ coinbase: coinbase.toChecksumString(),
134
+ publisher: {
135
+ mnemonic: publisherMnemonic,
136
+ accountIndex: 0,
137
+ addressIndex: publisher1Index,
138
+ addressCount: 2,
139
+ },
140
+ feeRecipient: feeRecipient.toString(),
141
+ },
142
+ ],
143
+ };
144
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
145
+ }
146
+
147
+ export async function createKeyFile3(
148
+ fileName: string,
149
+ validatorAddress: EthAddress,
150
+ publisher1Key: EthPrivateKey,
151
+ publisher2Key: EthPrivateKey,
152
+ coinbase: EthAddress,
153
+ remoteSignerUrl: string,
154
+ feeRecipient: AztecAddress,
155
+ ) {
156
+ const obj = {
157
+ schemaVersion: 1,
158
+ validators: [
159
+ {
160
+ attester: {
161
+ address: validatorAddress.toChecksumString(),
162
+ },
163
+ coinbase: coinbase.toChecksumString(),
164
+ publisher: [publisher1Key, publisher2Key],
165
+ feeRecipient: feeRecipient.toString(),
166
+ remoteSigner: {
167
+ remoteSignerUrl: remoteSignerUrl,
168
+ },
169
+ },
170
+ ],
171
+ };
172
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
173
+ }
174
+
175
+ export async function createKeyFile4(
176
+ fileName: string,
177
+ validator1Address: EthAddress,
178
+ validator2Address: EthAddress,
179
+ publisher1Index: number,
180
+ publisher2Key: EthPrivateKey,
181
+ mnemonic: string,
182
+ publisher3Key: EthPrivateKey,
183
+ coinbase1: EthAddress,
184
+ coinbase2: EthAddress,
185
+ remoteSignerUrl: string,
186
+ feeRecipient1: AztecAddress,
187
+ feeRecipient2: AztecAddress,
188
+ ) {
189
+ const obj = {
190
+ schemaVersion: 1,
191
+ remoteSigner: {
192
+ remoteSignerUrl: remoteSignerUrl,
193
+ },
194
+ validators: [
195
+ {
196
+ attester: {
197
+ address: validator1Address.toChecksumString(),
198
+ },
199
+ coinbase: coinbase1.toChecksumString(),
200
+ publisher: {
201
+ mnemonic: mnemonic,
202
+ accountIndex: 0,
203
+ addressIndex: publisher1Index,
204
+ addressCount: 2,
205
+ },
206
+ feeRecipient: feeRecipient1.toString(),
207
+ },
208
+ {
209
+ attester: {
210
+ address: validator2Address.toChecksumString(),
211
+ },
212
+ coinbase: coinbase2.toChecksumString(),
213
+ publisher: [publisher2Key, publisher3Key],
214
+ feeRecipient: feeRecipient2.toString(),
215
+ },
216
+ ],
217
+ };
218
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
219
+ }
220
+
221
+ export async function createKeyFile5(fileName: string, proverAddress: EthAddress, remoteSignerUrl: string) {
222
+ const obj = {
223
+ schemaVersion: 1,
224
+ prover: {
225
+ id: '0x1234567890123456789012345678901234567890',
226
+ publisher: [
227
+ {
228
+ address: proverAddress.toChecksumString(),
229
+ remoteSignerUrl: remoteSignerUrl,
230
+ },
231
+ ],
232
+ },
233
+ };
234
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
235
+ }
236
+
237
+ export async function createKeyFile6(
238
+ fileName: string,
239
+ mnemonic: string,
240
+ validator1Index: number,
241
+ coinbase: EthAddress,
242
+ feeRecipient: AztecAddress,
243
+ ) {
244
+ const obj = {
245
+ schemaVersion: 1,
246
+ validators: [
247
+ {
248
+ attester: {
249
+ mnemonic: mnemonic,
250
+ accountIndex: 0,
251
+ addressIndex: validator1Index,
252
+ addressCount: 2,
253
+ },
254
+ coinbase: coinbase.toChecksumString(),
255
+ feeRecipient: feeRecipient.toString(),
256
+ },
257
+ ],
258
+ };
259
+ await writeFile(fileName, JSON.stringify(obj, null, 2));
260
+ }
261
+
262
+ export function addressForPrivateKey(privateKey: EthPrivateKey): EthAddress {
263
+ return EthAddress.fromString(getAddressFromPrivateKey(privateKey));
264
+ }
@@ -5,11 +5,11 @@ import { type AccountWalletWithSecretKey, AztecAddress, EthAddress, Fr } from '@
5
5
  import {
6
6
  type ExtendedViemWalletClient,
7
7
  GSEContract,
8
- L1TxUtils,
9
8
  MultiAdderArtifact,
10
9
  type Operator,
11
10
  RollupContract,
12
11
  type ViemClient,
12
+ createL1TxUtilsFromViemWallet,
13
13
  deployL1Contract,
14
14
  getL1ContractsConfigEnvVars,
15
15
  } from '@aztec/ethereum';
@@ -349,7 +349,7 @@ export class P2PNetworkTest {
349
349
  }
350
350
 
351
351
  private async _sendDummyTx(l1Client: ExtendedViemWalletClient) {
352
- const l1TxUtils = new L1TxUtils(l1Client);
352
+ const l1TxUtils = createL1TxUtilsFromViemWallet(l1Client);
353
353
  return await l1TxUtils.sendAndMonitorTransaction({
354
354
  to: l1Client.account!.address,
355
355
  value: 1n,
@@ -296,10 +296,10 @@ export class FullProverTest {
296
296
  ...this.context.aztecNodeConfig,
297
297
  txCollectionNodeRpcUrls: [],
298
298
  dataDirectory: undefined,
299
- proverId: this.proverAddress.toField(),
299
+ proverId: this.proverAddress,
300
300
  realProofs: this.realProofs,
301
301
  proverAgentCount: 2,
302
- publisherPrivateKey: new SecretValue(`0x${proverNodePrivateKey!.toString('hex')}` as const),
302
+ publisherPrivateKeys: [new SecretValue(`0x${proverNodePrivateKey!.toString('hex')}` as const)],
303
303
  proverNodeMaxPendingJobs: 100,
304
304
  proverNodeMaxParallelBlocksPerEpoch: 32,
305
305
  proverNodePollingIntervalMs: 100,
@@ -154,7 +154,7 @@ export async function createValidatorConfig(
154
154
  const attesterPrivateKey = bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!);
155
155
 
156
156
  config.validatorPrivateKeys = new SecretValue([attesterPrivateKey]);
157
- config.publisherPrivateKey = new SecretValue(attesterPrivateKey);
157
+ config.publisherPrivateKeys = [new SecretValue(attesterPrivateKey)];
158
158
 
159
159
  const nodeConfig: AztecNodeConfig = {
160
160
  ...config,
@@ -8,6 +8,7 @@ import {
8
8
  type CompleteAddress,
9
9
  type ContractFunctionInteraction,
10
10
  DefaultWaitForProvenOpts,
11
+ EthAddress,
11
12
  type Logger,
12
13
  type PXE,
13
14
  type Wallet,
@@ -342,11 +343,14 @@ async function setupFromFresh(
342
343
  const publisherPrivKeyRaw = hdAccount.getHdKey().privateKey;
343
344
  const publisherPrivKey = publisherPrivKeyRaw === null ? null : Buffer.from(publisherPrivKeyRaw);
344
345
 
346
+ const l1Client = createExtendedL1Client([aztecNodeConfig.l1RpcUrls[0]], hdAccount, foundry);
347
+
345
348
  const validatorPrivKey = getPrivateKeyFromIndex(0);
346
349
  const proverNodePrivateKey = getPrivateKeyFromIndex(0);
347
350
 
348
- aztecNodeConfig.publisherPrivateKey = new SecretValue<`0x${string}`>(`0x${publisherPrivKey!.toString('hex')}`);
351
+ aztecNodeConfig.publisherPrivateKeys = [new SecretValue<`0x${string}`>(`0x${publisherPrivKey!.toString('hex')}`)];
349
352
  aztecNodeConfig.validatorPrivateKeys = new SecretValue([`0x${validatorPrivKey!.toString('hex')}`]);
353
+ aztecNodeConfig.coinbase = opts.coinbase ?? EthAddress.fromString(`${hdAccount.address}`);
350
354
 
351
355
  const ethCheatCodes = new EthCheatCodesWithState(aztecNodeConfig.l1RpcUrls);
352
356
 
@@ -361,7 +365,6 @@ async function setupFromFresh(
361
365
  opts.initialAccountFeeJuice,
362
366
  );
363
367
 
364
- const l1Client = createExtendedL1Client([aztecNodeConfig.l1RpcUrls[0]], hdAccount, foundry);
365
368
  await deployMulticall3(l1Client, logger);
366
369
 
367
370
  const deployL1ContractsValues = await setupL1Contracts(aztecNodeConfig.l1RpcUrls[0], hdAccount, logger, {
@@ -439,7 +442,7 @@ async function setupFromFresh(
439
442
  );
440
443
  await blobSink.start();
441
444
 
442
- logger.verbose('Creating and synching an aztec node...');
445
+ logger.info('Creating and synching an aztec node...');
443
446
  const aztecNode = await AztecNodeService.createAndSync(
444
447
  aztecNodeConfig,
445
448
  { telemetry, dateProvider },