@aztec/end-to-end 0.0.1-commit.f5d02921e → 0.0.1-commit.f650c0a5c
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/README.md +27 -0
- package/dest/bench/client_flows/client_flows_benchmark.js +1 -1
- package/dest/e2e_epochs/epochs_test.js +3 -3
- package/dest/e2e_fees/fees_test.js +1 -1
- package/dest/e2e_p2p/inactivity_slash_test.js +2 -2
- package/dest/e2e_p2p/p2p_network.d.ts +5 -7
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +8 -12
- package/dest/e2e_p2p/reqresp/utils.js +1 -1
- package/dest/e2e_p2p/shared.d.ts +5 -7
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +16 -42
- package/dest/fixtures/authwit_proxy.d.ts +1 -1
- package/dest/fixtures/authwit_proxy.d.ts.map +1 -1
- package/dest/fixtures/authwit_proxy.js +4 -0
- package/dest/fixtures/e2e_prover_test.d.ts +1 -1
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +2 -2
- package/dest/fixtures/setup.d.ts +5 -4
- package/dest/fixtures/setup.d.ts.map +1 -1
- package/dest/fixtures/setup.js +7 -6
- package/dest/fixtures/setup_p2p_test.d.ts +6 -6
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +8 -8
- package/dest/legacy-jest-resolver.d.cts +3 -0
- package/dest/legacy-jest-resolver.d.cts.map +1 -0
- package/dest/spartan/setup_test_wallets.d.ts +1 -1
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +7 -39
- package/dest/test-wallet/test_wallet.d.ts +6 -7
- package/dest/test-wallet/test_wallet.d.ts.map +1 -1
- package/dest/test-wallet/test_wallet.js +36 -27
- package/package.json +40 -39
- package/src/bench/client_flows/client_flows_benchmark.ts +1 -1
- package/src/e2e_epochs/epochs_test.ts +3 -3
- package/src/e2e_fees/fees_test.ts +1 -1
- package/src/e2e_p2p/inactivity_slash_test.ts +2 -2
- package/src/e2e_p2p/p2p_network.ts +16 -23
- package/src/e2e_p2p/reqresp/utils.ts +1 -1
- package/src/e2e_p2p/shared.ts +16 -57
- package/src/fixtures/authwit_proxy.ts +4 -0
- package/src/fixtures/e2e_prover_test.ts +5 -2
- package/src/fixtures/setup.ts +12 -13
- package/src/fixtures/setup_p2p_test.ts +9 -9
- package/src/legacy-jest-resolver.cjs +135 -0
- package/src/spartan/setup_test_wallets.ts +5 -31
- package/src/test-wallet/test_wallet.ts +53 -28
|
@@ -108,7 +108,7 @@ export class P2PInactivityTest {
|
|
|
108
108
|
this.test.bootstrapNodeEnr,
|
|
109
109
|
NUM_NODES - this.inactiveNodeCount - Number(this.keepInitialNode),
|
|
110
110
|
BOOT_NODE_UDP_PORT,
|
|
111
|
-
this.test.
|
|
111
|
+
this.test.genesis,
|
|
112
112
|
this.dataDir,
|
|
113
113
|
undefined,
|
|
114
114
|
Number(this.keepInitialNode),
|
|
@@ -122,7 +122,7 @@ export class P2PInactivityTest {
|
|
|
122
122
|
this.test.bootstrapNodeEnr,
|
|
123
123
|
this.inactiveNodeCount,
|
|
124
124
|
BOOT_NODE_UDP_PORT,
|
|
125
|
-
this.test.
|
|
125
|
+
this.test.genesis,
|
|
126
126
|
this.dataDir,
|
|
127
127
|
undefined,
|
|
128
128
|
NUM_NODES - this.inactiveNodeCount,
|
|
@@ -3,12 +3,7 @@ import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
|
3
3
|
import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
|
|
4
4
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
5
5
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
6
|
-
import {
|
|
7
|
-
type EmpireSlashingProposerContract,
|
|
8
|
-
GSEContract,
|
|
9
|
-
RollupContract,
|
|
10
|
-
type TallySlashingProposerContract,
|
|
11
|
-
} from '@aztec/ethereum/contracts';
|
|
6
|
+
import { GSEContract, RollupContract, type SlashingProposerContract } from '@aztec/ethereum/contracts';
|
|
12
7
|
import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
|
|
13
8
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
14
9
|
import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
|
|
@@ -24,9 +19,8 @@ import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
|
24
19
|
import type { BootstrapNode } from '@aztec/p2p/bootstrap';
|
|
25
20
|
import { createBootstrapNodeFromPrivateKey, getBootstrapNodeEnr } from '@aztec/p2p/test-helpers';
|
|
26
21
|
import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
27
|
-
import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
28
22
|
import { TopicType } from '@aztec/stdlib/p2p';
|
|
29
|
-
import type {
|
|
23
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
30
24
|
import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
|
|
31
25
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
32
26
|
|
|
@@ -77,7 +71,7 @@ export class P2PNetworkTest {
|
|
|
77
71
|
public validators: Operator[] = [];
|
|
78
72
|
|
|
79
73
|
public deployedAccounts: InitialAccountData[] = [];
|
|
80
|
-
public
|
|
74
|
+
public genesis: GenesisData | undefined;
|
|
81
75
|
|
|
82
76
|
// The re-execution test needs a wallet and a spam contract
|
|
83
77
|
public wallet?: TestWallet;
|
|
@@ -124,7 +118,7 @@ export class P2PNetworkTest {
|
|
|
124
118
|
initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
|
|
125
119
|
slashingRoundSizeInEpochs:
|
|
126
120
|
initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
|
|
127
|
-
|
|
121
|
+
slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
|
|
128
122
|
aztecTargetCommitteeSize: numberOfValidators,
|
|
129
123
|
metricsPort: metricsPort,
|
|
130
124
|
numberOfInitialFundedAccounts: 2,
|
|
@@ -137,7 +131,7 @@ export class P2PNetworkTest {
|
|
|
137
131
|
aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
|
|
138
132
|
slashingRoundSizeInEpochs:
|
|
139
133
|
initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
|
|
140
|
-
|
|
134
|
+
slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
|
|
141
135
|
|
|
142
136
|
ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
|
|
143
137
|
aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
|
|
@@ -360,7 +354,7 @@ export class P2PNetworkTest {
|
|
|
360
354
|
...this.setupOptions,
|
|
361
355
|
fundSponsoredFPC: true,
|
|
362
356
|
skipAccountDeployment: true,
|
|
363
|
-
|
|
357
|
+
slasherEnabled: this.setupOptions.slasherEnabled ?? this.deployL1ContractsArgs.slasherEnabled ?? false,
|
|
364
358
|
aztecTargetCommitteeSize: 0,
|
|
365
359
|
l1ContractsArgs: this.deployL1ContractsArgs,
|
|
366
360
|
},
|
|
@@ -372,8 +366,13 @@ export class P2PNetworkTest {
|
|
|
372
366
|
const sponsoredFPCAddress = await getSponsoredFPCAddress();
|
|
373
367
|
const initialFundedAccounts = [...this.context.initialFundedAccounts.map(a => a.address), sponsoredFPCAddress];
|
|
374
368
|
|
|
375
|
-
const {
|
|
376
|
-
|
|
369
|
+
const { genesis } = await getGenesisValues(
|
|
370
|
+
initialFundedAccounts,
|
|
371
|
+
undefined,
|
|
372
|
+
undefined,
|
|
373
|
+
this.context.genesis!.genesisTimestamp,
|
|
374
|
+
);
|
|
375
|
+
this.genesis = genesis;
|
|
377
376
|
|
|
378
377
|
const rollupContract = RollupContract.getFromL1ContractsValues(this.context.deployL1ContractsValues);
|
|
379
378
|
this.monitor = new ChainMonitor(rollupContract, this.context.dateProvider).start();
|
|
@@ -468,8 +467,7 @@ export class P2PNetworkTest {
|
|
|
468
467
|
async getContracts(): Promise<{
|
|
469
468
|
rollup: RollupContract;
|
|
470
469
|
slasherContract: GetContractReturnType<typeof SlasherAbi, ViemClient>;
|
|
471
|
-
slashingProposer:
|
|
472
|
-
slashFactory: SlashFactoryContract;
|
|
470
|
+
slashingProposer: SlashingProposerContract | undefined;
|
|
473
471
|
}> {
|
|
474
472
|
if (!this.ctx.deployL1ContractsValues) {
|
|
475
473
|
throw new Error('DeployAztecL1ContractsValues not set');
|
|
@@ -486,14 +484,9 @@ export class P2PNetworkTest {
|
|
|
486
484
|
client: this.ctx.deployL1ContractsValues.l1Client,
|
|
487
485
|
});
|
|
488
486
|
|
|
489
|
-
// Get the actual slashing proposer from rollup
|
|
487
|
+
// Get the actual slashing proposer from rollup
|
|
490
488
|
const slashingProposer = await rollup.getSlashingProposer();
|
|
491
489
|
|
|
492
|
-
|
|
493
|
-
this.ctx.deployL1ContractsValues.l1Client,
|
|
494
|
-
getAddress(this.ctx.deployL1ContractsValues.l1ContractAddresses.slashFactoryAddress!.toString()),
|
|
495
|
-
);
|
|
496
|
-
|
|
497
|
-
return { rollup, slasherContract, slashingProposer, slashFactory };
|
|
490
|
+
return { rollup, slasherContract, slashingProposer };
|
|
498
491
|
}
|
|
499
492
|
}
|
package/src/e2e_p2p/shared.ts
CHANGED
|
@@ -7,11 +7,7 @@ import type { Logger } from '@aztec/aztec.js/log';
|
|
|
7
7
|
import { TxHash } from '@aztec/aztec.js/tx';
|
|
8
8
|
import type { RollupCheatCodes } from '@aztec/aztec/testing';
|
|
9
9
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
10
|
-
import type {
|
|
11
|
-
EmpireSlashingProposerContract,
|
|
12
|
-
RollupContract,
|
|
13
|
-
TallySlashingProposerContract,
|
|
14
|
-
} from '@aztec/ethereum/contracts';
|
|
10
|
+
import type { RollupContract, SlashingProposerContract } from '@aztec/ethereum/contracts';
|
|
15
11
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
16
12
|
import { timesAsync, unique } from '@aztec/foundation/collection';
|
|
17
13
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -22,7 +18,6 @@ import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.j
|
|
|
22
18
|
import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
|
|
23
19
|
import { getRoundForOffense } from '@aztec/slasher';
|
|
24
20
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
25
|
-
import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
26
21
|
|
|
27
22
|
import { submitTxsTo } from '../shared/submit-transactions.js';
|
|
28
23
|
import { TestWallet } from '../test-wallet/test_wallet.js';
|
|
@@ -99,7 +94,7 @@ export async function prepareTransactions(
|
|
|
99
94
|
}
|
|
100
95
|
|
|
101
96
|
export function awaitProposalExecution(
|
|
102
|
-
slashingProposer:
|
|
97
|
+
slashingProposer: SlashingProposerContract,
|
|
103
98
|
timeoutSeconds: number,
|
|
104
99
|
logger: Logger,
|
|
105
100
|
): Promise<bigint> {
|
|
@@ -109,24 +104,12 @@ export function awaitProposalExecution(
|
|
|
109
104
|
reject(new Error(`Timeout waiting for proposal execution after ${timeoutSeconds}s`));
|
|
110
105
|
}, timeoutSeconds * 1000);
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
logger.warn(`Proposal ${args.payload} from round ${args.round} executed`);
|
|
115
|
-
clearTimeout(timeout);
|
|
116
|
-
unwatch();
|
|
117
|
-
resolve(args.round);
|
|
118
|
-
});
|
|
119
|
-
} else if (slashingProposer.type === 'tally') {
|
|
120
|
-
const unwatch = slashingProposer.listenToRoundExecuted(args => {
|
|
121
|
-
logger.warn(`Slash from round ${args.round} executed`);
|
|
122
|
-
clearTimeout(timeout);
|
|
123
|
-
unwatch();
|
|
124
|
-
resolve(args.round);
|
|
125
|
-
});
|
|
126
|
-
} else {
|
|
107
|
+
const unwatch = slashingProposer.listenToRoundExecuted(args => {
|
|
108
|
+
logger.warn(`Slash from round ${args.round} executed`);
|
|
127
109
|
clearTimeout(timeout);
|
|
128
|
-
|
|
129
|
-
|
|
110
|
+
unwatch();
|
|
111
|
+
resolve(args.round);
|
|
112
|
+
});
|
|
130
113
|
});
|
|
131
114
|
}
|
|
132
115
|
|
|
@@ -245,7 +228,6 @@ export async function awaitCommitteeKicked({
|
|
|
245
228
|
rollup,
|
|
246
229
|
cheatCodes,
|
|
247
230
|
committee,
|
|
248
|
-
slashFactory,
|
|
249
231
|
slashingProposer,
|
|
250
232
|
slashingRoundSize,
|
|
251
233
|
aztecSlotDuration,
|
|
@@ -256,8 +238,7 @@ export async function awaitCommitteeKicked({
|
|
|
256
238
|
rollup: RollupContract;
|
|
257
239
|
cheatCodes: RollupCheatCodes;
|
|
258
240
|
committee: readonly `0x${string}`[];
|
|
259
|
-
|
|
260
|
-
slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
|
|
241
|
+
slashingProposer: SlashingProposerContract | undefined;
|
|
261
242
|
slashingRoundSize: number;
|
|
262
243
|
aztecSlotDuration: number;
|
|
263
244
|
aztecEpochDuration: number;
|
|
@@ -270,36 +251,14 @@ export async function awaitCommitteeKicked({
|
|
|
270
251
|
|
|
271
252
|
await cheatCodes.debugRollup();
|
|
272
253
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const events = await slashFactory.getSlashPayloadCreatedEvents();
|
|
282
|
-
return events.length > 0 ? events : undefined;
|
|
283
|
-
},
|
|
284
|
-
'slash payload created',
|
|
285
|
-
120,
|
|
286
|
-
1,
|
|
287
|
-
);
|
|
288
|
-
expect(slashPayloadEvents.length).toBe(1);
|
|
289
|
-
// The uniqueness check is needed since a validator may be slashed more than once on the same round (eg because they let two epochs be pruned)
|
|
290
|
-
expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
|
|
291
|
-
committee.length,
|
|
292
|
-
);
|
|
293
|
-
} else {
|
|
294
|
-
// Use the slash offset to ensure we are in the right epoch for tally
|
|
295
|
-
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
296
|
-
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
297
|
-
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
298
|
-
const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
|
|
299
|
-
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
300
|
-
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
301
|
-
await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
|
|
302
|
-
}
|
|
254
|
+
// Use the slash offset to ensure we are in the right epoch for tally
|
|
255
|
+
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
256
|
+
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
257
|
+
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
258
|
+
const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
|
|
259
|
+
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
260
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
261
|
+
await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
|
|
303
262
|
|
|
304
263
|
const attestersPre = await rollup.getAttesters();
|
|
305
264
|
expect(attestersPre.length).toBe(committee.length);
|
|
@@ -17,6 +17,10 @@ async function buildProxyCall(proxy: GenericProxyContract, action: ContractFunct
|
|
|
17
17
|
return proxy.methods.forward_private_3(call.to, call.selector, call.args);
|
|
18
18
|
} else if (argCount === 4) {
|
|
19
19
|
return proxy.methods.forward_private_4(call.to, call.selector, call.args);
|
|
20
|
+
} else if (argCount === 5) {
|
|
21
|
+
return proxy.methods.forward_private_5(call.to, call.selector, call.args);
|
|
22
|
+
} else if (argCount === 6) {
|
|
23
|
+
return proxy.methods.forward_private_6(call.to, call.selector, call.args);
|
|
20
24
|
}
|
|
21
25
|
throw new Error(`No forward_private_${argCount} method on proxy`);
|
|
22
26
|
}
|
|
@@ -223,8 +223,11 @@ export class FullProverTest {
|
|
|
223
223
|
|
|
224
224
|
this.logger.verbose('Starting prover node');
|
|
225
225
|
const sponsoredFPCAddress = await getSponsoredFPCAddress();
|
|
226
|
-
const {
|
|
226
|
+
const { genesis } = await getGenesisValues(
|
|
227
227
|
this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress),
|
|
228
|
+
undefined,
|
|
229
|
+
undefined,
|
|
230
|
+
this.context.genesis!.genesisTimestamp,
|
|
228
231
|
);
|
|
229
232
|
|
|
230
233
|
const proverNodeConfig: Parameters<typeof AztecNodeService.createAndSync>[0] = {
|
|
@@ -252,7 +255,7 @@ export class FullProverTest {
|
|
|
252
255
|
this.proverAztecNode = await AztecNodeService.createAndSync(
|
|
253
256
|
proverNodeConfig,
|
|
254
257
|
{ dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } },
|
|
255
|
-
{
|
|
258
|
+
{ genesis },
|
|
256
259
|
);
|
|
257
260
|
this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs });
|
|
258
261
|
return this;
|
package/src/fixtures/setup.ts
CHANGED
|
@@ -52,6 +52,7 @@ import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationP
|
|
|
52
52
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
53
53
|
import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
54
54
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
55
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
55
56
|
import {
|
|
56
57
|
type TelemetryClient,
|
|
57
58
|
type TelemetryClientConfig,
|
|
@@ -249,8 +250,8 @@ export type EndToEndContext = {
|
|
|
249
250
|
sequencerDelayer: Delayer | undefined;
|
|
250
251
|
/** Delayer for prover node L1 txs (only when enableDelayer and startProverNode are true). */
|
|
251
252
|
proverDelayer: Delayer | undefined;
|
|
252
|
-
/**
|
|
253
|
-
|
|
253
|
+
/** Genesis data used for setting up nodes. */
|
|
254
|
+
genesis: GenesisData | undefined;
|
|
254
255
|
/** ACVM config (only set if running locally). */
|
|
255
256
|
acvmConfig: Awaited<ReturnType<typeof getACVMConfig>>;
|
|
256
257
|
/** BB config (only set if running locally). */
|
|
@@ -276,7 +277,7 @@ export async function setup(
|
|
|
276
277
|
let anvil: Anvil | undefined;
|
|
277
278
|
try {
|
|
278
279
|
opts.aztecTargetCommitteeSize ??= 0;
|
|
279
|
-
opts.
|
|
280
|
+
opts.slasherEnabled ??= false;
|
|
280
281
|
|
|
281
282
|
const config: AztecNodeConfig & SetupOptions = { ...getConfigEnvVars(), ...opts };
|
|
282
283
|
// use initialValidators for the node config
|
|
@@ -375,10 +376,12 @@ export async function setup(
|
|
|
375
376
|
addressesToFund.push(sponsoredFPCAddress);
|
|
376
377
|
}
|
|
377
378
|
|
|
378
|
-
const
|
|
379
|
+
const genesisTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
380
|
+
const { genesisArchiveRoot, genesis, fundingNeeded } = await getGenesisValues(
|
|
379
381
|
addressesToFund,
|
|
380
382
|
opts.initialAccountFeeJuice,
|
|
381
383
|
opts.genesisPublicData,
|
|
384
|
+
genesisTimestamp,
|
|
382
385
|
);
|
|
383
386
|
|
|
384
387
|
const wasAutomining = await ethCheatCodes.isAutoMining();
|
|
@@ -496,11 +499,7 @@ export async function setup(
|
|
|
496
499
|
}
|
|
497
500
|
|
|
498
501
|
const aztecNodeService = await withLoggerBindings({ actor: 'node-0' }, () =>
|
|
499
|
-
AztecNodeService.createAndSync(
|
|
500
|
-
config,
|
|
501
|
-
{ dateProvider, telemetry: telemetryClient, p2pClientDeps },
|
|
502
|
-
{ prefilledPublicData },
|
|
503
|
-
),
|
|
502
|
+
AztecNodeService.createAndSync(config, { dateProvider, telemetry: telemetryClient, p2pClientDeps }, { genesis }),
|
|
504
503
|
);
|
|
505
504
|
const sequencerClient = aztecNodeService.getSequencer();
|
|
506
505
|
|
|
@@ -524,7 +523,7 @@ export async function setup(
|
|
|
524
523
|
dataDirectory: proverNodeDataDirectory,
|
|
525
524
|
},
|
|
526
525
|
{ dateProvider, p2pClientDeps, telemetry: telemetryClient },
|
|
527
|
-
{
|
|
526
|
+
{ genesis },
|
|
528
527
|
));
|
|
529
528
|
}
|
|
530
529
|
|
|
@@ -629,7 +628,7 @@ export async function setup(
|
|
|
629
628
|
initialFundedAccounts,
|
|
630
629
|
logger,
|
|
631
630
|
mockGossipSubNetwork,
|
|
632
|
-
|
|
631
|
+
genesis,
|
|
633
632
|
proverNode,
|
|
634
633
|
sequencerDelayer,
|
|
635
634
|
proverDelayer,
|
|
@@ -729,7 +728,7 @@ export function createAndSyncProverNode(
|
|
|
729
728
|
dateProvider: DateProvider;
|
|
730
729
|
p2pClientDeps?: P2PClientDeps;
|
|
731
730
|
},
|
|
732
|
-
options: {
|
|
731
|
+
options: { genesis?: GenesisData; dontStart?: boolean },
|
|
733
732
|
): Promise<{ proverNode: AztecNodeService }> {
|
|
734
733
|
return withLoggerBindings({ actor: 'prover-0' }, async () => {
|
|
735
734
|
const proverNode = await AztecNodeService.createAndSync(
|
|
@@ -742,7 +741,7 @@ export function createAndSyncProverNode(
|
|
|
742
741
|
proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)],
|
|
743
742
|
},
|
|
744
743
|
deps,
|
|
745
|
-
{
|
|
744
|
+
{ genesis: options.genesis, dontStartProverNode: options.dontStart },
|
|
746
745
|
);
|
|
747
746
|
|
|
748
747
|
if (!proverNode.getProverNode()) {
|
|
@@ -7,7 +7,7 @@ import { SecretValue } from '@aztec/foundation/config';
|
|
|
7
7
|
import { withLoggerBindings } from '@aztec/foundation/log/server';
|
|
8
8
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
9
9
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
10
|
-
import type {
|
|
10
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
11
11
|
|
|
12
12
|
import getPort from 'get-port';
|
|
13
13
|
|
|
@@ -40,7 +40,7 @@ export async function createNodes(
|
|
|
40
40
|
bootstrapNodeEnr: string,
|
|
41
41
|
numNodes: number,
|
|
42
42
|
bootNodePort: number,
|
|
43
|
-
|
|
43
|
+
genesis?: GenesisData,
|
|
44
44
|
dataDirectory?: string,
|
|
45
45
|
metricsPort?: number,
|
|
46
46
|
indexOffset = 0,
|
|
@@ -65,7 +65,7 @@ export async function createNodes(
|
|
|
65
65
|
port,
|
|
66
66
|
bootstrapNodeEnr,
|
|
67
67
|
validatorIndices,
|
|
68
|
-
|
|
68
|
+
genesis,
|
|
69
69
|
dataDir,
|
|
70
70
|
metricsPort,
|
|
71
71
|
);
|
|
@@ -97,7 +97,7 @@ export async function createNode(
|
|
|
97
97
|
tcpPort: number,
|
|
98
98
|
bootstrapNode: string | undefined,
|
|
99
99
|
addressIndex: number | number[],
|
|
100
|
-
|
|
100
|
+
genesis?: GenesisData,
|
|
101
101
|
dataDirectory?: string,
|
|
102
102
|
metricsPort?: number,
|
|
103
103
|
) {
|
|
@@ -108,7 +108,7 @@ export async function createNode(
|
|
|
108
108
|
return await AztecNodeService.createAndSync(
|
|
109
109
|
validatorConfig,
|
|
110
110
|
{ telemetry, dateProvider },
|
|
111
|
-
{
|
|
111
|
+
{ genesis, dontStartSequencer: config.dontStartSequencer },
|
|
112
112
|
);
|
|
113
113
|
});
|
|
114
114
|
}
|
|
@@ -119,7 +119,7 @@ export async function createNonValidatorNode(
|
|
|
119
119
|
dateProvider: DateProvider,
|
|
120
120
|
tcpPort: number,
|
|
121
121
|
bootstrapNode: string | undefined,
|
|
122
|
-
|
|
122
|
+
genesis?: GenesisData,
|
|
123
123
|
dataDirectory?: string,
|
|
124
124
|
metricsPort?: number,
|
|
125
125
|
) {
|
|
@@ -133,7 +133,7 @@ export async function createNonValidatorNode(
|
|
|
133
133
|
sequencerPublisherPrivateKeys: [],
|
|
134
134
|
};
|
|
135
135
|
const telemetry = await getEndToEndTestTelemetryClient(metricsPort);
|
|
136
|
-
return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, {
|
|
136
|
+
return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { genesis });
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -143,7 +143,7 @@ export async function createProverNode(
|
|
|
143
143
|
bootstrapNode: string | undefined,
|
|
144
144
|
addressIndex: number,
|
|
145
145
|
deps: { dateProvider: DateProvider },
|
|
146
|
-
|
|
146
|
+
genesis?: GenesisData,
|
|
147
147
|
dataDirectory?: string,
|
|
148
148
|
metricsPort?: number,
|
|
149
149
|
): Promise<{ proverNode: AztecNodeService }> {
|
|
@@ -159,7 +159,7 @@ export async function createProverNode(
|
|
|
159
159
|
{ ...config, ...p2pConfig },
|
|
160
160
|
{ dataDirectory },
|
|
161
161
|
{ ...deps, telemetry },
|
|
162
|
-
{
|
|
162
|
+
{ genesis },
|
|
163
163
|
);
|
|
164
164
|
});
|
|
165
165
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Custom Jest resolver. When CONTRACT_ARTIFACTS_VERSION is set, redirects *only* JSON artifact files under
|
|
2
|
+
// @aztec/noir-contracts.js/artifacts/ and @aztec/noir-test-contracts.js/artifacts/ to a local cache of the pinned
|
|
3
|
+
// legacy versions. TypeScript wrapper classes (e.g. Token.ts) continue to load from the current workspace and use the
|
|
4
|
+
// current @aztec/aztec.js — only the artifact JSON (the deployed-contract ABI / bytecode / notes surface) is swapped.
|
|
5
|
+
//
|
|
6
|
+
// Why JSON-only: the JSON artifact is the actual interchange surface a "deployed contract" exposes. The TS wrapper is
|
|
7
|
+
// generated client-side ergonomics that's tightly coupled to the current @aztec/aztec.js API. Redirecting the wrapper
|
|
8
|
+
// would couple this test to a moving aztec.js surface and break at import time on unrelated breaking changes; we want
|
|
9
|
+
// to fail only on actual artifact-compat regressions.
|
|
10
|
+
//
|
|
11
|
+
// The cache is populated on demand by running `npm install` into .legacy-contracts/<version>/.
|
|
12
|
+
//
|
|
13
|
+
// Activated by env var; passthrough otherwise.
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
|
|
20
|
+
const version = process.env.CONTRACT_ARTIFACTS_VERSION;
|
|
21
|
+
const REDIRECTED = ['@aztec/noir-contracts.js', '@aztec/noir-test-contracts.js'];
|
|
22
|
+
|
|
23
|
+
// Jest sets rootDir to <e2e>/src; this file lives there too.
|
|
24
|
+
const e2eRoot = path.resolve(__dirname, '..');
|
|
25
|
+
const cacheRoot = version ? path.join(e2eRoot, '.legacy-contracts', version) : null;
|
|
26
|
+
|
|
27
|
+
function pkgJsonPath(name) {
|
|
28
|
+
return path.join(cacheRoot, 'node_modules', name, 'package.json');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function ensureCache() {
|
|
32
|
+
const missing = REDIRECTED.some(p => !fs.existsSync(pkgJsonPath(p)));
|
|
33
|
+
if (!missing) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
fs.mkdirSync(cacheRoot, { recursive: true });
|
|
37
|
+
// Seed a standalone package.json so `npm install --prefix` treats cacheRoot as its own project. Without this, npm
|
|
38
|
+
// walks up and finds the yarn-project workspace root, which breaks on `workspace:` protocol deps and risks
|
|
39
|
+
// clobbering the monorepo's node_modules.
|
|
40
|
+
const seed = path.join(cacheRoot, 'package.json');
|
|
41
|
+
if (!fs.existsSync(seed)) {
|
|
42
|
+
fs.writeFileSync(seed, JSON.stringify({ name: 'legacy-contracts-cache', private: true }));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const specs = REDIRECTED.map(p => `${p}@${version}`).join(' ');
|
|
46
|
+
process.stderr.write(`[legacy-contracts] installing ${specs} into ${cacheRoot}\n`);
|
|
47
|
+
// --prefix: install into cacheRoot instead of cwd, so the cache is isolated from the monorepo.
|
|
48
|
+
// --no-save: don't write the installed packages back to the seeded package.json.
|
|
49
|
+
// --ignore-scripts: skip lifecycle scripts (preinstall/postinstall) of the legacy packages and their transitive
|
|
50
|
+
// deps; we only want the files on disk, not to run any build steps.
|
|
51
|
+
// --legacy-peer-deps: tolerate peer-dependency mismatches between the pinned legacy @aztec/* graph and whatever
|
|
52
|
+
// current versions npm would otherwise try to reconcile.
|
|
53
|
+
execSync(`npm install --prefix "${cacheRoot}" --no-save --ignore-scripts --legacy-peer-deps ${specs}`, {
|
|
54
|
+
stdio: 'inherit',
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Verify versions on disk match the requested version.
|
|
58
|
+
for (const p of REDIRECTED) {
|
|
59
|
+
const onDisk = JSON.parse(fs.readFileSync(pkgJsonPath(p), 'utf8')).version;
|
|
60
|
+
if (onDisk !== version) {
|
|
61
|
+
throw new Error(`[legacy-contracts] ${p} on disk is ${onDisk}, expected ${version}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (version) {
|
|
67
|
+
ensureCache();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let bannerPrinted = false;
|
|
71
|
+
const seen = new Set();
|
|
72
|
+
|
|
73
|
+
function printBannerOnce() {
|
|
74
|
+
if (bannerPrinted || !version) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
bannerPrinted = true;
|
|
78
|
+
const lines = ['='.repeat(60), `[legacy-contracts][jest] CONTRACT_ARTIFACTS_VERSION=${version}`];
|
|
79
|
+
for (const p of REDIRECTED) {
|
|
80
|
+
const v = JSON.parse(fs.readFileSync(pkgJsonPath(p), 'utf8')).version;
|
|
81
|
+
if (v !== version) {
|
|
82
|
+
throw new Error(`[legacy-contracts] ${p} on disk is ${v}, expected ${version}`);
|
|
83
|
+
}
|
|
84
|
+
lines.push(`[legacy-contracts][jest] redirecting ${p}/artifacts/*.json -> .legacy-contracts/${version}/...`);
|
|
85
|
+
}
|
|
86
|
+
lines.push('='.repeat(60));
|
|
87
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Match a resolved absolute path against the workspace artifacts dirs and return the legacy cache equivalent, or null
|
|
91
|
+
// if it's not an artifact path we should redirect.
|
|
92
|
+
function legacyArtifactPath(resolved) {
|
|
93
|
+
if (!resolved.endsWith('.json')) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
for (const pkg of REDIRECTED) {
|
|
97
|
+
// pkg = '@aztec/noir-contracts.js' -> match '/noir-contracts.js/artifacts/'
|
|
98
|
+
const dirName = pkg.split('/')[1];
|
|
99
|
+
const marker = `/${dirName}/artifacts/`;
|
|
100
|
+
const idx = resolved.indexOf(marker);
|
|
101
|
+
if (idx === -1) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const basename = resolved.slice(idx + marker.length);
|
|
105
|
+
return path.join(cacheRoot, 'node_modules', pkg, 'artifacts', basename);
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = function legacyResolver(request, options) {
|
|
111
|
+
// Always run the default resolver first. We only inspect (and possibly rewrite) the *result*; this catches both
|
|
112
|
+
// bare-specifier imports of `@aztec/noir-contracts.js/artifacts/foo.json` and the relative `../artifacts/foo.json`
|
|
113
|
+
// imports inside the workspace TS wrapper classes — both resolve to the same workspace artifact path that we then
|
|
114
|
+
// redirect.
|
|
115
|
+
const resolved = options.defaultResolver(request, options);
|
|
116
|
+
if (!version) {
|
|
117
|
+
return resolved;
|
|
118
|
+
}
|
|
119
|
+
printBannerOnce();
|
|
120
|
+
const legacy = legacyArtifactPath(resolved);
|
|
121
|
+
if (!legacy) {
|
|
122
|
+
return resolved;
|
|
123
|
+
}
|
|
124
|
+
if (!fs.existsSync(legacy)) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`[legacy-contracts] artifact ${path.basename(legacy)} not present in legacy cache @${version}; ` +
|
|
127
|
+
`the contract may have been added after that release. Pin a newer CONTRACT_ARTIFACTS_VERSION or skip this test.`,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
if (!seen.has(resolved)) {
|
|
131
|
+
seen.add(resolved);
|
|
132
|
+
process.stderr.write(`[legacy-contracts][jest] redirected ${path.basename(legacy)} -> ${legacy}\n`);
|
|
133
|
+
}
|
|
134
|
+
return legacy;
|
|
135
|
+
};
|
|
@@ -138,37 +138,11 @@ async function deployAccountWithDiagnostics(
|
|
|
138
138
|
estimateGas?: boolean,
|
|
139
139
|
): Promise<void> {
|
|
140
140
|
const deployMethod = await account.getDeployMethod();
|
|
141
|
-
let txHash;
|
|
142
141
|
let gasSettings: any;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
logger.info(`${accountLabel} estimated gas: DA=${gasSettings.gasLimits.daGas} L2=${gasSettings.gasLimits.l2Gas}`);
|
|
148
|
-
}
|
|
149
|
-
const deployResult = await deployMethod.send({
|
|
150
|
-
from: NO_FROM,
|
|
151
|
-
fee: { paymentMethod, gasSettings },
|
|
152
|
-
wait: NO_WAIT,
|
|
153
|
-
});
|
|
154
|
-
txHash = deployResult.txHash;
|
|
155
|
-
await waitForTx(aztecNode, txHash, { timeout: 2400 });
|
|
156
|
-
logger.info(`${accountLabel} deployed at ${account.address}`);
|
|
157
|
-
} catch (error) {
|
|
158
|
-
const blockNumber = await aztecNode.getBlockNumber();
|
|
159
|
-
let receipt;
|
|
160
|
-
try {
|
|
161
|
-
receipt = await aztecNode.getTxReceipt(txHash);
|
|
162
|
-
} catch {
|
|
163
|
-
receipt = 'unavailable';
|
|
164
|
-
}
|
|
165
|
-
logger.error(`${accountLabel} deployment failed`, {
|
|
166
|
-
txHash: txHash.toString(),
|
|
167
|
-
receipt: JSON.stringify(receipt),
|
|
168
|
-
currentBlockNumber: blockNumber,
|
|
169
|
-
error: String(error),
|
|
170
|
-
});
|
|
171
|
-
throw error;
|
|
142
|
+
if (estimateGas) {
|
|
143
|
+
const sim = await deployMethod.simulate({ from: NO_FROM, fee: { paymentMethod } });
|
|
144
|
+
gasSettings = sim.estimatedGas;
|
|
145
|
+
logger.info(`${accountLabel} estimated gas: DA=${gasSettings.gasLimits.daGas} L2=${gasSettings.gasLimits.l2Gas}`);
|
|
172
146
|
}
|
|
173
147
|
|
|
174
148
|
// Track the tx hash across retries so we don't re-send when the previous tx is still pending.
|
|
@@ -196,7 +170,7 @@ async function deployAccountWithDiagnostics(
|
|
|
196
170
|
|
|
197
171
|
if (!sentTxHash) {
|
|
198
172
|
const deployResult = await deployMethod.send({
|
|
199
|
-
from:
|
|
173
|
+
from: NO_FROM,
|
|
200
174
|
fee: { paymentMethod, gasSettings },
|
|
201
175
|
wait: NO_WAIT,
|
|
202
176
|
});
|