@aztec/end-to-end 0.0.1-commit.96bb3f7 → 0.0.1-commit.993d240
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dest/bench/client_flows/benchmark.d.ts +17 -2
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/benchmark.js +38 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +14 -15
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +132 -150
- package/dest/bench/client_flows/config.d.ts +2 -2
- package/dest/bench/client_flows/config.d.ts.map +1 -1
- package/dest/bench/client_flows/config.js +18 -0
- package/dest/bench/utils.d.ts +6 -5
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +15 -8
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +12 -10
- 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 +120 -117
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +21 -11
- 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 +103 -67
- package/dest/e2e_deploy_contract/deploy_test.d.ts +6 -5
- package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
- package/dest/e2e_deploy_contract/deploy_test.js +20 -14
- package/dest/e2e_epochs/epochs_test.d.ts +39 -8
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +171 -50
- package/dest/e2e_fees/bridging_race.notest.js +3 -5
- package/dest/e2e_fees/fees_test.d.ts +18 -15
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +157 -142
- package/dest/e2e_l1_publisher/write_json.d.ts +4 -3
- package/dest/e2e_l1_publisher/write_json.d.ts.map +1 -1
- package/dest/e2e_l1_publisher/write_json.js +14 -13
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +7 -10
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +32 -41
- 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 +8 -6
- package/dest/e2e_p2p/p2p_network.d.ts +20 -17
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +166 -123
- package/dest/e2e_p2p/reqresp/utils.d.ts +22 -0
- package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -0
- package/dest/e2e_p2p/reqresp/utils.js +206 -0
- package/dest/e2e_p2p/shared.d.ts +30 -12
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +86 -66
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts +2 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.d.ts.map +1 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fetcher.js +184 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts +18 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.d.ts.map +1 -0
- package/dest/e2e_storage_proof/fixtures/storage_proof_fixture.js +120 -0
- package/dest/e2e_token_contract/token_contract_test.d.ts +20 -11
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +103 -93
- package/dest/fixtures/authwit_proxy.d.ts +15 -0
- package/dest/fixtures/authwit_proxy.d.ts.map +1 -0
- package/dest/fixtures/authwit_proxy.js +34 -0
- package/dest/fixtures/e2e_prover_test.d.ts +15 -20
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +115 -134
- package/dest/fixtures/elu_monitor.d.ts +21 -0
- package/dest/fixtures/elu_monitor.d.ts.map +1 -0
- package/dest/fixtures/elu_monitor.js +102 -0
- package/dest/fixtures/fixtures.d.ts +77 -1
- package/dest/fixtures/fixtures.d.ts.map +1 -1
- package/dest/fixtures/fixtures.js +74 -0
- package/dest/fixtures/get_bb_config.d.ts +1 -1
- package/dest/fixtures/get_bb_config.d.ts.map +1 -1
- package/dest/fixtures/get_bb_config.js +5 -5
- package/dest/fixtures/ha_setup.d.ts +71 -0
- package/dest/fixtures/ha_setup.d.ts.map +1 -0
- package/dest/fixtures/ha_setup.js +116 -0
- package/dest/fixtures/index.d.ts +2 -1
- package/dest/fixtures/index.d.ts.map +1 -1
- package/dest/fixtures/index.js +1 -0
- package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts +25 -0
- package/dest/fixtures/schnorr_hardcoded_account_contract.d.ts.map +1 -0
- package/dest/fixtures/schnorr_hardcoded_account_contract.js +37 -0
- package/dest/fixtures/setup.d.ts +266 -0
- package/dest/fixtures/setup.d.ts.map +1 -0
- package/dest/fixtures/setup.js +714 -0
- package/dest/fixtures/setup_p2p_test.d.ts +22 -11
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +43 -32
- package/dest/fixtures/token_utils.d.ts +2 -2
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +7 -6
- package/dest/fixtures/utils.d.ts +5 -191
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +4 -615
- package/dest/forward-compatibility/wallet_rpc_client.d.ts +7 -0
- package/dest/forward-compatibility/wallet_rpc_client.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_rpc_client.js +15 -0
- package/dest/forward-compatibility/wallet_service.d.ts +3 -0
- package/dest/forward-compatibility/wallet_service.d.ts.map +1 -0
- package/dest/forward-compatibility/wallet_service.js +109 -0
- package/dest/install_legacy_contracts.d.cts +10 -0
- package/dest/install_legacy_contracts.d.cts.map +1 -0
- package/dest/legacy-jest-resolver.d.cts +3 -0
- package/dest/legacy-jest-resolver.d.cts.map +1 -0
- 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 +17 -5
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +33 -29
- package/dest/shared/gas_portal_test_harness.d.ts +18 -5
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/gas_portal_test_harness.js +20 -11
- package/dest/shared/index.d.ts +2 -1
- package/dest/shared/index.d.ts.map +1 -1
- package/dest/shared/index.js +1 -0
- package/dest/shared/jest_setup.js +41 -1
- package/dest/shared/mock_state_view.d.ts +86 -0
- package/dest/shared/mock_state_view.d.ts.map +1 -0
- package/dest/shared/mock_state_view.js +186 -0
- package/dest/shared/submit-transactions.d.ts +4 -4
- package/dest/shared/submit-transactions.d.ts.map +1 -1
- package/dest/shared/submit-transactions.js +9 -11
- package/dest/shared/uniswap_l1_l2.d.ts +1 -1
- package/dest/shared/uniswap_l1_l2.d.ts.map +1 -1
- package/dest/shared/uniswap_l1_l2.js +73 -50
- package/dest/shared/wait_for_l1_to_l2_message.d.ts +13 -0
- package/dest/shared/wait_for_l1_to_l2_message.d.ts.map +1 -0
- package/dest/shared/wait_for_l1_to_l2_message.js +10 -0
- package/dest/simulators/lending_simulator.d.ts +14 -3
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +28 -16
- package/dest/simulators/token_simulator.d.ts +1 -1
- package/dest/simulators/token_simulator.d.ts.map +1 -1
- package/dest/simulators/token_simulator.js +3 -24
- package/dest/spartan/setup_test_wallets.d.ts +12 -3
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +133 -43
- package/dest/spartan/tx_metrics.d.ts +68 -5
- package/dest/spartan/tx_metrics.d.ts.map +1 -1
- package/dest/spartan/tx_metrics.js +399 -19
- package/dest/spartan/utils/bot.d.ts +28 -0
- package/dest/spartan/utils/bot.d.ts.map +1 -0
- package/dest/spartan/utils/bot.js +142 -0
- package/dest/spartan/utils/chaos.d.ts +79 -0
- package/dest/spartan/utils/chaos.d.ts.map +1 -0
- package/dest/spartan/utils/chaos.js +142 -0
- package/dest/spartan/utils/clients.d.ts +39 -0
- package/dest/spartan/utils/clients.d.ts.map +1 -0
- package/dest/spartan/utils/clients.js +90 -0
- package/dest/spartan/utils/config.d.ts +19 -0
- package/dest/spartan/utils/config.d.ts.map +1 -0
- package/dest/spartan/utils/config.js +23 -0
- package/dest/spartan/utils/health.d.ts +63 -0
- package/dest/spartan/utils/health.d.ts.map +1 -0
- package/dest/spartan/utils/health.js +202 -0
- package/dest/spartan/utils/helm.d.ts +15 -0
- package/dest/spartan/utils/helm.d.ts.map +1 -0
- package/dest/spartan/utils/helm.js +47 -0
- package/dest/spartan/utils/index.d.ts +11 -0
- package/dest/spartan/utils/index.d.ts.map +1 -0
- package/dest/spartan/utils/index.js +22 -0
- package/dest/spartan/utils/k8s.d.ts +128 -0
- package/dest/spartan/utils/k8s.d.ts.map +1 -0
- package/dest/spartan/utils/k8s.js +381 -0
- package/dest/spartan/utils/nodes.d.ts +40 -0
- package/dest/spartan/utils/nodes.d.ts.map +1 -0
- package/dest/spartan/utils/nodes.js +461 -0
- package/dest/spartan/utils/pod_logs.d.ts +25 -0
- package/dest/spartan/utils/pod_logs.d.ts.map +1 -0
- package/dest/spartan/utils/pod_logs.js +74 -0
- package/dest/spartan/utils/scripts.d.ts +30 -0
- package/dest/spartan/utils/scripts.d.ts.map +1 -0
- package/dest/spartan/utils/scripts.js +81 -0
- package/dest/spartan/utils.d.ts +2 -253
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +1 -892
- package/dest/test-wallet/test_wallet.d.ts +85 -0
- package/dest/test-wallet/test_wallet.d.ts.map +1 -0
- package/dest/test-wallet/test_wallet.js +273 -0
- package/dest/test-wallet/utils.d.ts +41 -0
- package/dest/test-wallet/utils.d.ts.map +1 -0
- package/dest/test-wallet/utils.js +66 -0
- package/dest/test-wallet/wallet_worker_script.d.ts +2 -0
- package/dest/test-wallet/wallet_worker_script.d.ts.map +1 -0
- package/dest/test-wallet/wallet_worker_script.js +48 -0
- package/dest/test-wallet/worker_wallet.d.ts +53 -0
- package/dest/test-wallet/worker_wallet.d.ts.map +1 -0
- package/dest/test-wallet/worker_wallet.js +155 -0
- package/dest/test-wallet/worker_wallet_schema.d.ts +160 -0
- package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -0
- package/dest/test-wallet/worker_wallet_schema.js +22 -0
- package/package.json +53 -45
- package/src/bench/client_flows/benchmark.ts +43 -2
- package/src/bench/client_flows/client_flows_benchmark.ts +189 -240
- package/src/bench/client_flows/config.ts +9 -1
- package/src/bench/utils.ts +17 -9
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +141 -152
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +144 -114
- package/src/e2e_deploy_contract/deploy_test.ts +24 -16
- package/src/e2e_epochs/epochs_test.ts +217 -93
- package/src/e2e_fees/bridging_race.notest.ts +4 -10
- package/src/e2e_fees/fees_test.ts +206 -227
- package/src/e2e_l1_publisher/write_json.ts +16 -13
- package/src/e2e_nested_contract/nested_contract_test.ts +38 -57
- package/src/e2e_p2p/inactivity_slash_test.ts +8 -6
- package/src/e2e_p2p/p2p_network.ts +238 -190
- package/src/e2e_p2p/reqresp/utils.ts +274 -0
- package/src/e2e_p2p/shared.ts +111 -83
- package/src/e2e_storage_proof/fixtures/storage_proof.json +915 -0
- package/src/e2e_storage_proof/fixtures/storage_proof_fetcher.ts +190 -0
- package/src/e2e_storage_proof/fixtures/storage_proof_fixture.ts +173 -0
- package/src/e2e_token_contract/token_contract_test.ts +129 -117
- package/src/fixtures/authwit_proxy.ts +54 -0
- package/src/fixtures/dumps/epoch_proof_result.json +1 -1
- package/src/fixtures/e2e_prover_test.ts +143 -184
- package/src/fixtures/elu_monitor.ts +126 -0
- package/src/fixtures/fixtures.ts +96 -0
- package/src/fixtures/get_bb_config.ts +7 -6
- package/src/fixtures/ha_setup.ts +188 -0
- package/src/fixtures/index.ts +1 -0
- package/src/fixtures/schnorr_hardcoded_account_contract.ts +49 -0
- package/src/fixtures/setup.ts +1037 -0
- package/src/fixtures/setup_p2p_test.ts +52 -52
- package/src/fixtures/token_utils.ts +7 -6
- package/src/fixtures/utils.ts +29 -901
- package/src/forward-compatibility/wallet_rpc_client.ts +14 -0
- package/src/forward-compatibility/wallet_service.ts +104 -0
- package/src/guides/up_quick_start.sh +3 -5
- package/src/install_legacy_contracts.cjs +75 -0
- package/src/legacy-jest-resolver.cjs +112 -0
- package/src/quality_of_service/prometheus_client.ts +113 -0
- package/src/shared/cross_chain_test_harness.ts +38 -38
- package/src/shared/gas_portal_test_harness.ts +22 -12
- package/src/shared/index.ts +1 -0
- package/src/shared/jest_setup.ts +51 -1
- package/src/shared/mock_state_view.ts +188 -0
- package/src/shared/submit-transactions.ts +11 -16
- package/src/shared/uniswap_l1_l2.ts +91 -73
- package/src/shared/wait_for_l1_to_l2_message.ts +23 -0
- package/src/simulators/lending_simulator.ts +34 -16
- package/src/simulators/token_simulator.ts +6 -30
- package/src/spartan/setup_test_wallets.ts +184 -28
- package/src/spartan/tx_metrics.ts +329 -25
- package/src/spartan/utils/bot.ts +188 -0
- package/src/spartan/utils/chaos.ts +253 -0
- package/src/spartan/utils/clients.ts +100 -0
- package/src/spartan/utils/config.ts +29 -0
- package/src/spartan/utils/health.ts +255 -0
- package/src/spartan/utils/helm.ts +84 -0
- package/src/spartan/utils/index.ts +71 -0
- package/src/spartan/utils/k8s.ts +535 -0
- package/src/spartan/utils/nodes.ts +543 -0
- package/src/spartan/utils/pod_logs.ts +99 -0
- package/src/spartan/utils/scripts.ts +99 -0
- package/src/spartan/utils.ts +1 -1158
- package/src/test-wallet/test_wallet.ts +376 -0
- package/src/test-wallet/utils.ts +108 -0
- package/src/test-wallet/wallet_worker_script.ts +60 -0
- package/src/test-wallet/worker_wallet.ts +218 -0
- package/src/test-wallet/worker_wallet_schema.ts +13 -0
- 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 -488
- package/src/fixtures/snapshot_manager.ts +0 -646
|
@@ -2,11 +2,11 @@ import { computeSecretHash } from '@aztec/aztec.js/crypto';
|
|
|
2
2
|
import { Fr } from '@aztec/aztec.js/fields';
|
|
3
3
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
4
4
|
import { TokenBlacklistContract } from '@aztec/noir-contracts.js/TokenBlacklist';
|
|
5
|
+
import { GenericProxyContract } from '@aztec/noir-test-contracts.js/GenericProxy';
|
|
5
6
|
import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount';
|
|
6
7
|
import { jest } from '@jest/globals';
|
|
7
|
-
import {
|
|
8
|
+
import { deployAccounts, ensureAuthRegistryPublished, publicDeployAccounts, setup, teardown } from '../fixtures/setup.js';
|
|
8
9
|
import { TokenSimulator } from '../simulators/token_simulator.js';
|
|
9
|
-
const { E2E_DATA_PATH: dataPath } = process.env;
|
|
10
10
|
export class Role {
|
|
11
11
|
isAdmin = false;
|
|
12
12
|
isMinter = false;
|
|
@@ -36,12 +36,13 @@ export class Role {
|
|
|
36
36
|
export class BlacklistTokenContractTest {
|
|
37
37
|
// This value MUST match the same value that we have in the contract
|
|
38
38
|
static CHANGE_ROLES_DELAY = 86400;
|
|
39
|
-
|
|
39
|
+
context;
|
|
40
40
|
logger;
|
|
41
41
|
wallet;
|
|
42
42
|
asset;
|
|
43
43
|
tokenSim;
|
|
44
44
|
badAccount;
|
|
45
|
+
authwitProxy;
|
|
45
46
|
cheatCodes;
|
|
46
47
|
sequencer;
|
|
47
48
|
aztecNode;
|
|
@@ -50,136 +51,138 @@ export class BlacklistTokenContractTest {
|
|
|
50
51
|
blacklistedAddress;
|
|
51
52
|
constructor(testName){
|
|
52
53
|
this.logger = createLogger(`e2e:e2e_blacklist_token_contract:${testName}`);
|
|
53
|
-
this.snapshotManager = createSnapshotManager(`e2e_blacklist_token_contract/${testName}`, dataPath);
|
|
54
54
|
}
|
|
55
55
|
async crossTimestampOfChange() {
|
|
56
|
-
|
|
56
|
+
// Under AUTOMINE_E2E_OPTS, the 86400s warp crosses many epochs without any proofs being
|
|
57
|
+
// submitted. Mark current pending checkpoints as proven first so the rollup contract's
|
|
58
|
+
// pruning window doesn't reset the chain tip to genesis (which would make the warp's
|
|
59
|
+
// own empty-checkpoint propose fail with Rollup__InvalidArchive). See the AutomineSequencer
|
|
60
|
+
// README "Epoch proving caveat" and the equivalent pattern in lending_simulator.progressSlots.
|
|
61
|
+
await this.cheatCodes.rollup.markAsProven();
|
|
62
|
+
await this.cheatCodes.warpL2TimeAtLeastBy(this.aztecNode, BlacklistTokenContractTest.CHANGE_ROLES_DELAY);
|
|
57
63
|
}
|
|
58
64
|
/**
|
|
59
|
-
*
|
|
65
|
+
* Applies base setup:
|
|
60
66
|
* 1. Add 3 accounts.
|
|
61
67
|
* 2. Publicly deploy accounts, deploy token contract and a "bad account".
|
|
62
|
-
*/ async
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
70
|
-
this.adminAddress = deployedAccounts[0].address;
|
|
71
|
-
this.otherAddress = deployedAccounts[1].address;
|
|
72
|
-
this.blacklistedAddress = deployedAccounts[2].address;
|
|
73
|
-
return Promise.resolve();
|
|
74
|
-
});
|
|
75
|
-
await this.snapshotManager.snapshot('e2e_blacklist_token_contract', async ()=>{
|
|
76
|
-
// Create the token contract state.
|
|
77
|
-
// Move this account thing to addAccounts above?
|
|
78
|
-
this.logger.verbose(`Public deploy accounts...`);
|
|
79
|
-
await publicDeployAccounts(this.wallet, [
|
|
80
|
-
this.adminAddress,
|
|
81
|
-
this.otherAddress,
|
|
82
|
-
this.blacklistedAddress
|
|
83
|
-
]);
|
|
84
|
-
this.logger.verbose(`Deploying TokenContract...`);
|
|
85
|
-
this.asset = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress).send({
|
|
86
|
-
from: this.adminAddress
|
|
87
|
-
}).deployed();
|
|
88
|
-
this.logger.verbose(`Token deployed to ${this.asset.address}`);
|
|
89
|
-
this.logger.verbose(`Deploying bad account...`);
|
|
90
|
-
this.badAccount = await InvalidAccountContract.deploy(this.wallet).send({
|
|
91
|
-
from: this.adminAddress
|
|
92
|
-
}).deployed();
|
|
93
|
-
this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
|
|
94
|
-
await this.crossTimestampOfChange();
|
|
95
|
-
return {
|
|
96
|
-
tokenContractAddress: this.asset.address,
|
|
97
|
-
badAccountAddress: this.badAccount.address
|
|
98
|
-
};
|
|
99
|
-
}, async ({ tokenContractAddress, badAccountAddress })=>{
|
|
100
|
-
// Restore the token contract state.
|
|
101
|
-
this.asset = TokenBlacklistContract.at(tokenContractAddress, this.wallet);
|
|
102
|
-
this.logger.verbose(`Token contract address: ${this.asset.address}`);
|
|
103
|
-
this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [
|
|
104
|
-
this.adminAddress,
|
|
105
|
-
this.otherAddress,
|
|
106
|
-
this.blacklistedAddress
|
|
107
|
-
]);
|
|
108
|
-
this.badAccount = InvalidAccountContract.at(badAccountAddress, this.wallet);
|
|
109
|
-
this.logger.verbose(`Bad account address: ${this.badAccount.address}`);
|
|
110
|
-
expect(await this.asset.methods.get_roles(this.adminAddress).simulate({
|
|
111
|
-
from: this.adminAddress
|
|
112
|
-
})).toEqual(new Role().withAdmin().toNoirStruct());
|
|
68
|
+
*/ async applyBaseSetup() {
|
|
69
|
+
// Bumped from 2 min: pipelined cadence (~24s/dependent-tx) makes the 3-account deploy plus token/bad-account/
|
|
70
|
+
// proxy deploys exceed the original window.
|
|
71
|
+
jest.setTimeout(600_000);
|
|
72
|
+
this.logger.info('Deploying 3 accounts');
|
|
73
|
+
const { deployedAccounts } = await deployAccounts(3, this.logger)({
|
|
74
|
+
wallet: this.context.wallet,
|
|
75
|
+
initialFundedAccounts: this.context.initialFundedAccounts
|
|
113
76
|
});
|
|
77
|
+
this.cheatCodes = this.context.cheatCodes;
|
|
78
|
+
this.aztecNode = this.context.aztecNodeService;
|
|
79
|
+
this.sequencer = this.context.sequencer;
|
|
80
|
+
this.wallet = this.context.wallet;
|
|
81
|
+
this.adminAddress = deployedAccounts[0].address;
|
|
82
|
+
this.otherAddress = deployedAccounts[1].address;
|
|
83
|
+
this.blacklistedAddress = deployedAccounts[2].address;
|
|
84
|
+
this.logger.info('Setting up blacklist token contract');
|
|
85
|
+
await ensureAuthRegistryPublished(this.wallet, this.adminAddress);
|
|
86
|
+
// Create the token contract state.
|
|
87
|
+
this.logger.verbose(`Public deploy accounts...`);
|
|
88
|
+
await publicDeployAccounts(this.wallet, [
|
|
89
|
+
this.adminAddress,
|
|
90
|
+
this.otherAddress,
|
|
91
|
+
this.blacklistedAddress
|
|
92
|
+
]);
|
|
93
|
+
this.logger.verbose(`Deploying TokenContract...`);
|
|
94
|
+
({ contract: this.asset } = await TokenBlacklistContract.deploy(this.wallet, this.adminAddress).send({
|
|
95
|
+
from: this.adminAddress
|
|
96
|
+
}));
|
|
97
|
+
this.logger.verbose(`Token deployed to ${this.asset.address}`);
|
|
98
|
+
this.logger.verbose(`Deploying bad account...`);
|
|
99
|
+
({ contract: this.badAccount } = await InvalidAccountContract.deploy(this.wallet).send({
|
|
100
|
+
from: this.adminAddress
|
|
101
|
+
}));
|
|
102
|
+
this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
|
|
103
|
+
// Deploy a proxy contract for "on behalf of other" tests. The note owner must be the tx sender
|
|
104
|
+
// (so their notes are in scope), but msg_sender in the target must differ from the note owner
|
|
105
|
+
// to trigger authwit validation. The proxy forwards calls so that msg_sender != tx sender.
|
|
106
|
+
this.logger.verbose(`Deploying generic proxy...`);
|
|
107
|
+
({ contract: this.authwitProxy } = await GenericProxyContract.deploy(this.wallet).send({
|
|
108
|
+
from: this.adminAddress
|
|
109
|
+
}));
|
|
110
|
+
this.logger.verbose(`Deployed to ${this.authwitProxy.address}.`);
|
|
111
|
+
await this.crossTimestampOfChange();
|
|
112
|
+
this.tokenSim = new TokenSimulator(this.asset, this.wallet, this.adminAddress, this.logger, [
|
|
113
|
+
this.adminAddress,
|
|
114
|
+
this.otherAddress,
|
|
115
|
+
this.blacklistedAddress
|
|
116
|
+
]);
|
|
117
|
+
expect((await this.asset.methods.get_roles(this.adminAddress).simulate({
|
|
118
|
+
from: this.adminAddress
|
|
119
|
+
})).result).toEqual(new Role().withAdmin().toNoirStruct());
|
|
114
120
|
}
|
|
115
|
-
async setup() {
|
|
116
|
-
|
|
121
|
+
async setup(opts = {}) {
|
|
122
|
+
this.logger.info('Setting up fresh context');
|
|
123
|
+
this.context = await setup(0, {
|
|
124
|
+
...opts,
|
|
125
|
+
fundSponsoredFPC: true,
|
|
126
|
+
skipAccountDeployment: true
|
|
127
|
+
});
|
|
128
|
+
await this.applyBaseSetup();
|
|
117
129
|
}
|
|
118
|
-
snapshot = (name, apply, restore = ()=>Promise.resolve())=>this.snapshotManager.snapshot(name, apply, restore);
|
|
119
130
|
async teardown() {
|
|
120
|
-
await this.
|
|
131
|
+
await teardown(this.context);
|
|
121
132
|
}
|
|
122
133
|
async addPendingShieldNoteToPXE(contract, recipient, amount, secretHash, txHash) {
|
|
123
134
|
const txEffects = await this.aztecNode.getTxEffect(txHash);
|
|
124
|
-
await contract.methods.
|
|
135
|
+
await contract.methods.process_transparent_note(contract.address, amount, secretHash, txHash.hash, txEffects.data.noteHashes, txEffects.data.nullifiers[0], recipient).simulate({
|
|
125
136
|
from: recipient
|
|
126
137
|
});
|
|
127
138
|
}
|
|
128
|
-
async
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
from: this.adminAddress
|
|
174
|
-
});
|
|
175
|
-
this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
|
|
176
|
-
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(this.adminAddress));
|
|
177
|
-
const totalSupply = await asset.methods.total_supply().simulate({
|
|
178
|
-
from: this.adminAddress
|
|
179
|
-
});
|
|
180
|
-
this.logger.verbose(`Total supply: ${totalSupply}`);
|
|
181
|
-
expect(totalSupply).toEqual(tokenSim.totalSupply);
|
|
182
|
-
return Promise.resolve();
|
|
139
|
+
async applyMint() {
|
|
140
|
+
this.logger.info('Applying mint setup');
|
|
141
|
+
const { asset, tokenSim } = this;
|
|
142
|
+
const amount = 10000n;
|
|
143
|
+
const adminMinterRole = new Role().withAdmin().withMinter();
|
|
144
|
+
await this.asset.methods.update_roles(this.adminAddress, adminMinterRole.toNoirStruct()).send({
|
|
145
|
+
from: this.adminAddress
|
|
146
|
+
});
|
|
147
|
+
const blacklistRole = new Role().withBlacklisted();
|
|
148
|
+
await this.asset.methods.update_roles(this.blacklistedAddress, blacklistRole.toNoirStruct()).send({
|
|
149
|
+
from: this.adminAddress
|
|
150
|
+
});
|
|
151
|
+
await this.crossTimestampOfChange();
|
|
152
|
+
expect((await this.asset.methods.get_roles(this.adminAddress).simulate({
|
|
153
|
+
from: this.adminAddress
|
|
154
|
+
})).result).toEqual(adminMinterRole.toNoirStruct());
|
|
155
|
+
this.logger.verbose(`Minting ${amount} publicly...`);
|
|
156
|
+
await asset.methods.mint_public(this.adminAddress, amount).send({
|
|
157
|
+
from: this.adminAddress
|
|
158
|
+
});
|
|
159
|
+
this.logger.verbose(`Minting ${amount} privately...`);
|
|
160
|
+
const secret = Fr.random();
|
|
161
|
+
const secretHash = await computeSecretHash(secret);
|
|
162
|
+
const { receipt } = await asset.methods.mint_private(amount, secretHash).send({
|
|
163
|
+
from: this.adminAddress
|
|
164
|
+
});
|
|
165
|
+
await this.addPendingShieldNoteToPXE(asset, this.adminAddress, amount, secretHash, receipt.txHash);
|
|
166
|
+
await asset.methods.redeem_shield(this.adminAddress, amount, secret).send({
|
|
167
|
+
from: this.adminAddress
|
|
168
|
+
});
|
|
169
|
+
this.logger.verbose(`Minting complete.`);
|
|
170
|
+
tokenSim.mintPublic(this.adminAddress, amount);
|
|
171
|
+
const { result: publicBalance } = await asset.methods.balance_of_public(this.adminAddress).simulate({
|
|
172
|
+
from: this.adminAddress
|
|
173
|
+
});
|
|
174
|
+
this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
|
|
175
|
+
expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(this.adminAddress));
|
|
176
|
+
tokenSim.mintPrivate(this.adminAddress, amount);
|
|
177
|
+
const { result: privateBalance } = await asset.methods.balance_of_private(this.adminAddress).simulate({
|
|
178
|
+
from: this.adminAddress
|
|
179
|
+
});
|
|
180
|
+
this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
|
|
181
|
+
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(this.adminAddress));
|
|
182
|
+
const { result: totalSupply } = await asset.methods.total_supply().simulate({
|
|
183
|
+
from: this.adminAddress
|
|
183
184
|
});
|
|
185
|
+
this.logger.verbose(`Total supply: ${totalSupply}`);
|
|
186
|
+
expect(totalSupply).toEqual(tokenSim.totalSupply);
|
|
184
187
|
}
|
|
185
188
|
}
|
|
@@ -3,26 +3,28 @@ import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses';
|
|
|
3
3
|
import { type Logger } from '@aztec/aztec.js/log';
|
|
4
4
|
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
5
5
|
import type { TxReceipt } from '@aztec/aztec.js/tx';
|
|
6
|
-
import { CheatCodes } from '@aztec/aztec/testing';
|
|
6
|
+
import { CheatCodes, EpochTestSettler } from '@aztec/aztec/testing';
|
|
7
7
|
import { InboxContract, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
8
8
|
import type { DeployAztecL1ContractsArgs, DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts';
|
|
9
9
|
import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
|
|
10
10
|
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
11
11
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
12
12
|
import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
|
|
13
|
+
import type { PXEConfig } from '@aztec/pxe/server';
|
|
13
14
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
14
|
-
import type
|
|
15
|
-
import { type SubsystemsContext } from '../fixtures/snapshot_manager.js';
|
|
16
|
-
import type { SetupOptions } from '../fixtures/utils.js';
|
|
15
|
+
import { type EndToEndContext, type SetupOptions } from '../fixtures/setup.js';
|
|
17
16
|
import { CrossChainTestHarness } from '../shared/cross_chain_test_harness.js';
|
|
17
|
+
import type { TestWallet } from '../test-wallet/test_wallet.js';
|
|
18
18
|
export declare class CrossChainMessagingTest {
|
|
19
|
-
private snapshotManager;
|
|
20
19
|
private requireEpochProven;
|
|
20
|
+
private setupOptions;
|
|
21
|
+
private deployL1ContractsArgs;
|
|
22
|
+
private pxeOpts;
|
|
21
23
|
logger: Logger;
|
|
24
|
+
context: EndToEndContext;
|
|
22
25
|
aztecNode: AztecNode;
|
|
23
26
|
aztecNodeConfig: AztecNodeConfig;
|
|
24
27
|
aztecNodeAdmin: AztecNodeAdmin;
|
|
25
|
-
ctx: SubsystemsContext;
|
|
26
28
|
l1Client: ExtendedViemWalletClient | undefined;
|
|
27
29
|
wallet: TestWallet;
|
|
28
30
|
ownerAddress: AztecAddress;
|
|
@@ -36,13 +38,21 @@ export declare class CrossChainMessagingTest {
|
|
|
36
38
|
inbox: InboxContract;
|
|
37
39
|
outbox: OutboxContract;
|
|
38
40
|
cheatCodes: CheatCodes;
|
|
41
|
+
/**
|
|
42
|
+
* Background loop that marks each completed epoch as proven on L1. Started in `applyBaseSetup`
|
|
43
|
+
* when the test runs without a real prover node, because the e2e fixture uses L1 interval mining
|
|
44
|
+
* and the AnvilTestWatcher's auto-prove loop only runs under L1 automine. Without this, L1's
|
|
45
|
+
* `aztecProofSubmissionEpochs` window expires mid-test and triggers a chain prune that drops
|
|
46
|
+
* in-flight wallet txs. Tests that intentionally pause proving (e.g. inbox drift tests) can
|
|
47
|
+
* stop it via `await t.epochTestSettler?.stop()`.
|
|
48
|
+
*/
|
|
49
|
+
epochTestSettler?: EpochTestSettler;
|
|
39
50
|
deployL1ContractsValues: DeployAztecL1ContractsReturnType;
|
|
40
|
-
constructor(testName: string, opts?: SetupOptions, deployL1ContractsArgs?: Partial<DeployAztecL1ContractsArgs>);
|
|
41
|
-
setup(): Promise<void>;
|
|
51
|
+
constructor(testName: string, opts?: SetupOptions, deployL1ContractsArgs?: Partial<DeployAztecL1ContractsArgs>, pxeOpts?: Partial<PXEConfig>);
|
|
52
|
+
setup(opts?: Partial<SetupOptions>, pxeOpts?: Partial<PXEConfig>): Promise<void>;
|
|
42
53
|
advanceToEpochProven(l2TxReceipt: TxReceipt): Promise<EpochNumber>;
|
|
43
54
|
catchUpProvenChain(): Promise<void>;
|
|
44
|
-
snapshot: <T>(name: string, apply: (context: SubsystemsContext) => Promise<T>, restore?: (snapshotData: T, context: SubsystemsContext) => Promise<void>) => Promise<void>;
|
|
45
55
|
teardown(): Promise<void>;
|
|
46
|
-
|
|
56
|
+
applyBaseSetup(): Promise<void>;
|
|
47
57
|
}
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3Jvc3NfY2hhaW5fbWVzc2FnaW5nX3Rlc3QuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lMmVfY3Jvc3NfY2hhaW5fbWVzc2FnaW5nL2Nyb3NzX2NoYWluX21lc3NhZ2luZ190ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckUsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHFCQUFxQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVwRSxPQUFPLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRixPQUFPLEtBQUssRUFDViwwQkFBMEIsRUFDMUIsZ0NBQWdDLEVBQ2pDLE1BQU0sMkNBQTJDLENBQUM7QUFHbkQsT0FBTyxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN0RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFHOUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQy9ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzNFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBR3RFLE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxZQUFZLEVBTWxCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDOUUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFaEUscUJBQWEsdUJBQXVCO0lBQ2xDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBVTtJQUNwQyxPQUFPLENBQUMsWUFBWSxDQUFlO0lBQ25DLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBc0M7SUFDbkUsT0FBTyxDQUFDLE9BQU8sQ0FBcUI7SUFDcEMsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLE9BQU8sRUFBRyxlQUFlLENBQUM7SUFDMUIsU0FBUyxFQUFHLFNBQVMsQ0FBQztJQUN0QixlQUFlLEVBQUcsZUFBZSxDQUFDO0lBQ2xDLGNBQWMsRUFBRyxjQUFjLENBQUM7SUFFaEMsUUFBUSxFQUFHLHdCQUF3QixHQUFHLFNBQVMsQ0FBQztJQUVoRCxNQUFNLEVBQUcsVUFBVSxDQUFDO0lBQ3BCLFlBQVksRUFBRyxZQUFZLENBQUM7SUFDNUIsWUFBWSxFQUFHLFlBQVksQ0FBQztJQUM1QixZQUFZLEVBQUcsWUFBWSxDQUFDO0lBQzVCLHFCQUFxQixFQUFHLHFCQUFxQixDQUFDO0lBQzlDLFVBQVUsRUFBRyxVQUFVLENBQUM7SUFDeEIsT0FBTyxFQUFHLGFBQWEsQ0FBQztJQUN4QixRQUFRLEVBQUcsbUJBQW1CLENBQUM7SUFFL0IsTUFBTSxFQUFHLGNBQWMsQ0FBQztJQUN4QixLQUFLLEVBQUcsYUFBYSxDQUFDO0lBQ3RCLE1BQU0sRUFBRyxjQUFjLENBQUM7SUFDeEIsVUFBVSxFQUFHLFVBQVUsQ0FBQztJQUV4Qjs7Ozs7OztPQU9HO0lBQ0gsZ0JBQWdCLENBQUMsRUFBRSxnQkFBZ0IsQ0FBQztJQUVwQyx1QkFBdUIsRUFBRyxnQ0FBZ0MsQ0FBQztJQUUzRCxZQUNFLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLElBQUksR0FBRSxZQUFpQixFQUN2QixxQkFBcUIsR0FBRSxPQUFPLENBQUMsMEJBQTBCLENBQU0sRUFDL0QsT0FBTyxHQUFFLE9BQU8sQ0FBQyxTQUFTLENBQU0sRUFVakM7SUFFSyxLQUFLLENBQUMsSUFBSSxHQUFFLE9BQU8sQ0FBQyxZQUFZLENBQU0sRUFBRSxPQUFPLEdBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBTSxpQkFnQjdFO0lBRUssb0JBQW9CLENBQUMsV0FBVyxFQUFFLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBU3ZFO0lBRUssa0JBQWtCLGtCQUt2QjtJQUVLLFFBQVEsa0JBR2I7SUFFSyxjQUFjLGtCQWdHbkI7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross_chain_messaging_test.d.ts","sourceRoot":"","sources":["../../src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cross_chain_messaging_test.d.ts","sourceRoot":"","sources":["../../src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,KAAK,EACV,0BAA0B,EAC1B,gCAAgC,EACjC,MAAM,2CAA2C,CAAC;AAGnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGtE,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EAMlB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,qBAAa,uBAAuB;IAClC,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,qBAAqB,CAAsC;IACnE,OAAO,CAAC,OAAO,CAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAG,eAAe,CAAC;IAC1B,SAAS,EAAG,SAAS,CAAC;IACtB,eAAe,EAAG,eAAe,CAAC;IAClC,cAAc,EAAG,cAAc,CAAC;IAEhC,QAAQ,EAAG,wBAAwB,GAAG,SAAS,CAAC;IAEhD,MAAM,EAAG,UAAU,CAAC;IACpB,YAAY,EAAG,YAAY,CAAC;IAC5B,YAAY,EAAG,YAAY,CAAC;IAC5B,YAAY,EAAG,YAAY,CAAC;IAC5B,qBAAqB,EAAG,qBAAqB,CAAC;IAC9C,UAAU,EAAG,UAAU,CAAC;IACxB,OAAO,EAAG,aAAa,CAAC;IACxB,QAAQ,EAAG,mBAAmB,CAAC;IAE/B,MAAM,EAAG,cAAc,CAAC;IACxB,KAAK,EAAG,aAAa,CAAC;IACtB,MAAM,EAAG,cAAc,CAAC;IACxB,UAAU,EAAG,UAAU,CAAC;IAExB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAEpC,uBAAuB,EAAG,gCAAgC,CAAC;IAE3D,YACE,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,YAAiB,EACvB,qBAAqB,GAAE,OAAO,CAAC,0BAA0B,CAAM,EAC/D,OAAO,GAAE,OAAO,CAAC,SAAS,CAAM,EAUjC;IAEK,KAAK,CAAC,IAAI,GAAE,OAAO,CAAC,YAAY,CAAM,EAAE,OAAO,GAAE,OAAO,CAAC,SAAS,CAAM,iBAgB7E;IAEK,oBAAoB,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CASvE;IAEK,kBAAkB,kBAKvB;IAEK,QAAQ,kBAGb;IAEK,cAAc,kBAgGnB;CACF"}
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/aztec.js/addresses';
|
|
2
2
|
import { waitForProven } from '@aztec/aztec.js/contracts';
|
|
3
3
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
4
|
+
import { EpochTestSettler } from '@aztec/aztec/testing';
|
|
4
5
|
import { createExtendedL1Client } from '@aztec/ethereum/client';
|
|
5
6
|
import { InboxContract, OutboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
6
7
|
import { deployL1Contract } from '@aztec/ethereum/deploy-l1-contract';
|
|
7
|
-
import {
|
|
8
|
+
import { pickL1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
9
|
+
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
8
10
|
import { sleep } from '@aztec/foundation/sleep';
|
|
9
11
|
import { TestERC20Abi, TestERC20Bytecode } from '@aztec/l1-artifacts';
|
|
10
12
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
11
13
|
import { TokenBridgeContract } from '@aztec/noir-contracts.js/TokenBridge';
|
|
12
14
|
import { MNEMONIC } from '../fixtures/fixtures.js';
|
|
13
|
-
import {
|
|
15
|
+
import { deployAccounts, ensureAuthRegistryPublished, publicDeployAccounts, setup, teardown } from '../fixtures/setup.js';
|
|
14
16
|
import { CrossChainTestHarness } from '../shared/cross_chain_test_harness.js';
|
|
15
|
-
const { E2E_DATA_PATH: dataPath } = process.env;
|
|
16
17
|
export class CrossChainMessagingTest {
|
|
17
|
-
snapshotManager;
|
|
18
18
|
requireEpochProven;
|
|
19
|
+
setupOptions;
|
|
20
|
+
deployL1ContractsArgs;
|
|
21
|
+
pxeOpts;
|
|
19
22
|
logger;
|
|
23
|
+
context;
|
|
20
24
|
aztecNode;
|
|
21
25
|
aztecNodeConfig;
|
|
22
26
|
aztecNodeAdmin;
|
|
23
|
-
ctx;
|
|
24
27
|
l1Client;
|
|
25
28
|
wallet;
|
|
26
29
|
ownerAddress;
|
|
@@ -34,30 +37,47 @@ export class CrossChainMessagingTest {
|
|
|
34
37
|
inbox;
|
|
35
38
|
outbox;
|
|
36
39
|
cheatCodes;
|
|
40
|
+
/**
|
|
41
|
+
* Background loop that marks each completed epoch as proven on L1. Started in `applyBaseSetup`
|
|
42
|
+
* when the test runs without a real prover node, because the e2e fixture uses L1 interval mining
|
|
43
|
+
* and the AnvilTestWatcher's auto-prove loop only runs under L1 automine. Without this, L1's
|
|
44
|
+
* `aztecProofSubmissionEpochs` window expires mid-test and triggers a chain prune that drops
|
|
45
|
+
* in-flight wallet txs. Tests that intentionally pause proving (e.g. inbox drift tests) can
|
|
46
|
+
* stop it via `await t.epochTestSettler?.stop()`.
|
|
47
|
+
*/ epochTestSettler;
|
|
37
48
|
deployL1ContractsValues;
|
|
38
|
-
constructor(testName, opts = {}, deployL1ContractsArgs = {}){
|
|
49
|
+
constructor(testName, opts = {}, deployL1ContractsArgs = {}, pxeOpts = {}){
|
|
39
50
|
this.logger = createLogger(`e2e:e2e_cross_chain_messaging:${testName}`);
|
|
40
|
-
this.
|
|
51
|
+
this.setupOptions = opts;
|
|
52
|
+
this.deployL1ContractsArgs = {
|
|
41
53
|
initialValidators: [],
|
|
42
54
|
...deployL1ContractsArgs
|
|
43
|
-
}
|
|
55
|
+
};
|
|
56
|
+
this.pxeOpts = pxeOpts;
|
|
44
57
|
this.requireEpochProven = opts.startProverNode ?? false;
|
|
45
58
|
}
|
|
46
|
-
async setup() {
|
|
47
|
-
this.
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
async setup(opts = {}, pxeOpts = {}) {
|
|
60
|
+
this.logger.info('Setting up cross chain messaging test');
|
|
61
|
+
// Recompute requireEpochProven from the merged options so per-call startProverNode is honored.
|
|
62
|
+
this.requireEpochProven = opts.startProverNode ?? this.setupOptions.startProverNode ?? false;
|
|
63
|
+
this.context = await setup(0, {
|
|
64
|
+
...this.setupOptions,
|
|
65
|
+
...opts,
|
|
66
|
+
fundSponsoredFPC: true,
|
|
67
|
+
skipAccountDeployment: true,
|
|
68
|
+
l1ContractsArgs: {
|
|
69
|
+
...this.deployL1ContractsArgs,
|
|
70
|
+
...opts.l1ContractsArgs
|
|
71
|
+
}
|
|
72
|
+
}, {
|
|
73
|
+
...this.pxeOpts,
|
|
74
|
+
...pxeOpts
|
|
75
|
+
});
|
|
76
|
+
await this.applyBaseSetup();
|
|
58
77
|
}
|
|
59
78
|
async advanceToEpochProven(l2TxReceipt) {
|
|
60
|
-
const
|
|
79
|
+
const block = await this.aztecNode.getBlock(l2TxReceipt.blockNumber);
|
|
80
|
+
const epoch = await this.rollup.getEpochNumberForCheckpoint(block.checkpointNumber);
|
|
61
81
|
// Warp to the next epoch.
|
|
62
82
|
await this.cheatCodes.rollup.advanceToEpoch(EpochNumber(epoch + 1));
|
|
63
83
|
// Wait for the tx to be proven.
|
|
@@ -69,57 +89,73 @@ export class CrossChainMessagingTest {
|
|
|
69
89
|
}
|
|
70
90
|
async catchUpProvenChain() {
|
|
71
91
|
const bn = await this.aztecNode.getBlockNumber();
|
|
72
|
-
while(await this.aztecNode.
|
|
92
|
+
while(await this.aztecNode.getBlockNumber('proven') < bn){
|
|
73
93
|
await sleep(1000);
|
|
74
94
|
}
|
|
75
95
|
}
|
|
76
|
-
snapshot = (name, apply, restore = ()=>Promise.resolve())=>this.snapshotManager.snapshot(name, apply, restore);
|
|
77
96
|
async teardown() {
|
|
78
|
-
await this.
|
|
97
|
+
await this.epochTestSettler?.stop();
|
|
98
|
+
await teardown(this.context);
|
|
79
99
|
}
|
|
80
|
-
async
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
this.
|
|
106
|
-
this.crossChainTestHarness = await CrossChainTestHarness.new(this.aztecNode, this.l1Client, this.wallet, this.ownerAddress, this.logger, underlyingERC20Address);
|
|
107
|
-
this.logger.verbose(`L2 token deployed to: ${this.crossChainTestHarness.l2Token.address}`);
|
|
108
|
-
return this.crossChainTestHarness.toCrossChainContext();
|
|
109
|
-
}, (crossChainContext)=>{
|
|
110
|
-
this.l2Token = TokenContract.at(crossChainContext.l2Token, this.wallet);
|
|
111
|
-
this.l2Bridge = TokenBridgeContract.at(crossChainContext.l2Bridge, this.wallet);
|
|
112
|
-
// There is an issue with the reviver so we are getting strings sometimes. Working around it here.
|
|
113
|
-
this.ethAccount = EthAddress.fromString(crossChainContext.ethAccount.toString());
|
|
114
|
-
const tokenPortalAddress = EthAddress.fromString(crossChainContext.tokenPortal.toString());
|
|
115
|
-
const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
|
|
116
|
-
this.l1Client = l1Client;
|
|
117
|
-
const l1Contracts = this.aztecNodeConfig.l1Contracts;
|
|
118
|
-
this.rollup = new RollupContract(l1Client, l1Contracts.rollupAddress.toString());
|
|
119
|
-
this.inbox = new InboxContract(l1Client, l1Contracts.inboxAddress.toString());
|
|
120
|
-
this.outbox = new OutboxContract(l1Client, l1Contracts.outboxAddress.toString());
|
|
121
|
-
this.crossChainTestHarness = new CrossChainTestHarness(this.aztecNode, this.logger, this.l2Token, this.l2Bridge, this.ethAccount, tokenPortalAddress, crossChainContext.underlying, l1Client, this.aztecNodeConfig.l1Contracts, this.wallet, this.ownerAddress);
|
|
122
|
-
return Promise.resolve();
|
|
100
|
+
async applyBaseSetup() {
|
|
101
|
+
// Set up base context fields
|
|
102
|
+
this.aztecNode = this.context.aztecNodeService;
|
|
103
|
+
this.wallet = this.context.wallet;
|
|
104
|
+
this.aztecNodeConfig = this.context.config;
|
|
105
|
+
this.cheatCodes = this.context.cheatCodes;
|
|
106
|
+
this.deployL1ContractsValues = this.context.deployL1ContractsValues;
|
|
107
|
+
this.aztecNodeAdmin = this.context.aztecNodeService;
|
|
108
|
+
if (this.requireEpochProven) {
|
|
109
|
+
// Turn off the watcher to prevent it from keep marking blocks as proven.
|
|
110
|
+
this.context.watcher.setIsMarkingAsProven(false);
|
|
111
|
+
} else {
|
|
112
|
+
// When no real prover is running, the L1 proof window (aztecProofSubmissionEpochs) would
|
|
113
|
+
// otherwise expire mid-test and trigger a chain prune. The AnvilTestWatcher's auto-prove
|
|
114
|
+
// loop is dormant under L1 interval mining (it gates on `isAutoMining`), so start an
|
|
115
|
+
// EpochTestSettler to mark each completed epoch as proven on L1.
|
|
116
|
+
this.epochTestSettler = new EpochTestSettler(this.context.ethCheatCodes, this.context.deployL1ContractsValues.l1ContractAddresses.rollupAddress, this.context.aztecNodeService.getBlockSource(), this.logger.createChild('epoch-settler'), {
|
|
117
|
+
pollingIntervalMs: 500
|
|
118
|
+
});
|
|
119
|
+
await this.epochTestSettler.start();
|
|
120
|
+
}
|
|
121
|
+
// Deploy 3 accounts
|
|
122
|
+
this.logger.info('Applying 3_accounts setup');
|
|
123
|
+
const { deployedAccounts } = await deployAccounts(3, this.logger)({
|
|
124
|
+
wallet: this.context.wallet,
|
|
125
|
+
initialFundedAccounts: this.context.initialFundedAccounts
|
|
123
126
|
});
|
|
127
|
+
[this.ownerAddress, this.user1Address, this.user2Address] = deployedAccounts.map((a)=>a.address);
|
|
128
|
+
// Set up cross chain messaging
|
|
129
|
+
this.logger.info('Applying e2e_cross_chain_messaging setup');
|
|
130
|
+
await ensureAuthRegistryPublished(this.wallet, this.ownerAddress);
|
|
131
|
+
// Create the token contract state.
|
|
132
|
+
this.logger.verbose(`Public deploy accounts...`);
|
|
133
|
+
await publicDeployAccounts(this.wallet, [
|
|
134
|
+
this.ownerAddress,
|
|
135
|
+
this.user1Address,
|
|
136
|
+
this.user2Address
|
|
137
|
+
]);
|
|
138
|
+
this.l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
|
|
139
|
+
const underlyingERC20Address = await deployL1Contract(this.l1Client, TestERC20Abi, TestERC20Bytecode, [
|
|
140
|
+
'Underlying',
|
|
141
|
+
'UND',
|
|
142
|
+
this.l1Client.account.address
|
|
143
|
+
]).then(({ address })=>address);
|
|
144
|
+
this.logger.verbose(`Setting up cross chain harness...`);
|
|
145
|
+
this.crossChainTestHarness = await CrossChainTestHarness.new(this.aztecNode, this.l1Client, this.wallet, this.ownerAddress, this.logger, underlyingERC20Address);
|
|
146
|
+
this.logger.verbose(`L2 token deployed to: ${this.crossChainTestHarness.l2Token.address}`);
|
|
147
|
+
const crossChainContext = this.crossChainTestHarness.toCrossChainContext();
|
|
148
|
+
this.l2Token = TokenContract.at(crossChainContext.l2Token, this.wallet);
|
|
149
|
+
this.l2Bridge = TokenBridgeContract.at(crossChainContext.l2Bridge, this.wallet);
|
|
150
|
+
// There is an issue with the reviver so we are getting strings sometimes. Working around it here.
|
|
151
|
+
this.ethAccount = EthAddress.fromString(crossChainContext.ethAccount.toString());
|
|
152
|
+
const tokenPortalAddress = EthAddress.fromString(crossChainContext.tokenPortal.toString());
|
|
153
|
+
const l1Client = createExtendedL1Client(this.aztecNodeConfig.l1RpcUrls, MNEMONIC);
|
|
154
|
+
this.l1Client = l1Client;
|
|
155
|
+
const l1Contracts = pickL1ContractAddresses(this.aztecNodeConfig);
|
|
156
|
+
this.rollup = new RollupContract(l1Client, l1Contracts.rollupAddress.toString());
|
|
157
|
+
this.inbox = new InboxContract(l1Client, l1Contracts.inboxAddress.toString());
|
|
158
|
+
this.outbox = new OutboxContract(l1Client, l1Contracts.outboxAddress.toString());
|
|
159
|
+
this.crossChainTestHarness = new CrossChainTestHarness(this.aztecNode, this.logger, this.l2Token, this.l2Bridge, this.ethAccount, tokenPortalAddress, crossChainContext.underlying, l1Client, pickL1ContractAddresses(this.aztecNodeConfig), this.wallet, this.ownerAddress);
|
|
124
160
|
}
|
|
125
161
|
}
|
|
@@ -8,18 +8,19 @@ import type { AztecNode } from '@aztec/aztec.js/node';
|
|
|
8
8
|
import type { Wallet } from '@aztec/aztec.js/wallet';
|
|
9
9
|
import type { StatefulTestContract } from '@aztec/noir-test-contracts.js/StatefulTest';
|
|
10
10
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
11
|
-
import type
|
|
11
|
+
import { type EndToEndContext, type SetupOptions } from '../fixtures/setup.js';
|
|
12
|
+
import type { TestWallet } from '../test-wallet/test_wallet.js';
|
|
12
13
|
export declare class DeployTest {
|
|
13
|
-
|
|
14
|
+
context: EndToEndContext;
|
|
14
15
|
logger: Logger;
|
|
15
16
|
wallet: TestWallet;
|
|
16
17
|
defaultAccountAddress: AztecAddress;
|
|
17
18
|
aztecNode: AztecNode;
|
|
18
19
|
aztecNodeAdmin: AztecNodeAdmin;
|
|
19
20
|
constructor(testName: string);
|
|
20
|
-
setup(): Promise<this>;
|
|
21
|
+
setup(opts?: Partial<SetupOptions>): Promise<this>;
|
|
21
22
|
teardown(): Promise<void>;
|
|
22
|
-
private
|
|
23
|
+
private applyInitialAccount;
|
|
23
24
|
registerContract<T extends ContractBase>(wallet: Wallet, contractArtifact: ContractArtifactClass<T>, opts?: {
|
|
24
25
|
salt?: Fr;
|
|
25
26
|
publicKeys?: PublicKeys;
|
|
@@ -33,4 +34,4 @@ export type ContractArtifactClass<T extends ContractBase> = {
|
|
|
33
34
|
at(address: AztecAddress, wallet: Wallet): T;
|
|
34
35
|
artifact: ContractArtifact;
|
|
35
36
|
};
|
|
36
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95X3Rlc3QuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lMmVfZGVwbG95X2NvbnRyYWN0L2RlcGxveV90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUssWUFBWSxFQUE4QyxNQUFNLDJCQUEyQixDQUFDO0FBQzFHLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0scUJBQXFCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUN2RixPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV0RSxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQUUsS0FBSyxZQUFZLEVBQW1DLE1BQU0sc0JBQXNCLENBQUM7QUFDaEgsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFaEUscUJBQWEsVUFBVTtJQUNkLE9BQU8sRUFBRyxlQUFlLENBQUM7SUFDMUIsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLE1BQU0sRUFBRyxVQUFVLENBQUM7SUFDcEIscUJBQXFCLEVBQUcsWUFBWSxDQUFDO0lBQ3JDLFNBQVMsRUFBRyxTQUFTLENBQUM7SUFDdEIsY0FBYyxFQUFHLGNBQWMsQ0FBQztJQUV2QyxZQUFZLFFBQVEsRUFBRSxNQUFNLEVBRTNCO0lBRUssS0FBSyxDQUFDLElBQUksR0FBRSxPQUFPLENBQUMsWUFBWSxDQUFNLGlCQVkzQztJQUVLLFFBQVEsa0JBRWI7WUFFYSxtQkFBbUI7SUFZM0IsZ0JBQWdCLENBQUMsQ0FBQyxTQUFTLFlBQVksRUFDM0MsTUFBTSxFQUFFLE1BQU0sRUFDZCxnQkFBZ0IsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsRUFDMUMsSUFBSSxHQUFFO1FBQ0osSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ1YsVUFBVSxDQUFDLEVBQUUsVUFBVSxDQUFDO1FBQ3hCLFFBQVEsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLGVBQWUsQ0FBQyxFQUFFLE1BQU0sQ0FBQztRQUN6QixRQUFRLENBQUMsRUFBRSxZQUFZLENBQUM7S0FDcEIsR0FDTCxPQUFPLENBQUMsQ0FBQyxDQUFDLENBV1o7Q0FDRjtBQUVELE1BQU0sTUFBTSx3QkFBd0IsR0FBRyxVQUFVLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztBQUVsRyxNQUFNLE1BQU0scUJBQXFCLENBQUMsQ0FBQyxTQUFTLFlBQVksSUFBSTtJQUMxRCxFQUFFLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUM3QyxRQUFRLEVBQUUsZ0JBQWdCLENBQUM7Q0FDNUIsQ0FBQyJ9
|