@aztec/end-to-end 0.0.0-test.1 → 0.0.1-commit.24de95ac
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 +61 -0
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -0
- package/dest/bench/client_flows/benchmark.js +261 -0
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +73 -0
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -0
- package/dest/bench/client_flows/client_flows_benchmark.js +311 -0
- package/dest/bench/client_flows/config.d.ts +14 -0
- package/dest/bench/client_flows/config.d.ts.map +1 -0
- package/dest/bench/client_flows/config.js +106 -0
- package/dest/bench/client_flows/data_extractor.d.ts +2 -0
- package/dest/bench/client_flows/data_extractor.d.ts.map +1 -0
- package/dest/bench/client_flows/data_extractor.js +99 -0
- package/dest/bench/utils.d.ts +10 -36
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +26 -66
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +20 -12
- 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 +85 -57
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +18 -24
- 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 +48 -69
- package/dest/e2e_deploy_contract/deploy_test.d.ts +14 -6
- package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
- package/dest/e2e_deploy_contract/deploy_test.js +13 -19
- package/dest/e2e_epochs/epochs_test.d.ts +58 -17
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +224 -43
- package/dest/e2e_fees/bridging_race.notest.d.ts +2 -0
- package/dest/e2e_fees/bridging_race.notest.d.ts.map +1 -0
- package/dest/e2e_fees/bridging_race.notest.js +63 -0
- package/dest/e2e_fees/fees_test.d.ts +20 -9
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +98 -107
- package/dest/e2e_l1_publisher/write_json.d.ts +10 -0
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -0
- package/dest/e2e_l1_publisher/write_json.js +57 -0
- package/dest/e2e_multi_validator/utils.d.ts +12 -0
- package/dest/e2e_multi_validator/utils.d.ts.map +1 -0
- package/dest/e2e_multi_validator/utils.js +214 -0
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +9 -6
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +22 -19
- 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 +135 -0
- package/dest/e2e_p2p/p2p_network.d.ts +69 -22
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +180 -129
- package/dest/e2e_p2p/shared.d.ts +41 -5
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +163 -19
- package/dest/e2e_token_contract/token_contract_test.d.ts +11 -5
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +50 -26
- package/dest/{e2e_prover → fixtures}/e2e_prover_test.d.ts +14 -9
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -0
- package/dest/{e2e_prover → fixtures}/e2e_prover_test.js +95 -100
- package/dest/fixtures/fixtures.d.ts +5 -6
- package/dest/fixtures/fixtures.d.ts.map +1 -1
- package/dest/fixtures/fixtures.js +4 -3
- 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_acvm_config.js +2 -14
- 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 +10 -17
- package/dest/fixtures/l1_to_l2_messaging.d.ts +8 -5
- package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -1
- package/dest/fixtures/l1_to_l2_messaging.js +44 -18
- package/dest/fixtures/setup_l1_contracts.d.ts +3 -3
- package/dest/fixtures/setup_l1_contracts.d.ts.map +1 -1
- package/dest/fixtures/setup_l1_contracts.js +4 -4
- package/dest/fixtures/setup_p2p_test.d.ts +14 -13
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +73 -21
- package/dest/fixtures/snapshot_manager.d.ts +15 -7
- package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
- package/dest/fixtures/snapshot_manager.js +147 -121
- package/dest/fixtures/token_utils.d.ts +6 -3
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +23 -10
- package/dest/fixtures/utils.d.ts +76 -37
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +464 -368
- 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/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 +41 -25
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +104 -50
- package/dest/shared/gas_portal_test_harness.d.ts +32 -24
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/gas_portal_test_harness.js +50 -29
- 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 +13 -11
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +138 -108
- package/dest/simulators/lending_simulator.d.ts +6 -6
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +13 -16
- package/dest/simulators/token_simulator.d.ts +5 -2
- package/dest/simulators/token_simulator.d.ts.map +1 -1
- package/dest/simulators/token_simulator.js +16 -13
- package/dest/spartan/setup_test_wallets.d.ts +23 -10
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +167 -58
- package/dest/spartan/utils.d.ts +106 -303
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +434 -130
- package/package.json +61 -56
- package/src/bench/client_flows/benchmark.ts +341 -0
- package/src/bench/client_flows/client_flows_benchmark.ts +402 -0
- package/src/bench/client_flows/config.ts +61 -0
- package/src/bench/client_flows/data_extractor.ts +111 -0
- package/src/bench/utils.ts +22 -76
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +80 -77
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +63 -105
- package/src/e2e_deploy_contract/deploy_test.ts +23 -38
- package/src/e2e_epochs/epochs_test.ts +274 -54
- package/src/e2e_fees/bridging_race.notest.ts +80 -0
- package/src/e2e_fees/fees_test.ts +137 -136
- package/src/e2e_l1_publisher/write_json.ts +76 -0
- package/src/e2e_multi_validator/utils.ts +258 -0
- package/src/e2e_nested_contract/nested_contract_test.ts +27 -18
- package/src/e2e_p2p/inactivity_slash_test.ts +178 -0
- package/src/e2e_p2p/p2p_network.ts +272 -166
- package/src/e2e_p2p/shared.ts +244 -29
- package/src/e2e_token_contract/token_contract_test.ts +43 -39
- package/src/fixtures/dumps/epoch_proof_result.json +1 -1
- package/src/{e2e_prover → fixtures}/e2e_prover_test.ts +101 -145
- package/src/fixtures/fixtures.ts +4 -3
- package/src/fixtures/get_acvm_config.ts +3 -11
- package/src/fixtures/get_bb_config.ts +18 -13
- package/src/fixtures/l1_to_l2_messaging.ts +53 -23
- package/src/fixtures/setup_l1_contracts.ts +6 -7
- package/src/fixtures/setup_p2p_test.ts +112 -38
- package/src/fixtures/snapshot_manager.ts +187 -139
- package/src/fixtures/token_utils.ts +29 -12
- package/src/fixtures/utils.ts +552 -425
- package/src/fixtures/web3signer.ts +63 -0
- package/src/guides/up_quick_start.sh +6 -14
- package/src/quality_of_service/alert_checker.ts +1 -1
- package/src/shared/cross_chain_test_harness.ts +108 -79
- package/src/shared/gas_portal_test_harness.ts +58 -49
- package/src/shared/jest_setup.ts +1 -1
- package/src/shared/submit-transactions.ts +12 -8
- package/src/shared/uniswap_l1_l2.ts +173 -176
- package/src/simulators/lending_simulator.ts +12 -15
- package/src/simulators/token_simulator.ts +21 -13
- package/src/spartan/DEVELOP.md +121 -0
- package/src/spartan/setup_test_wallets.ts +215 -93
- package/src/spartan/utils.ts +490 -130
- package/dest/e2e_prover/e2e_prover_test.d.ts.map +0 -1
- package/dest/sample-dapp/connect.js +0 -12
- package/dest/sample-dapp/contracts.js +0 -10
- package/dest/sample-dapp/deploy.js +0 -35
- package/dest/sample-dapp/index.js +0 -98
- package/src/sample-dapp/connect.mjs +0 -16
- package/src/sample-dapp/contracts.mjs +0 -14
- package/src/sample-dapp/deploy.mjs +0 -40
- package/src/sample-dapp/index.mjs +0 -128
|
@@ -1,20 +1,37 @@
|
|
|
1
|
-
import { AztecNodeService } from '@aztec/aztec-node';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
2
|
+
import { getTimestampRangeForEpoch } from '@aztec/aztec.js/block';
|
|
3
|
+
import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';
|
|
4
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
5
|
+
import type { Logger } from '@aztec/aztec.js/log';
|
|
6
|
+
import { MerkleTreeId } from '@aztec/aztec.js/trees';
|
|
7
|
+
import type { Wallet } from '@aztec/aztec.js/wallet';
|
|
8
|
+
import { EpochCache } from '@aztec/epoch-cache';
|
|
9
|
+
import { DefaultL1ContractsConfig, type ExtendedViemWalletClient, createExtendedL1Client } from '@aztec/ethereum';
|
|
4
10
|
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
5
|
-
import { DelayedTxUtils, type Delayer, waitUntilL1Timestamp } from '@aztec/ethereum/test';
|
|
11
|
+
import { ChainMonitor, DelayedTxUtils, type Delayer, waitUntilL1Timestamp, withDelayer } from '@aztec/ethereum/test';
|
|
12
|
+
import { SecretValue } from '@aztec/foundation/config';
|
|
6
13
|
import { randomBytes } from '@aztec/foundation/crypto';
|
|
7
14
|
import { withLogNameSuffix } from '@aztec/foundation/log';
|
|
8
|
-
import {
|
|
15
|
+
import { retryUntil } from '@aztec/foundation/retry';
|
|
16
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
17
|
+
import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
18
|
+
import { getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers';
|
|
19
|
+
import { ProverNode, type ProverNodeConfig, ProverNodePublisher } from '@aztec/prover-node';
|
|
9
20
|
import type { TestProverNode } from '@aztec/prover-node/test';
|
|
10
|
-
import
|
|
21
|
+
import {
|
|
22
|
+
type SequencerClient,
|
|
23
|
+
type SequencerEvents,
|
|
24
|
+
type SequencerPublisher,
|
|
25
|
+
SequencerState,
|
|
26
|
+
} from '@aztec/sequencer-client';
|
|
11
27
|
import type { TestSequencerClient } from '@aztec/sequencer-client/test';
|
|
12
|
-
import type
|
|
13
|
-
import type
|
|
14
|
-
import {
|
|
28
|
+
import { EthAddress, type L2BlockNumber } from '@aztec/stdlib/block';
|
|
29
|
+
import { type L1RollupConstants, getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
30
|
+
import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
15
31
|
|
|
16
32
|
import { join } from 'path';
|
|
17
|
-
import type { Hex
|
|
33
|
+
import type { Hex } from 'viem';
|
|
34
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
35
|
|
|
19
36
|
import {
|
|
20
37
|
type EndToEndContext,
|
|
@@ -24,15 +41,20 @@ import {
|
|
|
24
41
|
setup,
|
|
25
42
|
} from '../fixtures/utils.js';
|
|
26
43
|
|
|
27
|
-
// This can be lowered to as much as 2s in non-CI
|
|
28
|
-
export const L1_BLOCK_TIME_IN_S = process.env.L1_BLOCK_TIME ? parseInt(process.env.L1_BLOCK_TIME) : 8;
|
|
29
|
-
export const EPOCH_DURATION_IN_L2_SLOTS = 4;
|
|
30
|
-
export const L2_SLOT_DURATION_IN_L1_SLOTS = 2;
|
|
31
44
|
export const WORLD_STATE_BLOCK_HISTORY = 2;
|
|
32
45
|
export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
|
|
33
46
|
export const ARCHIVER_POLL_INTERVAL = 50;
|
|
47
|
+
export const DEFAULT_L1_BLOCK_TIME = process.env.CI ? 12 : 8;
|
|
48
|
+
|
|
49
|
+
export type EpochsTestOpts = Partial<SetupOptions> & { numberOfAccounts?: number };
|
|
34
50
|
|
|
35
|
-
export type
|
|
51
|
+
export type TrackedSequencerEvent = {
|
|
52
|
+
[K in keyof SequencerEvents]: Parameters<SequencerEvents[K]>[0] & {
|
|
53
|
+
type: K;
|
|
54
|
+
sequencerIndex: number;
|
|
55
|
+
validator: EthAddress;
|
|
56
|
+
};
|
|
57
|
+
}[keyof SequencerEvents];
|
|
36
58
|
|
|
37
59
|
/**
|
|
38
60
|
* Tests building of epochs using fast block times and short epochs.
|
|
@@ -41,46 +63,72 @@ export type EpochsTestOpts = Partial<Pick<SetupOptions, 'startProverNode'>>;
|
|
|
41
63
|
*/
|
|
42
64
|
export class EpochsTestContext {
|
|
43
65
|
public context!: EndToEndContext;
|
|
44
|
-
public l1Client!:
|
|
66
|
+
public l1Client!: ExtendedViemWalletClient;
|
|
45
67
|
public rollup!: RollupContract;
|
|
46
68
|
public constants!: L1RollupConstants;
|
|
47
69
|
public logger!: Logger;
|
|
48
70
|
public monitor!: ChainMonitor;
|
|
71
|
+
public epochCache!: EpochCache;
|
|
49
72
|
public proverDelayer!: Delayer;
|
|
50
73
|
public sequencerDelayer!: Delayer;
|
|
51
74
|
|
|
52
75
|
public proverNodes: ProverNode[] = [];
|
|
53
76
|
public nodes: AztecNodeService[] = [];
|
|
54
77
|
|
|
78
|
+
public epochDuration!: number;
|
|
79
|
+
|
|
80
|
+
public L1_BLOCK_TIME_IN_S!: number;
|
|
81
|
+
public L2_SLOT_DURATION_IN_S!: number;
|
|
82
|
+
|
|
55
83
|
public static async setup(opts: EpochsTestOpts = {}) {
|
|
56
84
|
const test = new EpochsTestContext();
|
|
57
85
|
await test.setup(opts);
|
|
58
86
|
return test;
|
|
59
87
|
}
|
|
60
88
|
|
|
89
|
+
public static getSlotDurations(opts: EpochsTestOpts = {}) {
|
|
90
|
+
const envEthereumSlotDuration = process.env.L1_BLOCK_TIME
|
|
91
|
+
? parseInt(process.env.L1_BLOCK_TIME)
|
|
92
|
+
: DEFAULT_L1_BLOCK_TIME;
|
|
93
|
+
const ethereumSlotDuration = opts.ethereumSlotDuration ?? envEthereumSlotDuration;
|
|
94
|
+
const aztecSlotDuration = opts.aztecSlotDuration ?? ethereumSlotDuration * 2;
|
|
95
|
+
const aztecEpochDuration = opts.aztecEpochDuration ?? 6;
|
|
96
|
+
const aztecProofSubmissionEpochs = opts.aztecProofSubmissionEpochs ?? 1;
|
|
97
|
+
return { ethereumSlotDuration, aztecSlotDuration, aztecEpochDuration, aztecProofSubmissionEpochs };
|
|
98
|
+
}
|
|
99
|
+
|
|
61
100
|
public async setup(opts: EpochsTestOpts = {}) {
|
|
101
|
+
const { ethereumSlotDuration, aztecSlotDuration, aztecEpochDuration, aztecProofSubmissionEpochs } =
|
|
102
|
+
EpochsTestContext.getSlotDurations(opts);
|
|
103
|
+
|
|
104
|
+
this.L1_BLOCK_TIME_IN_S = ethereumSlotDuration;
|
|
105
|
+
this.L2_SLOT_DURATION_IN_S = aztecSlotDuration;
|
|
106
|
+
|
|
62
107
|
// Set up system without any account nor protocol contracts
|
|
63
108
|
// and with faster block times and shorter epochs.
|
|
64
|
-
const context = await setup(0, {
|
|
109
|
+
const context = await setup(opts.numberOfAccounts ?? 0, {
|
|
110
|
+
automineL1Setup: true,
|
|
65
111
|
checkIntervalMs: 50,
|
|
66
112
|
archiverPollingIntervalMS: ARCHIVER_POLL_INTERVAL,
|
|
67
113
|
worldStateBlockCheckIntervalMS: WORLD_STATE_BLOCK_CHECK_INTERVAL,
|
|
68
114
|
skipProtocolContracts: true,
|
|
69
115
|
salt: 1,
|
|
70
|
-
aztecEpochDuration
|
|
71
|
-
aztecSlotDuration
|
|
72
|
-
ethereumSlotDuration
|
|
73
|
-
|
|
116
|
+
aztecEpochDuration,
|
|
117
|
+
aztecSlotDuration,
|
|
118
|
+
ethereumSlotDuration,
|
|
119
|
+
aztecProofSubmissionEpochs,
|
|
120
|
+
aztecTargetCommitteeSize: opts.initialValidators?.length ?? 0,
|
|
74
121
|
minTxsPerBlock: 0,
|
|
75
122
|
realProofs: false,
|
|
76
123
|
startProverNode: true,
|
|
124
|
+
proverTestDelayMs: opts.proverTestDelayMs ?? 0,
|
|
77
125
|
// We use numeric incremental prover ids for simplicity, but we can switch to
|
|
78
126
|
// using the prover's eth address if the proverId is used for something in the rollup contract
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// but not so much to hang the sequencer and timeout the teardown
|
|
82
|
-
txPropagationMaxQueryAttempts: 12,
|
|
127
|
+
// Use numeric EthAddress for deterministic prover id
|
|
128
|
+
proverId: EthAddress.fromNumber(1),
|
|
83
129
|
worldStateBlockHistory: WORLD_STATE_BLOCK_HISTORY,
|
|
130
|
+
exitDelaySeconds: DefaultL1ContractsConfig.exitDelaySeconds,
|
|
131
|
+
slasherFlavor: 'none',
|
|
84
132
|
...opts,
|
|
85
133
|
});
|
|
86
134
|
|
|
@@ -88,32 +136,38 @@ export class EpochsTestContext {
|
|
|
88
136
|
this.proverNodes = context.proverNode ? [context.proverNode] : [];
|
|
89
137
|
this.nodes = context.aztecNode ? [context.aztecNode as AztecNodeService] : [];
|
|
90
138
|
this.logger = context.logger;
|
|
91
|
-
this.l1Client = context.deployL1ContractsValues.
|
|
139
|
+
this.l1Client = context.deployL1ContractsValues.l1Client;
|
|
92
140
|
this.rollup = RollupContract.getFromConfig(context.config);
|
|
141
|
+
this.epochCache = await EpochCache.create(this.rollup, context.config, { dateProvider: context.dateProvider });
|
|
93
142
|
|
|
94
143
|
// Loop that tracks L1 and L2 block numbers and logs whenever there's a new one.
|
|
95
|
-
this.monitor = new ChainMonitor(this.rollup, this.logger).start();
|
|
144
|
+
this.monitor = new ChainMonitor(this.rollup, context.dateProvider, this.logger).start();
|
|
96
145
|
|
|
97
146
|
// This is hideous.
|
|
98
147
|
// We ought to have a definite reference to the l1TxUtils that we're using in both places, provided by the test context.
|
|
99
148
|
this.proverDelayer = context.proverNode
|
|
100
149
|
? (((context.proverNode as TestProverNode).publisher as ProverNodePublisher).l1TxUtils as DelayedTxUtils).delayer!
|
|
101
150
|
: undefined!;
|
|
102
|
-
this.sequencerDelayer =
|
|
103
|
-
(
|
|
104
|
-
|
|
151
|
+
this.sequencerDelayer = context.sequencer
|
|
152
|
+
? (
|
|
153
|
+
((context.sequencer as TestSequencerClient).sequencer.publisher as SequencerPublisher)
|
|
154
|
+
.l1TxUtils as DelayedTxUtils
|
|
155
|
+
).delayer!
|
|
156
|
+
: undefined!;
|
|
105
157
|
|
|
106
|
-
if ((context.proverNode && !this.proverDelayer) || !this.sequencerDelayer) {
|
|
158
|
+
if ((context.proverNode && !this.proverDelayer) || (context.sequencer && !this.sequencerDelayer)) {
|
|
107
159
|
throw new Error(`Could not find prover or sequencer delayer`);
|
|
108
160
|
}
|
|
109
161
|
|
|
110
162
|
// Constants used for time calculation
|
|
163
|
+
this.epochDuration = aztecEpochDuration;
|
|
111
164
|
this.constants = {
|
|
112
|
-
epochDuration:
|
|
113
|
-
slotDuration:
|
|
165
|
+
epochDuration: aztecEpochDuration,
|
|
166
|
+
slotDuration: aztecSlotDuration,
|
|
114
167
|
l1StartBlock: await this.rollup.getL1StartBlock(),
|
|
115
168
|
l1GenesisTime: await this.rollup.getL1GenesisTime(),
|
|
116
|
-
ethereumSlotDuration
|
|
169
|
+
ethereumSlotDuration,
|
|
170
|
+
proofSubmissionEpochs: Number(await this.rollup.getProofSubmissionEpochs()),
|
|
117
171
|
};
|
|
118
172
|
|
|
119
173
|
this.logger.info(
|
|
@@ -122,38 +176,98 @@ export class EpochsTestContext {
|
|
|
122
176
|
}
|
|
123
177
|
|
|
124
178
|
public async teardown() {
|
|
125
|
-
this.monitor.stop();
|
|
126
|
-
await Promise.all(this.proverNodes.map(node => node.
|
|
127
|
-
await Promise.all(this.nodes.map(node => node.
|
|
179
|
+
await this.monitor.stop();
|
|
180
|
+
await Promise.all(this.proverNodes.map(node => tryStop(node, this.logger)));
|
|
181
|
+
await Promise.all(this.nodes.map(node => tryStop(node, this.logger)));
|
|
128
182
|
await this.context.teardown();
|
|
129
183
|
}
|
|
130
184
|
|
|
131
|
-
public async createProverNode() {
|
|
185
|
+
public async createProverNode(opts: { dontStart?: boolean } & Partial<ProverNodeConfig> = {}) {
|
|
132
186
|
this.logger.warn('Creating and syncing a simulated prover node...');
|
|
133
187
|
const proverNodePrivateKey = this.getNextPrivateKey();
|
|
134
188
|
const suffix = (this.proverNodes.length + 1).toString();
|
|
135
189
|
const proverNode = await withLogNameSuffix(suffix, () =>
|
|
136
190
|
createAndSyncProverNode(
|
|
137
191
|
proverNodePrivateKey,
|
|
138
|
-
{ ...this.context.config
|
|
192
|
+
{ ...this.context.config },
|
|
193
|
+
{
|
|
194
|
+
dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
|
|
195
|
+
proverId: EthAddress.fromNumber(parseInt(suffix, 10)),
|
|
196
|
+
dontStart: opts.dontStart,
|
|
197
|
+
...opts,
|
|
198
|
+
},
|
|
139
199
|
this.context.aztecNode,
|
|
140
|
-
|
|
200
|
+
undefined,
|
|
201
|
+
{ dateProvider: this.context.dateProvider },
|
|
141
202
|
),
|
|
142
203
|
);
|
|
143
204
|
this.proverNodes.push(proverNode);
|
|
144
205
|
return proverNode;
|
|
145
206
|
}
|
|
146
207
|
|
|
147
|
-
public
|
|
208
|
+
public createNonValidatorNode(opts: Partial<AztecNodeConfig> = {}) {
|
|
148
209
|
this.logger.warn('Creating and syncing a node without a validator...');
|
|
210
|
+
return this.createNode({ ...opts, disableValidator: true });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public createValidatorNode(
|
|
214
|
+
privateKeys: `0x${string}`[],
|
|
215
|
+
opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; dontStartSequencer?: boolean } = {},
|
|
216
|
+
) {
|
|
217
|
+
this.logger.warn('Creating and syncing a validator node...');
|
|
218
|
+
return this.createNode({ ...opts, disableValidator: false, validatorPrivateKeys: new SecretValue(privateKeys) });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private async createNode(
|
|
222
|
+
opts: Partial<AztecNodeConfig> & { txDelayerMaxInclusionTimeIntoSlot?: number; dontStartSequencer?: boolean } = {},
|
|
223
|
+
) {
|
|
149
224
|
const suffix = (this.nodes.length + 1).toString();
|
|
225
|
+
const { mockGossipSubNetwork } = this.context;
|
|
226
|
+
const resolvedConfig = { ...this.context.config, ...opts };
|
|
227
|
+
const p2pEnabled = resolvedConfig.p2pEnabled || mockGossipSubNetwork !== undefined;
|
|
228
|
+
const p2pIp = resolvedConfig.p2pIp ?? (p2pEnabled ? '127.0.0.1' : undefined);
|
|
150
229
|
const node = await withLogNameSuffix(suffix, () =>
|
|
151
|
-
AztecNodeService.createAndSync(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
230
|
+
AztecNodeService.createAndSync(
|
|
231
|
+
{
|
|
232
|
+
...resolvedConfig,
|
|
233
|
+
dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')),
|
|
234
|
+
validatorPrivateKeys: opts.validatorPrivateKeys ?? new SecretValue([]),
|
|
235
|
+
p2pEnabled,
|
|
236
|
+
p2pIp,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
dateProvider: this.context.dateProvider,
|
|
240
|
+
p2pClientDeps: {
|
|
241
|
+
p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
prefilledPublicData: this.context.prefilledPublicData,
|
|
246
|
+
...opts,
|
|
247
|
+
},
|
|
248
|
+
),
|
|
156
249
|
);
|
|
250
|
+
|
|
251
|
+
// REFACTOR: We're getting too much into the internals of the sequencer here.
|
|
252
|
+
// We should have a single method for constructing an aztec node that returns a TestAztecNodeService
|
|
253
|
+
// which directly exposes the delayer and sets any test config.
|
|
254
|
+
if (opts.txDelayerMaxInclusionTimeIntoSlot !== undefined) {
|
|
255
|
+
this.logger.info(
|
|
256
|
+
`Setting tx delayer max inclusion time into slot to ${opts.txDelayerMaxInclusionTimeIntoSlot} seconds`,
|
|
257
|
+
);
|
|
258
|
+
// Here we reach into the sequencer and hook in a tx delayer. The problem is that the sequencer's l1 utils only uses a public client, not a wallet.
|
|
259
|
+
// The delayer needs a wallet (a client that can sign), so we have to create one here.
|
|
260
|
+
const l1Client = createExtendedL1Client(
|
|
261
|
+
resolvedConfig.l1RpcUrls!,
|
|
262
|
+
resolvedConfig.publisherPrivateKeys![0]!.getValue(),
|
|
263
|
+
);
|
|
264
|
+
const sequencer = node.getSequencer() as TestSequencerClient;
|
|
265
|
+
const publisher = sequencer.sequencer.publisher;
|
|
266
|
+
const delayed = DelayedTxUtils.fromL1TxUtils(publisher.l1TxUtils, this.L1_BLOCK_TIME_IN_S, l1Client);
|
|
267
|
+
delayed.delayer!.setMaxInclusionTimeIntoSlot(opts.txDelayerMaxInclusionTimeIntoSlot);
|
|
268
|
+
publisher.l1TxUtils = delayed;
|
|
269
|
+
}
|
|
270
|
+
|
|
157
271
|
this.nodes.push(node);
|
|
158
272
|
return node;
|
|
159
273
|
}
|
|
@@ -167,14 +281,19 @@ export class EpochsTestContext {
|
|
|
167
281
|
public async waitUntilEpochStarts(epoch: number) {
|
|
168
282
|
const [start] = getTimestampRangeForEpoch(BigInt(epoch), this.constants);
|
|
169
283
|
this.logger.info(`Waiting until L1 timestamp ${start} is reached as the start of epoch ${epoch}`);
|
|
170
|
-
await waitUntilL1Timestamp(
|
|
284
|
+
await waitUntilL1Timestamp(
|
|
285
|
+
this.l1Client,
|
|
286
|
+
start - BigInt(this.L1_BLOCK_TIME_IN_S),
|
|
287
|
+
undefined,
|
|
288
|
+
30 * this.epochDuration,
|
|
289
|
+
);
|
|
171
290
|
return start;
|
|
172
291
|
}
|
|
173
292
|
|
|
174
293
|
/** Waits until the given L2 block number is mined. */
|
|
175
294
|
public async waitUntilL2BlockNumber(target: number, timeout = 60) {
|
|
176
295
|
await retryUntil(
|
|
177
|
-
() => Promise.resolve(target
|
|
296
|
+
() => Promise.resolve(target <= this.monitor.l2BlockNumber),
|
|
178
297
|
`Wait until L2 block ${target}`,
|
|
179
298
|
timeout,
|
|
180
299
|
0.1,
|
|
@@ -184,34 +303,135 @@ export class EpochsTestContext {
|
|
|
184
303
|
/** Waits until the given L2 block number is marked as proven. */
|
|
185
304
|
public async waitUntilProvenL2BlockNumber(t: number, timeout = 60) {
|
|
186
305
|
await retryUntil(
|
|
187
|
-
() => Promise.resolve(t
|
|
306
|
+
() => Promise.resolve(t <= this.monitor.l2ProvenBlockNumber),
|
|
188
307
|
`Wait proven L2 block ${t}`,
|
|
189
308
|
timeout,
|
|
190
309
|
0.1,
|
|
191
310
|
);
|
|
311
|
+
return this.monitor.l2ProvenBlockNumber;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Waits until the last slot of the proof submission window for a given epoch. */
|
|
315
|
+
public async waitUntilLastSlotOfProofSubmissionWindow(epochNumber: number | bigint) {
|
|
316
|
+
const deadline = getProofSubmissionDeadlineTimestamp(BigInt(epochNumber), this.constants);
|
|
317
|
+
const oneSlotBefore = deadline - BigInt(this.constants.slotDuration);
|
|
318
|
+
const date = new Date(Number(oneSlotBefore) * 1000);
|
|
319
|
+
this.logger.info(`Waiting until last slot of submission window for epoch ${epochNumber} at ${date}`, {
|
|
320
|
+
oneSlotBefore,
|
|
321
|
+
});
|
|
322
|
+
await waitUntilL1Timestamp(this.l1Client, oneSlotBefore);
|
|
192
323
|
}
|
|
193
324
|
|
|
194
325
|
/** Waits for the aztec node to sync to the target block number. */
|
|
195
|
-
public async waitForNodeToSync(blockNumber: number, type: '
|
|
326
|
+
public async waitForNodeToSync(blockNumber: number, type: 'proven' | 'finalized' | 'historic') {
|
|
196
327
|
const waitTime = ARCHIVER_POLL_INTERVAL + WORLD_STATE_BLOCK_CHECK_INTERVAL;
|
|
197
328
|
let synched = false;
|
|
198
329
|
while (!synched) {
|
|
199
330
|
await sleep(waitTime);
|
|
200
|
-
const syncState = await
|
|
201
|
-
|
|
202
|
-
|
|
331
|
+
const [syncState, tips] = await Promise.all([
|
|
332
|
+
this.context.aztecNode.getWorldStateSyncStatus(),
|
|
333
|
+
await this.context.aztecNode.getL2Tips(),
|
|
334
|
+
]);
|
|
335
|
+
this.logger.info(`Wait for node synch ${blockNumber} ${type}`, { blockNumber, type, syncState, tips });
|
|
336
|
+
if (type === 'proven') {
|
|
337
|
+
synched = tips.proven.number >= blockNumber && syncState.latestBlockNumber >= blockNumber;
|
|
338
|
+
} else if (type === 'finalized') {
|
|
339
|
+
synched = syncState.finalizedBlockNumber >= blockNumber;
|
|
203
340
|
} else {
|
|
204
341
|
synched = syncState.oldestHistoricBlockNumber >= blockNumber;
|
|
205
342
|
}
|
|
206
343
|
}
|
|
207
344
|
}
|
|
208
345
|
|
|
346
|
+
/** Registers the SpamContract on the given wallet. */
|
|
347
|
+
public async registerSpamContract(wallet: Wallet, salt = Fr.ZERO) {
|
|
348
|
+
const instance = await getContractInstanceFromInstantiationParams(SpamContract.artifact, {
|
|
349
|
+
constructorArgs: [],
|
|
350
|
+
constructorArtifact: undefined,
|
|
351
|
+
salt,
|
|
352
|
+
publicKeys: undefined,
|
|
353
|
+
deployer: undefined,
|
|
354
|
+
});
|
|
355
|
+
await wallet.registerContract(instance, SpamContract.artifact);
|
|
356
|
+
return SpamContract.at(instance.address, wallet);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** Creates an L1 client using a fresh account with funds from anvil, with a tx delayer already set up. */
|
|
360
|
+
public async createL1Client() {
|
|
361
|
+
const { client, delayer } = withDelayer(
|
|
362
|
+
createExtendedL1Client(
|
|
363
|
+
[...this.l1Client.chain.rpcUrls.default.http],
|
|
364
|
+
privateKeyToAccount(this.getNextPrivateKey()),
|
|
365
|
+
this.l1Client.chain,
|
|
366
|
+
),
|
|
367
|
+
this.context.dateProvider!,
|
|
368
|
+
{ ethereumSlotDuration: this.L1_BLOCK_TIME_IN_S },
|
|
369
|
+
);
|
|
370
|
+
expect(await client.getBalance({ address: client.account.address })).toBeGreaterThan(0n);
|
|
371
|
+
return { client, delayer };
|
|
372
|
+
}
|
|
373
|
+
|
|
209
374
|
/** Verifies whether the given block number is found on the aztec node. */
|
|
210
375
|
public async verifyHistoricBlock(blockNumber: L2BlockNumber, expectedSuccess: boolean) {
|
|
376
|
+
// We use `findLeavesIndexes` here, but could use any function that queries the world-state
|
|
377
|
+
// at a particular block, so we know whether that historic block is available or has been
|
|
378
|
+
// pruned. Note that `getBlock` would not work here, since it only hits the archiver.
|
|
211
379
|
const result = await this.context.aztecNode
|
|
212
|
-
.
|
|
380
|
+
.findLeavesIndexes(blockNumber, MerkleTreeId.NULLIFIER_TREE, [Fr.ZERO])
|
|
213
381
|
.then(_ => true)
|
|
214
382
|
.catch(_ => false);
|
|
215
383
|
expect(result).toBe(expectedSuccess);
|
|
216
384
|
}
|
|
385
|
+
|
|
386
|
+
public watchSequencerEvents(
|
|
387
|
+
sequencers: SequencerClient[],
|
|
388
|
+
getMetadata: (i: number) => Record<string, any> = () => ({}),
|
|
389
|
+
) {
|
|
390
|
+
const stateChanges: TrackedSequencerEvent[] = [];
|
|
391
|
+
const failEvents: TrackedSequencerEvent[] = [];
|
|
392
|
+
|
|
393
|
+
// Note we do not include the 'tx-count-check-failed' event here, since it is fine if we dont build
|
|
394
|
+
// due to lack of txs available.
|
|
395
|
+
const failEventsKeys: (keyof SequencerEvents)[] = [
|
|
396
|
+
'block-build-failed',
|
|
397
|
+
'block-publish-failed',
|
|
398
|
+
'proposer-rollup-check-failed',
|
|
399
|
+
];
|
|
400
|
+
|
|
401
|
+
const makeEvent = (
|
|
402
|
+
i: number,
|
|
403
|
+
eventName: keyof SequencerEvents,
|
|
404
|
+
args: Parameters<SequencerEvents[keyof SequencerEvents]>[0],
|
|
405
|
+
) =>
|
|
406
|
+
({
|
|
407
|
+
...args,
|
|
408
|
+
type: eventName,
|
|
409
|
+
sequencerIndex: i + 2,
|
|
410
|
+
...getMetadata(i),
|
|
411
|
+
}) as TrackedSequencerEvent;
|
|
412
|
+
|
|
413
|
+
sequencers.forEach((sequencer, i) => {
|
|
414
|
+
const sequencerIndex = i + 2;
|
|
415
|
+
sequencer.getSequencer().on('state-changed', (args: Parameters<SequencerEvents['state-changed']>[0]) => {
|
|
416
|
+
const noisyStates = [SequencerState.IDLE, SequencerState.PROPOSER_CHECK, SequencerState.SYNCHRONIZING];
|
|
417
|
+
if (!noisyStates.includes(args.newState)) {
|
|
418
|
+
const evt = makeEvent(i, 'state-changed', args);
|
|
419
|
+
stateChanges.push(evt);
|
|
420
|
+
this.logger.verbose(
|
|
421
|
+
`Sequencer ${sequencerIndex} transitioned from state ${args.oldState} to state ${args.newState}`,
|
|
422
|
+
evt,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
failEventsKeys.forEach(eventName => {
|
|
427
|
+
sequencer.getSequencer().on(eventName, (args: Parameters<SequencerEvents[typeof eventName]>[0]) => {
|
|
428
|
+
const evt = makeEvent(i, eventName, args);
|
|
429
|
+
failEvents.push(evt);
|
|
430
|
+
this.logger.error(`Failed event ${eventName} from sequencer ${sequencerIndex}`, undefined, evt);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
return { failEvents, stateChanges };
|
|
436
|
+
}
|
|
217
437
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SchnorrAccountContract } from '@aztec/accounts/schnorr';
|
|
2
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
|
+
import type { Logger } from '@aztec/aztec.js/log';
|
|
4
|
+
import { Fq } from '@aztec/foundation/fields';
|
|
5
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
6
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
7
|
+
import type { TestWallet } from '@aztec/test-wallet/server';
|
|
8
|
+
|
|
9
|
+
import { jest } from '@jest/globals';
|
|
10
|
+
import type { Hex } from 'viem';
|
|
11
|
+
|
|
12
|
+
import { FeesTest } from './fees_test.js';
|
|
13
|
+
|
|
14
|
+
jest.setTimeout(300_000);
|
|
15
|
+
|
|
16
|
+
// Regression for https://github.com/AztecProtocol/aztec-packages/issues/12366
|
|
17
|
+
// Similar to e2e_fees/account_init but with no automine
|
|
18
|
+
describe('e2e_fees bridging_race', () => {
|
|
19
|
+
const ETHEREUM_SLOT_DURATION = 4;
|
|
20
|
+
const AZTEC_SLOT_DURATION = ETHEREUM_SLOT_DURATION * 2;
|
|
21
|
+
|
|
22
|
+
const t = new FeesTest('bridging_race', 1, {
|
|
23
|
+
ethereumSlotDuration: ETHEREUM_SLOT_DURATION,
|
|
24
|
+
aztecSlotDuration: AZTEC_SLOT_DURATION,
|
|
25
|
+
minTxsPerBlock: 0,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
beforeAll(async () => {
|
|
29
|
+
await t.applyInitialAccountsSnapshot();
|
|
30
|
+
await t.applyPublicDeployAccountsSnapshot();
|
|
31
|
+
await t.applySetupFeeJuiceSnapshot();
|
|
32
|
+
|
|
33
|
+
({ wallet, logger } = await t.setup());
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterAll(async () => {
|
|
37
|
+
await t.teardown();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
let logger: Logger;
|
|
41
|
+
let bobsAddress: AztecAddress;
|
|
42
|
+
let wallet: TestWallet;
|
|
43
|
+
|
|
44
|
+
beforeEach(async () => {
|
|
45
|
+
const bobsSecretKey = Fr.random();
|
|
46
|
+
const bobsPrivateSigningKey = Fq.random();
|
|
47
|
+
const bobsSalt = Fr.random();
|
|
48
|
+
const bobsAccountManager = await wallet.createAccount({
|
|
49
|
+
secret: bobsSecretKey,
|
|
50
|
+
salt: bobsSalt,
|
|
51
|
+
contract: new SchnorrAccountContract(bobsPrivateSigningKey),
|
|
52
|
+
});
|
|
53
|
+
bobsAddress = bobsAccountManager.address;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('Alice bridges funds to Bob', async () => {
|
|
57
|
+
// Tweak the token manager so the bridging happens immediately before the end of the current L2 slot
|
|
58
|
+
// This caused the message to be "not in state" when tried to be used
|
|
59
|
+
const l1TokenManager = t.feeJuiceBridgeTestHarness.l1TokenManager;
|
|
60
|
+
const origApprove = l1TokenManager.approve.bind(l1TokenManager);
|
|
61
|
+
l1TokenManager.approve = async (amount: bigint, address: Hex, addressName = '') => {
|
|
62
|
+
await origApprove(amount, address, addressName);
|
|
63
|
+
const sleepTime = (Number(t.chainMonitor.l2BlockTimestamp) + AZTEC_SLOT_DURATION) * 1000 - Date.now() - 500;
|
|
64
|
+
logger.info(`Sleeping for ${sleepTime}ms until near end of L2 slot before sending L1 fee juice to L2 inbox`);
|
|
65
|
+
await sleep(sleepTime);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Waiting for the archiver to sync the message _before_ waiting for the mandatory 2 L2 blocks to pass fixed it
|
|
69
|
+
// This was added everywhere we wait for two blocks, which is spread across three different places in the codebase
|
|
70
|
+
// Yes, we need to REFACTOR it at some point
|
|
71
|
+
const claim = await t.feeJuiceBridgeTestHarness.prepareTokensOnL1(bobsAddress);
|
|
72
|
+
const { claimSecret: secret, messageLeafIndex: index } = claim;
|
|
73
|
+
await t.feeJuiceContract.methods
|
|
74
|
+
.claim(bobsAddress, claim.claimAmount, secret, index)
|
|
75
|
+
.send({ from: bobsAddress })
|
|
76
|
+
.wait();
|
|
77
|
+
const [balance] = await t.getGasBalanceFn(bobsAddress);
|
|
78
|
+
expect(balance).toEqual(claim.claimAmount);
|
|
79
|
+
});
|
|
80
|
+
});
|