@aztec/end-to-end 1.2.1 → 2.0.0-nightly.20250813
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 +2 -2
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/benchmark.js +4 -2
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +33 -15
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/bench/utils.js +7 -4
- package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +11 -3
- 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 +59 -24
- package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +3 -2
- 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 +13 -10
- package/dest/e2e_deploy_contract/deploy_test.d.ts +1 -1
- package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -1
- package/dest/e2e_deploy_contract/deploy_test.js +7 -6
- package/dest/e2e_epochs/epochs_test.d.ts +16 -2
- package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
- package/dest/e2e_epochs/epochs_test.js +65 -7
- package/dest/e2e_fees/bridging_race.notest.js +3 -1
- package/dest/e2e_fees/fees_test.d.ts +5 -4
- package/dest/e2e_fees/fees_test.d.ts.map +1 -1
- package/dest/e2e_fees/fees_test.js +44 -59
- package/dest/e2e_nested_contract/nested_contract_test.d.ts +3 -3
- package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -1
- package/dest/e2e_nested_contract/nested_contract_test.js +17 -12
- package/dest/e2e_p2p/p2p_network.d.ts +7 -4
- package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
- package/dest/e2e_p2p/p2p_network.js +43 -22
- package/dest/e2e_p2p/shared.d.ts +3 -3
- package/dest/e2e_p2p/shared.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +16 -12
- package/dest/e2e_token_contract/token_contract_test.d.ts +8 -4
- package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -1
- package/dest/e2e_token_contract/token_contract_test.js +48 -23
- package/dest/fixtures/e2e_prover_test.d.ts +1 -1
- package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
- package/dest/fixtures/e2e_prover_test.js +27 -10
- package/dest/fixtures/setup_p2p_test.d.ts +4 -1
- package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
- package/dest/fixtures/setup_p2p_test.js +39 -8
- package/dest/fixtures/snapshot_manager.d.ts +3 -1
- package/dest/fixtures/snapshot_manager.d.ts.map +1 -1
- package/dest/fixtures/snapshot_manager.js +20 -17
- package/dest/fixtures/token_utils.d.ts +3 -3
- package/dest/fixtures/token_utils.d.ts.map +1 -1
- package/dest/fixtures/token_utils.js +14 -10
- package/dest/fixtures/utils.d.ts +23 -8
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +88 -56
- package/dest/integration_l1_publisher/write_json.d.ts +8 -0
- package/dest/integration_l1_publisher/write_json.d.ts.map +1 -0
- package/dest/integration_l1_publisher/write_json.js +57 -0
- package/dest/sample-dapp/connect.d.mts +2 -0
- package/dest/sample-dapp/connect.d.mts.map +1 -0
- package/dest/sample-dapp/connect.js +1 -1
- package/dest/sample-dapp/contracts.d.mts +3 -0
- package/dest/sample-dapp/contracts.d.mts.map +1 -0
- package/dest/sample-dapp/contracts.js +1 -1
- package/dest/sample-dapp/deploy.d.mts +3 -0
- package/dest/sample-dapp/deploy.d.mts.map +1 -0
- package/dest/sample-dapp/deploy.js +4 -1
- package/dest/sample-dapp/index.d.mts +2 -0
- package/dest/sample-dapp/index.d.mts.map +1 -0
- package/dest/sample-dapp/index.js +18 -8
- package/dest/shared/cross_chain_test_harness.d.ts +6 -3
- package/dest/shared/cross_chain_test_harness.d.ts.map +1 -1
- package/dest/shared/cross_chain_test_harness.js +50 -20
- package/dest/shared/gas_portal_test_harness.d.ts +3 -3
- package/dest/shared/gas_portal_test_harness.d.ts.map +1 -1
- package/dest/shared/gas_portal_test_harness.js +21 -6
- 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 +45 -22
- package/dest/simulators/lending_simulator.d.ts +1 -1
- package/dest/simulators/lending_simulator.d.ts.map +1 -1
- package/dest/simulators/lending_simulator.js +6 -2
- package/dest/simulators/token_simulator.d.ts +2 -1
- package/dest/simulators/token_simulator.d.ts.map +1 -1
- package/dest/simulators/token_simulator.js +12 -4
- package/dest/spartan/setup_test_wallets.d.ts +7 -0
- package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
- package/dest/spartan/setup_test_wallets.js +96 -11
- package/dest/spartan/utils.d.ts +23 -3
- package/dest/spartan/utils.d.ts.map +1 -1
- package/dest/spartan/utils.js +9 -6
- package/package.json +36 -36
- package/src/bench/client_flows/benchmark.ts +8 -3
- package/src/bench/client_flows/client_flows_benchmark.ts +23 -14
- package/src/bench/utils.ts +5 -4
- package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +47 -26
- package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +14 -9
- package/src/e2e_deploy_contract/deploy_test.ts +7 -7
- package/src/e2e_epochs/epochs_test.ts +97 -25
- package/src/e2e_fees/bridging_race.notest.ts +1 -1
- package/src/e2e_fees/fees_test.ts +55 -82
- package/src/e2e_nested_contract/nested_contract_test.ts +16 -11
- package/src/e2e_p2p/p2p_network.ts +51 -26
- package/src/e2e_p2p/shared.ts +14 -12
- package/src/e2e_token_contract/token_contract_test.ts +38 -36
- package/src/fixtures/e2e_prover_test.ts +17 -10
- package/src/fixtures/setup_p2p_test.ts +51 -9
- package/src/fixtures/snapshot_manager.ts +24 -17
- package/src/fixtures/token_utils.ts +14 -9
- package/src/fixtures/utils.ts +116 -57
- package/src/guides/up_quick_start.sh +1 -1
- package/src/integration_l1_publisher/write_json.ts +74 -0
- package/src/sample-dapp/connect.mjs +1 -1
- package/src/sample-dapp/contracts.mjs +1 -1
- package/src/sample-dapp/deploy.mjs +3 -3
- package/src/sample-dapp/index.mjs +11 -8
- package/src/shared/cross_chain_test_harness.ts +31 -18
- package/src/shared/gas_portal_test_harness.ts +17 -7
- package/src/shared/uniswap_l1_l2.ts +28 -24
- package/src/simulators/lending_simulator.ts +3 -3
- package/src/simulators/token_simulator.ts +12 -3
- package/src/spartan/setup_test_wallets.ts +130 -19
- package/src/spartan/utils.ts +10 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"p2p_network.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/p2p_network.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,KAAK,0BAA0B,
|
|
1
|
+
{"version":3,"file":"p2p_network.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/p2p_network.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,KAAK,0BAA0B,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAC;AAChG,OAAO,EAKL,KAAK,QAAQ,EACb,cAAc,EACd,KAAK,UAAU,EAGhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAa,eAAe,EAAE,UAAU,EAAE,mBAAmB,EAAgB,MAAM,qBAAqB,CAAC;AAChH,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAK9D,OAAO,EAAE,KAAK,qBAAqB,EAA2B,MAAM,MAAM,CAAC;AAQ3E,OAAO,EAEL,KAAK,iBAAiB,EAGvB,MAAM,iCAAiC,CAAC;AAOzC,eAAO,MAAM,mBAAmB,QAA0C,CAAC;AAE3E,eAAO,MAAM,qCAAqC;;;;CAIjD,CAAC;AAEF,qBAAa,cAAc;IAyBhB,gBAAgB,EAAE,MAAM;IACxB,YAAY,EAAE,MAAM;IACpB,kBAAkB,EAAE,MAAM;IAE1B,aAAa;IAEpB,OAAO,CAAC,WAAW,CAAC;IA9BtB,OAAO,CAAC,eAAe,CAAmB;IACnC,qBAAqB,EAAE,KAAK,MAAM,EAAE,CAAC;IACrC,WAAW;;;;;;;;;;wTAlBP,CAAC;sBAAsB,CAAC;;;;;;MAkBhB;IAEZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAG,YAAY,CAAC;IAEvB,GAAG,EAAG,iBAAiB,CAAC;IACxB,mBAAmB,EAAE,KAAK,MAAM,EAAE,EAAE,CAAM;IAC1C,kBAAkB,EAAE,MAAM,EAAE,CAAM;IAClC,iBAAiB,EAAE,MAAM,EAAE,CAAM;IACjC,UAAU,EAAE,QAAQ,EAAE,CAAM;IAE5B,gBAAgB,EAAE,kBAAkB,EAAE,CAAM;IAC5C,mBAAmB,EAAE,kBAAkB,EAAE,CAAM;IAE/C,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,qBAAqB,CAAC,EAAE,YAAY,CAAC;IACrC,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B,aAAa,CAAC,EAAE,aAAa,CAAC;gBAGnC,QAAQ,EAAE,MAAM,EACT,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EACjC,sBAAsB,EAAE,eAAe,EAChC,aAAa,SAAI,EAEhB,WAAW,CAAC,EAAE,MAAM,YAAA,EAC5B,eAAe,CAAC,EAAE,OAAO,EACzB,sBAAsB,CAAC,EAAE,OAAO;WAiDrB,MAAM,CAAC,EAClB,QAAQ,EACR,aAAa,EACb,kBAAkB,EAClB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,eAAe,EACf,sBAAsB,GACvB,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QACzC,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,sBAAsB,CAAC,EAAE,OAAO,CAAC;KAClC;IAwBD,IAAI,aAAa,uBAKhB;IAEK,gBAAgB;IActB,aAAa;;;IAkBP,kBAAkB;IA2ElB,YAAY;IAaZ,kBAAkB;IAsBlB,iBAAiB;IAgBjB,WAAW;;;;YAIH,YAAY;IAQpB,KAAK;IAcL,SAAS,CAAC,KAAK,EAAE,gBAAgB,EAAE;IAanC,QAAQ;IAMR,YAAY,IAAI,OAAO,CAAC;QAC5B,MAAM,EAAE,cAAc,CAAC;QACvB,eAAe,EAAE,qBAAqB,CAAC,OAAO,UAAU,EAAE,UAAU,CAAC,CAAC;QACtE,gBAAgB,EAAE,qBAAqB,CAAC,OAAO,mBAAmB,EAAE,UAAU,CAAC,CAAC;QAChF,YAAY,EAAE,qBAAqB,CAAC,OAAO,eAAe,EAAE,UAAU,CAAC,CAAC;KACzE,CAAC;CA8BH"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getSchnorrWalletWithSecretKey } from '@aztec/accounts/schnorr';
|
|
2
|
-
import { EthAddress } from '@aztec/aztec.js';
|
|
3
|
-
import { L1TxUtils, RollupContract, deployL1Contract, getL1ContractsConfigEnvVars
|
|
2
|
+
import { EthAddress, Fr } from '@aztec/aztec.js';
|
|
3
|
+
import { GSEContract, L1TxUtils, MultiAdderArtifact, RollupContract, deployL1Contract, getL1ContractsConfigEnvVars } from '@aztec/ethereum';
|
|
4
4
|
import { ChainMonitor } from '@aztec/ethereum/test';
|
|
5
|
+
import { SecretValue } from '@aztec/foundation/config';
|
|
5
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
7
|
import { RollupAbi, SlashFactoryAbi, SlasherAbi, SlashingProposerAbi, TestERC20Abi } from '@aztec/l1-artifacts';
|
|
7
8
|
import { SpamContract } from '@aztec/noir-test-contracts.js/Spam';
|
|
@@ -28,6 +29,7 @@ export const SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES = {
|
|
|
28
29
|
export class P2PNetworkTest {
|
|
29
30
|
bootstrapNodeEnr;
|
|
30
31
|
bootNodePort;
|
|
32
|
+
numberOfValidators;
|
|
31
33
|
numberOfNodes;
|
|
32
34
|
metricsPort;
|
|
33
35
|
snapshotManager;
|
|
@@ -44,12 +46,14 @@ export class P2PNetworkTest {
|
|
|
44
46
|
prefilledPublicData;
|
|
45
47
|
// The re-execution test needs a wallet and a spam contract
|
|
46
48
|
wallet;
|
|
49
|
+
defaultAccountAddress;
|
|
47
50
|
spamContract;
|
|
48
51
|
bootstrapNode;
|
|
49
|
-
constructor(testName, bootstrapNodeEnr, bootNodePort,
|
|
52
|
+
constructor(testName, bootstrapNodeEnr, bootNodePort, numberOfValidators, initialValidatorConfig, numberOfNodes = 0, // If set enable metrics collection
|
|
50
53
|
metricsPort, startProverNode, mockZkPassportVerifier){
|
|
51
54
|
this.bootstrapNodeEnr = bootstrapNodeEnr;
|
|
52
55
|
this.bootNodePort = bootNodePort;
|
|
56
|
+
this.numberOfValidators = numberOfValidators;
|
|
53
57
|
this.numberOfNodes = numberOfNodes;
|
|
54
58
|
this.metricsPort = metricsPort;
|
|
55
59
|
this.attesterPrivateKeys = [];
|
|
@@ -62,7 +66,7 @@ export class P2PNetworkTest {
|
|
|
62
66
|
// Set up the base account and node private keys for the initial network deployment
|
|
63
67
|
this.baseAccountPrivateKey = `0x${getPrivateKeyFromIndex(1).toString('hex')}`;
|
|
64
68
|
this.baseAccount = privateKeyToAccount(this.baseAccountPrivateKey);
|
|
65
|
-
this.attesterPrivateKeys = generatePrivateKeys(ATTESTER_PRIVATE_KEYS_START_INDEX,
|
|
69
|
+
this.attesterPrivateKeys = generatePrivateKeys(ATTESTER_PRIVATE_KEYS_START_INDEX + numberOfNodes, numberOfValidators);
|
|
66
70
|
this.attesterPublicKeys = this.attesterPrivateKeys.map((privateKey)=>privateKeyToAccount(privateKey).address);
|
|
67
71
|
const zkPassportParams = ZkPassportProofParams.random();
|
|
68
72
|
this.snapshotManager = createSnapshotManager(`e2e_p2p_network/${testName}`, process.env.E2E_DATA_PATH, {
|
|
@@ -71,7 +75,7 @@ export class P2PNetworkTest {
|
|
|
71
75
|
aztecEpochDuration: initialValidatorConfig.aztecEpochDuration ?? l1ContractsConfig.aztecEpochDuration,
|
|
72
76
|
aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
|
|
73
77
|
aztecProofSubmissionEpochs: initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
|
|
74
|
-
aztecTargetCommitteeSize:
|
|
78
|
+
aztecTargetCommitteeSize: numberOfValidators,
|
|
75
79
|
salt: 420,
|
|
76
80
|
metricsPort: metricsPort,
|
|
77
81
|
numberOfInitialFundedAccounts: 2,
|
|
@@ -82,7 +86,7 @@ export class P2PNetworkTest {
|
|
|
82
86
|
ethereumSlotDuration: initialValidatorConfig.ethereumSlotDuration ?? l1ContractsConfig.ethereumSlotDuration,
|
|
83
87
|
aztecSlotDuration: initialValidatorConfig.aztecSlotDuration ?? l1ContractsConfig.aztecSlotDuration,
|
|
84
88
|
aztecProofSubmissionEpochs: initialValidatorConfig.aztecProofSubmissionEpochs ?? l1ContractsConfig.aztecProofSubmissionEpochs,
|
|
85
|
-
aztecTargetCommitteeSize:
|
|
89
|
+
aztecTargetCommitteeSize: numberOfValidators,
|
|
86
90
|
initialValidators: [],
|
|
87
91
|
zkPassportArgs: {
|
|
88
92
|
mockZkPassportVerifier,
|
|
@@ -91,12 +95,12 @@ export class P2PNetworkTest {
|
|
|
91
95
|
}
|
|
92
96
|
});
|
|
93
97
|
}
|
|
94
|
-
static async create({ testName, numberOfNodes, basePort, metricsPort, initialConfig, startProverNode, mockZkPassportVerifier }) {
|
|
98
|
+
static async create({ testName, numberOfNodes, numberOfValidators, basePort, metricsPort, initialConfig, startProverNode, mockZkPassportVerifier }) {
|
|
95
99
|
const port = basePort || await getPort();
|
|
96
100
|
const bootstrapNodeENR = await getBootstrapNodeEnr(BOOTSTRAP_NODE_PRIVATE_KEY, port);
|
|
97
101
|
const bootstrapNodeEnr = bootstrapNodeENR.encodeTxt();
|
|
98
102
|
const initialValidatorConfig = await createValidatorConfig(initialConfig ?? {}, bootstrapNodeEnr);
|
|
99
|
-
return new P2PNetworkTest(testName, bootstrapNodeEnr, port,
|
|
103
|
+
return new P2PNetworkTest(testName, bootstrapNodeEnr, port, numberOfValidators, initialValidatorConfig, numberOfNodes, metricsPort, startProverNode, mockZkPassportVerifier);
|
|
100
104
|
}
|
|
101
105
|
get fundedAccount() {
|
|
102
106
|
if (!this.deployedAccounts[0]) {
|
|
@@ -114,11 +118,13 @@ export class P2PNetworkTest {
|
|
|
114
118
|
}
|
|
115
119
|
getValidators() {
|
|
116
120
|
const validators = [];
|
|
117
|
-
for(let i = 0; i < this.
|
|
118
|
-
const
|
|
121
|
+
for(let i = 0; i < this.numberOfValidators; i++){
|
|
122
|
+
const keyIndex = i;
|
|
123
|
+
const attester = privateKeyToAccount(this.attesterPrivateKeys[keyIndex]);
|
|
119
124
|
validators.push({
|
|
120
125
|
attester: EthAddress.fromString(attester.address),
|
|
121
|
-
withdrawer: EthAddress.fromString(attester.address)
|
|
126
|
+
withdrawer: EthAddress.fromString(attester.address),
|
|
127
|
+
bn254SecretKey: new SecretValue(Fr.random().toBigInt())
|
|
122
128
|
});
|
|
123
129
|
this.logger.info(`Adding attester ${attester.address} as validator`);
|
|
124
130
|
}
|
|
@@ -134,22 +140,22 @@ export class P2PNetworkTest {
|
|
|
134
140
|
abi: RollupAbi,
|
|
135
141
|
client: deployL1ContractsValues.l1Client
|
|
136
142
|
});
|
|
137
|
-
this.logger.
|
|
143
|
+
this.logger.info(`Adding ${this.numberOfValidators} validators`);
|
|
138
144
|
const stakingAsset = getContract({
|
|
139
145
|
address: deployL1ContractsValues.l1ContractAddresses.stakingAssetAddress.toString(),
|
|
140
146
|
abi: TestERC20Abi,
|
|
141
147
|
client: deployL1ContractsValues.l1Client
|
|
142
148
|
});
|
|
143
|
-
const { address: multiAdderAddress } = await deployL1Contract(deployL1ContractsValues.l1Client,
|
|
149
|
+
const { address: multiAdderAddress } = await deployL1Contract(deployL1ContractsValues.l1Client, MultiAdderArtifact.contractAbi, MultiAdderArtifact.contractBytecode, [
|
|
144
150
|
rollup.address,
|
|
145
151
|
deployL1ContractsValues.l1Client.account.address
|
|
146
152
|
]);
|
|
147
153
|
const multiAdder = getContract({
|
|
148
154
|
address: multiAdderAddress.toString(),
|
|
149
|
-
abi:
|
|
155
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
150
156
|
client: deployL1ContractsValues.l1Client
|
|
151
157
|
});
|
|
152
|
-
const stakeNeeded = l1ContractsConfig.
|
|
158
|
+
const stakeNeeded = l1ContractsConfig.activationThreshold * BigInt(this.numberOfValidators);
|
|
153
159
|
await Promise.all([
|
|
154
160
|
await stakingAsset.write.mint([
|
|
155
161
|
multiAdder.address,
|
|
@@ -160,12 +166,23 @@ export class P2PNetworkTest {
|
|
|
160
166
|
})));
|
|
161
167
|
const { validators } = this.getValidators();
|
|
162
168
|
this.validators = validators;
|
|
169
|
+
const gseAddress = deployL1ContractsValues.l1ContractAddresses.gseAddress;
|
|
170
|
+
if (!gseAddress) {
|
|
171
|
+
throw new Error('GSE contract not deployed');
|
|
172
|
+
}
|
|
173
|
+
const gseContract = new GSEContract(deployL1ContractsValues.l1Client, gseAddress.toString());
|
|
174
|
+
const makeValidatorTuples = async (validator)=>{
|
|
175
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
176
|
+
return {
|
|
177
|
+
attester: validator.attester.toString(),
|
|
178
|
+
withdrawer: validator.withdrawer.toString(),
|
|
179
|
+
...registrationTuple
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
const validatorTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
163
183
|
await deployL1ContractsValues.l1Client.waitForTransactionReceipt({
|
|
164
184
|
hash: await multiAdder.write.addValidators([
|
|
165
|
-
|
|
166
|
-
attester: v.attester.toString(),
|
|
167
|
-
withdrawer: v.withdrawer.toString()
|
|
168
|
-
}))
|
|
185
|
+
validatorTuples
|
|
169
186
|
])
|
|
170
187
|
});
|
|
171
188
|
const timestamp = await cheatCodes.rollup.advanceToEpoch(2n, {
|
|
@@ -183,6 +200,7 @@ export class P2PNetworkTest {
|
|
|
183
200
|
this.deployedAccounts = deployedAccounts;
|
|
184
201
|
const [account] = deployedAccounts;
|
|
185
202
|
this.wallet = await getSchnorrWalletWithSecretKey(pxe, account.secret, account.signingKey, account.salt);
|
|
203
|
+
this.defaultAccountAddress = this.wallet.getAddress();
|
|
186
204
|
});
|
|
187
205
|
}
|
|
188
206
|
async deploySpamContract() {
|
|
@@ -190,7 +208,9 @@ export class P2PNetworkTest {
|
|
|
190
208
|
if (!this.wallet) {
|
|
191
209
|
throw new Error('Call snapshot t.setupAccount before deploying account contract');
|
|
192
210
|
}
|
|
193
|
-
const spamContract = await SpamContract.deploy(this.wallet).send(
|
|
211
|
+
const spamContract = await SpamContract.deploy(this.wallet).send({
|
|
212
|
+
from: this.defaultAccountAddress
|
|
213
|
+
}).deployed();
|
|
194
214
|
return {
|
|
195
215
|
contractAddress: spamContract.address
|
|
196
216
|
};
|
|
@@ -202,7 +222,7 @@ export class P2PNetworkTest {
|
|
|
202
222
|
});
|
|
203
223
|
}
|
|
204
224
|
async removeInitialNode() {
|
|
205
|
-
await this.snapshotManager.snapshot('remove-
|
|
225
|
+
await this.snapshotManager.snapshot('remove-initial-validator', async ({ deployL1ContractsValues, aztecNode, dateProvider })=>{
|
|
206
226
|
// Send and await a tx to make sure we mine a block for the warp to correctly progress.
|
|
207
227
|
const { receipt } = await this._sendDummyTx(deployL1ContractsValues.l1Client);
|
|
208
228
|
const block = await deployL1ContractsValues.l1Client.getBlock({
|
|
@@ -231,7 +251,8 @@ export class P2PNetworkTest {
|
|
|
231
251
|
];
|
|
232
252
|
const { prefilledPublicData } = await getGenesisValues(initialFundedAccounts);
|
|
233
253
|
this.prefilledPublicData = prefilledPublicData;
|
|
234
|
-
|
|
254
|
+
const rollupContract = RollupContract.getFromL1ContractsValues(this.ctx.deployL1ContractsValues);
|
|
255
|
+
this.monitor = new ChainMonitor(rollupContract, this.ctx.dateProvider).start();
|
|
235
256
|
this.monitor.on('l1-block', ({ timestamp })=>this.ctx.dateProvider.setTime(Number(timestamp) * 1000));
|
|
236
257
|
}
|
|
237
258
|
async stopNodes(nodes) {
|
package/dest/e2e_p2p/shared.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { InitialAccountData } from '@aztec/accounts/testing';
|
|
2
2
|
import type { AztecNodeService } from '@aztec/aztec-node';
|
|
3
|
-
import { type Logger, ProvenTx, type SentTx } from '@aztec/aztec.js';
|
|
4
|
-
import type { RollupCheatCodes } from '@aztec/aztec
|
|
3
|
+
import { AztecAddress, type Logger, ProvenTx, type SentTx } from '@aztec/aztec.js';
|
|
4
|
+
import type { RollupCheatCodes } from '@aztec/aztec/testing';
|
|
5
5
|
import type { RollupContract, ViemClient } from '@aztec/ethereum';
|
|
6
6
|
import type { SlashFactoryAbi } from '@aztec/l1-artifacts/SlashFactoryAbi';
|
|
7
7
|
import type { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
|
|
@@ -10,7 +10,7 @@ import { PXEService } from '@aztec/pxe/server';
|
|
|
10
10
|
import { Offense } from '@aztec/slasher';
|
|
11
11
|
import type { GetContractReturnType } from 'viem';
|
|
12
12
|
import type { NodeContext } from '../fixtures/setup_p2p_test.js';
|
|
13
|
-
export declare const submitComplexTxsTo: (logger: Logger, spamContract: SpamContract, numTxs: number, opts?: {
|
|
13
|
+
export declare const submitComplexTxsTo: (logger: Logger, from: AztecAddress, spamContract: SpamContract, numTxs: number, opts?: {
|
|
14
14
|
callPublic?: boolean;
|
|
15
15
|
}) => Promise<SentTx[]>;
|
|
16
16
|
export declare const createPXEServiceAndSubmitTransactions: (logger: Logger, node: AztecNodeService, numTxs: number, fundedAccount: InitialAccountData) => Promise<NodeContext>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/e2e_p2p/shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,YAAY,EAEZ,KAAK,MAAM,EACX,QAAQ,EACR,KAAK,MAAM,EAIZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAyD,MAAM,mBAAmB,CAAC;AACtG,OAAO,EAAE,OAAO,EAAmB,MAAM,gBAAgB,CAAC;AAE1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,MAAM,CAAC;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,MAAM,EACd,MAAM,YAAY,EAClB,cAAc,YAAY,EAC1B,QAAQ,MAAM,EACd,OAAM;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,sBAsBpC,CAAC;AAGF,eAAO,MAAM,qCAAqC,GAChD,QAAQ,MAAM,EACd,MAAM,gBAAgB,EACtB,QAAQ,MAAM,EACd,eAAe,kBAAkB,KAChC,OAAO,CAAC,WAAW,CAgBrB,CAAC;AAEF,wBAAsB,sCAAsC,CAC1D,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,kBAAkB,GAChC,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAqB9E;AAED,wBAAsB,sBAAsB,CAC1C,gBAAgB,EAAE,qBAAqB,CAAC,OAAO,mBAAmB,EAAE,UAAU,CAAC,EAC/E,cAAc,EAAE,MAAM,iBAiBvB;AAED,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,MAAM,GACP,EAAE;IACD,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC,CAYpC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,OAAO,EACP,MAAM,EACN,UAAU,EACV,SAAS,EACT,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,WAAW,GACZ,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,SAAS,EAAE,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,qBAAqB,CAAC,OAAO,eAAe,EAAE,UAAU,CAAC,CAAC;IACxE,gBAAgB,EAAE,qBAAqB,CAAC,OAAO,mBAAmB,EAAE,UAAU,CAAC,CAAC;IAChF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,iBAgEA"}
|
package/dest/e2e_p2p/shared.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
|
|
2
|
-
import { Fr, TxStatus,
|
|
2
|
+
import { Fr, TxStatus, getContractInstanceFromInstantiationParams, retryUntil } from '@aztec/aztec.js';
|
|
3
3
|
import { timesAsync } from '@aztec/foundation/collection';
|
|
4
4
|
import { TestContract, TestContractArtifact } from '@aztec/noir-test-contracts.js/Test';
|
|
5
5
|
import { createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe/server';
|
|
6
6
|
import { OffenseToBigInt } from '@aztec/slasher';
|
|
7
7
|
import { submitTxsTo } from '../shared/submit-transactions.js';
|
|
8
8
|
// submits a set of transactions to the provided Private eXecution Environment (PXE)
|
|
9
|
-
export const submitComplexTxsTo = async (logger, spamContract, numTxs, opts = {})=>{
|
|
9
|
+
export const submitComplexTxsTo = async (logger, from, spamContract, numTxs, opts = {})=>{
|
|
10
10
|
const txs = [];
|
|
11
11
|
const seed = 1234n;
|
|
12
12
|
const spamCount = 15;
|
|
13
13
|
for(let i = 0; i < numTxs; i++){
|
|
14
|
-
const tx = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic).send(
|
|
14
|
+
const tx = spamContract.methods.spam(seed + BigInt(i * spamCount), spamCount, !!opts.callPublic).send({
|
|
15
|
+
from
|
|
16
|
+
});
|
|
15
17
|
const txHash = await tx.getTxHash();
|
|
16
|
-
logger.info(`Tx sent with hash ${txHash}`);
|
|
18
|
+
logger.info(`Tx sent with hash ${txHash.toString()}`);
|
|
17
19
|
const receipt = await tx.getReceipt();
|
|
18
20
|
expect(receipt).toEqual(expect.objectContaining({
|
|
19
21
|
status: TxStatus.PENDING,
|
|
20
22
|
error: ''
|
|
21
23
|
}));
|
|
22
|
-
logger.info(`Receipt received for ${txHash}`);
|
|
24
|
+
logger.info(`Receipt received for ${txHash.toString()}`);
|
|
23
25
|
txs.push(tx);
|
|
24
26
|
}
|
|
25
27
|
return txs;
|
|
@@ -50,15 +52,17 @@ export async function createPXEServiceAndPrepareTransactions(logger, node, numTx
|
|
|
50
52
|
const account = await getSchnorrAccount(pxe, fundedAccount.secret, fundedAccount.signingKey, fundedAccount.salt);
|
|
51
53
|
await account.register();
|
|
52
54
|
const wallet = await account.getWallet();
|
|
53
|
-
const testContractInstance = await
|
|
55
|
+
const testContractInstance = await getContractInstanceFromInstantiationParams(TestContractArtifact, {});
|
|
54
56
|
await wallet.registerContract({
|
|
55
57
|
instance: testContractInstance,
|
|
56
58
|
artifact: TestContractArtifact
|
|
57
59
|
});
|
|
58
60
|
const contract = await TestContract.at(testContractInstance.address, wallet);
|
|
59
61
|
const txs = await timesAsync(numTxs, async ()=>{
|
|
60
|
-
const tx = await contract.methods.emit_nullifier(Fr.random()).prove(
|
|
61
|
-
|
|
62
|
+
const tx = await contract.methods.emit_nullifier(Fr.random()).prove({
|
|
63
|
+
from: account.getAddress()
|
|
64
|
+
});
|
|
65
|
+
const txHash = tx.getTxHash();
|
|
62
66
|
logger.info(`Tx prepared with hash ${txHash}`);
|
|
63
67
|
return tx;
|
|
64
68
|
});
|
|
@@ -70,15 +74,15 @@ export async function createPXEServiceAndPrepareTransactions(logger, node, numTx
|
|
|
70
74
|
}
|
|
71
75
|
export async function awaitProposalExecution(slashingProposer, timeoutSeconds) {
|
|
72
76
|
await retryUntil(async ()=>{
|
|
73
|
-
const events = await slashingProposer.getEvents.
|
|
77
|
+
const events = await slashingProposer.getEvents.PayloadSubmitted();
|
|
74
78
|
if (events.length === 0) {
|
|
75
79
|
return false;
|
|
76
80
|
}
|
|
77
81
|
const event = events[0];
|
|
78
82
|
const roundNumber = event.args.round;
|
|
79
|
-
const
|
|
80
|
-
return roundNumber &&
|
|
81
|
-
}, '
|
|
83
|
+
const payload = event.args.payload;
|
|
84
|
+
return roundNumber && payload;
|
|
85
|
+
}, 'payload submitted', timeoutSeconds, 1);
|
|
82
86
|
}
|
|
83
87
|
export async function awaitCommitteeExists({ rollup, logger }) {
|
|
84
88
|
logger.info(`Waiting for committee to be set`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AccountWallet,
|
|
1
|
+
import { type AccountWallet, AztecAddress, type AztecNode, type Logger } from '@aztec/aztec.js';
|
|
2
2
|
import { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
3
3
|
import { InvalidAccountContract } from '@aztec/noir-test-contracts.js/InvalidAccount';
|
|
4
4
|
import { type SubsystemsContext } from '../fixtures/snapshot_manager.js';
|
|
@@ -9,12 +9,16 @@ export declare class TokenContractTest {
|
|
|
9
9
|
static TOKEN_DECIMALS: bigint;
|
|
10
10
|
private snapshotManager;
|
|
11
11
|
logger: Logger;
|
|
12
|
-
wallets: AccountWallet[];
|
|
13
|
-
accounts: CompleteAddress[];
|
|
14
12
|
asset: TokenContract;
|
|
15
13
|
tokenSim: TokenSimulator;
|
|
16
|
-
badAccount: InvalidAccountContract;
|
|
17
14
|
node: AztecNode;
|
|
15
|
+
badAccount: InvalidAccountContract;
|
|
16
|
+
admin: AccountWallet;
|
|
17
|
+
adminAddress: AztecAddress;
|
|
18
|
+
account1: AccountWallet;
|
|
19
|
+
account1Address: AztecAddress;
|
|
20
|
+
account2: AccountWallet;
|
|
21
|
+
account2Address: AztecAddress;
|
|
18
22
|
constructor(testName: string);
|
|
19
23
|
/**
|
|
20
24
|
* Adds two state shifts to snapshot manager.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token_contract_test.d.ts","sourceRoot":"","sources":["../../src/e2e_token_contract/token_contract_test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"token_contract_test.d.ts","sourceRoot":"","sources":["../../src/e2e_token_contract/token_contract_test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAItF,OAAO,EAEL,KAAK,iBAAiB,EAIvB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAIlE,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,UAAU,SAAU;IAC3B,MAAM,CAAC,YAAY,SAAS;IAC5B,MAAM,CAAC,cAAc,SAAO;IAC5B,OAAO,CAAC,eAAe,CAAmB;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAG,aAAa,CAAC;IACtB,QAAQ,EAAG,cAAc,CAAC;IAC1B,IAAI,EAAG,SAAS,CAAC;IAEjB,UAAU,EAAG,sBAAsB,CAAC;IACpC,KAAK,EAAG,aAAa,CAAC;IACtB,YAAY,EAAG,YAAY,CAAC;IAC5B,QAAQ,EAAG,aAAa,CAAC;IACzB,eAAe,EAAG,YAAY,CAAC;IAC/B,QAAQ,EAAG,aAAa,CAAC;IACzB,eAAe,EAAG,YAAY,CAAC;gBAEnB,QAAQ,EAAE,MAAM;IAO5B;;;;OAIG;IACG,kBAAkB;IAkElB,KAAK;IAIX,QAAQ,GAAI,CAAC,EACX,MAAM,MAAM,EACZ,OAAO,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,UAAS,CAAC,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAA2B,KAChG,OAAO,CAAC,IAAI,CAAC,CAAwD;IAElE,QAAQ;IAIR,iBAAiB;CAqCxB"}
|
|
@@ -13,12 +13,16 @@ export class TokenContractTest {
|
|
|
13
13
|
static TOKEN_DECIMALS = 18n;
|
|
14
14
|
snapshotManager;
|
|
15
15
|
logger;
|
|
16
|
-
wallets = [];
|
|
17
|
-
accounts = [];
|
|
18
16
|
asset;
|
|
19
17
|
tokenSim;
|
|
20
|
-
badAccount;
|
|
21
18
|
node;
|
|
19
|
+
badAccount;
|
|
20
|
+
admin;
|
|
21
|
+
adminAddress;
|
|
22
|
+
account1;
|
|
23
|
+
account1Address;
|
|
24
|
+
account2;
|
|
25
|
+
account2Address;
|
|
22
26
|
constructor(testName){
|
|
23
27
|
this.logger = createLogger(`e2e:e2e_token_contract:${testName}`);
|
|
24
28
|
this.snapshotManager = createSnapshotManager(`e2e_token_contract/${testName}`, dataPath, {
|
|
@@ -34,19 +38,27 @@ export class TokenContractTest {
|
|
|
34
38
|
jest.setTimeout(120_000);
|
|
35
39
|
await this.snapshotManager.snapshot('3_accounts', deployAccounts(3, this.logger), async ({ deployedAccounts }, { pxe, aztecNode })=>{
|
|
36
40
|
this.node = aztecNode;
|
|
37
|
-
|
|
38
|
-
this.
|
|
41
|
+
const wallets = await Promise.all(deployedAccounts.map((a)=>getSchnorrWallet(pxe, a.address, a.signingKey)));
|
|
42
|
+
[this.admin, this.account1, this.account2] = wallets;
|
|
43
|
+
[this.adminAddress, this.account1Address, this.account2Address] = wallets.map((w)=>w.getAddress());
|
|
39
44
|
});
|
|
40
45
|
await this.snapshotManager.snapshot('e2e_token_contract', async ()=>{
|
|
41
46
|
// Create the token contract state.
|
|
42
47
|
// Move this account thing to addAccounts above?
|
|
43
48
|
this.logger.verbose(`Public deploy accounts...`);
|
|
44
|
-
await publicDeployAccounts(this.
|
|
49
|
+
await publicDeployAccounts(this.admin, [
|
|
50
|
+
this.adminAddress,
|
|
51
|
+
this.account1Address
|
|
52
|
+
]);
|
|
45
53
|
this.logger.verbose(`Deploying TokenContract...`);
|
|
46
|
-
const asset = await TokenContract.deploy(this.
|
|
54
|
+
const asset = await TokenContract.deploy(this.admin, this.adminAddress, TokenContractTest.TOKEN_NAME, TokenContractTest.TOKEN_SYMBOL, TokenContractTest.TOKEN_DECIMALS).send({
|
|
55
|
+
from: this.adminAddress
|
|
56
|
+
}).deployed();
|
|
47
57
|
this.logger.verbose(`Token deployed to ${asset.address}`);
|
|
48
58
|
this.logger.verbose(`Deploying bad account...`);
|
|
49
|
-
this.badAccount = await InvalidAccountContract.deploy(this.
|
|
59
|
+
this.badAccount = await InvalidAccountContract.deploy(this.admin).send({
|
|
60
|
+
from: this.adminAddress
|
|
61
|
+
}).deployed();
|
|
50
62
|
this.logger.verbose(`Deployed to ${this.badAccount.address}.`);
|
|
51
63
|
return {
|
|
52
64
|
tokenContractAddress: asset.address,
|
|
@@ -54,12 +66,17 @@ export class TokenContractTest {
|
|
|
54
66
|
};
|
|
55
67
|
}, async ({ tokenContractAddress, badAccountAddress })=>{
|
|
56
68
|
// Restore the token contract state.
|
|
57
|
-
this.asset = await TokenContract.at(tokenContractAddress, this.
|
|
69
|
+
this.asset = await TokenContract.at(tokenContractAddress, this.admin);
|
|
58
70
|
this.logger.verbose(`Token contract address: ${this.asset.address}`);
|
|
59
|
-
this.tokenSim = new TokenSimulator(this.asset, this.
|
|
60
|
-
|
|
71
|
+
this.tokenSim = new TokenSimulator(this.asset, this.admin, this.adminAddress, this.logger, [
|
|
72
|
+
this.adminAddress,
|
|
73
|
+
this.account1Address
|
|
74
|
+
]);
|
|
75
|
+
this.badAccount = await InvalidAccountContract.at(badAccountAddress, this.admin);
|
|
61
76
|
this.logger.verbose(`Bad account address: ${this.badAccount.address}`);
|
|
62
|
-
expect(await this.asset.methods.get_admin().simulate(
|
|
77
|
+
expect(await this.asset.methods.get_admin().simulate({
|
|
78
|
+
from: this.adminAddress
|
|
79
|
+
})).toBe(this.adminAddress.toBigInt());
|
|
63
80
|
});
|
|
64
81
|
// TokenContract.artifact.functions.forEach(fn => {
|
|
65
82
|
// const sig = decodeFunctionSignature(fn.name, fn.parameters);
|
|
@@ -75,27 +92,35 @@ export class TokenContractTest {
|
|
|
75
92
|
}
|
|
76
93
|
async applyMintSnapshot() {
|
|
77
94
|
await this.snapshotManager.snapshot('mint', async ()=>{
|
|
78
|
-
const { asset,
|
|
95
|
+
const { asset, admin, adminAddress } = this;
|
|
79
96
|
const amount = 10000n;
|
|
80
97
|
this.logger.verbose(`Minting ${amount} publicly...`);
|
|
81
|
-
await asset.methods.mint_to_public(
|
|
98
|
+
await asset.methods.mint_to_public(adminAddress, amount).send({
|
|
99
|
+
from: adminAddress
|
|
100
|
+
}).wait();
|
|
82
101
|
this.logger.verbose(`Minting ${amount} privately...`);
|
|
83
|
-
await mintTokensToPrivate(asset,
|
|
102
|
+
await mintTokensToPrivate(asset, adminAddress, admin, adminAddress, amount);
|
|
84
103
|
this.logger.verbose(`Minting complete.`);
|
|
85
104
|
return {
|
|
86
105
|
amount
|
|
87
106
|
};
|
|
88
107
|
}, async ({ amount })=>{
|
|
89
|
-
const { asset,
|
|
90
|
-
tokenSim.mintPublic(
|
|
91
|
-
const publicBalance = await asset.methods.balance_of_public(
|
|
108
|
+
const { asset, adminAddress, tokenSim } = this;
|
|
109
|
+
tokenSim.mintPublic(adminAddress, amount);
|
|
110
|
+
const publicBalance = await asset.methods.balance_of_public(adminAddress).simulate({
|
|
111
|
+
from: adminAddress
|
|
112
|
+
});
|
|
92
113
|
this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
|
|
93
|
-
expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(
|
|
94
|
-
tokenSim.mintPrivate(
|
|
95
|
-
const privateBalance = await asset.methods.balance_of_private(
|
|
114
|
+
expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(adminAddress));
|
|
115
|
+
tokenSim.mintPrivate(adminAddress, amount);
|
|
116
|
+
const privateBalance = await asset.methods.balance_of_private(adminAddress).simulate({
|
|
117
|
+
from: adminAddress
|
|
118
|
+
});
|
|
96
119
|
this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
|
|
97
|
-
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(
|
|
98
|
-
const totalSupply = await asset.methods.total_supply().simulate(
|
|
120
|
+
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(adminAddress));
|
|
121
|
+
const totalSupply = await asset.methods.total_supply().simulate({
|
|
122
|
+
from: adminAddress
|
|
123
|
+
});
|
|
99
124
|
this.logger.verbose(`Total supply: ${totalSupply}`);
|
|
100
125
|
expect(totalSupply).toEqual(tokenSim.totalSupply);
|
|
101
126
|
return Promise.resolve();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { InitialAccountData } from '@aztec/accounts/testing';
|
|
2
2
|
import { type AccountWalletWithSecretKey, type AztecNode, type CompleteAddress, EthAddress, type Logger } from '@aztec/aztec.js';
|
|
3
|
-
import { CheatCodes } from '@aztec/aztec
|
|
3
|
+
import { CheatCodes } from '@aztec/aztec/testing';
|
|
4
4
|
import { type ClientProtocolCircuitVerifier } from '@aztec/bb-prover';
|
|
5
5
|
import type { BlobSinkServer } from '@aztec/blob-sink/server';
|
|
6
6
|
import type { DeployL1ContractsReturnType } from '@aztec/ethereum';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2e_prover_test.d.ts","sourceRoot":"","sources":["../../src/fixtures/e2e_prover_test.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,UAAU,EACV,KAAK,MAAM,EAGZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"e2e_prover_test.d.ts","sourceRoot":"","sources":["../../src/fixtures/e2e_prover_test.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,UAAU,EACV,KAAK,MAAM,EAGZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAEL,KAAK,6BAA6B,EAGnC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAInE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMtE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGlE,OAAO,EAEL,KAAK,iBAAiB,EAIvB,MAAM,uBAAuB,CAAC;AAU/B;;;;;GAKG;AAEH,qBAAa,cAAc;IA6BvB,OAAO,CAAC,sBAAsB;IAE9B,OAAO,CAAC,UAAU;IA9BpB,MAAM,CAAC,UAAU,SAAU;IAC3B,MAAM,CAAC,YAAY,SAAS;IAC5B,MAAM,CAAC,cAAc,SAAO;IAC5B,OAAO,CAAC,eAAe,CAAmB;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,kBAAkB,EAAE,CAAM;IAC5C,OAAO,EAAE,0BAA0B,EAAE,CAAM;IAC3C,QAAQ,EAAE,eAAe,EAAE,CAAM;IACjC,eAAe,EAAG,aAAa,CAAC;IAChC,QAAQ,EAAG,cAAc,CAAC;IAC1B,SAAS,EAAG,SAAS,CAAC;IACtB,cAAc,EAAG,cAAc,CAAC;IAChC,GAAG,EAAG,UAAU,CAAC;IACjB,UAAU,EAAG,UAAU,CAAC;IACxB,QAAQ,EAAG,cAAc,CAAC;IAC1B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,eAAe,CAAC,CAAsB;IAC9C,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,oBAAoB,CAAC,EAAE,6BAA6B,CAAC;IACrD,YAAY,EAAE,aAAa,EAAE,CAAM;IACnC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,mBAAmB,CAAc;IAClC,WAAW,EAAG,2BAA2B,CAAC;IAC1C,aAAa,EAAG,UAAU,CAAC;gBAGhC,QAAQ,EAAE,MAAM,EACR,sBAAsB,EAAE,MAAM,EACtC,QAAQ,EAAE,UAAU,EACZ,UAAU,UAAO;IAa3B;;;;OAIG;IACG,kBAAkB;IAwDlB,KAAK;YAiKG,WAAW;IAQzB,QAAQ,GAAI,CAAC,EACX,MAAM,MAAM,EACZ,OAAO,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,UAAS,CAAC,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAA2B,KAChG,OAAO,CAAC,IAAI,CAAC,CAAwD;IAElE,QAAQ;IAeR,iBAAiB;CAiDxB"}
|
|
@@ -85,7 +85,9 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
85
85
|
this.logger.verbose(`Public deploy accounts...`);
|
|
86
86
|
await publicDeployAccounts(this.wallets[0], this.accounts.slice(0, 2));
|
|
87
87
|
this.logger.verbose(`Deploying TokenContract...`);
|
|
88
|
-
const asset = await TokenContract.deploy(this.wallets[0], this.accounts[0], FullProverTest.TOKEN_NAME, FullProverTest.TOKEN_SYMBOL, FullProverTest.TOKEN_DECIMALS).send(
|
|
88
|
+
const asset = await TokenContract.deploy(this.wallets[0], this.accounts[0], FullProverTest.TOKEN_NAME, FullProverTest.TOKEN_SYMBOL, FullProverTest.TOKEN_DECIMALS).send({
|
|
89
|
+
from: this.wallets[0].getAddress()
|
|
90
|
+
}).deployed();
|
|
89
91
|
this.logger.verbose(`Token deployed to ${asset.address}`);
|
|
90
92
|
return {
|
|
91
93
|
tokenContractAddress: asset.address
|
|
@@ -94,8 +96,10 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
94
96
|
// Restore the token contract state.
|
|
95
97
|
this.fakeProofsAsset = await TokenContract.at(tokenContractAddress, this.wallets[0]);
|
|
96
98
|
this.logger.verbose(`Token contract address: ${this.fakeProofsAsset.address}`);
|
|
97
|
-
this.tokenSim = new TokenSimulator(this.fakeProofsAsset, this.wallets[0], this.logger, this.accounts.map((a)=>a.address));
|
|
98
|
-
expect(await this.fakeProofsAsset.methods.get_admin().simulate(
|
|
99
|
+
this.tokenSim = new TokenSimulator(this.fakeProofsAsset, this.wallets[0], this.wallets[0].getAddress(), this.logger, this.accounts.map((a)=>a.address));
|
|
100
|
+
expect(await this.fakeProofsAsset.methods.get_admin().simulate({
|
|
101
|
+
from: this.accounts[0].address
|
|
102
|
+
})).toBe(this.accounts[0].address.toBigInt());
|
|
99
103
|
});
|
|
100
104
|
}
|
|
101
105
|
async setup() {
|
|
@@ -177,7 +181,9 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
177
181
|
const archiver = await createArchiver({
|
|
178
182
|
...this.context.aztecNodeConfig,
|
|
179
183
|
dataDirectory: undefined
|
|
180
|
-
},
|
|
184
|
+
}, {
|
|
185
|
+
blobSinkClient
|
|
186
|
+
}, {
|
|
181
187
|
blockUntilSync: true
|
|
182
188
|
});
|
|
183
189
|
// The simulated prover node (now shutdown) used private key index 2
|
|
@@ -189,7 +195,7 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
189
195
|
this.logger.verbose('Starting prover node');
|
|
190
196
|
const proverConfig = {
|
|
191
197
|
...this.context.aztecNodeConfig,
|
|
192
|
-
|
|
198
|
+
txCollectionNodeRpcUrls: [],
|
|
193
199
|
dataDirectory: undefined,
|
|
194
200
|
proverId: this.proverAddress.toField(),
|
|
195
201
|
realProofs: this.realProofs,
|
|
@@ -201,6 +207,7 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
201
207
|
txGatheringIntervalMs: 1000,
|
|
202
208
|
txGatheringBatchSize: 10,
|
|
203
209
|
txGatheringMaxParallelRequestsPerNode: 100,
|
|
210
|
+
txGatheringTimeoutMs: 24_000,
|
|
204
211
|
proverNodeFailedEpochStore: undefined
|
|
205
212
|
};
|
|
206
213
|
const sponsoredFPCAddress = await getSponsoredFPCAddress();
|
|
@@ -250,9 +257,13 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
250
257
|
const privateAmount = 10000n;
|
|
251
258
|
const publicAmount = 10000n;
|
|
252
259
|
this.logger.verbose(`Minting ${privateAmount + publicAmount} publicly...`);
|
|
253
|
-
await asset.methods.mint_to_public(accounts[0].address, privateAmount + publicAmount).send(
|
|
260
|
+
await asset.methods.mint_to_public(accounts[0].address, privateAmount + publicAmount).send({
|
|
261
|
+
from: accounts[0].address
|
|
262
|
+
}).wait();
|
|
254
263
|
this.logger.verbose(`Transferring ${privateAmount} to private...`);
|
|
255
|
-
await asset.methods.transfer_to_private(accounts[0].address, privateAmount).send(
|
|
264
|
+
await asset.methods.transfer_to_private(accounts[0].address, privateAmount).send({
|
|
265
|
+
from: accounts[0].address
|
|
266
|
+
}).wait();
|
|
256
267
|
this.logger.verbose(`Minting complete.`);
|
|
257
268
|
return {
|
|
258
269
|
amount: publicAmount
|
|
@@ -260,14 +271,20 @@ const { E2E_DATA_PATH: dataPath } = process.env;
|
|
|
260
271
|
}, async ({ amount })=>{
|
|
261
272
|
const { fakeProofsAsset: asset, accounts: [{ address }], tokenSim } = this;
|
|
262
273
|
tokenSim.mintPublic(address, amount);
|
|
263
|
-
const publicBalance = await asset.methods.balance_of_public(address).simulate(
|
|
274
|
+
const publicBalance = await asset.methods.balance_of_public(address).simulate({
|
|
275
|
+
from: address
|
|
276
|
+
});
|
|
264
277
|
this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
|
|
265
278
|
expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address));
|
|
266
279
|
tokenSim.mintPrivate(address, amount);
|
|
267
|
-
const privateBalance = await asset.methods.balance_of_private(address).simulate(
|
|
280
|
+
const privateBalance = await asset.methods.balance_of_private(address).simulate({
|
|
281
|
+
from: address
|
|
282
|
+
});
|
|
268
283
|
this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
|
|
269
284
|
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address));
|
|
270
|
-
const totalSupply = await asset.methods.total_supply().simulate(
|
|
285
|
+
const totalSupply = await asset.methods.total_supply().simulate({
|
|
286
|
+
from: address
|
|
287
|
+
});
|
|
271
288
|
this.logger.verbose(`Total supply: ${totalSupply}`);
|
|
272
289
|
expect(totalSupply).toEqual(tokenSim.totalSupply);
|
|
273
290
|
return Promise.resolve();
|
|
@@ -4,17 +4,20 @@
|
|
|
4
4
|
import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
5
5
|
import type { SentTx } from '@aztec/aztec.js';
|
|
6
6
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
7
|
+
import type { ProverNodeDeps } from '@aztec/prover-node';
|
|
7
8
|
import type { PXEService } from '@aztec/pxe/server';
|
|
8
9
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
9
10
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
10
11
|
export declare const ATTESTER_PRIVATE_KEYS_START_INDEX = 2;
|
|
12
|
+
export declare const SLASHER_PRIVATE_KEYS_START_INDEX = 12;
|
|
11
13
|
export interface NodeContext {
|
|
12
14
|
node: AztecNodeService;
|
|
13
15
|
pxeService: PXEService;
|
|
14
16
|
txs: SentTx[];
|
|
15
17
|
}
|
|
16
18
|
export declare function generatePrivateKeys(startIndex: number, numberOfKeys: number): `0x${string}`[];
|
|
17
|
-
export declare function createNodes(config: AztecNodeConfig, dateProvider: DateProvider, bootstrapNodeEnr: string, numNodes: number, bootNodePort: number, prefilledPublicData?: PublicDataTreeLeaf[], dataDirectory?: string, metricsPort?: number): Promise<AztecNodeService[]>;
|
|
19
|
+
export declare function createNodes(config: AztecNodeConfig, dateProvider: DateProvider, bootstrapNodeEnr: string, numNodes: number, bootNodePort: number, prefilledPublicData?: PublicDataTreeLeaf[], dataDirectory?: string, metricsPort?: number, indexOffset?: number): Promise<AztecNodeService[]>;
|
|
18
20
|
export declare function createNode(config: AztecNodeConfig, dateProvider: DateProvider, tcpPort: number, bootstrapNode: string | undefined, addressIndex: number, prefilledPublicData?: PublicDataTreeLeaf[], dataDirectory?: string, metricsPort?: number, loggerIdStorage?: AsyncLocalStorage<string>): Promise<AztecNodeService>;
|
|
21
|
+
export declare function createProverNode(config: AztecNodeConfig, tcpPort: number, bootstrapNode: string | undefined, addressIndex: number, proverNodeDeps: ProverNodeDeps & Required<Pick<ProverNodeDeps, 'dateProvider'>>, prefilledPublicData?: PublicDataTreeLeaf[], dataDirectory?: string, metricsPort?: number, loggerIdStorage?: AsyncLocalStorage<string>): Promise<import("@aztec/prover-node").ProverNode>;
|
|
19
22
|
export declare function createValidatorConfig(config: AztecNodeConfig, bootstrapNodeEnr?: string, port?: number, addressIndex?: number, dataDirectory?: string): Promise<AztecNodeConfig>;
|
|
20
23
|
//# sourceMappingURL=setup_p2p_test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup_p2p_test.d.ts","sourceRoot":"","sources":["../../src/fixtures/setup_p2p_test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"setup_p2p_test.d.ts","sourceRoot":"","sources":["../../src/fixtures/setup_p2p_test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAI9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAQrD,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD,eAAO,MAAM,gCAAgC,KAAK,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,EAAE,CAO7F;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,YAAY,EAC1B,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,EAC1C,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,EACpB,WAAW,SAAI,GACd,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoC7B;AAGD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,YAAY,EAAE,MAAM,EACpB,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,EAC1C,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,6BAQ5C;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,EAC/E,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,EAC1C,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,oDAyB5C;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,eAAe,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,GAAE,MAAU,EACxB,aAAa,CAAC,EAAE,MAAM,4BAuBvB"}
|