@aztec/end-to-end 2.1.0-rc.9 → 3.0.0-devnet.2
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 +3 -2
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +16 -12
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +54 -58
- package/dest/bench/utils.d.ts +2 -11
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +10 -34
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +7 -7
- 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 +10 -8
- 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 +31 -33
- package/dest/e2e_deploy_contract/deploy_test.d.ts +10 -4
- 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 +3 -1
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +10 -9
- package/dest/e2e_fees/bridging_race.notest.js +12 -9
- package/dest/e2e_fees/fees_test.d.ts +5 -5
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +23 -31
- package/dest/e2e_l1_publisher/write_json.d.ts +3 -1
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
- package/dest/e2e_l1_publisher/write_json.js +5 -5
- package/dest/e2e_multi_validator/utils.d.ts +1 -1
- package/dest/e2e_multi_validator/utils.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +6 -3
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +7 -9
- package/dest/e2e_p2p/inactivity_slash_test.d.ts +2 -2
- package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
- package/dest/e2e_p2p/inactivity_slash_test.js +5 -2
- package/dest/e2e_p2p/p2p_network.d.ts +16 -4
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +32 -10
- package/dest/e2e_p2p/shared.d.ts +11 -13
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +49 -45
- package/dest/e2e_token_contract/token_contract_test.d.ts +5 -4
- 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 +8 -6
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +40 -50
- package/dest/fixtures/get_acvm_config.d.ts +1 -1
- package/dest/fixtures/get_acvm_config.d.ts.map +1 -1
- 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 +2 -2
- package/dest/fixtures/setup_l1_contracts.d.ts +1 -1
- package/dest/fixtures/setup_l1_contracts.d.ts.map +1 -1
- package/dest/fixtures/setup_l1_contracts.js +2 -2
- package/dest/fixtures/setup_p2p_test.d.ts +0 -7
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/snapshot_manager.d.ts +10 -7
- package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
- package/dest/fixtures/snapshot_manager.js +44 -34
- package/dest/fixtures/token_utils.d.ts +6 -4
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +11 -15
- package/dest/fixtures/utils.d.ts +23 -27
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +76 -101
- package/dest/fixtures/web3signer.d.ts +1 -1
- package/dest/fixtures/web3signer.d.ts.map +1 -1
- package/dest/fixtures/web3signer.js +16 -5
- package/dest/quality_of_service/alert_checker.d.ts +1 -1
- package/dest/quality_of_service/alert_checker.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.d.ts +16 -10
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +13 -15
- package/dest/shared/gas_portal_test_harness.d.ts +9 -6
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/gas_portal_test_harness.js +10 -7
- package/dest/shared/jest_setup.js +1 -1
- package/dest/shared/submit-transactions.d.ts +5 -3
- 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 +9 -6
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +29 -45
- package/dest/simulators/lending_simulator.d.ts +2 -1
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +3 -2
- package/dest/simulators/token_simulator.d.ts +3 -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 +19 -13
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +108 -85
- package/dest/spartan/utils.d.ts +44 -0
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +212 -20
- package/package.json +38 -37
- package/src/bench/client_flows/benchmark.ts +6 -6
- package/src/bench/client_flows/client_flows_benchmark.ts +62 -82
- package/src/bench/client_flows/data_extractor.ts +1 -1
- package/src/bench/utils.ts +9 -37
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +46 -63
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +33 -47
- package/src/e2e_deploy_contract/deploy_test.ts +17 -35
- package/src/e2e_epochs/epochs_test.ts +12 -14
- package/src/e2e_fees/bridging_race.notest.ts +14 -9
- package/src/e2e_fees/fees_test.ts +26 -38
- package/src/e2e_l1_publisher/write_json.ts +8 -6
- package/src/e2e_multi_validator/utils.ts +1 -1
- package/src/e2e_nested_contract/nested_contract_test.ts +11 -10
- package/src/e2e_p2p/inactivity_slash_test.ts +7 -3
- package/src/e2e_p2p/p2p_network.ts +105 -67
- package/src/e2e_p2p/shared.ts +50 -55
- package/src/e2e_token_contract/token_contract_test.ts +17 -17
- package/src/fixtures/e2e_prover_test.ts +51 -88
- package/src/fixtures/get_acvm_config.ts +1 -1
- package/src/fixtures/get_bb_config.ts +3 -2
- package/src/fixtures/setup_l1_contracts.ts +3 -3
- package/src/fixtures/setup_p2p_test.ts +0 -8
- package/src/fixtures/snapshot_manager.ts +61 -61
- package/src/fixtures/token_utils.ts +13 -21
- package/src/fixtures/utils.ts +87 -138
- package/src/fixtures/web3signer.ts +22 -5
- package/src/guides/up_quick_start.sh +2 -10
- package/src/quality_of_service/alert_checker.ts +1 -1
- package/src/shared/cross_chain_test_harness.ts +18 -29
- package/src/shared/gas_portal_test_harness.ts +12 -19
- package/src/shared/jest_setup.ts +1 -1
- package/src/shared/submit-transactions.ts +12 -8
- package/src/shared/uniswap_l1_l2.ts +61 -67
- package/src/simulators/lending_simulator.ts +3 -2
- package/src/simulators/token_simulator.ts +5 -2
- package/src/spartan/DEVELOP.md +8 -3
- package/src/spartan/setup_test_wallets.ts +133 -126
- package/src/spartan/utils.ts +268 -18
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AztecNodeService } from '@aztec/aztec-node';
|
|
2
|
-
import { EthAddress } from '@aztec/aztec.js';
|
|
2
|
+
import { EthAddress } from '@aztec/aztec.js/addresses';
|
|
3
3
|
import { RollupContract } from '@aztec/ethereum';
|
|
4
4
|
|
|
5
5
|
import fs from 'fs';
|
|
@@ -17,8 +17,8 @@ const SLASHING_QUORUM = 3;
|
|
|
17
17
|
const EPOCH_DURATION = 2;
|
|
18
18
|
const SLASHING_ROUND_SIZE_IN_EPOCHS = 2;
|
|
19
19
|
const BOOT_NODE_UDP_PORT = 4500;
|
|
20
|
-
const ETHEREUM_SLOT_DURATION = 4;
|
|
21
|
-
const AZTEC_SLOT_DURATION =
|
|
20
|
+
const ETHEREUM_SLOT_DURATION = process.env.CI ? 8 : 4;
|
|
21
|
+
const AZTEC_SLOT_DURATION = ETHEREUM_SLOT_DURATION * 2;
|
|
22
22
|
const SLASHING_UNIT = BigInt(1e18);
|
|
23
23
|
const SLASHING_AMOUNT = SLASHING_UNIT * 3n;
|
|
24
24
|
|
|
@@ -146,6 +146,10 @@ export class P2PInactivityTest {
|
|
|
146
146
|
offlineValidators: this.offlineValidators,
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
+
// Wait for P2P mesh to be fully formed before starting slashing period
|
|
150
|
+
// This prevents race conditions where validators propose blocks before the network is ready
|
|
151
|
+
await this.test.waitForP2PMeshConnectivity(this.nodes, NUM_NODES);
|
|
152
|
+
|
|
149
153
|
this.test.logger.warn(`Advancing to epoch ${SETUP_EPOCH_DURATION + 1} to start slashing`);
|
|
150
154
|
await this.test.ctx.cheatCodes.rollup.advanceToEpoch(SETUP_EPOCH_DURATION + 1);
|
|
151
155
|
|
|
@@ -1,7 +1,7 @@
|
|
|
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
5
|
import {
|
|
6
6
|
type EmpireSlashingProposerContract,
|
|
7
7
|
type ExtendedViemWalletClient,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { ChainMonitor } from '@aztec/ethereum/test';
|
|
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';
|
|
@@ -75,7 +77,7 @@ 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
|
|
|
@@ -230,89 +232,83 @@ export class P2PNetworkTest {
|
|
|
230
232
|
|
|
231
233
|
async applyBaseSnapshots() {
|
|
232
234
|
await this.addBootstrapNode();
|
|
233
|
-
await this.snapshotManager.snapshot(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
client: deployL1ContractsValues.l1Client,
|
|
240
|
-
});
|
|
235
|
+
await this.snapshotManager.snapshot('add-validators', async ({ deployL1ContractsValues, cheatCodes }) => {
|
|
236
|
+
const rollup = getContract({
|
|
237
|
+
address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(),
|
|
238
|
+
abi: RollupAbi,
|
|
239
|
+
client: deployL1ContractsValues.l1Client,
|
|
240
|
+
});
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
this.logger.info(`Adding ${this.numberOfValidators} validators`);
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
const stakingAsset = getContract({
|
|
245
|
+
address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(),
|
|
246
|
+
abi: TestERC20Abi,
|
|
247
|
+
client: deployL1ContractsValues.l1Client,
|
|
248
|
+
});
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
250
|
+
const { address: multiAdderAddress } = await deployL1Contract(
|
|
251
|
+
deployL1ContractsValues.l1Client,
|
|
252
|
+
MultiAdderArtifact.contractAbi,
|
|
253
|
+
MultiAdderArtifact.contractBytecode,
|
|
254
|
+
[rollup.address, deployL1ContractsValues.l1Client.account.address],
|
|
255
|
+
);
|
|
256
256
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
257
|
+
const multiAdder = getContract({
|
|
258
|
+
address: multiAdderAddress.toString(),
|
|
259
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
260
|
+
client: deployL1ContractsValues.l1Client,
|
|
261
|
+
});
|
|
262
262
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
263
|
+
const stakeNeeded = (await rollup.read.getActivationThreshold()) * BigInt(this.numberOfValidators);
|
|
264
|
+
await Promise.all(
|
|
265
|
+
[await stakingAsset.write.mint([multiAdder.address, stakeNeeded], {} as any)].map(txHash =>
|
|
266
|
+
deployL1ContractsValues.l1Client.waitForTransactionReceipt({ hash: txHash }),
|
|
267
|
+
),
|
|
268
|
+
);
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
const { validators } = this.getValidators();
|
|
271
|
+
this.validators = validators;
|
|
272
272
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress!;
|
|
274
|
+
if (!gseAddress) {
|
|
275
|
+
throw new Error('GSE contract not deployed');
|
|
276
|
+
}
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString());
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
};
|
|
280
|
+
const makeValidatorTuples = async (validator: Operator) => {
|
|
281
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
282
|
+
return {
|
|
283
|
+
attester: validator.attester.toString() as `0x${string}`,
|
|
284
|
+
withdrawer: validator.withdrawer.toString() as `0x${string}`,
|
|
285
|
+
...registrationTuple,
|
|
287
286
|
};
|
|
288
|
-
|
|
287
|
+
};
|
|
288
|
+
const validatorTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
289
289
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
await deployL1ContractsValues.l1Client.waitForTransactionReceipt({
|
|
291
|
+
hash: await multiAdder.write.addValidators([validatorTuples]),
|
|
292
|
+
});
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
updateDateProvider: dateProvider,
|
|
298
|
-
},
|
|
299
|
-
);
|
|
294
|
+
await cheatCodes.rollup.advanceToEpoch(
|
|
295
|
+
(await cheatCodes.rollup.getEpoch()) + (await rollup.read.getLagInEpochs()) + 1n,
|
|
296
|
+
);
|
|
300
297
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
);
|
|
298
|
+
// Send and await a tx to make sure we mine a block for the warp to correctly progress.
|
|
299
|
+
await this._sendDummyTx(deployL1ContractsValues.l1Client);
|
|
300
|
+
});
|
|
305
301
|
}
|
|
306
302
|
|
|
307
303
|
async setupAccount() {
|
|
308
304
|
await this.snapshotManager.snapshot(
|
|
309
305
|
'setup-account',
|
|
310
|
-
deployAccounts(1, this.logger
|
|
311
|
-
|
|
306
|
+
deployAccounts(1, this.logger),
|
|
307
|
+
({ deployedAccounts }, { wallet }) => {
|
|
312
308
|
this.deployedAccounts = deployedAccounts;
|
|
313
|
-
|
|
314
|
-
this.wallet =
|
|
315
|
-
|
|
309
|
+
[{ address: this.defaultAccountAddress }] = deployedAccounts;
|
|
310
|
+
this.wallet = wallet;
|
|
311
|
+
return Promise.resolve();
|
|
316
312
|
},
|
|
317
313
|
);
|
|
318
314
|
}
|
|
@@ -394,6 +390,48 @@ export class P2PNetworkTest {
|
|
|
394
390
|
this.logger.info('Nodes stopped');
|
|
395
391
|
}
|
|
396
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Wait for P2P mesh to be fully formed across all nodes.
|
|
395
|
+
* This ensures that all nodes are connected to each other before proceeding,
|
|
396
|
+
* preventing race conditions where validators propose blocks before the network is ready.
|
|
397
|
+
*
|
|
398
|
+
* @param nodes - Array of nodes to check for P2P connectivity
|
|
399
|
+
* @param expectedNodeCount - Expected number of nodes in the network (defaults to nodes.length)
|
|
400
|
+
* @param timeoutSeconds - Maximum time to wait for connections (default: 30 seconds)
|
|
401
|
+
* @param checkIntervalSeconds - How often to check connectivity (default: 0.1 seconds)
|
|
402
|
+
*/
|
|
403
|
+
async waitForP2PMeshConnectivity(
|
|
404
|
+
nodes: AztecNodeService[],
|
|
405
|
+
expectedNodeCount?: number,
|
|
406
|
+
timeoutSeconds = 30,
|
|
407
|
+
checkIntervalSeconds = 0.1,
|
|
408
|
+
) {
|
|
409
|
+
const nodeCount = expectedNodeCount ?? nodes.length;
|
|
410
|
+
const minPeerCount = nodeCount - 1;
|
|
411
|
+
|
|
412
|
+
this.logger.warn(
|
|
413
|
+
`Waiting for all ${nodeCount} nodes to connect to P2P mesh (at least ${minPeerCount} peers each)...`,
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
await Promise.all(
|
|
417
|
+
nodes.map(async (node, index) => {
|
|
418
|
+
const p2p = node.getP2P();
|
|
419
|
+
await retryUntil(
|
|
420
|
+
async () => {
|
|
421
|
+
const peers = await p2p.getPeers();
|
|
422
|
+
// Each node should be connected to at least N-1 other nodes
|
|
423
|
+
return peers.length >= minPeerCount ? true : undefined;
|
|
424
|
+
},
|
|
425
|
+
`Node ${index} to connect to at least ${minPeerCount} peers`,
|
|
426
|
+
timeoutSeconds,
|
|
427
|
+
checkIntervalSeconds,
|
|
428
|
+
);
|
|
429
|
+
}),
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
this.logger.warn('All nodes connected to P2P mesh');
|
|
433
|
+
}
|
|
434
|
+
|
|
397
435
|
async teardown() {
|
|
398
436
|
await this.monitor.stop();
|
|
399
437
|
await tryStop(this.bootstrapNode, this.logger);
|
package/src/e2e_p2p/shared.ts
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
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
9
|
import type { EmpireSlashingProposerContract, RollupContract, TallySlashingProposerContract } from '@aztec/ethereum';
|
|
16
10
|
import { timesAsync, unique } from '@aztec/foundation/collection';
|
|
11
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
17
12
|
import { pluralize } from '@aztec/foundation/string';
|
|
18
|
-
import type { TestDateProvider } from '@aztec/foundation/timer';
|
|
19
13
|
import type { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
20
14
|
import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
|
|
21
|
-
import {
|
|
15
|
+
import { getPXEConfig, getPXEConfig as getRpcConfig } from '@aztec/pxe/server';
|
|
22
16
|
import { getRoundForOffense } from '@aztec/slasher';
|
|
23
17
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
24
18
|
import type { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
19
|
+
import { TestWallet, proveInteraction } from '@aztec/test-wallet/server';
|
|
25
20
|
|
|
26
|
-
import type { NodeContext } from '../fixtures/setup_p2p_test.js';
|
|
27
21
|
import { submitTxsTo } from '../shared/submit-transactions.js';
|
|
28
22
|
|
|
29
23
|
// submits a set of transactions to the provided Private eXecution Environment (PXE)
|
|
@@ -56,56 +50,46 @@ export const submitComplexTxsTo = async (
|
|
|
56
50
|
return txs;
|
|
57
51
|
};
|
|
58
52
|
|
|
59
|
-
// creates
|
|
60
|
-
export const
|
|
53
|
+
// creates a wallet and submit a given number of transactions through it.
|
|
54
|
+
export const submitTransactions = async (
|
|
61
55
|
logger: Logger,
|
|
62
56
|
node: AztecNodeService,
|
|
63
57
|
numTxs: number,
|
|
64
58
|
fundedAccount: InitialAccountData,
|
|
65
|
-
): Promise<
|
|
59
|
+
): Promise<SentTx[]> => {
|
|
66
60
|
const rpcConfig = getRpcConfig();
|
|
67
61
|
rpcConfig.proverEnabled = false;
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
pxeService,
|
|
72
|
-
fundedAccount.secret,
|
|
73
|
-
fundedAccount.signingKey,
|
|
74
|
-
fundedAccount.salt,
|
|
75
|
-
);
|
|
76
|
-
await account.register();
|
|
77
|
-
const wallet = await account.getWallet();
|
|
78
|
-
|
|
79
|
-
const txs = await submitTxsTo(pxeService, numTxs, wallet, logger);
|
|
80
|
-
return { txs, pxeService, node };
|
|
62
|
+
const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
|
|
63
|
+
const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
|
|
64
|
+
return submitTxsTo(wallet, fundedAccountManager.address, numTxs, logger);
|
|
81
65
|
};
|
|
82
66
|
|
|
83
|
-
export async function
|
|
67
|
+
export async function prepareTransactions(
|
|
84
68
|
logger: Logger,
|
|
85
69
|
node: AztecNodeService,
|
|
86
70
|
numTxs: number,
|
|
87
71
|
fundedAccount: InitialAccountData,
|
|
88
|
-
): Promise<
|
|
72
|
+
): Promise<Tx[]> {
|
|
89
73
|
const rpcConfig = getRpcConfig();
|
|
90
74
|
rpcConfig.proverEnabled = false;
|
|
91
|
-
const pxe = await createPXEService(node, rpcConfig, { useLogSuffix: true });
|
|
92
75
|
|
|
93
|
-
const
|
|
94
|
-
await
|
|
95
|
-
const wallet = await account.getWallet();
|
|
76
|
+
const wallet = await TestWallet.create(node, { ...getPXEConfig(), proverEnabled: false }, { useLogSuffix: true });
|
|
77
|
+
const fundedAccountManager = await wallet.createSchnorrAccount(fundedAccount.secret, fundedAccount.salt);
|
|
96
78
|
|
|
97
|
-
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
|
|
98
|
-
|
|
79
|
+
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {
|
|
80
|
+
salt: Fr.random(),
|
|
81
|
+
});
|
|
82
|
+
await wallet.registerContract(testContractInstance, TestContractArtifact);
|
|
99
83
|
const contract = await TestContract.at(testContractInstance.address, wallet);
|
|
100
84
|
|
|
101
|
-
|
|
102
|
-
const tx = await contract.methods.emit_nullifier(Fr.random())
|
|
85
|
+
return timesAsync(numTxs, async () => {
|
|
86
|
+
const tx = await proveInteraction(wallet, contract.methods.emit_nullifier(Fr.random()), {
|
|
87
|
+
from: fundedAccountManager.address,
|
|
88
|
+
});
|
|
103
89
|
const txHash = tx.getTxHash();
|
|
104
90
|
logger.info(`Tx prepared with hash ${txHash}`);
|
|
105
91
|
return tx;
|
|
106
92
|
});
|
|
107
|
-
|
|
108
|
-
return { txs, pxeService: pxe, node };
|
|
109
93
|
}
|
|
110
94
|
|
|
111
95
|
export function awaitProposalExecution(
|
|
@@ -166,12 +150,14 @@ export async function awaitOffenseDetected({
|
|
|
166
150
|
slashingRoundSize,
|
|
167
151
|
epochDuration,
|
|
168
152
|
waitUntilOffenseCount,
|
|
153
|
+
timeoutSeconds = 120,
|
|
169
154
|
}: {
|
|
170
155
|
nodeAdmin: AztecNodeAdmin;
|
|
171
156
|
logger: Logger;
|
|
172
157
|
slashingRoundSize: number;
|
|
173
158
|
epochDuration: number;
|
|
174
159
|
waitUntilOffenseCount?: number;
|
|
160
|
+
timeoutSeconds?: number;
|
|
175
161
|
}) {
|
|
176
162
|
const targetOffenseCount = waitUntilOffenseCount ?? 1;
|
|
177
163
|
logger.warn(`Waiting for ${pluralize('offense', targetOffenseCount)} to be detected`);
|
|
@@ -183,11 +169,11 @@ export async function awaitOffenseDetected({
|
|
|
183
169
|
}
|
|
184
170
|
},
|
|
185
171
|
'non-empty offenses',
|
|
186
|
-
|
|
172
|
+
timeoutSeconds,
|
|
187
173
|
);
|
|
188
174
|
logger.info(
|
|
189
175
|
`Hit ${offenses.length} offenses on rounds ${unique(offenses.map(o => getRoundForOffense(o, { slashingRoundSize, epochDuration })))}`,
|
|
190
|
-
offenses,
|
|
176
|
+
{ offenses },
|
|
191
177
|
);
|
|
192
178
|
return offenses;
|
|
193
179
|
}
|
|
@@ -204,8 +190,9 @@ export async function awaitCommitteeKicked({
|
|
|
204
190
|
slashingProposer,
|
|
205
191
|
slashingRoundSize,
|
|
206
192
|
aztecSlotDuration,
|
|
193
|
+
aztecEpochDuration,
|
|
207
194
|
logger,
|
|
208
|
-
|
|
195
|
+
offenseEpoch,
|
|
209
196
|
}: {
|
|
210
197
|
rollup: RollupContract;
|
|
211
198
|
cheatCodes: RollupCheatCodes;
|
|
@@ -214,21 +201,22 @@ export async function awaitCommitteeKicked({
|
|
|
214
201
|
slashingProposer: EmpireSlashingProposerContract | TallySlashingProposerContract | undefined;
|
|
215
202
|
slashingRoundSize: number;
|
|
216
203
|
aztecSlotDuration: number;
|
|
217
|
-
|
|
204
|
+
aztecEpochDuration: number;
|
|
218
205
|
logger: Logger;
|
|
206
|
+
offenseEpoch: number;
|
|
219
207
|
}) {
|
|
220
208
|
if (!slashingProposer) {
|
|
221
209
|
throw new Error('No slashing proposer configured. Cannot test slashing.');
|
|
222
210
|
}
|
|
223
211
|
|
|
224
|
-
logger.info(`Advancing epochs so we start slashing`);
|
|
225
212
|
await cheatCodes.debugRollup();
|
|
226
|
-
await cheatCodes.advanceToEpoch((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n, {
|
|
227
|
-
updateDateProvider: dateProvider,
|
|
228
|
-
});
|
|
229
213
|
|
|
230
|
-
// Await for the slash payload to be created if empire (no payload is created on tally until execution time)
|
|
231
214
|
if (slashingProposer.type === 'empire') {
|
|
215
|
+
// Await for the slash payload to be created if empire (no payload is created on tally until execution time)
|
|
216
|
+
const targetEpoch = (await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n;
|
|
217
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
218
|
+
await cheatCodes.advanceToEpoch(targetEpoch);
|
|
219
|
+
|
|
232
220
|
const slashPayloadEvents = await retryUntil(
|
|
233
221
|
async () => {
|
|
234
222
|
const events = await slashFactory.getSlashPayloadCreatedEvents();
|
|
@@ -243,6 +231,15 @@ export async function awaitCommitteeKicked({
|
|
|
243
231
|
expect(unique(slashPayloadEvents[0].slashes.map(slash => slash.validator.toString()))).toHaveLength(
|
|
244
232
|
committee.length,
|
|
245
233
|
);
|
|
234
|
+
} else {
|
|
235
|
+
// Use the slash offset to ensure we are in the right epoch for tally
|
|
236
|
+
const slashOffsetInRounds = await slashingProposer.getSlashOffsetInRounds();
|
|
237
|
+
const slashingRoundSizeInEpochs = slashingRoundSize / aztecEpochDuration;
|
|
238
|
+
const slashingOffsetInEpochs = Number(slashOffsetInRounds) * slashingRoundSizeInEpochs;
|
|
239
|
+
const firstEpochInOffenseRound = offenseEpoch - (offenseEpoch % slashingRoundSizeInEpochs);
|
|
240
|
+
const targetEpoch = firstEpochInOffenseRound + slashingOffsetInEpochs;
|
|
241
|
+
logger.info(`Advancing to epoch ${targetEpoch} so we start slashing`);
|
|
242
|
+
await cheatCodes.advanceToEpoch(targetEpoch, { offset: -aztecSlotDuration / 2 });
|
|
246
243
|
}
|
|
247
244
|
|
|
248
245
|
const attestersPre = await rollup.getAttesters();
|
|
@@ -253,7 +250,7 @@ export async function awaitCommitteeKicked({
|
|
|
253
250
|
expect(attesterInfo.status).toEqual(1); // Validating
|
|
254
251
|
}
|
|
255
252
|
|
|
256
|
-
const timeout = slashingRoundSize * 2 * aztecSlotDuration;
|
|
253
|
+
const timeout = slashingRoundSize * 2 * aztecSlotDuration + 30;
|
|
257
254
|
logger.info(`Waiting for slash to be executed (timeout ${timeout}s)`);
|
|
258
255
|
await awaitProposalExecution(slashingProposer, timeout, logger);
|
|
259
256
|
|
|
@@ -272,9 +269,7 @@ export async function awaitCommitteeKicked({
|
|
|
272
269
|
|
|
273
270
|
logger.info(`Advancing to check current committee`);
|
|
274
271
|
await cheatCodes.debugRollup();
|
|
275
|
-
await cheatCodes.advanceToEpoch((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n
|
|
276
|
-
updateDateProvider: dateProvider,
|
|
277
|
-
});
|
|
272
|
+
await cheatCodes.advanceToEpoch((await cheatCodes.getEpoch()) + (await rollup.getLagInEpochs()) + 1n);
|
|
278
273
|
await cheatCodes.debugRollup();
|
|
279
274
|
|
|
280
275
|
const committeeNextEpoch = await rollup.getCurrentEpochCommittee();
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type
|
|
1
|
+
import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
2
|
+
import { type Logger, createLogger } from '@aztec/aztec.js/log';
|
|
3
|
+
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
3
4
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
4
5
|
import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount';
|
|
6
|
+
import type { TestWallet } from '@aztec/test-wallet/server';
|
|
5
7
|
|
|
6
8
|
import { jest } from '@jest/globals';
|
|
7
9
|
|
|
@@ -28,11 +30,9 @@ export class TokenContractTest {
|
|
|
28
30
|
node!: AztecNode;
|
|
29
31
|
|
|
30
32
|
badAccount!: InvalidAccountContract;
|
|
31
|
-
|
|
33
|
+
wallet!: TestWallet;
|
|
32
34
|
adminAddress!: AztecAddress;
|
|
33
|
-
account1!: AccountWallet;
|
|
34
35
|
account1Address!: AztecAddress;
|
|
35
|
-
account2!: AccountWallet;
|
|
36
36
|
account2Address!: AztecAddress;
|
|
37
37
|
|
|
38
38
|
constructor(testName: string) {
|
|
@@ -54,11 +54,11 @@ export class TokenContractTest {
|
|
|
54
54
|
await this.snapshotManager.snapshot(
|
|
55
55
|
'3_accounts',
|
|
56
56
|
deployAccounts(3, this.logger),
|
|
57
|
-
|
|
57
|
+
({ deployedAccounts }, { wallet, aztecNode }) => {
|
|
58
58
|
this.node = aztecNode;
|
|
59
|
-
|
|
60
|
-
[this.
|
|
61
|
-
|
|
59
|
+
this.wallet = wallet;
|
|
60
|
+
[this.adminAddress, this.account1Address, this.account2Address] = deployedAccounts.map(acc => acc.address);
|
|
61
|
+
return Promise.resolve();
|
|
62
62
|
},
|
|
63
63
|
);
|
|
64
64
|
|
|
@@ -68,11 +68,11 @@ export class TokenContractTest {
|
|
|
68
68
|
// Create the token contract state.
|
|
69
69
|
// Move this account thing to addAccounts above?
|
|
70
70
|
this.logger.verbose(`Public deploy accounts...`);
|
|
71
|
-
await publicDeployAccounts(this.
|
|
71
|
+
await publicDeployAccounts(this.wallet, [this.adminAddress, this.account1Address]);
|
|
72
72
|
|
|
73
73
|
this.logger.verbose(`Deploying TokenContract...`);
|
|
74
74
|
const asset = await TokenContract.deploy(
|
|
75
|
-
this.
|
|
75
|
+
this.wallet,
|
|
76
76
|
this.adminAddress,
|
|
77
77
|
TokenContractTest.TOKEN_NAME,
|
|
78
78
|
TokenContractTest.TOKEN_SYMBOL,
|
|
@@ -83,22 +83,22 @@ export class TokenContractTest {
|
|
|
83
83
|
this.logger.verbose(`Token deployed to ${asset.address}`);
|
|
84
84
|
|
|
85
85
|
this.logger.verbose(`Deploying bad account...`);
|
|
86
|
-
this.badAccount = await InvalidAccountContract.deploy(this.
|
|
86
|
+
this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({ from: this.adminAddress }).deployed();
|
|
87
87
|
this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
|
|
88
88
|
|
|
89
89
|
return { tokenContractAddress: asset.address, badAccountAddress: this.badAccount.address };
|
|
90
90
|
},
|
|
91
91
|
async ({ tokenContractAddress, badAccountAddress }) => {
|
|
92
92
|
// Restore the token contract state.
|
|
93
|
-
this.asset = await TokenContract.at(tokenContractAddress, this.
|
|
93
|
+
this.asset = await TokenContract.at(tokenContractAddress, this.wallet);
|
|
94
94
|
this.logger.verbose(`Token contract address: ${this.asset.address}`);
|
|
95
95
|
|
|
96
|
-
this.tokenSim = new TokenSimulator(this.asset, this.
|
|
96
|
+
this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [
|
|
97
97
|
this.adminAddress,
|
|
98
98
|
this.account1Address,
|
|
99
99
|
]);
|
|
100
100
|
|
|
101
|
-
this.badAccount = await InvalidAccountContract.at(badAccountAddress, this.
|
|
101
|
+
this.badAccount = await InvalidAccountContract.at(badAccountAddress, this.wallet);
|
|
102
102
|
this.logger.verbose(`Bad account address: ${this.badAccount.address}`);
|
|
103
103
|
|
|
104
104
|
expect(await this.asset.methods.get_admin().simulate({ from: this.adminAddress })).toBe(
|
|
@@ -131,14 +131,14 @@ export class TokenContractTest {
|
|
|
131
131
|
await this.snapshotManager.snapshot(
|
|
132
132
|
'mint',
|
|
133
133
|
async () => {
|
|
134
|
-
const { asset,
|
|
134
|
+
const { asset, adminAddress } = this;
|
|
135
135
|
const amount = 10000n;
|
|
136
136
|
|
|
137
137
|
this.logger.verbose(`Minting ${amount} publicly...`);
|
|
138
138
|
await asset.methods.mint_to_public(adminAddress, amount).send({ from: adminAddress }).wait();
|
|
139
139
|
|
|
140
140
|
this.logger.verbose(`Minting ${amount} privately...`);
|
|
141
|
-
await mintTokensToPrivate(asset, adminAddress,
|
|
141
|
+
await mintTokensToPrivate(asset, adminAddress, adminAddress, amount);
|
|
142
142
|
this.logger.verbose(`Minting complete.`);
|
|
143
143
|
|
|
144
144
|
return { amount };
|