@aztec/end-to-end 0.0.1-commit.c7c42ec → 0.0.1-commit.f295ac2
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/benchmark.js +21 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +12 -13
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +105 -135
- package/dest/bench/client_flows/data_extractor.js +3 -1
- package/dest/bench/utils.d.ts +5 -5
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +8 -5
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +6 -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 +98 -113
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +15 -10
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -1
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +89 -70
- package/dest/e2e_deploy_contract/deploy_test.d.ts +4 -3
- package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
- package/dest/e2e_deploy_contract/deploy_test.js +18 -13
- package/dest/e2e_epochs/epochs_test.js +2 -2
- package/dest/e2e_fees/bridging_race.notest.js +2 -4
- package/dest/e2e_fees/fees_test.d.ts +13 -13
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +123 -141
- package/dest/e2e_l1_publisher/write_json.d.ts +3 -3
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
- package/dest/e2e_l1_publisher/write_json.js +19 -15
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +6 -9
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +32 -40
- package/dest/e2e_p2p/inactivity_slash_test.d.ts +3 -3
- package/dest/e2e_p2p/inactivity_slash_test.d.ts.map +1 -1
- package/dest/e2e_p2p/inactivity_slash_test.js +3 -3
- package/dest/e2e_p2p/p2p_network.d.ts +7 -6
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +107 -104
- package/dest/e2e_p2p/shared.d.ts +1 -1
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +4 -4
- package/dest/e2e_token_contract/token_contract_test.d.ts +16 -9
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +90 -92
- package/dest/fixtures/e2e_prover_test.d.ts +8 -14
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +83 -95
- package/dest/fixtures/setup.d.ts +216 -0
- package/dest/fixtures/setup.d.ts.map +1 -0
- package/dest/fixtures/setup.js +684 -0
- package/dest/fixtures/utils.d.ts +5 -194
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +4 -619
- package/dest/quality_of_service/grafana_client.d.ts +41 -0
- package/dest/quality_of_service/grafana_client.d.ts.map +1 -0
- package/dest/quality_of_service/{alert_checker.js → grafana_client.js} +1 -1
- package/dest/quality_of_service/prometheus_client.d.ts +38 -0
- package/dest/quality_of_service/prometheus_client.d.ts.map +1 -0
- package/dest/quality_of_service/prometheus_client.js +67 -0
- package/dest/shared/cross_chain_test_harness.d.ts +14 -3
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +2 -2
- package/dest/shared/gas_portal_test_harness.d.ts +11 -1
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/index.d.ts +2 -2
- package/dest/shared/index.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts +3 -28
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +39 -21
- package/dest/simulators/lending_simulator.d.ts +5 -1
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.d.ts +4 -3
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/tx_metrics.d.ts +4 -1
- package/dest/spartan/tx_metrics.d.ts.map +1 -1
- package/dest/spartan/tx_metrics.js +24 -1
- package/dest/spartan/utils.d.ts +12 -5
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +123 -73
- package/package.json +40 -39
- package/src/bench/client_flows/benchmark.ts +24 -2
- package/src/bench/client_flows/client_flows_benchmark.ts +143 -196
- package/src/bench/client_flows/data_extractor.ts +1 -1
- package/src/bench/utils.ts +11 -7
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +107 -142
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +127 -116
- package/src/e2e_deploy_contract/deploy_test.ts +21 -14
- package/src/e2e_epochs/epochs_test.ts +2 -2
- package/src/e2e_fees/bridging_race.notest.ts +2 -5
- package/src/e2e_fees/fees_test.ts +172 -216
- package/src/e2e_l1_publisher/write_json.ts +22 -17
- package/src/e2e_nested_contract/nested_contract_test.ts +35 -56
- package/src/e2e_p2p/inactivity_slash_test.ts +5 -5
- package/src/e2e_p2p/p2p_network.ts +166 -168
- package/src/e2e_p2p/shared.ts +6 -5
- package/src/e2e_token_contract/token_contract_test.ts +105 -118
- package/src/fixtures/e2e_prover_test.ts +107 -137
- package/src/fixtures/setup.ts +1010 -0
- package/src/fixtures/utils.ts +27 -907
- package/src/quality_of_service/{alert_checker.ts → grafana_client.ts} +1 -1
- package/src/quality_of_service/prometheus_client.ts +113 -0
- package/src/shared/cross_chain_test_harness.ts +3 -9
- package/src/shared/index.ts +1 -1
- package/src/shared/uniswap_l1_l2.ts +46 -58
- package/src/spartan/setup_test_wallets.ts +7 -1
- package/src/spartan/tx_metrics.ts +27 -4
- package/src/spartan/utils.ts +112 -24
- package/dest/fixtures/snapshot_manager.d.ts +0 -93
- package/dest/fixtures/snapshot_manager.d.ts.map +0 -1
- package/dest/fixtures/snapshot_manager.js +0 -493
- package/dest/quality_of_service/alert_checker.d.ts +0 -41
- package/dest/quality_of_service/alert_checker.d.ts.map +0 -1
- package/src/fixtures/snapshot_manager.ts +0 -651
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export type PromteheusClientOptions = {
|
|
2
|
+
server: URL;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export class PrometheusClient {
|
|
6
|
+
constructor(
|
|
7
|
+
private config: PromteheusClientOptions,
|
|
8
|
+
private httpClient: typeof fetch = fetch,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
public async querySingleValue(query: string, time = new Date()): Promise<number> {
|
|
12
|
+
const resp = await this.queryRaw(query, time);
|
|
13
|
+
if (resp.status === 'success') {
|
|
14
|
+
if (resp.data.resultType === 'vector') {
|
|
15
|
+
if (resp.data.result.length === 0) {
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
const [_, value] = resp.data.result[0].value;
|
|
19
|
+
return parseFloat(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
throw new TypeError('Unsupported response body', { cause: JSON.stringify(resp) });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public queryRaw(query: string, time = new Date()): Promise<PrometheusResponse> {
|
|
27
|
+
const searchParams = new URLSearchParams();
|
|
28
|
+
searchParams.set('query', query);
|
|
29
|
+
searchParams.set('time', String(Math.trunc(time.getTime() / 1000)));
|
|
30
|
+
searchParams.set('limit', '10');
|
|
31
|
+
|
|
32
|
+
return this.callPrometheus('query', searchParams);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public queryRangeRaw(
|
|
36
|
+
query: string,
|
|
37
|
+
step: PrometheusDuration,
|
|
38
|
+
start: Date,
|
|
39
|
+
end = new Date(),
|
|
40
|
+
): Promise<PrometheusResponse> {
|
|
41
|
+
const searchParams = new URLSearchParams();
|
|
42
|
+
searchParams.set('query', query);
|
|
43
|
+
searchParams.set('step', step);
|
|
44
|
+
searchParams.set('start', String(Math.trunc(start.getTime() / 1000)));
|
|
45
|
+
searchParams.set('end', String(Math.trunc(end.getTime() / 1000)));
|
|
46
|
+
searchParams.set('limit', '10');
|
|
47
|
+
|
|
48
|
+
return this.callPrometheus('query_range', searchParams);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private async callPrometheus(api: string, searchParams: URLSearchParams): Promise<PrometheusResponse> {
|
|
52
|
+
const url = new URL('api/v1/' + api, this.config.server);
|
|
53
|
+
for (const [name, value] of searchParams) {
|
|
54
|
+
url.searchParams.append(name, value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const resp = await this.httpClient(url, { method: 'GET' });
|
|
58
|
+
if (!resp.ok || resp.status !== 200) {
|
|
59
|
+
throw new Error('Invalid HTTP response from Prometheus', {
|
|
60
|
+
cause: {
|
|
61
|
+
url,
|
|
62
|
+
status: resp.status,
|
|
63
|
+
statusText: resp.statusText,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const body = await resp.json();
|
|
69
|
+
if ('status' in body && (body.status === 'error' || body.status === 'success')) {
|
|
70
|
+
return body;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
throw new Error('Invalid response from Prometheus', {
|
|
74
|
+
cause: {
|
|
75
|
+
url,
|
|
76
|
+
body,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export type PrometheusDuration = `${number}s` | `${number}m` | `${number}h`;
|
|
83
|
+
|
|
84
|
+
export type PrometheusData =
|
|
85
|
+
| {
|
|
86
|
+
resultType: 'vector';
|
|
87
|
+
result: Array<{
|
|
88
|
+
metric: unknown;
|
|
89
|
+
value: [unixTimestamp: number, value: string];
|
|
90
|
+
}>;
|
|
91
|
+
}
|
|
92
|
+
| {
|
|
93
|
+
resultType: 'matrix';
|
|
94
|
+
result: Array<{
|
|
95
|
+
metric: unknown;
|
|
96
|
+
values: [unixTimestamp: number, value: string];
|
|
97
|
+
}>;
|
|
98
|
+
}
|
|
99
|
+
| {
|
|
100
|
+
resultType: 'scalar' | 'string';
|
|
101
|
+
result: unknown;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type PrometheusResponse =
|
|
105
|
+
| {
|
|
106
|
+
status: 'error';
|
|
107
|
+
errorType: string;
|
|
108
|
+
error: string;
|
|
109
|
+
}
|
|
110
|
+
| {
|
|
111
|
+
status: 'success';
|
|
112
|
+
data: PrometheusData;
|
|
113
|
+
};
|
|
@@ -16,7 +16,7 @@ import type { Wallet } from '@aztec/aztec.js/wallet';
|
|
|
16
16
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
17
17
|
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
18
18
|
import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
|
|
19
|
-
import {
|
|
19
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
20
20
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
21
21
|
import type { FieldsOf } from '@aztec/foundation/types';
|
|
22
22
|
import { TestERC20Abi, TokenPortalAbi, TokenPortalBytecode } from '@aztec/l1-artifacts';
|
|
@@ -324,17 +324,11 @@ export class CrossChainTestHarness {
|
|
|
324
324
|
|
|
325
325
|
withdrawFundsFromBridgeOnL1(
|
|
326
326
|
amount: bigint,
|
|
327
|
-
|
|
327
|
+
epochNumber: EpochNumber,
|
|
328
328
|
messageIndex: bigint,
|
|
329
329
|
siblingPath: SiblingPath<number>,
|
|
330
330
|
) {
|
|
331
|
-
return this.l1TokenPortalManager.withdrawFunds(
|
|
332
|
-
amount,
|
|
333
|
-
this.ethAccount,
|
|
334
|
-
BigInt(blockNumber),
|
|
335
|
-
messageIndex,
|
|
336
|
-
siblingPath,
|
|
337
|
-
);
|
|
331
|
+
return this.l1TokenPortalManager.withdrawFunds(amount, this.ethAccount, epochNumber, messageIndex, siblingPath);
|
|
338
332
|
}
|
|
339
333
|
|
|
340
334
|
async transferToPrivateOnL2(shieldAmount: bigint) {
|
package/src/shared/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { uniswapL1L2TestSuite
|
|
1
|
+
export { uniswapL1L2TestSuite } from './uniswap_l1_l2.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
|
|
2
2
|
import { computeAuthWitMessageHash } from '@aztec/aztec.js/authorization';
|
|
3
|
+
import { waitForProven } from '@aztec/aztec.js/contracts';
|
|
3
4
|
import { generateClaimSecret } from '@aztec/aztec.js/ethereum';
|
|
4
5
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
5
6
|
import type { Logger } from '@aztec/aztec.js/log';
|
|
@@ -10,6 +11,7 @@ import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-az
|
|
|
10
11
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
11
12
|
import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
|
|
12
13
|
import { extractEvent } from '@aztec/ethereum/utils';
|
|
14
|
+
import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
13
15
|
import { sha256ToField } from '@aztec/foundation/crypto/sha256';
|
|
14
16
|
import { InboxAbi, UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-artifacts';
|
|
15
17
|
import { UniswapContract } from '@aztec/noir-contracts.js/Uniswap';
|
|
@@ -20,7 +22,7 @@ import type { TestWallet } from '@aztec/test-wallet/server';
|
|
|
20
22
|
import { jest } from '@jest/globals';
|
|
21
23
|
import { type GetContractReturnType, getContract, parseEther, toFunctionSelector } from 'viem';
|
|
22
24
|
|
|
23
|
-
import { ensureAccountContractsPublished } from '../fixtures/utils.js';
|
|
25
|
+
import { type EndToEndContext, ensureAccountContractsPublished } from '../fixtures/utils.js';
|
|
24
26
|
import { CrossChainTestHarness } from './cross_chain_test_harness.js';
|
|
25
27
|
|
|
26
28
|
// PSA: This tests works on forked mainnet. There is a dump of the data in `dumpedState` such that we
|
|
@@ -32,28 +34,8 @@ import { CrossChainTestHarness } from './cross_chain_test_harness.js';
|
|
|
32
34
|
|
|
33
35
|
const TIMEOUT = 360_000;
|
|
34
36
|
|
|
35
|
-
/** Objects to be returned by the uniswap setup function */
|
|
36
|
-
export type UniswapSetupContext = {
|
|
37
|
-
/** Aztec Node instance */
|
|
38
|
-
aztecNode: AztecNode;
|
|
39
|
-
/** Logger instance named as the current test. */
|
|
40
|
-
logger: Logger;
|
|
41
|
-
/** The L1 wallet client, extended with public actions. */
|
|
42
|
-
l1Client: ExtendedViemWalletClient;
|
|
43
|
-
/** The wallet. */
|
|
44
|
-
wallet: TestWallet;
|
|
45
|
-
/** The owner address. */
|
|
46
|
-
ownerAddress: AztecAddress;
|
|
47
|
-
/** The sponsor wallet. */
|
|
48
|
-
sponsorAddress: AztecAddress;
|
|
49
|
-
/** */
|
|
50
|
-
deployL1ContractsValues: DeployAztecL1ContractsReturnType;
|
|
51
|
-
/** Cheat codes instance. */
|
|
52
|
-
cheatCodes: CheatCodes;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
37
|
export const uniswapL1L2TestSuite = (
|
|
56
|
-
setup: () => Promise<
|
|
38
|
+
setup: () => Promise<EndToEndContext>,
|
|
57
39
|
cleanup: () => Promise<void>,
|
|
58
40
|
expectedForkBlockNumber = 17514288,
|
|
59
41
|
) => {
|
|
@@ -90,8 +72,19 @@ export const uniswapL1L2TestSuite = (
|
|
|
90
72
|
let cheatCodes: CheatCodes;
|
|
91
73
|
let version: number;
|
|
92
74
|
beforeAll(async () => {
|
|
93
|
-
|
|
94
|
-
|
|
75
|
+
const t = await setup();
|
|
76
|
+
({
|
|
77
|
+
aztecNode,
|
|
78
|
+
logger,
|
|
79
|
+
deployL1ContractsValues,
|
|
80
|
+
cheatCodes,
|
|
81
|
+
wallet,
|
|
82
|
+
accounts: [ownerAddress, sponsorAddress],
|
|
83
|
+
} = t);
|
|
84
|
+
|
|
85
|
+
l1Client = deployL1ContractsValues.l1Client;
|
|
86
|
+
|
|
87
|
+
t.watcher?.setIsMarkingAsProven(false);
|
|
95
88
|
|
|
96
89
|
if (Number(await l1Client.getBlockNumber()) < expectedForkBlockNumber) {
|
|
97
90
|
throw new Error('This test must be run on a fork of mainnet with the expected fork block');
|
|
@@ -259,24 +252,19 @@ export const uniswapL1L2TestSuite = (
|
|
|
259
252
|
// ensure that uniswap contract didn't eat the funds.
|
|
260
253
|
await wethCrossChainHarness.expectPublicBalanceOnL2(uniswapL2Contract.address, 0n);
|
|
261
254
|
|
|
262
|
-
// Since the outbox is only consumable when the
|
|
263
|
-
|
|
255
|
+
// Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
|
|
256
|
+
const checkpointNumber = CheckpointNumber.fromBlockNumber(l2UniswapInteractionReceipt.blockNumber!);
|
|
257
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(checkpointNumber);
|
|
258
|
+
await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
259
|
+
await waitForProven(aztecNode, l2UniswapInteractionReceipt, { provenTimeout: 300 });
|
|
264
260
|
|
|
265
261
|
// 5. Consume L2 to L1 message by calling uniswapPortal.swap_private()
|
|
266
262
|
logger.info('Execute withdraw and swap on the uniswapPortal!');
|
|
267
263
|
const daiL1BalanceOfPortalBeforeSwap = await daiCrossChainHarness.getL1BalanceOf(
|
|
268
264
|
daiCrossChainHarness.tokenPortalAddress,
|
|
269
265
|
);
|
|
270
|
-
const swapResult = await computeL2ToL1MembershipWitness(
|
|
271
|
-
|
|
272
|
-
l2UniswapInteractionReceipt.blockNumber!,
|
|
273
|
-
swapPrivateLeaf,
|
|
274
|
-
);
|
|
275
|
-
const withdrawResult = await computeL2ToL1MembershipWitness(
|
|
276
|
-
aztecNode,
|
|
277
|
-
l2UniswapInteractionReceipt.blockNumber!,
|
|
278
|
-
withdrawLeaf,
|
|
279
|
-
);
|
|
266
|
+
const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
|
|
267
|
+
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
280
268
|
|
|
281
269
|
const swapPrivateL2MessageIndex = swapResult!.leafIndex;
|
|
282
270
|
const swapPrivateSiblingPath = swapResult!.siblingPath;
|
|
@@ -285,7 +273,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
285
273
|
const withdrawSiblingPath = withdrawResult!.siblingPath;
|
|
286
274
|
|
|
287
275
|
const withdrawMessageMetadata = {
|
|
288
|
-
|
|
276
|
+
_epoch: BigInt(epoch),
|
|
289
277
|
_leafIndex: BigInt(withdrawL2MessageIndex),
|
|
290
278
|
_path: withdrawSiblingPath
|
|
291
279
|
.toBufferArray()
|
|
@@ -293,7 +281,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
293
281
|
};
|
|
294
282
|
|
|
295
283
|
const swapPrivateMessageMetadata = {
|
|
296
|
-
|
|
284
|
+
_epoch: BigInt(epoch),
|
|
297
285
|
_leafIndex: BigInt(swapPrivateL2MessageIndex),
|
|
298
286
|
_path: swapPrivateSiblingPath
|
|
299
287
|
.toBufferArray()
|
|
@@ -504,7 +492,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
504
492
|
// );
|
|
505
493
|
|
|
506
494
|
// const withdrawMessageMetadata = {
|
|
507
|
-
//
|
|
495
|
+
// _epoch: epoch,
|
|
508
496
|
// _leafIndex: BigInt(withdrawL2MessageIndex),
|
|
509
497
|
// _path: withdrawSiblingPath
|
|
510
498
|
// .toBufferArray()
|
|
@@ -512,7 +500,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
512
500
|
// };
|
|
513
501
|
|
|
514
502
|
// const swapPrivateMessageMetadata = {
|
|
515
|
-
//
|
|
503
|
+
// _epoch: epoch,
|
|
516
504
|
// _leafIndex: BigInt(swapPrivateL2MessageIndex),
|
|
517
505
|
// _path: swapPrivateSiblingPath
|
|
518
506
|
// .toBufferArray()
|
|
@@ -856,12 +844,11 @@ export const uniswapL1L2TestSuite = (
|
|
|
856
844
|
chainId: new Fr(l1Client.chain.id),
|
|
857
845
|
});
|
|
858
846
|
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
aztecNode,
|
|
862
|
-
withdrawReceipt.blockNumber!,
|
|
863
|
-
withdrawLeaf,
|
|
847
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(
|
|
848
|
+
CheckpointNumber.fromBlockNumber(withdrawReceipt.blockNumber!),
|
|
864
849
|
);
|
|
850
|
+
const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPrivateLeaf);
|
|
851
|
+
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
865
852
|
|
|
866
853
|
const swapPrivateL2MessageIndex = swapResult!.leafIndex;
|
|
867
854
|
const swapPrivateSiblingPath = swapResult!.siblingPath;
|
|
@@ -870,7 +857,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
870
857
|
const withdrawSiblingPath = withdrawResult!.siblingPath;
|
|
871
858
|
|
|
872
859
|
const withdrawMessageMetadata = {
|
|
873
|
-
|
|
860
|
+
_epoch: BigInt(epoch),
|
|
874
861
|
_leafIndex: BigInt(withdrawL2MessageIndex),
|
|
875
862
|
_path: withdrawSiblingPath
|
|
876
863
|
.toBufferArray()
|
|
@@ -878,7 +865,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
878
865
|
};
|
|
879
866
|
|
|
880
867
|
const swapPrivateMessageMetadata = {
|
|
881
|
-
|
|
868
|
+
_epoch: BigInt(epoch),
|
|
882
869
|
_leafIndex: BigInt(swapPrivateL2MessageIndex),
|
|
883
870
|
_path: swapPrivateSiblingPath
|
|
884
871
|
.toBufferArray()
|
|
@@ -888,8 +875,9 @@ export const uniswapL1L2TestSuite = (
|
|
|
888
875
|
// ensure that user's funds were burnt
|
|
889
876
|
await wethCrossChainHarness.expectPrivateBalanceOnL2(ownerAddress, wethL2BalanceBeforeSwap - wethAmountToBridge);
|
|
890
877
|
|
|
891
|
-
// Since the outbox is only consumable when the
|
|
892
|
-
await cheatCodes.rollup.
|
|
878
|
+
// Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
|
|
879
|
+
await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
880
|
+
await waitForProven(aztecNode, withdrawReceipt, { provenTimeout: 300 });
|
|
893
881
|
|
|
894
882
|
// On L1 call swap_public!
|
|
895
883
|
logger.info('call swap_public on L1');
|
|
@@ -991,12 +979,11 @@ export const uniswapL1L2TestSuite = (
|
|
|
991
979
|
chainId: new Fr(l1Client.chain.id),
|
|
992
980
|
});
|
|
993
981
|
|
|
994
|
-
const
|
|
995
|
-
|
|
996
|
-
aztecNode,
|
|
997
|
-
withdrawReceipt.blockNumber!,
|
|
998
|
-
withdrawLeaf,
|
|
982
|
+
const epoch = await rollup.getEpochNumberForCheckpoint(
|
|
983
|
+
CheckpointNumber.fromBlockNumber(withdrawReceipt.blockNumber!),
|
|
999
984
|
);
|
|
985
|
+
const swapResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, swapPublicLeaf);
|
|
986
|
+
const withdrawResult = await computeL2ToL1MembershipWitness(aztecNode, epoch, withdrawLeaf);
|
|
1000
987
|
|
|
1001
988
|
const swapPublicL2MessageIndex = swapResult!.leafIndex;
|
|
1002
989
|
const swapPublicSiblingPath = swapResult!.siblingPath;
|
|
@@ -1005,7 +992,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
1005
992
|
const withdrawSiblingPath = withdrawResult!.siblingPath;
|
|
1006
993
|
|
|
1007
994
|
const withdrawMessageMetadata = {
|
|
1008
|
-
|
|
995
|
+
_epoch: BigInt(epoch),
|
|
1009
996
|
_leafIndex: BigInt(withdrawL2MessageIndex),
|
|
1010
997
|
_path: withdrawSiblingPath
|
|
1011
998
|
.toBufferArray()
|
|
@@ -1013,7 +1000,7 @@ export const uniswapL1L2TestSuite = (
|
|
|
1013
1000
|
};
|
|
1014
1001
|
|
|
1015
1002
|
const swapPublicMessageMetadata = {
|
|
1016
|
-
|
|
1003
|
+
_epoch: BigInt(epoch),
|
|
1017
1004
|
_leafIndex: BigInt(swapPublicL2MessageIndex),
|
|
1018
1005
|
_path: swapPublicSiblingPath
|
|
1019
1006
|
.toBufferArray()
|
|
@@ -1023,8 +1010,9 @@ export const uniswapL1L2TestSuite = (
|
|
|
1023
1010
|
// check weth balance of owner on L2 (we first bridged `wethAmountToBridge` into L2 and now withdrew it!)
|
|
1024
1011
|
await wethCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, 0n);
|
|
1025
1012
|
|
|
1026
|
-
// Since the outbox is only consumable when the
|
|
1027
|
-
await cheatCodes.rollup.
|
|
1013
|
+
// Since the outbox is only consumable when the epoch is proven, we need to advance to the next epoch.
|
|
1014
|
+
await cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
1015
|
+
await waitForProven(aztecNode, withdrawReceipt, { provenTimeout: 300 });
|
|
1028
1016
|
|
|
1029
1017
|
// Call swap_private on L1
|
|
1030
1018
|
logger.info('Execute withdraw and swap on the uniswapPortal!');
|
|
@@ -315,11 +315,17 @@ export async function performTransfers({
|
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
export type WalletWrapper = {
|
|
319
|
+
wallet: TestWallet;
|
|
320
|
+
aztecNode: AztecNode;
|
|
321
|
+
cleanup: () => Promise<void>;
|
|
322
|
+
};
|
|
323
|
+
|
|
318
324
|
export async function createWalletAndAztecNodeClient(
|
|
319
325
|
nodeUrl: string,
|
|
320
326
|
proverEnabled: boolean,
|
|
321
327
|
logger: Logger,
|
|
322
|
-
): Promise<
|
|
328
|
+
): Promise<WalletWrapper> {
|
|
323
329
|
const aztecNode = createAztecNodeClient(nodeUrl);
|
|
324
330
|
const [bbConfig, acvmConfig] = await Promise.all([getBBConfig(logger), getACVMConfig(logger)]);
|
|
325
331
|
const pxeConfig = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
2
|
-
import type {
|
|
2
|
+
import type { L2BlockNew } from '@aztec/stdlib/block';
|
|
3
|
+
import type { TopicType } from '@aztec/stdlib/p2p';
|
|
3
4
|
import { Tx, type TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
4
5
|
|
|
5
6
|
import { createHistogram } from 'perf_hooks';
|
|
@@ -19,7 +20,9 @@ export type TxInclusionData = {
|
|
|
19
20
|
export class TxInclusionMetrics {
|
|
20
21
|
private data = new Map<string, TxInclusionData>();
|
|
21
22
|
private groups = new Set<string>();
|
|
22
|
-
private blocks = new Map<number, Promise<
|
|
23
|
+
private blocks = new Map<number, Promise<L2BlockNew | undefined>>();
|
|
24
|
+
|
|
25
|
+
private p2pGossipLatencyByTopic: Partial<Record<TopicType, { p50: number; p95: number }>> = {};
|
|
23
26
|
|
|
24
27
|
constructor(private aztecNode: AztecNode) {}
|
|
25
28
|
|
|
@@ -48,10 +51,13 @@ export class TxInclusionMetrics {
|
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
if (!this.blocks.has(blockNumber)) {
|
|
51
|
-
this.blocks.set(blockNumber, this.aztecNode.getBlock(blockNumber)
|
|
54
|
+
this.blocks.set(blockNumber, this.aztecNode.getBlock(blockNumber));
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
const block = await this.blocks.get(blockNumber)!;
|
|
58
|
+
if (!block) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
55
61
|
const data = this.data.get(txHash.toString())!;
|
|
56
62
|
data.blocknumber = blockNumber;
|
|
57
63
|
data.minedAt = Number(block.header.globalVariables.timestamp);
|
|
@@ -71,7 +77,7 @@ export class TxInclusionMetrics {
|
|
|
71
77
|
} {
|
|
72
78
|
const histogram = createHistogram({});
|
|
73
79
|
for (const tx of this.data.values()) {
|
|
74
|
-
if (!tx.blocknumber || tx.group !== group) {
|
|
80
|
+
if (!tx.blocknumber || tx.group !== group || tx.minedAt === -1) {
|
|
75
81
|
continue;
|
|
76
82
|
}
|
|
77
83
|
|
|
@@ -101,6 +107,10 @@ export class TxInclusionMetrics {
|
|
|
101
107
|
};
|
|
102
108
|
}
|
|
103
109
|
|
|
110
|
+
public recordP2PGossipLatency(topicName: TopicType, p50: number, p95: number): void {
|
|
111
|
+
this.p2pGossipLatencyByTopic[topicName] = { p50, p95 };
|
|
112
|
+
}
|
|
113
|
+
|
|
104
114
|
toGithubActionBenchmarkJSON(): Array<{ name: string; unit: string; value: number; range?: number; extra?: string }> {
|
|
105
115
|
const data: Array<{ name: string; unit: string; value: number; range?: number; extra?: string }> = [];
|
|
106
116
|
for (const group of this.groups) {
|
|
@@ -125,6 +135,19 @@ export class TxInclusionMetrics {
|
|
|
125
135
|
);
|
|
126
136
|
}
|
|
127
137
|
|
|
138
|
+
for (const [topic, { p50, p95 }] of Object.entries(this.p2pGossipLatencyByTopic)) {
|
|
139
|
+
data.push({
|
|
140
|
+
name: `p2p_gossip_latency/${topic}/p50`,
|
|
141
|
+
unit: 'ms',
|
|
142
|
+
value: p50,
|
|
143
|
+
});
|
|
144
|
+
data.push({
|
|
145
|
+
name: `p2p_gossip_latency/${topic}/p95`,
|
|
146
|
+
unit: 'ms',
|
|
147
|
+
value: p95,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
128
151
|
return data;
|
|
129
152
|
}
|
|
130
153
|
}
|
package/src/spartan/utils.ts
CHANGED
|
@@ -34,6 +34,7 @@ const testConfigSchema = z.object({
|
|
|
34
34
|
AZTEC_SLOT_DURATION: z.coerce.number().optional().default(24),
|
|
35
35
|
AZTEC_EPOCH_DURATION: z.coerce.number().optional().default(32),
|
|
36
36
|
AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().optional().default(5),
|
|
37
|
+
AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: z.coerce.number().optional().default(2),
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
export type TestConfig = z.infer<typeof testConfigSchema>;
|
|
@@ -117,7 +118,7 @@ export async function startPortForward({
|
|
|
117
118
|
);
|
|
118
119
|
|
|
119
120
|
let isResolved = false;
|
|
120
|
-
const connected = new Promise<number>(resolve => {
|
|
121
|
+
const connected = new Promise<number>((resolve, reject) => {
|
|
121
122
|
process.stdout?.on('data', data => {
|
|
122
123
|
const str = data.toString() as string;
|
|
123
124
|
if (!isResolved && str.includes('Forwarding from')) {
|
|
@@ -125,7 +126,8 @@ export async function startPortForward({
|
|
|
125
126
|
logger.debug(`Port forward for ${resource}: ${str}`);
|
|
126
127
|
const port = str.search(/:\d+/);
|
|
127
128
|
if (port === -1) {
|
|
128
|
-
|
|
129
|
+
reject(new Error('Port not found in port forward output'));
|
|
130
|
+
return;
|
|
129
131
|
}
|
|
130
132
|
const portNumber = parseInt(str.slice(port + 1));
|
|
131
133
|
logger.verbose(`Port forwarded for ${resource} at ${portNumber}:${containerPort}`);
|
|
@@ -145,17 +147,26 @@ export async function startPortForward({
|
|
|
145
147
|
process.on('close', () => {
|
|
146
148
|
if (!isResolved) {
|
|
147
149
|
isResolved = true;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
const msg = `Port forward for ${resource} closed before connection established`;
|
|
151
|
+
logger.warn(msg);
|
|
152
|
+
reject(new Error(msg));
|
|
150
153
|
}
|
|
151
154
|
});
|
|
152
155
|
process.on('error', error => {
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
if (!isResolved) {
|
|
157
|
+
isResolved = true;
|
|
158
|
+
const msg = `Port forward for ${resource} error: ${error}`;
|
|
159
|
+
logger.error(msg);
|
|
160
|
+
reject(new Error(msg));
|
|
161
|
+
}
|
|
155
162
|
});
|
|
156
163
|
process.on('exit', code => {
|
|
157
|
-
|
|
158
|
-
|
|
164
|
+
if (!isResolved) {
|
|
165
|
+
isResolved = true;
|
|
166
|
+
const msg = `Port forward for ${resource} exited with code ${code}`;
|
|
167
|
+
logger.verbose(msg);
|
|
168
|
+
reject(new Error(msg));
|
|
169
|
+
}
|
|
159
170
|
});
|
|
160
171
|
});
|
|
161
172
|
|
|
@@ -197,6 +208,14 @@ export function getExternalIP(namespace: string, serviceName: string): Promise<s
|
|
|
197
208
|
return promise;
|
|
198
209
|
}
|
|
199
210
|
|
|
211
|
+
export function startPortForwardForPrometeheus(namespace: string) {
|
|
212
|
+
return startPortForward({
|
|
213
|
+
resource: `svc/${namespace}-prometheus-server`,
|
|
214
|
+
namespace,
|
|
215
|
+
containerPort: 80,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
200
219
|
export function startPortForwardForRPC(namespace: string, index = 0) {
|
|
201
220
|
return startPortForward({
|
|
202
221
|
resource: `pod/${namespace}-rpc-aztec-node-${index}`,
|
|
@@ -1089,24 +1108,93 @@ export async function getL1DeploymentAddresses(env: TestConfig): Promise<L1Contr
|
|
|
1089
1108
|
/**
|
|
1090
1109
|
* Rolls the Aztec pods in the given namespace.
|
|
1091
1110
|
* @param namespace - The namespace to roll the Aztec pods in.
|
|
1092
|
-
* @
|
|
1093
|
-
* This
|
|
1094
|
-
*
|
|
1111
|
+
* @param clearState - If true, also deletes the underlying PVCs to clear persistent storage.
|
|
1112
|
+
* This is required for rollup upgrades where the old state is incompatible with the new rollup.
|
|
1113
|
+
* Defaults to false, which preserves the existing storage.
|
|
1095
1114
|
*/
|
|
1096
|
-
export async function rollAztecPods(namespace: string) {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1115
|
+
export async function rollAztecPods(namespace: string, clearState: boolean = false) {
|
|
1116
|
+
// Pod components use 'validator', but StatefulSets and PVCs use 'sequencer-node' for validators
|
|
1117
|
+
const podComponents = ['p2p-bootstrap', 'prover-node', 'prover-broker', 'prover-agent', 'sequencer-node', 'rpc'];
|
|
1118
|
+
const pvcComponents = ['p2p-bootstrap', 'prover-node', 'prover-broker', 'sequencer-node', 'rpc'];
|
|
1119
|
+
// StatefulSet components that need to be scaled down before PVC deletion
|
|
1120
|
+
// Note: validators use 'sequencer-node' as component label, not 'validator'
|
|
1121
|
+
const statefulSetComponents = ['p2p-bootstrap', 'prover-node', 'prover-broker', 'sequencer-node', 'rpc'];
|
|
1122
|
+
|
|
1123
|
+
if (clearState) {
|
|
1124
|
+
// To delete PVCs, we must first scale down StatefulSets so pods release the volumes
|
|
1125
|
+
// Otherwise PVC deletion will hang waiting for pods to terminate
|
|
1126
|
+
|
|
1127
|
+
// First, save original replica counts
|
|
1128
|
+
const originalReplicas: Map<string, number> = new Map();
|
|
1129
|
+
for (const component of statefulSetComponents) {
|
|
1130
|
+
try {
|
|
1131
|
+
const getCmd = `kubectl get statefulset -l app.kubernetes.io/component=${component} -n ${namespace} -o jsonpath='{.items[0].spec.replicas}'`;
|
|
1132
|
+
const { stdout } = await execAsync(getCmd);
|
|
1133
|
+
const replicas = parseInt(stdout.replace(/'/g, '').trim(), 10);
|
|
1134
|
+
if (!isNaN(replicas) && replicas > 0) {
|
|
1135
|
+
originalReplicas.set(component, replicas);
|
|
1136
|
+
}
|
|
1137
|
+
} catch {
|
|
1138
|
+
// Component might not exist, continue
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// Scale down to 0
|
|
1143
|
+
for (const component of statefulSetComponents) {
|
|
1144
|
+
try {
|
|
1145
|
+
const scaleCmd = `kubectl scale statefulset -l app.kubernetes.io/component=${component} -n ${namespace} --replicas=0 --timeout=2m`;
|
|
1146
|
+
logger.info(`command: ${scaleCmd}`);
|
|
1147
|
+
await execAsync(scaleCmd);
|
|
1148
|
+
} catch (e) {
|
|
1149
|
+
// Component might not exist or might be a Deployment, continue
|
|
1150
|
+
logger.verbose(`Scale down ${component} skipped: ${e}`);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// Wait for pods to terminate
|
|
1155
|
+
await sleep(15 * 1000);
|
|
1156
|
+
|
|
1157
|
+
// Now delete PVCs (they should no longer be in use)
|
|
1158
|
+
for (const component of pvcComponents) {
|
|
1159
|
+
await deleteResourceByLabel({
|
|
1160
|
+
resource: 'persistentvolumeclaims',
|
|
1161
|
+
namespace: namespace,
|
|
1162
|
+
label: `app.kubernetes.io/component=${component}`,
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// Scale StatefulSets back up to original replica counts
|
|
1167
|
+
for (const component of statefulSetComponents) {
|
|
1168
|
+
const replicas = originalReplicas.get(component) ?? 1;
|
|
1169
|
+
try {
|
|
1170
|
+
const scaleCmd = `kubectl scale statefulset -l app.kubernetes.io/component=${component} -n ${namespace} --replicas=${replicas} --timeout=2m`;
|
|
1171
|
+
logger.info(`command: ${scaleCmd}`);
|
|
1172
|
+
await execAsync(scaleCmd);
|
|
1173
|
+
} catch (e) {
|
|
1174
|
+
logger.verbose(`Scale up ${component} skipped: ${e}`);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
} else {
|
|
1178
|
+
// Just delete pods (no state clearing)
|
|
1179
|
+
for (const component of podComponents) {
|
|
1180
|
+
await deleteResourceByLabel({
|
|
1181
|
+
resource: 'pods',
|
|
1182
|
+
namespace: namespace,
|
|
1183
|
+
label: `app.kubernetes.io/component=${component}`,
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1103
1188
|
await sleep(10 * 1000);
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1189
|
+
|
|
1190
|
+
// Wait for pods to come back
|
|
1191
|
+
for (const component of podComponents) {
|
|
1192
|
+
await waitForResourceByLabel({
|
|
1193
|
+
resource: 'pods',
|
|
1194
|
+
namespace: namespace,
|
|
1195
|
+
label: `app.kubernetes.io/component=${component}`,
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1110
1198
|
}
|
|
1111
1199
|
|
|
1112
1200
|
/**
|