@aztec/end-to-end 0.0.1-commit.0c875d939 → 0.0.1-commit.0dc957cde
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.d.ts +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +21 -28
- package/dest/bench/utils.d.ts +1 -1
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +6 -3
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +3 -2
- 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 +15 -15
- package/dest/e2e_epochs/epochs_test.d.ts +26 -7
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +113 -43
- package/dest/e2e_fees/fees_test.d.ts +1 -1
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +16 -9
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +4 -6
- package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
- package/dest/e2e_p2p/p2p_network.d.ts +13 -11
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +70 -34
- package/dest/e2e_p2p/reqresp/utils.d.ts +3 -3
- package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
- package/dest/e2e_p2p/reqresp/utils.js +46 -9
- package/dest/e2e_p2p/shared.d.ts +25 -7
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +69 -49
- package/dest/e2e_token_contract/token_contract_test.d.ts +1 -1
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +11 -11
- package/dest/fixtures/authwit_proxy.d.ts +3 -3
- 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 +6 -5
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +37 -49
- package/dest/fixtures/elu_monitor.d.ts +21 -0
- package/dest/fixtures/elu_monitor.d.ts.map +1 -0
- package/dest/fixtures/elu_monitor.js +102 -0
- package/dest/fixtures/fixtures.d.ts +16 -1
- package/dest/fixtures/fixtures.d.ts.map +1 -1
- package/dest/fixtures/fixtures.js +16 -0
- package/dest/fixtures/get_bb_config.d.ts +1 -1
- package/dest/fixtures/get_bb_config.d.ts.map +1 -1
- package/dest/fixtures/get_bb_config.js +5 -5
- package/dest/fixtures/ha_setup.d.ts +2 -2
- package/dest/fixtures/ha_setup.d.ts.map +1 -1
- package/dest/fixtures/ha_setup.js +1 -1
- package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
- package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
- package/dest/fixtures/schnorr_hardcoded_account_contract.js +39 -0
- package/dest/fixtures/setup.d.ts +45 -17
- package/dest/fixtures/setup.d.ts.map +1 -1
- package/dest/fixtures/setup.js +88 -99
- package/dest/fixtures/setup_p2p_test.d.ts +10 -7
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +18 -15
- package/dest/fixtures/token_utils.d.ts +2 -2
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +5 -7
- package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
- package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
- package/dest/forward-compatibility/wallet_service.d.ts +3 -0
- package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_service.js +109 -0
- package/dest/legacy-jest-resolver.d.cts +3 -0
- package/dest/legacy-jest-resolver.d.cts.map +1 -0
- package/dest/shared/cross_chain_test_harness.d.ts +1 -1
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +13 -13
- package/dest/shared/gas_portal_test_harness.js +3 -3
- package/dest/shared/jest_setup.js +41 -1
- package/dest/shared/submit-transactions.js +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +14 -21
- package/dest/simulators/lending_simulator.d.ts +1 -1
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +4 -4
- package/dest/simulators/token_simulator.d.ts +1 -1
- 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 +11 -2
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +97 -38
- package/dest/spartan/tx_metrics.js +1 -1
- package/dest/spartan/utils/bot.d.ts +3 -2
- package/dest/spartan/utils/bot.d.ts.map +1 -1
- package/dest/spartan/utils/bot.js +2 -1
- package/dest/spartan/utils/config.d.ts +7 -1
- package/dest/spartan/utils/config.d.ts.map +1 -1
- package/dest/spartan/utils/config.js +3 -1
- package/dest/spartan/utils/index.d.ts +4 -2
- package/dest/spartan/utils/index.d.ts.map +1 -1
- package/dest/spartan/utils/index.js +5 -1
- package/dest/spartan/utils/k8s.d.ts +3 -1
- package/dest/spartan/utils/k8s.d.ts.map +1 -1
- package/dest/spartan/utils/k8s.js +6 -0
- package/dest/spartan/utils/nodes.d.ts +4 -5
- package/dest/spartan/utils/nodes.d.ts.map +1 -1
- package/dest/spartan/utils/nodes.js +9 -9
- package/dest/spartan/utils/pod_logs.d.ts +25 -0
- package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
- package/dest/spartan/utils/pod_logs.js +74 -0
- package/dest/test-wallet/test_wallet.d.ts +24 -23
- package/dest/test-wallet/test_wallet.d.ts.map +1 -1
- package/dest/test-wallet/test_wallet.js +119 -82
- package/dest/test-wallet/wallet_worker_script.d.ts +2 -0
- package/dest/test-wallet/wallet_worker_script.d.ts.map +1 -0
- package/dest/test-wallet/wallet_worker_script.js +48 -0
- package/dest/test-wallet/worker_wallet.d.ts +52 -0
- package/dest/test-wallet/worker_wallet.d.ts.map +1 -0
- package/dest/test-wallet/worker_wallet.js +151 -0
- package/dest/test-wallet/worker_wallet_schema.d.ts +279 -0
- package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -0
- package/dest/test-wallet/worker_wallet_schema.js +10 -0
- package/package.json +43 -44
- package/src/bench/client_flows/client_flows_benchmark.ts +29 -12
- package/src/bench/utils.ts +7 -2
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +21 -20
- package/src/e2e_epochs/epochs_test.ts +131 -70
- package/src/e2e_fees/fees_test.ts +17 -8
- package/src/e2e_nested_contract/nested_contract_test.ts +6 -4
- package/src/e2e_p2p/inactivity_slash_test.ts +3 -3
- package/src/e2e_p2p/p2p_network.ts +88 -44
- package/src/e2e_p2p/reqresp/utils.ts +58 -9
- package/src/e2e_p2p/shared.ts +88 -63
- package/src/e2e_token_contract/token_contract_test.ts +16 -8
- package/src/fixtures/authwit_proxy.ts +4 -0
- package/src/fixtures/dumps/epoch_proof_result.json +1 -1
- package/src/fixtures/e2e_prover_test.ts +43 -52
- package/src/fixtures/elu_monitor.ts +126 -0
- package/src/fixtures/fixtures.ts +32 -0
- package/src/fixtures/get_bb_config.ts +7 -6
- package/src/fixtures/ha_setup.ts +4 -2
- package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
- package/src/fixtures/setup.ts +125 -132
- package/src/fixtures/setup_p2p_test.ts +17 -25
- package/src/fixtures/token_utils.ts +3 -3
- package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
- package/src/forward-compatibility/wallet_service.ts +104 -0
- package/src/guides/up_quick_start.sh +0 -2
- package/src/legacy-jest-resolver.cjs +135 -0
- package/src/shared/cross_chain_test_harness.ts +13 -9
- package/src/shared/gas_portal_test_harness.ts +1 -2
- package/src/shared/jest_setup.ts +51 -1
- package/src/shared/submit-transactions.ts +1 -1
- package/src/shared/uniswap_l1_l2.ts +35 -32
- package/src/simulators/lending_simulator.ts +8 -4
- package/src/simulators/token_simulator.ts +6 -2
- package/src/spartan/setup_test_wallets.ts +138 -31
- package/src/spartan/tx_metrics.ts +1 -1
- package/src/spartan/utils/bot.ts +3 -0
- package/src/spartan/utils/config.ts +2 -0
- package/src/spartan/utils/index.ts +7 -0
- package/src/spartan/utils/k8s.ts +8 -0
- package/src/spartan/utils/nodes.ts +15 -10
- package/src/spartan/utils/pod_logs.ts +99 -0
- package/src/test-wallet/test_wallet.ts +148 -101
- package/src/test-wallet/wallet_worker_script.ts +60 -0
- package/src/test-wallet/worker_wallet.ts +214 -0
- package/src/test-wallet/worker_wallet_schema.ts +13 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { generateSchnorrAccounts } from '@aztec/accounts/testing';
|
|
2
|
+
import { getAccountContractAddress } from '@aztec/aztec.js/account';
|
|
1
3
|
import { EthAddress } from '@aztec/aztec.js/addresses';
|
|
2
4
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
5
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
4
6
|
import { GSEContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
5
7
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
6
8
|
import { MultiAdderArtifact } from '@aztec/ethereum/l1-artifacts';
|
|
7
|
-
import {
|
|
9
|
+
import { createL1TxUtils } from '@aztec/ethereum/l1-tx-utils';
|
|
8
10
|
import { ChainMonitor } from '@aztec/ethereum/test';
|
|
9
11
|
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
10
12
|
import { SecretValue } from '@aztec/foundation/config';
|
|
@@ -14,13 +16,14 @@ import { RollupAbi, SlasherAbi, TestERC20Abi } from '@aztec/l1-artifacts';
|
|
|
14
16
|
import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
15
17
|
import { createBootstrapNodeFromPrivateKey, getBootstrapNodeEnr } from '@aztec/p2p/test-helpers';
|
|
16
18
|
import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
17
|
-
import {
|
|
19
|
+
import { TopicType } from '@aztec/stdlib/p2p';
|
|
18
20
|
import { ZkPassportProofParams } from '@aztec/stdlib/zkpassport';
|
|
19
21
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
20
22
|
import getPort from 'get-port';
|
|
21
23
|
import { getAddress, getContract } from 'viem';
|
|
22
24
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
23
|
-
import {
|
|
25
|
+
import { SCHNORR_HARDCODED_PRIVATE_KEY, SchnorrHardcodedKeyAccountContract } from '../fixtures/schnorr_hardcoded_account_contract.js';
|
|
26
|
+
import { getPrivateKeyFromIndex, getSponsoredFPCAddress, setup, teardown } from '../fixtures/setup.js';
|
|
24
27
|
import { ATTESTER_PRIVATE_KEYS_START_INDEX, createValidatorConfig, generatePrivateKeys } from '../fixtures/setup_p2p_test.js';
|
|
25
28
|
import { getEndToEndTestTelemetryClient } from '../fixtures/with_telemetry_utils.js';
|
|
26
29
|
// Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other
|
|
@@ -30,7 +33,7 @@ export const WAIT_FOR_TX_TIMEOUT = l1ContractsConfig.aztecSlotDuration * 3;
|
|
|
30
33
|
export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = {
|
|
31
34
|
aztecSlotDuration: 12,
|
|
32
35
|
ethereumSlotDuration: 4,
|
|
33
|
-
|
|
36
|
+
aztecProofSubmissionEpochs: 640
|
|
34
37
|
};
|
|
35
38
|
export class P2PNetworkTest {
|
|
36
39
|
testName;
|
|
@@ -49,8 +52,8 @@ export class P2PNetworkTest {
|
|
|
49
52
|
attesterPublicKeys;
|
|
50
53
|
peerIdPrivateKeys;
|
|
51
54
|
validators;
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
hardcodedAccountData;
|
|
56
|
+
genesis;
|
|
54
57
|
// The re-execution test needs a wallet and a spam contract
|
|
55
58
|
wallet;
|
|
56
59
|
defaultAccountAddress;
|
|
@@ -71,8 +74,6 @@ export class P2PNetworkTest {
|
|
|
71
74
|
this.attesterPublicKeys = [];
|
|
72
75
|
this.peerIdPrivateKeys = [];
|
|
73
76
|
this.validators = [];
|
|
74
|
-
this.deployedAccounts = [];
|
|
75
|
-
this.prefilledPublicData = [];
|
|
76
77
|
this.logger = createLogger(`e2e:e2e_p2p:${testName}`);
|
|
77
78
|
// Set up the base account and node private keys for the initial network deployment
|
|
78
79
|
this.baseAccountPrivateKey = `0x${getPrivateKeyFromIndex(1).toString('hex')}`;
|
|
@@ -88,18 +89,17 @@ export class P2PNetworkTest {
|
|
|
88
89
|
aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
|
|
89
90
|
aztecProofSubmissionEpochs: initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
|
|
90
91
|
slashingRoundSizeInEpochs: initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
|
|
91
|
-
|
|
92
|
+
slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
|
|
92
93
|
aztecTargetCommitteeSize: numberOfValidators,
|
|
93
94
|
metricsPort: metricsPort,
|
|
94
95
|
numberOfInitialFundedAccounts: 2,
|
|
95
|
-
startProverNode
|
|
96
|
-
walletMinFeePadding: 2.0
|
|
96
|
+
startProverNode
|
|
97
97
|
};
|
|
98
98
|
this.deployL1ContractsArgs = {
|
|
99
99
|
...initialValidatorConfig,
|
|
100
100
|
aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
|
|
101
101
|
slashingRoundSizeInEpochs: initialValidatorConfig.slashingRoundSizeInEpochs ?? l1ContractsConfig.slashingRoundSizeInEpochs,
|
|
102
|
-
|
|
102
|
+
slasherEnabled: initialValidatorConfig.slasherEnabled ?? true,
|
|
103
103
|
ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
|
|
104
104
|
aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
|
|
105
105
|
aztecProofSubmissionEpochs: initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
|
|
@@ -119,10 +119,10 @@ export class P2PNetworkTest {
|
|
|
119
119
|
return new P2PNetworkTest(testName, bootstrapNodeEnr, port, numberOfValidators, initialValidatorConfig, numberOfNodes, metricsPort, startProverNode);
|
|
120
120
|
}
|
|
121
121
|
get fundedAccount() {
|
|
122
|
-
if (!this.
|
|
123
|
-
throw new Error('Call
|
|
122
|
+
if (!this.hardcodedAccountData) {
|
|
123
|
+
throw new Error('Call setup to initialize the hardcoded account.');
|
|
124
124
|
}
|
|
125
|
-
return this.
|
|
125
|
+
return this.hardcodedAccountData;
|
|
126
126
|
}
|
|
127
127
|
async addBootstrapNode() {
|
|
128
128
|
this.logger.info('Adding bootstrap node');
|
|
@@ -204,14 +204,19 @@ export class P2PNetworkTest {
|
|
|
204
204
|
// Send and await a tx to make sure we mine a block for the warp to correctly progress.
|
|
205
205
|
await this._sendDummyTx(this.context.deployL1ContractsValues.l1Client);
|
|
206
206
|
}
|
|
207
|
-
|
|
208
|
-
this.logger.info('
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
207
|
+
/** Points the wallet to a P2P-enabled node so transactions can propagate through the network. */ setupWalletOnNode(node) {
|
|
208
|
+
this.logger.info('Pointing wallet to a P2P-enabled node');
|
|
209
|
+
this.context.wallet.updateNode(node);
|
|
210
|
+
}
|
|
211
|
+
/** Registers the hardcoded account in PXE without on-chain deployment. No sequencer needed. */ async setupAccount() {
|
|
212
|
+
this.logger.info('Registering hardcoded account (no deployment)');
|
|
213
|
+
const contract = new SchnorrHardcodedKeyAccountContract();
|
|
214
|
+
const accountManager = await this.context.wallet.createAccount({
|
|
215
|
+
secret: this.hardcodedAccountData.secret,
|
|
216
|
+
salt: this.hardcodedAccountData.salt,
|
|
217
|
+
contract
|
|
212
218
|
});
|
|
213
|
-
this.
|
|
214
|
-
[{ address: this.defaultAccountAddress }] = deployedAccounts;
|
|
219
|
+
this.defaultAccountAddress = accountManager.address;
|
|
215
220
|
this.wallet = this.context.wallet;
|
|
216
221
|
}
|
|
217
222
|
async deploySpamContract() {
|
|
@@ -219,10 +224,9 @@ export class P2PNetworkTest {
|
|
|
219
224
|
if (!this.wallet) {
|
|
220
225
|
throw new Error('Call setupAccount before deploying spam contract');
|
|
221
226
|
}
|
|
222
|
-
|
|
227
|
+
({ contract: this.spamContract } = await SpamContract.deploy(this.wallet).send({
|
|
223
228
|
from: this.defaultAccountAddress
|
|
224
|
-
});
|
|
225
|
-
this.spamContract = spamContract;
|
|
229
|
+
}));
|
|
226
230
|
}
|
|
227
231
|
async removeInitialNode() {
|
|
228
232
|
this.logger.info('Removing initial node');
|
|
@@ -238,7 +242,7 @@ export class P2PNetworkTest {
|
|
|
238
242
|
return await this._sendDummyTx(this.ctx.deployL1ContractsValues.l1Client);
|
|
239
243
|
}
|
|
240
244
|
async _sendDummyTx(l1Client) {
|
|
241
|
-
const l1TxUtils =
|
|
245
|
+
const l1TxUtils = createL1TxUtils(l1Client);
|
|
242
246
|
return await l1TxUtils.sendAndMonitorTransaction({
|
|
243
247
|
to: l1Client.account.address,
|
|
244
248
|
value: 1n
|
|
@@ -246,11 +250,28 @@ export class P2PNetworkTest {
|
|
|
246
250
|
}
|
|
247
251
|
async setup() {
|
|
248
252
|
this.logger.info('Setting up subsystems from fresh');
|
|
253
|
+
// Pre-compute hardcoded account data so it gets funded in genesis.
|
|
254
|
+
const contract = new SchnorrHardcodedKeyAccountContract();
|
|
255
|
+
const secret = Fr.random();
|
|
256
|
+
const salt = Fr.random();
|
|
257
|
+
this.hardcodedAccountData = {
|
|
258
|
+
secret,
|
|
259
|
+
salt,
|
|
260
|
+
signingKey: SCHNORR_HARDCODED_PRIVATE_KEY,
|
|
261
|
+
address: await getAccountContractAddress(contract, secret, salt)
|
|
262
|
+
};
|
|
263
|
+
// Generate regular Schnorr accounts for tests that need deployable accounts (e.g. add_rollup).
|
|
264
|
+
const regularAccounts = await generateSchnorrAccounts(this.setupOptions.numberOfInitialFundedAccounts ?? 2);
|
|
249
265
|
this.context = await setup(0, {
|
|
250
266
|
...this.setupOptions,
|
|
251
267
|
fundSponsoredFPC: true,
|
|
252
268
|
skipAccountDeployment: true,
|
|
253
|
-
|
|
269
|
+
skipInitialSequencer: true,
|
|
270
|
+
initialFundedAccounts: [
|
|
271
|
+
...regularAccounts,
|
|
272
|
+
this.hardcodedAccountData
|
|
273
|
+
],
|
|
274
|
+
slasherEnabled: this.setupOptions.slasherEnabled ?? this.deployL1ContractsArgs.slasherEnabled ?? false,
|
|
254
275
|
aztecTargetCommitteeSize: 0,
|
|
255
276
|
l1ContractsArgs: this.deployL1ContractsArgs
|
|
256
277
|
}, // Use checkpointed chain tip for PXE to avoid issues with blocks being dropped due to pruned anchor blocks.
|
|
@@ -263,8 +284,8 @@ export class P2PNetworkTest {
|
|
|
263
284
|
...this.context.initialFundedAccounts.map((a)=>a.address),
|
|
264
285
|
sponsoredFPCAddress
|
|
265
286
|
];
|
|
266
|
-
const {
|
|
267
|
-
this.
|
|
287
|
+
const { genesis } = await getGenesisValues(initialFundedAccounts, undefined, undefined, this.context.genesis.genesisTimestamp);
|
|
288
|
+
this.genesis = genesis;
|
|
268
289
|
const rollupContract = RollupContract.getFromL1ContractsValues(this.context.deployL1ContractsValues);
|
|
269
290
|
this.monitor = new ChainMonitor(rollupContract, this.context.dateProvider).start();
|
|
270
291
|
this.monitor.on('l1-block', ({ timestamp })=>this.context.dateProvider.setTime(Number(timestamp) * 1000));
|
|
@@ -287,7 +308,9 @@ export class P2PNetworkTest {
|
|
|
287
308
|
* @param expectedNodeCount - Expected number of nodes in the network (defaults to nodes.length)
|
|
288
309
|
* @param timeoutSeconds - Maximum time to wait for connections (default: 30 seconds)
|
|
289
310
|
* @param checkIntervalSeconds - How often to check connectivity (default: 0.1 seconds)
|
|
290
|
-
*/ async waitForP2PMeshConnectivity(nodes, expectedNodeCount, timeoutSeconds = 30, checkIntervalSeconds = 0.1
|
|
311
|
+
*/ async waitForP2PMeshConnectivity(nodes, expectedNodeCount, timeoutSeconds = 30, checkIntervalSeconds = 0.1, topics = [
|
|
312
|
+
TopicType.tx
|
|
313
|
+
]) {
|
|
291
314
|
const nodeCount = expectedNodeCount ?? nodes.length;
|
|
292
315
|
const minPeerCount = nodeCount - 1;
|
|
293
316
|
this.logger.warn(`Waiting for all ${nodeCount} nodes to connect to P2P mesh (at least ${minPeerCount} peers each)...`);
|
|
@@ -300,6 +323,21 @@ export class P2PNetworkTest {
|
|
|
300
323
|
}, `Node ${index} to connect to at least ${minPeerCount} peers`, timeoutSeconds, checkIntervalSeconds);
|
|
301
324
|
}));
|
|
302
325
|
this.logger.warn('All nodes connected to P2P mesh');
|
|
326
|
+
// Wait for GossipSub mesh to form for all specified topics.
|
|
327
|
+
// We only require at least 1 mesh peer per node because GossipSub
|
|
328
|
+
// stops grafting once it reaches Dlo peers and won't fill the mesh to all available peers.
|
|
329
|
+
for (const topic of topics){
|
|
330
|
+
this.logger.warn(`Waiting for GossipSub mesh to form for ${topic} topic...`);
|
|
331
|
+
await Promise.all(nodes.map(async (node, index)=>{
|
|
332
|
+
const p2p = node.getP2P();
|
|
333
|
+
await retryUntil(async ()=>{
|
|
334
|
+
const meshPeers = await p2p.getGossipMeshPeerCount(topic);
|
|
335
|
+
this.logger.debug(`Node ${index} has ${meshPeers} gossip mesh peers for ${topic} topic`);
|
|
336
|
+
return meshPeers >= 1 ? true : undefined;
|
|
337
|
+
}, `Node ${index} to have gossip mesh peers for ${topic} topic`, timeoutSeconds, checkIntervalSeconds);
|
|
338
|
+
}));
|
|
339
|
+
this.logger.warn(`All nodes have gossip mesh peers for ${topic} topic`);
|
|
340
|
+
}
|
|
303
341
|
}
|
|
304
342
|
async teardown() {
|
|
305
343
|
await this.monitor.stop();
|
|
@@ -316,14 +354,12 @@ export class P2PNetworkTest {
|
|
|
316
354
|
abi: SlasherAbi,
|
|
317
355
|
client: this.ctx.deployL1ContractsValues.l1Client
|
|
318
356
|
});
|
|
319
|
-
// Get the actual slashing proposer from rollup
|
|
357
|
+
// Get the actual slashing proposer from rollup
|
|
320
358
|
const slashingProposer = await rollup.getSlashingProposer();
|
|
321
|
-
const slashFactory = new SlashFactoryContract(this.ctx.deployL1ContractsValues.l1Client, getAddress(this.ctx.deployL1ContractsValues.l1ContractAddresses.slashFactoryAddress.toString()));
|
|
322
359
|
return {
|
|
323
360
|
rollup,
|
|
324
361
|
slasherContract,
|
|
325
|
-
slashingProposer
|
|
326
|
-
slashFactory
|
|
362
|
+
slashingProposer
|
|
327
363
|
};
|
|
328
364
|
}
|
|
329
365
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AztecNodeService } from '@aztec/aztec-node';
|
|
2
2
|
import { P2PNetworkTest } from '../p2p_network.js';
|
|
3
3
|
export declare const NUM_VALIDATORS = 6;
|
|
4
|
-
export declare const NUM_TXS_PER_NODE =
|
|
5
|
-
export declare const BOOT_NODE_UDP_PORT
|
|
4
|
+
export declare const NUM_TXS_PER_NODE = 4;
|
|
5
|
+
export declare const BOOT_NODE_UDP_PORT: number;
|
|
6
6
|
export declare const createReqrespDataDir: () => string;
|
|
7
7
|
type ReqrespOptions = {
|
|
8
8
|
disableStatusHandshake?: boolean;
|
|
@@ -19,4 +19,4 @@ export declare function runReqrespTxTest(params: {
|
|
|
19
19
|
disableStatusHandshake?: boolean;
|
|
20
20
|
}): Promise<AztecNodeService[]>;
|
|
21
21
|
export {};
|
|
22
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lMmVfcDJwL3JlcXJlc3AvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQWdCMUQsT0FBTyxFQUFFLGNBQWMsRUFBdUIsTUFBTSxtQkFBbUIsQ0FBQztBQUl4RSxlQUFPLE1BQU0sY0FBYyxJQUFJLENBQUM7QUFDaEMsZUFBTyxNQUFNLGdCQUFnQixJQUFJLENBQUM7QUFDbEMsZUFBTyxNQUFNLGtCQUFrQixRQUF1QixDQUFDO0FBRXZELGVBQU8sTUFBTSxvQkFBb0IsY0FBMkQsQ0FBQztBQUU3RixLQUFLLGNBQWMsR0FBRztJQUNwQixzQkFBc0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQztDQUNsQyxDQUFDO0FBRUYsd0JBQXNCLGlCQUFpQixDQUFDLE9BQU8sR0FBRSxjQUFtQixHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0EwQjdGO0FBRUQsd0JBQXNCLGtCQUFrQixDQUFDLE1BQU0sRUFBRTtJQUFFLENBQUMsRUFBRSxjQUFjLENBQUM7SUFBQyxLQUFLLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO0lBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQTtDQUFFLGlCQVNsSDtBQUlELHdCQUFzQixnQkFBZ0IsQ0FBQyxNQUFNLEVBQUU7SUFDN0MsQ0FBQyxFQUFFLGNBQWMsQ0FBQztJQUNsQixPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLHNCQUFzQixDQUFDLEVBQUUsT0FBTyxDQUFDO0NBQ2xDLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FtSjlCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/e2e_p2p/reqresp/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAgB1D,OAAO,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/e2e_p2p/reqresp/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAgB1D,OAAO,EAAE,cAAc,EAAuB,MAAM,mBAAmB,CAAC;AAIxE,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,kBAAkB,QAAuB,CAAC;AAEvD,eAAO,MAAM,oBAAoB,cAA2D,CAAC;AAE7F,KAAK,cAAc,GAAG;IACpB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0B7F;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAAE,CAAC,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,iBASlH;AAID,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,CAAC,EAAE,cAAc,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAmJ9B"}
|
|
@@ -2,21 +2,21 @@ import { createLogger } from '@aztec/aztec.js/log';
|
|
|
2
2
|
import { waitForTx } from '@aztec/aztec.js/node';
|
|
3
3
|
import { Tx } from '@aztec/aztec.js/tx';
|
|
4
4
|
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
5
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
5
|
+
import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
6
6
|
import { timesAsync } from '@aztec/foundation/collection';
|
|
7
7
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
8
|
-
import { jest } from '@jest/globals';
|
|
8
|
+
import { expect, jest } from '@jest/globals';
|
|
9
9
|
import fs from 'fs';
|
|
10
10
|
import os from 'os';
|
|
11
11
|
import path from 'path';
|
|
12
|
-
import { shouldCollectMetrics } from '../../fixtures/fixtures.js';
|
|
12
|
+
import { getBootNodeUdpPort, shouldCollectMetrics } from '../../fixtures/fixtures.js';
|
|
13
13
|
import { createNodes } from '../../fixtures/setup_p2p_test.js';
|
|
14
|
-
import { P2PNetworkTest,
|
|
14
|
+
import { P2PNetworkTest, WAIT_FOR_TX_TIMEOUT } from '../p2p_network.js';
|
|
15
15
|
import { prepareTransactions } from '../shared.js';
|
|
16
16
|
// Don't set this to a higher value than 9 because each node will use a different L1 publisher account and anvil seeds
|
|
17
17
|
export const NUM_VALIDATORS = 6;
|
|
18
|
-
export const NUM_TXS_PER_NODE =
|
|
19
|
-
export const BOOT_NODE_UDP_PORT =
|
|
18
|
+
export const NUM_TXS_PER_NODE = 4;
|
|
19
|
+
export const BOOT_NODE_UDP_PORT = getBootNodeUdpPort();
|
|
20
20
|
export const createReqrespDataDir = ()=>fs.mkdtempSync(path.join(os.tmpdir(), 'reqresp-'));
|
|
21
21
|
export async function createReqrespTest(options = {}) {
|
|
22
22
|
const { disableStatusHandshake = false } = options;
|
|
@@ -28,8 +28,14 @@ export async function createReqrespTest(options = {}) {
|
|
|
28
28
|
// To collect metrics - run in aztec-packages `docker compose --profile metrics up`
|
|
29
29
|
metricsPort: shouldCollectMetrics(),
|
|
30
30
|
initialConfig: {
|
|
31
|
-
|
|
32
|
-
aztecSlotDuration:
|
|
31
|
+
ethereumSlotDuration: 8,
|
|
32
|
+
aztecSlotDuration: 36,
|
|
33
|
+
blockDurationMs: 6000,
|
|
34
|
+
l1PublishingTime: 8,
|
|
35
|
+
minTxsPerBlock: 1,
|
|
36
|
+
maxTxsPerBlock: 2,
|
|
37
|
+
enforceTimeTable: true,
|
|
38
|
+
aztecProofSubmissionEpochs: 1024,
|
|
33
39
|
...disableStatusHandshake ? {
|
|
34
40
|
p2pDisableStatusHandshake: true
|
|
35
41
|
} : {},
|
|
@@ -66,7 +72,7 @@ export async function runReqrespTxTest(params) {
|
|
|
66
72
|
...t.ctx.aztecNodeConfig,
|
|
67
73
|
p2pDisableStatusHandshake: true
|
|
68
74
|
} : t.ctx.aztecNodeConfig;
|
|
69
|
-
const nodes = await createNodes(aztecNodeConfig, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, BOOT_NODE_UDP_PORT, t.
|
|
75
|
+
const nodes = await createNodes(aztecNodeConfig, t.ctx.dateProvider, t.bootstrapNodeEnr, NUM_VALIDATORS, BOOT_NODE_UDP_PORT, t.genesis, dataDir, shouldCollectMetrics());
|
|
70
76
|
t.logger.info('Waiting for nodes to connect');
|
|
71
77
|
await t.waitForP2PMeshConnectivity(nodes, NUM_VALIDATORS);
|
|
72
78
|
await t.setupAccount();
|
|
@@ -102,6 +108,11 @@ export async function runReqrespTxTest(params) {
|
|
|
102
108
|
t.logger.info('Sending transactions through proposer nodes');
|
|
103
109
|
const submittedTxs = await Promise.all(txBatches.map(async (batch, batchIndex)=>{
|
|
104
110
|
const proposerNode = nodes[proposerIndexes[batchIndex]];
|
|
111
|
+
for (const tx of batch){
|
|
112
|
+
t.logger.info(`Tx ${tx.getTxHash().toString()} base64: ${tx.toBuffer().toString('base64')}`);
|
|
113
|
+
}
|
|
114
|
+
const txHashes = batch.map((tx)=>tx.getTxHash().toString());
|
|
115
|
+
t.logger.info(`Sending batch ${batchIndex} to proposer ${getNodePort(proposerIndexes[batchIndex])}: ${txHashes.join(', ')}`);
|
|
105
116
|
await Promise.all(batch.map(async (tx)=>{
|
|
106
117
|
try {
|
|
107
118
|
await proposerNode.sendTx(tx);
|
|
@@ -115,6 +126,11 @@ export async function runReqrespTxTest(params) {
|
|
|
115
126
|
txHash: tx.getTxHash()
|
|
116
127
|
}));
|
|
117
128
|
}));
|
|
129
|
+
// Log pool state per node after sending
|
|
130
|
+
for(let i = 0; i < NUM_VALIDATORS; i++){
|
|
131
|
+
const count = await nodes[i].getPendingTxCount();
|
|
132
|
+
t.logger.info(`Node ${getNodePort(i)} pool has ${count} pending txs`);
|
|
133
|
+
}
|
|
118
134
|
t.logger.info('Waiting for all transactions to be mined');
|
|
119
135
|
await Promise.all(submittedTxs.flatMap((batch, batchIndex)=>batch.map(async (submittedTx, txIndex)=>{
|
|
120
136
|
t.logger.info(`Waiting for tx ${batchIndex}-${txIndex} ${submittedTx.txHash.toString()} to be mined`);
|
|
@@ -124,6 +140,27 @@ export async function runReqrespTxTest(params) {
|
|
|
124
140
|
t.logger.info(`Tx ${batchIndex}-${txIndex} ${submittedTx.txHash.toString()} has been mined`);
|
|
125
141
|
})));
|
|
126
142
|
t.logger.info('All transactions mined');
|
|
143
|
+
// Assert that multiple blocks were built for at least one slot
|
|
144
|
+
t.logger.info('Verifying multiple blocks for at least one checkpoint');
|
|
145
|
+
// Wait for L1 checkpoint sync, which may lag behind P2P block propagation.
|
|
146
|
+
const checkpoints = await retryUntil(async ()=>{
|
|
147
|
+
const cps = await nodes[0].getCheckpoints(CheckpointNumber(1), 50);
|
|
148
|
+
return cps.length > 0 && cps.some((cp)=>cp.checkpoint.blocks.length >= 2) ? cps : undefined;
|
|
149
|
+
}, 'waiting for multi-block checkpoint to sync from L1', 30, 1);
|
|
150
|
+
let mbpsFound = false;
|
|
151
|
+
let expectedBlockNumber = checkpoints[0].checkpoint.blocks[0].number;
|
|
152
|
+
for (const published of checkpoints){
|
|
153
|
+
const blockCount = published.checkpoint.blocks.length;
|
|
154
|
+
mbpsFound = mbpsFound || blockCount >= 2;
|
|
155
|
+
for(let i = 0; i < blockCount; i++){
|
|
156
|
+
const block = published.checkpoint.blocks[i];
|
|
157
|
+
expect(block.indexWithinCheckpoint).toBe(i);
|
|
158
|
+
expect(block.checkpointNumber).toBe(published.checkpoint.number);
|
|
159
|
+
expect(block.number).toBe(expectedBlockNumber);
|
|
160
|
+
expectedBlockNumber++;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
expect(mbpsFound).toBe(true);
|
|
127
164
|
return nodes;
|
|
128
165
|
}
|
|
129
166
|
async function getProposerIndexes(t, startSlotTimestamp) {
|
package/dest/e2e_p2p/shared.d.ts
CHANGED
|
@@ -4,21 +4,40 @@ import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
|
4
4
|
import type { Logger } from '@aztec/aztec.js/log';
|
|
5
5
|
import { TxHash } from '@aztec/aztec.js/tx';
|
|
6
6
|
import type { RollupCheatCodes } from '@aztec/aztec/testing';
|
|
7
|
-
import type {
|
|
7
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
8
|
+
import type { RollupContract, SlashingProposerContract } from '@aztec/ethereum/contracts';
|
|
9
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
10
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
8
11
|
import type { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
9
12
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
10
|
-
import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
11
13
|
import { type ProvenTx } from '../test-wallet/utils.js';
|
|
12
14
|
export declare const submitComplexTxsTo: (logger: Logger, from: AztecAddress, spamContract: SpamContract, numTxs: number, opts?: {
|
|
13
15
|
callPublic?: boolean | undefined;
|
|
14
16
|
}) => Promise<TxHash[]>;
|
|
15
17
|
export declare const submitTransactions: (logger: Logger, node: AztecNodeService, numTxs: number, fundedAccount: InitialAccountData) => Promise<TxHash[]>;
|
|
16
18
|
export declare function prepareTransactions(logger: Logger, node: AztecNodeService, numTxs: number, fundedAccount: InitialAccountData): Promise<ProvenTx[]>;
|
|
17
|
-
export declare function awaitProposalExecution(slashingProposer:
|
|
19
|
+
export declare function awaitProposalExecution(slashingProposer: SlashingProposerContract, timeoutSeconds: number, logger: Logger): Promise<bigint>;
|
|
18
20
|
export declare function awaitCommitteeExists({ rollup, logger }: {
|
|
19
21
|
rollup: RollupContract;
|
|
20
22
|
logger: Logger;
|
|
21
23
|
}): Promise<readonly `0x${string}`[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Advance epochs until we find one where the target proposer is selected for at least one slot,
|
|
26
|
+
* then stop one epoch before it. This leaves time for the caller to start sequencers before
|
|
27
|
+
* warping to the target epoch, avoiding the race where the target epoch passes before sequencers
|
|
28
|
+
* are ready.
|
|
29
|
+
*
|
|
30
|
+
* Returns the target epoch number so the caller can warp to it after starting sequencers.
|
|
31
|
+
*/
|
|
32
|
+
export declare function advanceToEpochBeforeProposer({ epochCache, cheatCodes, targetProposer, logger, maxAttempts }: {
|
|
33
|
+
epochCache: EpochCacheInterface;
|
|
34
|
+
cheatCodes: RollupCheatCodes;
|
|
35
|
+
targetProposer: EthAddress;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
maxAttempts?: number;
|
|
38
|
+
}): Promise<{
|
|
39
|
+
targetEpoch: EpochNumber;
|
|
40
|
+
}>;
|
|
22
41
|
export declare function awaitOffenseDetected({ logger, nodeAdmin, slashingRoundSize, epochDuration, waitUntilOffenseCount, timeoutSeconds }: {
|
|
23
42
|
nodeAdmin: AztecNodeAdmin;
|
|
24
43
|
logger: Logger;
|
|
@@ -31,16 +50,15 @@ export declare function awaitOffenseDetected({ logger, nodeAdmin, slashingRoundS
|
|
|
31
50
|
* Await the committee to be slashed out of the validator set.
|
|
32
51
|
* Currently assumes that the committee is the same size as the validator set.
|
|
33
52
|
*/
|
|
34
|
-
export declare function awaitCommitteeKicked({ rollup, cheatCodes, committee,
|
|
53
|
+
export declare function awaitCommitteeKicked({ rollup, cheatCodes, committee, slashingProposer, slashingRoundSize, aztecSlotDuration, aztecEpochDuration, logger, offenseEpoch }: {
|
|
35
54
|
rollup: RollupContract;
|
|
36
55
|
cheatCodes: RollupCheatCodes;
|
|
37
56
|
committee: readonly `0x${string}`[];
|
|
38
|
-
|
|
39
|
-
slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
|
|
57
|
+
slashingProposer: SlashingProposerContract | undefined;
|
|
40
58
|
slashingRoundSize: number;
|
|
41
59
|
aztecSlotDuration: number;
|
|
42
60
|
aztecEpochDuration: number;
|
|
43
61
|
logger: Logger;
|
|
44
62
|
offenseEpoch: number;
|
|
45
63
|
}): Promise<void>;
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZTJlX3AycC9zaGFyZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNsRSxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzFELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUd6RCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM3RCxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzFGLE9BQU8sRUFBRSxXQUFXLEVBQWMsTUFBTSxpQ0FBaUMsQ0FBQztBQUUxRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFHM0QsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFJdkUsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFLdEUsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFvQixNQUFNLHlCQUF5QixDQUFDO0FBRzFFLGVBQU8sTUFBTSxrQkFBa0I7O3VCQWtCOUIsQ0FBQztBQUdGLGVBQU8sTUFBTSxrQkFBa0Isa0hBc0I5QixDQUFDO0FBRUYsd0JBQXNCLG1CQUFtQixDQUN2QyxNQUFNLEVBQUUsTUFBTSxFQUNkLElBQUksRUFBRSxnQkFBZ0IsRUFDdEIsTUFBTSxFQUFFLE1BQU0sRUFDZCxhQUFhLEVBQUUsa0JBQWtCLEdBQ2hDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQTZCckI7QUFFRCx3QkFBZ0Isc0JBQXNCLENBQ3BDLGdCQUFnQixFQUFFLHdCQUF3QixFQUMxQyxjQUFjLEVBQUUsTUFBTSxFQUN0QixNQUFNLEVBQUUsTUFBTSxHQUNiLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FjakI7QUFFRCx3QkFBc0Isb0JBQW9CLENBQUMsRUFDekMsTUFBTSxFQUNOLE1BQU0sRUFDUCxFQUFFO0lBQ0QsTUFBTSxFQUFFLGNBQWMsQ0FBQztJQUN2QixNQUFNLEVBQUUsTUFBTSxDQUFDO0NBQ2hCLEdBQUcsT0FBTyxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBYXBDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILHdCQUFzQiw0QkFBNEIsQ0FBQyxFQUNqRCxVQUFVLEVBQ1YsVUFBVSxFQUNWLGNBQWMsRUFDZCxNQUFNLEVBQ04sV0FBZ0IsRUFDakIsRUFBRTtJQUNELFVBQVUsRUFBRSxtQkFBbUIsQ0FBQztJQUNoQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUM7SUFDN0IsY0FBYyxFQUFFLFVBQVUsQ0FBQztJQUMzQixNQUFNLEVBQUUsTUFBTSxDQUFDO0lBQ2YsV0FBVyxDQUFDLEVBQUUsTUFBTSxDQUFDO0NBQ3RCLEdBQUcsT0FBTyxDQUFDO0lBQUUsV0FBVyxFQUFFLFdBQVcsQ0FBQTtDQUFFLENBQUMsQ0E4QnhDO0FBRUQsd0JBQXNCLG9CQUFvQixDQUFDLEVBQ3pDLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ2pCLGFBQWEsRUFDYixxQkFBcUIsRUFDckIsY0FBb0IsRUFDckIsRUFBRTtJQUNELFNBQVMsRUFBRSxjQUFjLENBQUM7SUFDMUIsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLGlCQUFpQixFQUFFLE1BQU0sQ0FBQztJQUMxQixhQUFhLEVBQUUsTUFBTSxDQUFDO0lBQ3RCLHFCQUFxQixDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQy9CLGNBQWMsQ0FBQyxFQUFFLE1BQU0sQ0FBQztDQUN6QiwrQ0FrQkE7QUFFRDs7O0dBR0c7QUFDSCx3QkFBc0Isb0JBQW9CLENBQUMsRUFDekMsTUFBTSxFQUNOLFVBQVUsRUFDVixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsa0JBQWtCLEVBQ2xCLE1BQU0sRUFDTixZQUFZLEVBQ2IsRUFBRTtJQUNELE1BQU0sRUFBRSxjQUFjLENBQUM7SUFDdkIsVUFBVSxFQUFFLGdCQUFnQixDQUFDO0lBQzdCLFNBQVMsRUFBRSxTQUFTLEtBQUssTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUNwQyxnQkFBZ0IsRUFBRSx3QkFBd0IsR0FBRyxTQUFTLENBQUM7SUFDdkQsaUJBQWlCLEVBQUUsTUFBTSxDQUFDO0lBQzFCLGlCQUFpQixFQUFFLE1BQU0sQ0FBQztJQUMxQixrQkFBa0IsRUFBRSxNQUFNLENBQUM7SUFDM0IsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLFlBQVksRUFBRSxNQUFNLENBQUM7Q0FDdEIsaUJBdURBIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/shared.ts"],"names":[],"mappings":"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"}
|
package/dest/e2e_p2p/shared.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { NO_WAIT, getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
|
|
2
2
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
|
-
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { timesAsync, unique } from '@aztec/foundation/collection';
|
|
5
5
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
6
6
|
import { pluralize } from '@aztec/foundation/string';
|
|
7
7
|
import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
|
|
8
8
|
import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
|
|
9
9
|
import { getRoundForOffense } from '@aztec/slasher';
|
|
10
|
+
import { SchnorrHardcodedKeyAccountContract } from '../fixtures/schnorr_hardcoded_account_contract.js';
|
|
10
11
|
import { submitTxsTo } from '../shared/submit-transactions.js';
|
|
11
12
|
import { TestWallet } from '../test-wallet/test_wallet.js';
|
|
12
13
|
import { proveInteraction } from '../test-wallet/utils.js';
|
|
@@ -17,7 +18,7 @@ export const submitComplexTxsTo = async (logger, from, spamContract, numTxs, opt
|
|
|
17
18
|
const spamCount = 15;
|
|
18
19
|
for(let i = 0; i < numTxs; i++){
|
|
19
20
|
const method = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic);
|
|
20
|
-
const txHash = await method.send({
|
|
21
|
+
const { txHash } = await method.send({
|
|
21
22
|
from,
|
|
22
23
|
wait: NO_WAIT
|
|
23
24
|
});
|
|
@@ -30,13 +31,21 @@ export const submitComplexTxsTo = async (logger, from, spamContract, numTxs, opt
|
|
|
30
31
|
export const submitTransactions = async (logger, node, numTxs, fundedAccount)=>{
|
|
31
32
|
const rpcConfig = getRpcConfig();
|
|
32
33
|
rpcConfig.proverEnabled = false;
|
|
33
|
-
const wallet = await TestWallet.create(node,
|
|
34
|
+
const wallet = await TestWallet.create(node, // Use checkpointed chain tip to avoid anchoring on provisional blocks that the archiver can prune
|
|
35
|
+
// when their slot ends without a checkpoint landing on L1.
|
|
36
|
+
{
|
|
34
37
|
...getPXEConfig(),
|
|
35
|
-
proverEnabled: false
|
|
38
|
+
proverEnabled: false,
|
|
39
|
+
syncChainTip: 'checkpointed'
|
|
36
40
|
}, {
|
|
37
41
|
loggerActorLabel: 'pxe-tx'
|
|
38
42
|
});
|
|
39
|
-
const
|
|
43
|
+
const contract = new SchnorrHardcodedKeyAccountContract();
|
|
44
|
+
const fundedAccountManager = await wallet.createAccount({
|
|
45
|
+
secret: fundedAccount.secret,
|
|
46
|
+
salt: fundedAccount.salt,
|
|
47
|
+
contract
|
|
48
|
+
});
|
|
40
49
|
return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
|
|
41
50
|
};
|
|
42
51
|
export async function prepareTransactions(logger, node, numTxs, fundedAccount) {
|
|
@@ -44,11 +53,17 @@ export async function prepareTransactions(logger, node, numTxs, fundedAccount) {
|
|
|
44
53
|
rpcConfig.proverEnabled = false;
|
|
45
54
|
const wallet = await TestWallet.create(node, {
|
|
46
55
|
...getPXEConfig(),
|
|
47
|
-
proverEnabled: false
|
|
56
|
+
proverEnabled: false,
|
|
57
|
+
syncChainTip: 'checkpointed'
|
|
48
58
|
}, {
|
|
49
59
|
loggerActorLabel: 'pxe-tx'
|
|
50
60
|
});
|
|
51
|
-
const
|
|
61
|
+
const accountContract = new SchnorrHardcodedKeyAccountContract();
|
|
62
|
+
const fundedAccountManager = await wallet.createAccount({
|
|
63
|
+
secret: fundedAccount.secret,
|
|
64
|
+
salt: fundedAccount.salt,
|
|
65
|
+
contract: accountContract
|
|
66
|
+
});
|
|
52
67
|
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
|
|
53
68
|
salt: Fr.random()
|
|
54
69
|
});
|
|
@@ -68,24 +83,12 @@ export function awaitProposalExecution(slashingProposer, timeoutSeconds, logger)
|
|
|
68
83
|
logger.warn(`Timed out waiting for proposal execution`);
|
|
69
84
|
reject(new Error(`Timeout waiting for proposal execution after ${timeoutSeconds}s`));
|
|
70
85
|
}, timeoutSeconds * 1000);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
logger.warn(`Proposal ${args.payload} from round ${args.round} executed`);
|
|
74
|
-
clearTimeout(timeout);
|
|
75
|
-
unwatch();
|
|
76
|
-
resolve(args.round);
|
|
77
|
-
});
|
|
78
|
-
} else if (slashingProposer.type === 'tally') {
|
|
79
|
-
const unwatch = slashingProposer.listenToRoundExecuted((args)=>{
|
|
80
|
-
logger.warn(`Slash from round ${args.round} executed`);
|
|
81
|
-
clearTimeout(timeout);
|
|
82
|
-
unwatch();
|
|
83
|
-
resolve(args.round);
|
|
84
|
-
});
|
|
85
|
-
} else {
|
|
86
|
+
const unwatch = slashingProposer.listenToRoundExecuted((args)=>{
|
|
87
|
+
logger.warn(`Slash from round ${args.round} executed`);
|
|
86
88
|
clearTimeout(timeout);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
unwatch();
|
|
90
|
+
resolve(args.round);
|
|
91
|
+
});
|
|
89
92
|
});
|
|
90
93
|
}
|
|
91
94
|
export async function awaitCommitteeExists({ rollup, logger }) {
|
|
@@ -100,6 +103,37 @@ export async function awaitCommitteeExists({ rollup, logger }) {
|
|
|
100
103
|
});
|
|
101
104
|
return committee.map((c)=>c.toString());
|
|
102
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Advance epochs until we find one where the target proposer is selected for at least one slot,
|
|
108
|
+
* then stop one epoch before it. This leaves time for the caller to start sequencers before
|
|
109
|
+
* warping to the target epoch, avoiding the race where the target epoch passes before sequencers
|
|
110
|
+
* are ready.
|
|
111
|
+
*
|
|
112
|
+
* Returns the target epoch number so the caller can warp to it after starting sequencers.
|
|
113
|
+
*/ export async function advanceToEpochBeforeProposer({ epochCache, cheatCodes, targetProposer, logger, maxAttempts = 20 }) {
|
|
114
|
+
const { epochDuration } = await cheatCodes.getConfig();
|
|
115
|
+
for(let attempt = 0; attempt < maxAttempts; attempt++){
|
|
116
|
+
const currentEpoch = await cheatCodes.getEpoch();
|
|
117
|
+
// Check the NEXT epoch's slots so we stay one epoch before the target,
|
|
118
|
+
// giving the caller time to start sequencers before the target epoch arrives.
|
|
119
|
+
const nextEpoch = Number(currentEpoch) + 1;
|
|
120
|
+
const startSlot = nextEpoch * Number(epochDuration);
|
|
121
|
+
const endSlot = startSlot + Number(epochDuration);
|
|
122
|
+
logger.info(`Checking next epoch ${nextEpoch} (slots ${startSlot}-${endSlot - 1}) for proposer ${targetProposer} (current epoch: ${currentEpoch})`);
|
|
123
|
+
for(let s = startSlot; s < endSlot; s++){
|
|
124
|
+
const proposer = await epochCache.getProposerAttesterAddressInSlot(SlotNumber(s));
|
|
125
|
+
if (proposer && proposer.equals(targetProposer)) {
|
|
126
|
+
logger.warn(`Found target proposer ${targetProposer} in slot ${s} of epoch ${nextEpoch}. Staying at epoch ${currentEpoch} to allow sequencer startup.`);
|
|
127
|
+
return {
|
|
128
|
+
targetEpoch: EpochNumber(nextEpoch)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
logger.info(`Target proposer not found in epoch ${nextEpoch}, advancing to next epoch`);
|
|
133
|
+
await cheatCodes.advanceToNextEpoch();
|
|
134
|
+
}
|
|
135
|
+
throw new Error(`Target proposer ${targetProposer} not found in any slot after ${maxAttempts} epoch attempts`);
|
|
136
|
+
}
|
|
103
137
|
export async function awaitOffenseDetected({ logger, nodeAdmin, slashingRoundSize, epochDuration, waitUntilOffenseCount, timeoutSeconds = 120 }) {
|
|
104
138
|
const targetOffenseCount = waitUntilOffenseCount ?? 1;
|
|
105
139
|
logger.warn(`Waiting for ${pluralize('offense', targetOffenseCount)} to be detected`);
|
|
@@ -120,35 +154,21 @@ export async function awaitOffenseDetected({ logger, nodeAdmin, slashingRoundSiz
|
|
|
120
154
|
/**
|
|
121
155
|
* Await the committee to be slashed out of the validator set.
|
|
122
156
|
* Currently assumes that the committee is the same size as the validator set.
|
|
123
|
-
*/ export async function awaitCommitteeKicked({ rollup, cheatCodes, committee,
|
|
157
|
+
*/ export async function awaitCommitteeKicked({ rollup, cheatCodes, committee, slashingProposer, slashingRoundSize, aztecSlotDuration, aztecEpochDuration, logger, offenseEpoch }) {
|
|
124
158
|
if (!slashingProposer) {
|
|
125
159
|
throw new Error('No slashing proposer configured. Cannot test slashing.');
|
|
126
160
|
}
|
|
127
161
|
await cheatCodes.debugRollup();
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// 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)
|
|
139
|
-
expect(unique(slashPayloadEvents[0].slashes.map((slash)=>slash.validator.toString()))).toHaveLength(committee.length);
|
|
140
|
-
} else {
|
|
141
|
-
// Use the slash offset to ensure we are in the right epoch for tally
|
|
142
|
-
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
143
|
-
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
144
|
-
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
145
|
-
const firstEpochInOffenseRound = offenseEpoch - offenseEpoch % slashingRoundSizeInEpochs;
|
|
146
|
-
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
147
|
-
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
148
|
-
await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), {
|
|
149
|
-
offset: -aztecSlotDuration / 2
|
|
150
|
-
});
|
|
151
|
-
}
|
|
162
|
+
// Use the slash offset to ensure we are in the right epoch for tally
|
|
163
|
+
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
164
|
+
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
165
|
+
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
166
|
+
const firstEpochInOffenseRound = offenseEpoch - offenseEpoch % slashingRoundSizeInEpochs;
|
|
167
|
+
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
168
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
169
|
+
await cheatCodes.advanceToEpoch(EpochNumber(targetEpoch), {
|
|
170
|
+
offset: -aztecSlotDuration / 2
|
|
171
|
+
});
|
|
152
172
|
const attestersPre = await rollup.getAttesters();
|
|
153
173
|
expect(attestersPre.length).toBe(committee.length);
|
|
154
174
|
for (const attester of attestersPre){
|