@aztec/end-to-end 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108
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/bench/client_flows/benchmark.d.ts +4 -3
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/benchmark.js +2 -2
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +26 -15
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +111 -90
- package/dest/bench/client_flows/config.d.ts +1 -1
- package/dest/bench/client_flows/data_extractor.d.ts +1 -1
- package/dest/bench/client_flows/data_extractor.js +10 -30
- package/dest/bench/utils.d.ts +3 -12
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +17 -37
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +8 -8
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -1
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +42 -42
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +13 -10
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +35 -35
- package/dest/e2e_deploy_contract/deploy_test.d.ts +12 -6
- package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
- package/dest/e2e_deploy_contract/deploy_test.js +9 -18
- package/dest/e2e_epochs/epochs_test.d.ts +20 -12
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +36 -27
- package/dest/e2e_fees/bridging_race.notest.d.ts +1 -1
- package/dest/e2e_fees/bridging_race.notest.js +14 -11
- package/dest/e2e_fees/fees_test.d.ts +13 -9
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +39 -40
- package/dest/e2e_l1_publisher/write_json.d.ts +4 -2
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
- package/dest/e2e_l1_publisher/write_json.js +9 -8
- package/dest/e2e_multi_validator/utils.d.ts +2 -2
- package/dest/e2e_multi_validator/utils.d.ts.map +1 -1
- package/dest/e2e_multi_validator/utils.js +4 -10
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +7 -4
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +11 -12
- package/dest/e2e_p2p/inactivity_slash_test.d.ts +31 -0
- package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -0
- package/dest/e2e_p2p/inactivity_slash_test.js +136 -0
- package/dest/e2e_p2p/p2p_network.d.ts +238 -18
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +50 -25
- package/dest/e2e_p2p/shared.d.ts +16 -17
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +57 -56
- package/dest/e2e_token_contract/token_contract_test.d.ts +6 -5
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +14 -17
- package/dest/fixtures/e2e_prover_test.d.ts +13 -11
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +57 -66
- package/dest/fixtures/fixtures.d.ts +2 -3
- package/dest/fixtures/fixtures.d.ts.map +1 -1
- package/dest/fixtures/fixtures.js +2 -3
- package/dest/fixtures/get_acvm_config.d.ts +2 -2
- package/dest/fixtures/get_acvm_config.d.ts.map +1 -1
- package/dest/fixtures/get_acvm_config.js +1 -1
- package/dest/fixtures/get_bb_config.d.ts +2 -2
- package/dest/fixtures/get_bb_config.d.ts.map +1 -1
- package/dest/fixtures/get_bb_config.js +2 -2
- package/dest/fixtures/index.d.ts +1 -1
- package/dest/fixtures/l1_to_l2_messaging.d.ts +4 -3
- package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -1
- package/dest/fixtures/l1_to_l2_messaging.js +2 -2
- package/dest/fixtures/logging.d.ts +1 -1
- package/dest/fixtures/setup_p2p_test.d.ts +12 -11
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +50 -24
- package/dest/fixtures/snapshot_manager.d.ts +16 -15
- package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
- package/dest/fixtures/snapshot_manager.js +84 -88
- package/dest/fixtures/token_utils.d.ts +10 -5
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +17 -18
- package/dest/fixtures/utils.d.ts +44 -47
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +128 -185
- package/dest/fixtures/web3signer.d.ts +5 -0
- package/dest/fixtures/web3signer.d.ts.map +1 -0
- package/dest/fixtures/web3signer.js +53 -0
- package/dest/fixtures/with_telemetry_utils.d.ts +2 -2
- package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -1
- package/dest/fixtures/with_telemetry_utils.js +2 -2
- package/dest/index.d.ts +1 -1
- package/dest/quality_of_service/alert_checker.d.ts +2 -2
- package/dest/quality_of_service/alert_checker.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.d.ts +20 -23
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +14 -16
- package/dest/shared/gas_portal_test_harness.d.ts +10 -17
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/gas_portal_test_harness.js +11 -8
- package/dest/shared/index.d.ts +1 -1
- package/dest/shared/jest_setup.d.ts +1 -1
- package/dest/shared/jest_setup.js +1 -1
- package/dest/shared/submit-transactions.d.ts +6 -4
- package/dest/shared/submit-transactions.d.ts.map +1 -1
- package/dest/shared/submit-transactions.js +8 -7
- package/dest/shared/uniswap_l1_l2.d.ts +13 -9
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +44 -58
- package/dest/simulators/index.d.ts +1 -1
- package/dest/simulators/lending_simulator.d.ts +4 -7
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +8 -5
- package/dest/simulators/token_simulator.d.ts +4 -2
- package/dest/simulators/token_simulator.d.ts.map +1 -1
- package/dest/simulators/token_simulator.js +2 -2
- package/dest/spartan/setup_test_wallets.d.ts +22 -14
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +144 -86
- package/dest/spartan/tx_metrics.d.ts +39 -0
- package/dest/spartan/tx_metrics.d.ts.map +1 -0
- package/dest/spartan/tx_metrics.js +95 -0
- package/dest/spartan/utils.d.ts +101 -16
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +414 -52
- package/package.json +43 -40
- package/src/bench/client_flows/benchmark.ts +8 -8
- package/src/bench/client_flows/client_flows_benchmark.ts +143 -115
- package/src/bench/client_flows/data_extractor.ts +9 -31
- package/src/bench/utils.ts +15 -39
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +46 -63
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +46 -55
- package/src/e2e_deploy_contract/deploy_test.ts +18 -36
- package/src/e2e_epochs/epochs_test.ts +59 -42
- package/src/e2e_fees/bridging_race.notest.ts +16 -11
- package/src/e2e_fees/fees_test.ts +48 -52
- package/src/e2e_l1_publisher/write_json.ts +12 -9
- package/src/e2e_multi_validator/utils.ts +5 -11
- package/src/e2e_nested_contract/nested_contract_test.ts +15 -13
- package/src/e2e_p2p/inactivity_slash_test.ts +179 -0
- package/src/e2e_p2p/p2p_network.ts +125 -89
- package/src/e2e_p2p/shared.ts +69 -60
- package/src/e2e_token_contract/token_contract_test.ts +17 -17
- package/src/fixtures/e2e_prover_test.ts +65 -105
- package/src/fixtures/fixtures.ts +2 -5
- package/src/fixtures/get_acvm_config.ts +2 -2
- package/src/fixtures/get_bb_config.ts +3 -2
- package/src/fixtures/l1_to_l2_messaging.ts +4 -2
- package/src/fixtures/setup_p2p_test.ts +79 -32
- package/src/fixtures/snapshot_manager.ts +120 -131
- package/src/fixtures/token_utils.ts +16 -24
- package/src/fixtures/utils.ts +175 -269
- package/src/fixtures/web3signer.ts +63 -0
- package/src/fixtures/with_telemetry_utils.ts +2 -2
- package/src/guides/up_quick_start.sh +3 -11
- package/src/quality_of_service/alert_checker.ts +1 -1
- package/src/shared/cross_chain_test_harness.ts +23 -31
- package/src/shared/gas_portal_test_harness.ts +14 -21
- package/src/shared/jest_setup.ts +1 -1
- package/src/shared/submit-transactions.ts +12 -8
- package/src/shared/uniswap_l1_l2.ts +80 -88
- package/src/simulators/lending_simulator.ts +9 -6
- package/src/simulators/token_simulator.ts +5 -2
- package/src/spartan/DEVELOP.md +15 -3
- package/src/spartan/setup_test_wallets.ts +171 -127
- package/src/spartan/tx_metrics.ts +130 -0
- package/src/spartan/utils.ts +543 -45
- package/dest/fixtures/setup_l1_contracts.d.ts +0 -6
- package/dest/fixtures/setup_l1_contracts.d.ts.map +0 -1
- package/dest/fixtures/setup_l1_contracts.js +0 -17
- package/src/fixtures/setup_l1_contracts.ts +0 -26
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import { getSchnorrWalletWithSecretKey } from '@aztec/accounts/schnorr';
|
|
2
1
|
import type { InitialAccountData } from '@aztec/accounts/testing';
|
|
3
2
|
import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
4
|
-
import {
|
|
3
|
+
import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
|
|
4
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
5
|
+
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
5
6
|
import {
|
|
6
7
|
type EmpireSlashingProposerContract,
|
|
7
|
-
type ExtendedViemWalletClient,
|
|
8
8
|
GSEContract,
|
|
9
|
-
MultiAdderArtifact,
|
|
10
|
-
type Operator,
|
|
11
9
|
RollupContract,
|
|
12
10
|
type TallySlashingProposerContract,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from '@aztec/ethereum';
|
|
11
|
+
} from '@aztec/ethereum/contracts';
|
|
12
|
+
import type { Operator } from '@aztec/ethereum/deploy-aztec-l1-contracts';
|
|
13
|
+
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
14
|
+
import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
|
|
15
|
+
import { createL1TxUtilsFromViemWallet } from '@aztec/ethereum/l1-tx-utils';
|
|
18
16
|
import { ChainMonitor } from '@aztec/ethereum/test';
|
|
17
|
+
import type { ExtendedViemWalletClient, ViemClient } from '@aztec/ethereum/types';
|
|
18
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
19
19
|
import { SecretValue } from '@aztec/foundation/config';
|
|
20
20
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
21
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
21
22
|
import { RollupAbi, SlasherAbi, TestERC20Abi } from '@aztec/l1-artifacts';
|
|
22
23
|
import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
23
24
|
import type { BootstrapNode } from '@aztec/p2p/bootstrap';
|
|
@@ -26,6 +27,7 @@ import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
|
26
27
|
import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
27
28
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
28
29
|
import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
|
|
30
|
+
import type { TestWallet } from '@aztec/test-wallet/server';
|
|
29
31
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
30
32
|
|
|
31
33
|
import getPort from 'get-port';
|
|
@@ -43,7 +45,7 @@ import {
|
|
|
43
45
|
createSnapshotManager,
|
|
44
46
|
deployAccounts,
|
|
45
47
|
} from '../fixtures/snapshot_manager.js';
|
|
46
|
-
import { getPrivateKeyFromIndex, getSponsoredFPCAddress } from '../fixtures/utils.js';
|
|
48
|
+
import { type SetupOptions, getPrivateKeyFromIndex, getSponsoredFPCAddress } from '../fixtures/utils.js';
|
|
47
49
|
import { getEndToEndTestTelemetryClient } from '../fixtures/with_telemetry_utils.js';
|
|
48
50
|
|
|
49
51
|
// Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other
|
|
@@ -75,23 +77,22 @@ export class P2PNetworkTest {
|
|
|
75
77
|
public prefilledPublicData: PublicDataTreeLeaf[] = [];
|
|
76
78
|
|
|
77
79
|
// The re-execution test needs a wallet and a spam contract
|
|
78
|
-
public wallet?:
|
|
80
|
+
public wallet?: TestWallet;
|
|
79
81
|
public defaultAccountAddress?: AztecAddress;
|
|
80
82
|
public spamContract?: SpamContract;
|
|
81
83
|
|
|
82
84
|
public bootstrapNode?: BootstrapNode;
|
|
83
85
|
|
|
84
86
|
constructor(
|
|
85
|
-
testName: string,
|
|
87
|
+
public readonly testName: string,
|
|
86
88
|
public bootstrapNodeEnr: string,
|
|
87
89
|
public bootNodePort: number,
|
|
88
90
|
public numberOfValidators: number,
|
|
89
|
-
initialValidatorConfig:
|
|
91
|
+
initialValidatorConfig: SetupOptions,
|
|
90
92
|
public numberOfNodes = 0,
|
|
91
93
|
// If set enable metrics collection
|
|
92
94
|
private metricsPort?: number,
|
|
93
95
|
startProverNode?: boolean,
|
|
94
|
-
mockZkPassportVerifier?: boolean,
|
|
95
96
|
) {
|
|
96
97
|
this.logger = createLogger(`e2e:e2e_p2p:${testName}`);
|
|
97
98
|
|
|
@@ -120,7 +121,6 @@ export class P2PNetworkTest {
|
|
|
120
121
|
initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
|
|
121
122
|
slasherFlavor: initialValidatorConfig.slasherFlavor ?? 'tally',
|
|
122
123
|
aztecTargetCommitteeSize: numberOfValidators,
|
|
123
|
-
salt: 420,
|
|
124
124
|
metricsPort: metricsPort,
|
|
125
125
|
numberOfInitialFundedAccounts: 2,
|
|
126
126
|
startProverNode,
|
|
@@ -139,7 +139,6 @@ export class P2PNetworkTest {
|
|
|
139
139
|
aztecTargetCommitteeSize: numberOfValidators,
|
|
140
140
|
initialValidators: [],
|
|
141
141
|
zkPassportArgs: {
|
|
142
|
-
mockZkPassportVerifier,
|
|
143
142
|
zkPassportDomain: zkPassportParams.domain,
|
|
144
143
|
zkPassportScope: zkPassportParams.scope,
|
|
145
144
|
},
|
|
@@ -155,16 +154,14 @@ export class P2PNetworkTest {
|
|
|
155
154
|
metricsPort,
|
|
156
155
|
initialConfig,
|
|
157
156
|
startProverNode,
|
|
158
|
-
mockZkPassportVerifier,
|
|
159
157
|
}: {
|
|
160
158
|
testName: string;
|
|
161
159
|
numberOfNodes: number;
|
|
162
160
|
numberOfValidators: number;
|
|
163
161
|
basePort?: number;
|
|
164
162
|
metricsPort?: number;
|
|
165
|
-
initialConfig?:
|
|
163
|
+
initialConfig?: SetupOptions;
|
|
166
164
|
startProverNode?: boolean;
|
|
167
|
-
mockZkPassportVerifier?: boolean;
|
|
168
165
|
}) {
|
|
169
166
|
const port = basePort || (await getPort());
|
|
170
167
|
|
|
@@ -185,7 +182,6 @@ export class P2PNetworkTest {
|
|
|
185
182
|
numberOfNodes,
|
|
186
183
|
metricsPort,
|
|
187
184
|
startProverNode,
|
|
188
|
-
mockZkPassportVerifier,
|
|
189
185
|
);
|
|
190
186
|
}
|
|
191
187
|
|
|
@@ -198,7 +194,7 @@ export class P2PNetworkTest {
|
|
|
198
194
|
|
|
199
195
|
async addBootstrapNode() {
|
|
200
196
|
await this.snapshotManager.snapshot('add-bootstrap-node', async ({ aztecNodeConfig }) => {
|
|
201
|
-
const telemetry = getEndToEndTestTelemetryClient(this.metricsPort);
|
|
197
|
+
const telemetry = await getEndToEndTestTelemetryClient(this.metricsPort);
|
|
202
198
|
this.bootstrapNode = await createBootstrapNodeFromPrivateKey(
|
|
203
199
|
BOOTSTRAP_NODE_PRIVATE_KEY,
|
|
204
200
|
this.bootNodePort,
|
|
@@ -230,88 +226,85 @@ export class P2PNetworkTest {
|
|
|
230
226
|
|
|
231
227
|
async applyBaseSnapshots() {
|
|
232
228
|
await this.addBootstrapNode();
|
|
233
|
-
await this.snapshotManager.snapshot(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
client: deployL1ContractsValues.l1Client,
|
|
240
|
-
});
|
|
229
|
+
await this.snapshotManager.snapshot('add-validators', async ({ deployL1ContractsValues, cheatCodes }) => {
|
|
230
|
+
const rollup = getContract({
|
|
231
|
+
address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(),
|
|
232
|
+
abi: RollupAbi,
|
|
233
|
+
client: deployL1ContractsValues.l1Client,
|
|
234
|
+
});
|
|
241
235
|
|
|
242
|
-
|
|
236
|
+
this.logger.info(`Adding ${this.numberOfValidators} validators`);
|
|
243
237
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
238
|
+
const stakingAsset = getContract({
|
|
239
|
+
address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(),
|
|
240
|
+
abi: TestERC20Abi,
|
|
241
|
+
client: deployL1ContractsValues.l1Client,
|
|
242
|
+
});
|
|
249
243
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
244
|
+
const { address: multiAdderAddress } = await deployL1Contract(
|
|
245
|
+
deployL1ContractsValues.l1Client,
|
|
246
|
+
MultiAdderArtifact.contractAbi,
|
|
247
|
+
MultiAdderArtifact.contractBytecode,
|
|
248
|
+
[rollup.address, deployL1ContractsValues.l1Client.account.address],
|
|
249
|
+
);
|
|
256
250
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
251
|
+
const multiAdder = getContract({
|
|
252
|
+
address: multiAdderAddress.toString(),
|
|
253
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
254
|
+
client: deployL1ContractsValues.l1Client,
|
|
255
|
+
});
|
|
262
256
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
257
|
+
const stakeNeeded = (await rollup.read.getActivationThreshold()) * BigInt(this.numberOfValidators);
|
|
258
|
+
await Promise.all(
|
|
259
|
+
[await stakingAsset.write.mint([multiAdder.address, stakeNeeded], {} as any)].map(txHash =>
|
|
260
|
+
deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }),
|
|
261
|
+
),
|
|
262
|
+
);
|
|
269
263
|
|
|
270
|
-
|
|
271
|
-
|
|
264
|
+
const { validators } = this.getValidators();
|
|
265
|
+
this.validators = validators;
|
|
272
266
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
267
|
+
const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress!;
|
|
268
|
+
if (!gseAddress) {
|
|
269
|
+
throw new Error('GSE contract not deployed');
|
|
270
|
+
}
|
|
277
271
|
|
|
278
|
-
|
|
272
|
+
const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString());
|
|
279
273
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
};
|
|
274
|
+
const makeValidatorTuples = async (validator: Operator) => {
|
|
275
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
276
|
+
return {
|
|
277
|
+
attester: validator.attester.toString() as `0x${string}`,
|
|
278
|
+
withdrawer: validator.withdrawer.toString() as `0x${string}`,
|
|
279
|
+
...registrationTuple,
|
|
287
280
|
};
|
|
288
|
-
|
|
281
|
+
};
|
|
282
|
+
const validatorTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
289
283
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const timestamp = await cheatCodes.rollup.advanceToEpoch(2n, { updateDateProvider: dateProvider });
|
|
284
|
+
await deployL1ContractsValues.l1Client.waitForTransactionReceipt({
|
|
285
|
+
hash: await multiAdder.write.addValidators([validatorTuples]),
|
|
286
|
+
});
|
|
295
287
|
|
|
296
|
-
|
|
297
|
-
|
|
288
|
+
await cheatCodes.rollup.advanceToEpoch(
|
|
289
|
+
EpochNumber.fromBigInt(
|
|
290
|
+
BigInt(await cheatCodes.rollup.getEpoch()) + (await rollup.read.getLagInEpochsForValidatorSet()) + 1n,
|
|
291
|
+
),
|
|
292
|
+
);
|
|
298
293
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
},
|
|
303
|
-
);
|
|
294
|
+
// Send and await a tx to make sure we mine a block for the warp to correctly progress.
|
|
295
|
+
await this._sendDummyTx(deployL1ContractsValues.l1Client);
|
|
296
|
+
});
|
|
304
297
|
}
|
|
305
298
|
|
|
306
299
|
async setupAccount() {
|
|
307
300
|
await this.snapshotManager.snapshot(
|
|
308
301
|
'setup-account',
|
|
309
|
-
deployAccounts(1, this.logger
|
|
310
|
-
|
|
302
|
+
deployAccounts(1, this.logger),
|
|
303
|
+
({ deployedAccounts }, { wallet }) => {
|
|
311
304
|
this.deployedAccounts = deployedAccounts;
|
|
312
|
-
|
|
313
|
-
this.wallet =
|
|
314
|
-
|
|
305
|
+
[{ address: this.defaultAccountAddress }] = deployedAccounts;
|
|
306
|
+
this.wallet = wallet;
|
|
307
|
+
return Promise.resolve();
|
|
315
308
|
},
|
|
316
309
|
);
|
|
317
310
|
}
|
|
@@ -329,11 +322,12 @@ export class P2PNetworkTest {
|
|
|
329
322
|
.deployed();
|
|
330
323
|
return { contractAddress: spamContract.address };
|
|
331
324
|
},
|
|
332
|
-
|
|
325
|
+
({ contractAddress }) => {
|
|
333
326
|
if (!this.wallet) {
|
|
334
327
|
throw new Error('Call snapshot t.setupAccount before deploying account contract');
|
|
335
328
|
}
|
|
336
|
-
this.spamContract =
|
|
329
|
+
this.spamContract = SpamContract.at(contractAddress, this.wallet);
|
|
330
|
+
return Promise.resolve();
|
|
337
331
|
},
|
|
338
332
|
);
|
|
339
333
|
}
|
|
@@ -393,6 +387,48 @@ export class P2PNetworkTest {
|
|
|
393
387
|
this.logger.info('Nodes stopped');
|
|
394
388
|
}
|
|
395
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Wait for P2P mesh to be fully formed across all nodes.
|
|
392
|
+
* This ensures that all nodes are connected to each other before proceeding,
|
|
393
|
+
* preventing race conditions where validators propose blocks before the network is ready.
|
|
394
|
+
*
|
|
395
|
+
* @param nodes - Array of nodes to check for P2P connectivity
|
|
396
|
+
* @param expectedNodeCount - Expected number of nodes in the network (defaults to nodes.length)
|
|
397
|
+
* @param timeoutSeconds - Maximum time to wait for connections (default: 30 seconds)
|
|
398
|
+
* @param checkIntervalSeconds - How often to check connectivity (default: 0.1 seconds)
|
|
399
|
+
*/
|
|
400
|
+
async waitForP2PMeshConnectivity(
|
|
401
|
+
nodes: AztecNodeService[],
|
|
402
|
+
expectedNodeCount?: number,
|
|
403
|
+
timeoutSeconds = 30,
|
|
404
|
+
checkIntervalSeconds = 0.1,
|
|
405
|
+
) {
|
|
406
|
+
const nodeCount = expectedNodeCount ?? nodes.length;
|
|
407
|
+
const minPeerCount = nodeCount - 1;
|
|
408
|
+
|
|
409
|
+
this.logger.warn(
|
|
410
|
+
`Waiting for all ${nodeCount} nodes to connect to P2P mesh (at least ${minPeerCount} peers each)...`,
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
await Promise.all(
|
|
414
|
+
nodes.map(async (node, index) => {
|
|
415
|
+
const p2p = node.getP2P();
|
|
416
|
+
await retryUntil(
|
|
417
|
+
async () => {
|
|
418
|
+
const peers = await p2p.getPeers();
|
|
419
|
+
// Each node should be connected to at least N-1 other nodes
|
|
420
|
+
return peers.length >= minPeerCount ? true : undefined;
|
|
421
|
+
},
|
|
422
|
+
`Node ${index} to connect to at least ${minPeerCount} peers`,
|
|
423
|
+
timeoutSeconds,
|
|
424
|
+
checkIntervalSeconds,
|
|
425
|
+
);
|
|
426
|
+
}),
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
this.logger.warn('All nodes connected to P2P mesh');
|
|
430
|
+
}
|
|
431
|
+
|
|
396
432
|
async teardown() {
|
|
397
433
|
await this.monitor.stop();
|
|
398
434
|
await tryStop(this.bootstrapNode, this.logger);
|
|
@@ -406,7 +442,7 @@ export class P2PNetworkTest {
|
|
|
406
442
|
slashFactory: SlashFactoryContract;
|
|
407
443
|
}> {
|
|
408
444
|
if (!this.ctx.deployL1ContractsValues) {
|
|
409
|
-
throw new Error('
|
|
445
|
+
throw new Error('DeployAztecL1ContractsValues not set');
|
|
410
446
|
}
|
|
411
447
|
|
|
412
448
|
const rollup = new RollupContract(
|
|
@@ -415,7 +451,7 @@ export class P2PNetworkTest {
|
|
|
415
451
|
);
|
|
416
452
|
|
|
417
453
|
const slasherContract = getContract({
|
|
418
|
-
address: getAddress(await rollup.
|
|
454
|
+
address: getAddress((await rollup.getSlasherAddress()).toString()),
|
|
419
455
|
abi: SlasherAbi,
|
|
420
456
|
client: this.ctx.deployL1ContractsValues.l1Client,
|
|
421
457
|
});
|
package/src/e2e_p2p/shared.ts
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
|
|
2
1
|
import type { InitialAccountData } from '@aztec/accounts/testing';
|
|
3
2
|
import type { AztecNodeService } from '@aztec/aztec-node';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type SentTx,
|
|
10
|
-
TxStatus,
|
|
11
|
-
getContractInstanceFromInstantiationParams,
|
|
12
|
-
retryUntil,
|
|
13
|
-
} from '@aztec/aztec.js';
|
|
3
|
+
import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
4
|
+
import { type SentTx, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
|
|
5
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
6
|
+
import type { Logger } from '@aztec/aztec.js/log';
|
|
7
|
+
import { Tx, TxStatus } from '@aztec/aztec.js/tx';
|
|
14
8
|
import type { RollupCheatCodes } from '@aztec/aztec/testing';
|
|
15
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
EmpireSlashingProposerContract,
|
|
11
|
+
RollupContract,
|
|
12
|
+
TallySlashingProposerContract,
|
|
13
|
+
} from '@aztec/ethereum/contracts';
|
|
14
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
16
15
|
import { timesAsync, unique } from '@aztec/foundation/collection';
|
|
17
|
-
import
|
|
16
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
17
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
18
|
+
import { pluralize } from '@aztec/foundation/string';
|
|
18
19
|
import type { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
19
20
|
import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
|
|
20
|
-
import {
|
|
21
|
+
import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
|
|
21
22
|
import { getRoundForOffense } from '@aztec/slasher';
|
|
22
23
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
23
24
|
import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
25
|
+
import { TestWallet, proveInteraction } from '@aztec/test-wallet/server';
|
|
24
26
|
|
|
25
|
-
import type { NodeContext } from '../fixtures/setup_p2p_test.js';
|
|
26
27
|
import { submitTxsTo } from '../shared/submit-transactions.js';
|
|
27
28
|
|
|
28
29
|
// submits a set of transactions to the provided Private eXecution Environment (PXE)
|
|
@@ -55,56 +56,46 @@ export const submitComplexTxsTo = async (
|
|
|
55
56
|
return txs;
|
|
56
57
|
};
|
|
57
58
|
|
|
58
|
-
// creates
|
|
59
|
-
export const
|
|
59
|
+
// creates a wallet and submit a given number of transactions through it.
|
|
60
|
+
export const submitTransactions = async (
|
|
60
61
|
logger: Logger,
|
|
61
62
|
node: AztecNodeService,
|
|
62
63
|
numTxs: number,
|
|
63
64
|
fundedAccount: InitialAccountData,
|
|
64
|
-
): Promise<
|
|
65
|
+
): Promise<SentTx[]> => {
|
|
65
66
|
const rpcConfig = getRpcConfig();
|
|
66
67
|
rpcConfig.proverEnabled = false;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
pxeService,
|
|
71
|
-
fundedAccount.secret,
|
|
72
|
-
fundedAccount.signingKey,
|
|
73
|
-
fundedAccount.salt,
|
|
74
|
-
);
|
|
75
|
-
await account.register();
|
|
76
|
-
const wallet = await account.getWallet();
|
|
77
|
-
|
|
78
|
-
const txs = await submitTxsTo(pxeService, numTxs, wallet, logger);
|
|
79
|
-
return { txs, pxeService, node };
|
|
68
|
+
const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
|
|
69
|
+
const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
|
|
70
|
+
return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
|
|
80
71
|
};
|
|
81
72
|
|
|
82
|
-
export async function
|
|
73
|
+
export async function prepareTransactions(
|
|
83
74
|
logger: Logger,
|
|
84
75
|
node: AztecNodeService,
|
|
85
76
|
numTxs: number,
|
|
86
77
|
fundedAccount: InitialAccountData,
|
|
87
|
-
): Promise<
|
|
78
|
+
): Promise<Tx[]> {
|
|
88
79
|
const rpcConfig = getRpcConfig();
|
|
89
80
|
rpcConfig.proverEnabled = false;
|
|
90
|
-
const pxe = await createPXEService(node, rpcConfig, { useLogSuffix: true });
|
|
91
81
|
|
|
92
|
-
const
|
|
93
|
-
await
|
|
94
|
-
const wallet = await account.getWallet();
|
|
82
|
+
const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
|
|
83
|
+
const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
|
|
95
84
|
|
|
96
|
-
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
|
|
86
|
+
salt: Fr.random(),
|
|
87
|
+
});
|
|
88
|
+
await wallet.registerContract(testContractInstance, TestContractArtifact);
|
|
89
|
+
const contract = TestContract.at(testContractInstance.address, wallet);
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
const tx = await contract.methods.emit_nullifier(Fr.random())
|
|
91
|
+
return timesAsync(numTxs, async () => {
|
|
92
|
+
const tx = await proveInteraction(wallet, contract.methods.emit_nullifier(Fr.random()), {
|
|
93
|
+
from: fundedAccountManager.address,
|
|
94
|
+
});
|
|
102
95
|
const txHash = tx.getTxHash();
|
|
103
96
|
logger.info(`Tx prepared with hash ${txHash}`);
|
|
104
97
|
return tx;
|
|
105
98
|
});
|
|
106
|
-
|
|
107
|
-
return { txs, pxeService: pxe, node };
|
|
108
99
|
}
|
|
109
100
|
|
|
110
101
|
export function awaitProposalExecution(
|
|
@@ -147,7 +138,7 @@ export async function awaitCommitteeExists({
|
|
|
147
138
|
logger: Logger;
|
|
148
139
|
}): Promise<readonly `0x${string}`[]> {
|
|
149
140
|
logger.info(`Waiting for committee to be set`);
|
|
150
|
-
let committee:
|
|
141
|
+
let committee: EthAddress[] | undefined;
|
|
151
142
|
await retryUntil(
|
|
152
143
|
async () => {
|
|
153
144
|
committee = await rollup.getCurrentEpochCommittee();
|
|
@@ -156,7 +147,7 @@ export async function awaitCommitteeExists({
|
|
|
156
147
|
'non-empty committee',
|
|
157
148
|
60,
|
|
158
149
|
);
|
|
159
|
-
return committee
|
|
150
|
+
return committee!.map(c => c.toString() as `0x${string}`);
|
|
160
151
|
}
|
|
161
152
|
|
|
162
153
|
export async function awaitOffenseDetected({
|
|
@@ -164,26 +155,31 @@ export async function awaitOffenseDetected({
|
|
|
164
155
|
nodeAdmin,
|
|
165
156
|
slashingRoundSize,
|
|
166
157
|
epochDuration,
|
|
158
|
+
waitUntilOffenseCount,
|
|
159
|
+
timeoutSeconds = 120,
|
|
167
160
|
}: {
|
|
168
161
|
nodeAdmin: AztecNodeAdmin;
|
|
169
162
|
logger: Logger;
|
|
170
163
|
slashingRoundSize: number;
|
|
171
164
|
epochDuration: number;
|
|
165
|
+
waitUntilOffenseCount?: number;
|
|
166
|
+
timeoutSeconds?: number;
|
|
172
167
|
}) {
|
|
173
|
-
|
|
168
|
+
const targetOffenseCount = waitUntilOffenseCount ?? 1;
|
|
169
|
+
logger.warn(`Waiting for ${pluralize('offense', targetOffenseCount)} to be detected`);
|
|
174
170
|
const offenses = await retryUntil(
|
|
175
171
|
async () => {
|
|
176
172
|
const offenses = await nodeAdmin.getSlashOffenses('all');
|
|
177
|
-
if (offenses.length
|
|
173
|
+
if (offenses.length >= targetOffenseCount) {
|
|
178
174
|
return offenses;
|
|
179
175
|
}
|
|
180
176
|
},
|
|
181
177
|
'non-empty offenses',
|
|
182
|
-
|
|
178
|
+
timeoutSeconds,
|
|
183
179
|
);
|
|
184
180
|
logger.info(
|
|
185
181
|
`Hit ${offenses.length} offenses on rounds ${unique(offenses.map(o => getRoundForOffense(o, { slashingRoundSize, epochDuration })))}`,
|
|
186
|
-
offenses,
|
|
182
|
+
{ offenses },
|
|
187
183
|
);
|
|
188
184
|
return offenses;
|
|
189
185
|
}
|
|
@@ -200,8 +196,9 @@ export async function awaitCommitteeKicked({
|
|
|
200
196
|
slashingProposer,
|
|
201
197
|
slashingRoundSize,
|
|
202
198
|
aztecSlotDuration,
|
|
199
|
+
aztecEpochDuration,
|
|
203
200
|
logger,
|
|
204
|
-
|
|
201
|
+
offenseEpoch,
|
|
205
202
|
}: {
|
|
206
203
|
rollup: RollupContract;
|
|
207
204
|
cheatCodes: RollupCheatCodes;
|
|
@@ -210,20 +207,22 @@ export async function awaitCommitteeKicked({
|
|
|
210
207
|
slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
|
|
211
208
|
slashingRoundSize: number;
|
|
212
209
|
aztecSlotDuration: number;
|
|
213
|
-
|
|
210
|
+
aztecEpochDuration: number;
|
|
214
211
|
logger: Logger;
|
|
212
|
+
offenseEpoch: number;
|
|
215
213
|
}) {
|
|
216
214
|
if (!slashingProposer) {
|
|
217
215
|
throw new Error('No slashing proposer configured. Cannot test slashing.');
|
|
218
216
|
}
|
|
219
217
|
|
|
220
|
-
logger.info(`Advancing epochs so we start slashing`);
|
|
221
218
|
await cheatCodes.debugRollup();
|
|
222
|
-
await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
|
|
223
|
-
await cheatCodes.advanceToNextEpoch({ updateDateProvider: dateProvider });
|
|
224
219
|
|
|
225
|
-
// Await for the slash payload to be created if empire (no payload is created on tally until execution time)
|
|
226
220
|
if (slashingProposer.type === 'empire') {
|
|
221
|
+
// Await for the slash payload to be created if empire (no payload is created on tally until execution time)
|
|
222
|
+
const targetEpoch = EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1);
|
|
223
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
224
|
+
await cheatCodes.advanceToEpoch(targetEpoch);
|
|
225
|
+
|
|
227
226
|
const slashPayloadEvents = await retryUntil(
|
|
228
227
|
async () => {
|
|
229
228
|
const events = await slashFactory.getSlashPayloadCreatedEvents();
|
|
@@ -238,6 +237,15 @@ export async function awaitCommitteeKicked({
|
|
|
238
237
|
expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
|
|
239
238
|
committee.length,
|
|
240
239
|
);
|
|
240
|
+
} else {
|
|
241
|
+
// Use the slash offset to ensure we are in the right epoch for tally
|
|
242
|
+
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
243
|
+
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
244
|
+
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
245
|
+
const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
|
|
246
|
+
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
247
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
248
|
+
await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), { offset: -aztecSlotDuration / 2 });
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
const attestersPre = await rollup.getAttesters();
|
|
@@ -248,7 +256,7 @@ export async function awaitCommitteeKicked({
|
|
|
248
256
|
expect(attesterInfo.status).toEqual(1); // Validating
|
|
249
257
|
}
|
|
250
258
|
|
|
251
|
-
const timeout = slashingRoundSize * 2 * aztecSlotDuration;
|
|
259
|
+
const timeout = slashingRoundSize * 2 * aztecSlotDuration + 30;
|
|
252
260
|
logger.info(`Waiting for slash to be executed (timeout ${timeout}s)`);
|
|
253
261
|
await awaitProposalExecution(slashingProposer, timeout, logger);
|
|
254
262
|
|
|
@@ -265,10 +273,11 @@ export async function awaitCommitteeKicked({
|
|
|
265
273
|
expect(attesterInfo.status).toEqual(2); // Living
|
|
266
274
|
}
|
|
267
275
|
|
|
268
|
-
logger.info(`Advancing
|
|
276
|
+
logger.info(`Advancing to check current committee`);
|
|
269
277
|
await cheatCodes.debugRollup();
|
|
270
|
-
await cheatCodes.
|
|
271
|
-
|
|
278
|
+
await cheatCodes.advanceToEpoch(
|
|
279
|
+
EpochNumber((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochsForValidatorSet()) + 1),
|
|
280
|
+
);
|
|
272
281
|
await cheatCodes.debugRollup();
|
|
273
282
|
|
|
274
283
|
const committeeNextEpoch = await rollup.getCurrentEpochCommittee();
|