@aztec/cli 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2 → 0.77.0-testnet-ignition.21
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 +1 -1
- package/dest/cmds/contracts/index.d.ts +4 -0
- package/dest/cmds/contracts/index.d.ts.map +1 -0
- package/dest/cmds/contracts/inspect_contract.d.ts +3 -0
- package/dest/cmds/contracts/inspect_contract.d.ts.map +1 -0
- package/dest/cmds/contracts/inspect_contract.js +3 -3
- package/dest/cmds/contracts/parse_parameter_struct.d.ts +3 -0
- package/dest/cmds/contracts/parse_parameter_struct.d.ts.map +1 -0
- package/dest/cmds/devnet/bootstrap_network.d.ts +3 -0
- package/dest/cmds/devnet/bootstrap_network.d.ts.map +1 -0
- package/dest/cmds/devnet/bootstrap_network.js +13 -10
- package/dest/cmds/devnet/faucet.d.ts +4 -0
- package/dest/cmds/devnet/faucet.d.ts.map +1 -0
- package/dest/cmds/devnet/index.d.ts +4 -0
- package/dest/cmds/devnet/index.d.ts.map +1 -0
- package/dest/cmds/devnet/index.js +5 -3
- package/dest/cmds/infrastructure/index.d.ts +4 -0
- package/dest/cmds/infrastructure/index.d.ts.map +1 -0
- package/dest/cmds/infrastructure/index.js +8 -6
- package/dest/cmds/infrastructure/sequencers.d.ts +13 -0
- package/dest/cmds/infrastructure/sequencers.d.ts.map +1 -0
- package/dest/cmds/infrastructure/sequencers.js +5 -5
- package/dest/cmds/infrastructure/setup_l2_contract.d.ts +3 -0
- package/dest/cmds/infrastructure/setup_l2_contract.d.ts.map +1 -0
- package/dest/cmds/infrastructure/setup_l2_contract.js +43 -0
- package/dest/cmds/l1/advance_epoch.d.ts +3 -0
- package/dest/cmds/l1/advance_epoch.d.ts.map +1 -0
- package/dest/cmds/l1/advance_epoch.js +3 -3
- package/dest/cmds/l1/assume_proven_through.d.ts +3 -0
- package/dest/cmds/l1/assume_proven_through.d.ts.map +1 -0
- package/dest/cmds/l1/assume_proven_through.js +8 -8
- package/dest/cmds/l1/bridge_erc20.d.ts +4 -0
- package/dest/cmds/l1/bridge_erc20.d.ts.map +1 -0
- package/dest/cmds/l1/bridge_erc20.js +3 -3
- package/dest/cmds/l1/create_l1_account.d.ts +3 -0
- package/dest/cmds/l1/create_l1_account.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_l1_contracts.d.ts +4 -0
- package/dest/cmds/l1/deploy_l1_contracts.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_l1_contracts.js +7 -3
- package/dest/cmds/l1/deploy_l1_verifier.d.ts +5 -0
- package/dest/cmds/l1/deploy_l1_verifier.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_l1_verifier.js +4 -4
- package/dest/cmds/l1/deploy_new_rollup.d.ts +4 -0
- package/dest/cmds/l1/deploy_new_rollup.d.ts.map +1 -0
- package/dest/cmds/l1/deploy_new_rollup.js +19 -0
- package/dest/cmds/l1/get_l1_addresses.d.ts +4 -0
- package/dest/cmds/l1/get_l1_addresses.d.ts.map +1 -0
- package/dest/cmds/l1/get_l1_addresses.js +18 -0
- package/dest/cmds/l1/get_l1_balance.d.ts +4 -0
- package/dest/cmds/l1/get_l1_balance.d.ts.map +1 -0
- package/dest/cmds/l1/get_l1_balance.js +4 -4
- package/dest/cmds/l1/governance_utils.d.ts +50 -0
- package/dest/cmds/l1/governance_utils.d.ts.map +1 -0
- package/dest/cmds/l1/governance_utils.js +85 -0
- package/dest/cmds/l1/index.d.ts +4 -0
- package/dest/cmds/l1/index.d.ts.map +1 -0
- package/dest/cmds/l1/index.js +108 -27
- package/dest/cmds/l1/prover_stats.d.ts +14 -0
- package/dest/cmds/l1/prover_stats.d.ts.map +1 -0
- package/dest/cmds/l1/prover_stats.js +6 -6
- package/dest/cmds/l1/update_l1_validators.d.ts +30 -0
- package/dest/cmds/l1/update_l1_validators.d.ts.map +1 -0
- package/dest/cmds/l1/update_l1_validators.js +22 -22
- package/dest/cmds/misc/compute_selector.d.ts +3 -0
- package/dest/cmds/misc/compute_selector.d.ts.map +1 -0
- package/dest/cmds/misc/compute_selector.js +1 -1
- package/dest/cmds/misc/example_contracts.d.ts +3 -0
- package/dest/cmds/misc/example_contracts.d.ts.map +1 -0
- package/dest/cmds/misc/generate_bootnode_enr.d.ts +3 -0
- package/dest/cmds/misc/generate_bootnode_enr.d.ts.map +1 -0
- package/dest/cmds/misc/generate_bootnode_enr.js +5 -0
- package/dest/cmds/misc/generate_p2p_private_key.d.ts +3 -0
- package/dest/cmds/misc/generate_p2p_private_key.d.ts.map +1 -0
- package/dest/cmds/misc/generate_secret_and_hash.d.ts +3 -0
- package/dest/cmds/misc/generate_secret_and_hash.d.ts.map +1 -0
- package/dest/cmds/misc/generate_secret_key.d.ts +5 -0
- package/dest/cmds/misc/generate_secret_key.d.ts.map +1 -0
- package/dest/cmds/misc/index.d.ts +4 -0
- package/dest/cmds/misc/index.d.ts.map +1 -0
- package/dest/cmds/misc/index.js +9 -1
- package/dest/cmds/misc/setup_contracts.d.ts +7 -0
- package/dest/cmds/misc/setup_contracts.d.ts.map +1 -0
- package/dest/cmds/misc/setup_contracts.js +5 -3
- package/dest/cmds/misc/update/common.d.ts +17 -0
- package/dest/cmds/misc/update/common.d.ts.map +1 -0
- package/dest/cmds/misc/update/github.d.ts +4 -0
- package/dest/cmds/misc/update/github.d.ts.map +1 -0
- package/dest/cmds/misc/update/noir.d.ts +10 -0
- package/dest/cmds/misc/update/noir.d.ts.map +1 -0
- package/dest/cmds/misc/update/npm.d.ts +34 -0
- package/dest/cmds/misc/update/npm.d.ts.map +1 -0
- package/dest/cmds/misc/update/utils.d.ts +14 -0
- package/dest/cmds/misc/update/utils.d.ts.map +1 -0
- package/dest/cmds/misc/update.d.ts +3 -0
- package/dest/cmds/misc/update.d.ts.map +1 -0
- package/dest/cmds/pxe/add_contract.d.ts +5 -0
- package/dest/cmds/pxe/add_contract.d.ts.map +1 -0
- package/dest/cmds/pxe/add_contract.js +6 -4
- package/dest/cmds/pxe/block_number.d.ts +3 -0
- package/dest/cmds/pxe/block_number.d.ts.map +1 -0
- package/dest/cmds/pxe/get_account.d.ts +4 -0
- package/dest/cmds/pxe/get_account.d.ts.map +1 -0
- package/dest/cmds/pxe/get_accounts.d.ts +3 -0
- package/dest/cmds/pxe/get_accounts.d.ts.map +1 -0
- package/dest/cmds/pxe/get_block.d.ts +3 -0
- package/dest/cmds/pxe/get_block.d.ts.map +1 -0
- package/dest/cmds/pxe/get_contract_data.d.ts +4 -0
- package/dest/cmds/pxe/get_contract_data.d.ts.map +1 -0
- package/dest/cmds/pxe/get_contract_data.js +1 -1
- package/dest/cmds/pxe/get_current_base_fee.d.ts +3 -0
- package/dest/cmds/pxe/get_current_base_fee.d.ts.map +1 -0
- package/dest/cmds/pxe/get_l1_to_l2_message_witness.d.ts +4 -0
- package/dest/cmds/pxe/get_l1_to_l2_message_witness.d.ts.map +1 -0
- package/dest/cmds/pxe/get_logs.d.ts +4 -0
- package/dest/cmds/pxe/get_logs.d.ts.map +1 -0
- package/dest/cmds/pxe/get_node_info.d.ts +3 -0
- package/dest/cmds/pxe/get_node_info.d.ts.map +1 -0
- package/dest/cmds/pxe/get_node_info.js +2 -2
- package/dest/cmds/pxe/get_pxe_info.d.ts +3 -0
- package/dest/cmds/pxe/get_pxe_info.d.ts.map +1 -0
- package/dest/cmds/pxe/index.d.ts +4 -0
- package/dest/cmds/pxe/index.d.ts.map +1 -0
- package/dest/cmds/pxe/index.js +1 -1
- package/dest/utils/aztec.d.ts +68 -0
- package/dest/utils/aztec.d.ts.map +1 -0
- package/dest/utils/aztec.js +34 -23
- package/dest/utils/commands.d.ts +143 -0
- package/dest/utils/commands.d.ts.map +1 -0
- package/dest/utils/commands.js +2 -2
- package/dest/utils/encoding.d.ts +15 -0
- package/dest/utils/encoding.d.ts.map +1 -0
- package/dest/utils/encoding.js +6 -13
- package/dest/utils/github.d.ts +4 -0
- package/dest/utils/github.d.ts.map +1 -0
- package/dest/utils/index.d.ts +5 -0
- package/dest/utils/index.d.ts.map +1 -0
- package/dest/utils/inspect.d.ts +17 -0
- package/dest/utils/inspect.d.ts.map +1 -0
- package/dest/utils/inspect.js +4 -4
- package/package.json +21 -20
- package/src/cmds/contracts/index.ts +2 -2
- package/src/cmds/contracts/inspect_contract.ts +5 -5
- package/src/cmds/contracts/parse_parameter_struct.ts +2 -2
- package/src/cmds/devnet/bootstrap_network.ts +24 -12
- package/src/cmds/devnet/faucet.ts +2 -2
- package/src/cmds/devnet/index.ts +16 -8
- package/src/cmds/infrastructure/index.ts +12 -11
- package/src/cmds/infrastructure/sequencers.ts +10 -7
- package/src/cmds/infrastructure/setup_l2_contract.ts +47 -0
- package/src/cmds/l1/advance_epoch.ts +4 -4
- package/src/cmds/l1/assume_proven_through.ts +8 -14
- package/src/cmds/l1/bridge_erc20.ts +5 -6
- package/src/cmds/l1/create_l1_account.ts +1 -1
- package/src/cmds/l1/deploy_l1_contracts.ts +13 -5
- package/src/cmds/l1/deploy_l1_verifier.ts +7 -7
- package/src/cmds/l1/deploy_new_rollup.ts +58 -0
- package/src/cmds/l1/get_l1_addresses.ts +30 -0
- package/src/cmds/l1/get_l1_balance.ts +9 -6
- package/src/cmds/l1/governance_utils.ts +187 -0
- package/src/cmds/l1/index.ts +238 -97
- package/src/cmds/l1/prover_stats.ts +21 -11
- package/src/cmds/l1/update_l1_validators.ts +25 -25
- package/src/cmds/misc/compute_selector.ts +2 -2
- package/src/cmds/misc/example_contracts.ts +1 -1
- package/src/cmds/misc/generate_bootnode_enr.ts +12 -0
- package/src/cmds/misc/generate_p2p_private_key.ts +1 -1
- package/src/cmds/misc/generate_secret_and_hash.ts +1 -1
- package/src/cmds/misc/index.ts +25 -3
- package/src/cmds/misc/setup_contracts.ts +6 -4
- package/src/cmds/misc/update/noir.ts +2 -2
- package/src/cmds/misc/update/npm.ts +2 -2
- package/src/cmds/misc/update/utils.ts +1 -1
- package/src/cmds/misc/update.ts +2 -2
- package/src/cmds/pxe/add_contract.ts +7 -5
- package/src/cmds/pxe/block_number.ts +1 -1
- package/src/cmds/pxe/get_account.ts +2 -2
- package/src/cmds/pxe/get_accounts.ts +1 -1
- package/src/cmds/pxe/get_block.ts +1 -1
- package/src/cmds/pxe/get_contract_data.ts +5 -3
- package/src/cmds/pxe/get_current_base_fee.ts +1 -1
- package/src/cmds/pxe/get_l1_to_l2_message_witness.ts +1 -1
- package/src/cmds/pxe/get_logs.ts +2 -2
- package/src/cmds/pxe/get_node_info.ts +3 -3
- package/src/cmds/pxe/get_pxe_info.ts +1 -1
- package/src/cmds/pxe/index.ts +3 -3
- package/src/utils/aztec.ts +74 -44
- package/src/utils/commands.ts +4 -4
- package/src/utils/encoding.ts +7 -13
- package/src/utils/inspect.ts +8 -7
- package/dest/cmds/infrastructure/setup_protocol_contract.js +0 -31
- package/src/cmds/infrastructure/setup_protocol_contract.ts +0 -36
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type EthAddress } from '@aztec/circuits.js';
|
|
2
1
|
import {
|
|
3
2
|
EthCheatCodes,
|
|
4
3
|
createEthereumChain,
|
|
@@ -6,14 +5,15 @@ import {
|
|
|
6
5
|
getL1ContractsConfigEnvVars,
|
|
7
6
|
isAnvilTestChain,
|
|
8
7
|
} from '@aztec/ethereum';
|
|
9
|
-
import
|
|
8
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
9
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
10
10
|
import { ForwarderAbi, ForwarderBytecode, RollupAbi, TestERC20Abi } from '@aztec/l1-artifacts';
|
|
11
11
|
|
|
12
|
-
import { createPublicClient, createWalletClient, getContract, http } from 'viem';
|
|
12
|
+
import { createPublicClient, createWalletClient, fallback, getContract, http } from 'viem';
|
|
13
13
|
import { generatePrivateKey, mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
14
14
|
|
|
15
15
|
export interface RollupCommandArgs {
|
|
16
|
-
|
|
16
|
+
rpcUrls: string[];
|
|
17
17
|
chainId: number;
|
|
18
18
|
privateKey?: string;
|
|
19
19
|
mnemonic?: string;
|
|
@@ -37,7 +37,7 @@ export function generateL1Account() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export async function addL1Validator({
|
|
40
|
-
|
|
40
|
+
rpcUrls,
|
|
41
41
|
chainId,
|
|
42
42
|
privateKey,
|
|
43
43
|
mnemonic,
|
|
@@ -49,8 +49,8 @@ export async function addL1Validator({
|
|
|
49
49
|
}: RollupCommandArgs & LoggerArgs & { validatorAddress: EthAddress }) {
|
|
50
50
|
const config = getL1ContractsConfigEnvVars();
|
|
51
51
|
const dualLog = makeDualLog(log, debugLogger);
|
|
52
|
-
const publicClient = getPublicClient(
|
|
53
|
-
const walletClient = getWalletClient(
|
|
52
|
+
const publicClient = getPublicClient(rpcUrls, chainId);
|
|
53
|
+
const walletClient = getWalletClient(rpcUrls, chainId, privateKey, mnemonic);
|
|
54
54
|
const rollup = getContract({
|
|
55
55
|
address: rollupAddress.toString(),
|
|
56
56
|
abi: RollupAbi,
|
|
@@ -83,7 +83,7 @@ export async function addL1Validator({
|
|
|
83
83
|
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
84
84
|
if (isAnvilTestChain(chainId)) {
|
|
85
85
|
dualLog(`Funding validator on L1`);
|
|
86
|
-
const cheatCodes = new EthCheatCodes(
|
|
86
|
+
const cheatCodes = new EthCheatCodes(rpcUrls, debugLogger);
|
|
87
87
|
await cheatCodes.setBalance(validatorAddress, 10n ** 20n);
|
|
88
88
|
} else {
|
|
89
89
|
const balance = await publicClient.getBalance({ address: validatorAddress.toString() });
|
|
@@ -96,7 +96,7 @@ export async function addL1Validator({
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export async function removeL1Validator({
|
|
99
|
-
|
|
99
|
+
rpcUrls,
|
|
100
100
|
chainId,
|
|
101
101
|
privateKey,
|
|
102
102
|
mnemonic,
|
|
@@ -106,8 +106,8 @@ export async function removeL1Validator({
|
|
|
106
106
|
debugLogger,
|
|
107
107
|
}: RollupCommandArgs & LoggerArgs & { validatorAddress: EthAddress }) {
|
|
108
108
|
const dualLog = makeDualLog(log, debugLogger);
|
|
109
|
-
const publicClient = getPublicClient(
|
|
110
|
-
const walletClient = getWalletClient(
|
|
109
|
+
const publicClient = getPublicClient(rpcUrls, chainId);
|
|
110
|
+
const walletClient = getWalletClient(rpcUrls, chainId, privateKey, mnemonic);
|
|
111
111
|
const rollup = getContract({
|
|
112
112
|
address: rollupAddress.toString(),
|
|
113
113
|
abi: RollupAbi,
|
|
@@ -121,7 +121,7 @@ export async function removeL1Validator({
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export async function pruneRollup({
|
|
124
|
-
|
|
124
|
+
rpcUrls,
|
|
125
125
|
chainId,
|
|
126
126
|
privateKey,
|
|
127
127
|
mnemonic,
|
|
@@ -130,8 +130,8 @@ export async function pruneRollup({
|
|
|
130
130
|
debugLogger,
|
|
131
131
|
}: RollupCommandArgs & LoggerArgs) {
|
|
132
132
|
const dualLog = makeDualLog(log, debugLogger);
|
|
133
|
-
const publicClient = getPublicClient(
|
|
134
|
-
const walletClient = getWalletClient(
|
|
133
|
+
const publicClient = getPublicClient(rpcUrls, chainId);
|
|
134
|
+
const walletClient = getWalletClient(rpcUrls, chainId, privateKey, mnemonic);
|
|
135
135
|
const rollup = getContract({
|
|
136
136
|
address: rollupAddress.toString(),
|
|
137
137
|
abi: RollupAbi,
|
|
@@ -145,7 +145,7 @@ export async function pruneRollup({
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export async function fastForwardEpochs({
|
|
148
|
-
|
|
148
|
+
rpcUrls,
|
|
149
149
|
chainId,
|
|
150
150
|
rollupAddress,
|
|
151
151
|
numEpochs,
|
|
@@ -153,14 +153,14 @@ export async function fastForwardEpochs({
|
|
|
153
153
|
debugLogger,
|
|
154
154
|
}: RollupCommandArgs & LoggerArgs & { numEpochs: bigint }) {
|
|
155
155
|
const dualLog = makeDualLog(log, debugLogger);
|
|
156
|
-
const publicClient = getPublicClient(
|
|
156
|
+
const publicClient = getPublicClient(rpcUrls, chainId);
|
|
157
157
|
const rollup = getContract({
|
|
158
158
|
address: rollupAddress.toString(),
|
|
159
159
|
abi: RollupAbi,
|
|
160
160
|
client: publicClient,
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
const cheatCodes = new EthCheatCodes(
|
|
163
|
+
const cheatCodes = new EthCheatCodes(rpcUrls, debugLogger);
|
|
164
164
|
const currentSlot = await rollup.read.getCurrentSlot();
|
|
165
165
|
const l2SlotsInEpoch = await rollup.read.getEpochDuration();
|
|
166
166
|
const timestamp = await rollup.read.getTimestampForSlot([currentSlot + l2SlotsInEpoch * numEpochs]);
|
|
@@ -178,9 +178,9 @@ export async function fastForwardEpochs({
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
export async function debugRollup({
|
|
181
|
+
export async function debugRollup({ rpcUrls, chainId, rollupAddress, log }: RollupCommandArgs & LoggerArgs) {
|
|
182
182
|
const config = getL1ContractsConfigEnvVars();
|
|
183
|
-
const publicClient = getPublicClient(
|
|
183
|
+
const publicClient = getPublicClient(rpcUrls, chainId);
|
|
184
184
|
const rollup = getContract({
|
|
185
185
|
address: rollupAddress.toString(),
|
|
186
186
|
abi: RollupAbi,
|
|
@@ -215,13 +215,13 @@ function makeDualLog(log: LogFn, debugLogger: Logger) {
|
|
|
215
215
|
};
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
function getPublicClient(
|
|
219
|
-
const chain = createEthereumChain(
|
|
220
|
-
return createPublicClient({ chain: chain.chainInfo, transport: http(
|
|
218
|
+
function getPublicClient(rpcUrls: string[], chainId: number) {
|
|
219
|
+
const chain = createEthereumChain(rpcUrls, chainId);
|
|
220
|
+
return createPublicClient({ chain: chain.chainInfo, transport: fallback(rpcUrls.map(url => http(url))) });
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
function getWalletClient(
|
|
224
|
-
|
|
224
|
+
rpcUrls: string[],
|
|
225
225
|
chainId: number,
|
|
226
226
|
privateKey: string | undefined,
|
|
227
227
|
mnemonic: string | undefined,
|
|
@@ -230,9 +230,9 @@ function getWalletClient(
|
|
|
230
230
|
throw new Error('Either privateKey or mnemonic must be provided to create a wallet client');
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
const chain = createEthereumChain(
|
|
233
|
+
const chain = createEthereumChain(rpcUrls, chainId);
|
|
234
234
|
const account = !privateKey
|
|
235
235
|
? mnemonicToAccount(mnemonic!)
|
|
236
236
|
: privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`);
|
|
237
|
-
return createWalletClient({ account, chain: chain.chainInfo, transport: http(
|
|
237
|
+
return createWalletClient({ account, chain: chain.chainInfo, transport: fallback(rpcUrls.map(url => http(url))) });
|
|
238
238
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
2
|
+
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
3
3
|
|
|
4
4
|
export async function computeSelector(functionSignature: string, log: LogFn) {
|
|
5
5
|
const selector = await FunctionSelector.fromSignature(functionSignature);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
2
|
+
import { createBootnodeENRandPeerId } from '@aztec/p2p/enr';
|
|
3
|
+
|
|
4
|
+
export async function generateEncodedBootnodeENR(
|
|
5
|
+
privateKey: string,
|
|
6
|
+
udpAnnounceAddress: string,
|
|
7
|
+
l1ChainId: number,
|
|
8
|
+
log: LogFn,
|
|
9
|
+
) {
|
|
10
|
+
const { enr } = await createBootnodeENRandPeerId(privateKey, udpAnnounceAddress, l1ChainId);
|
|
11
|
+
log(`ENR: ${enr.encodeTxt()}`);
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computeSecretHash } from '@aztec/aztec.js';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
-
import {
|
|
3
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
5
|
export function generateSecretAndHash(log: LogFn) {
|
|
6
6
|
const secret = Fr.random();
|
package/src/cmds/misc/index.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
2
|
+
import { printENR } from '@aztec/p2p/enr';
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import type { Command } from 'commander';
|
|
4
5
|
|
|
5
|
-
import { prettyPrintJSON } from '../../utils/commands.js';
|
|
6
|
+
import { l1ChainIdOption, prettyPrintJSON } from '../../utils/commands.js';
|
|
6
7
|
|
|
7
8
|
export function injectCommands(program: Command, log: LogFn) {
|
|
8
9
|
program
|
|
@@ -29,6 +30,27 @@ export function injectCommands(program: Command, log: LogFn) {
|
|
|
29
30
|
await generateP2PPrivateKey(log);
|
|
30
31
|
});
|
|
31
32
|
|
|
33
|
+
program
|
|
34
|
+
.command('generate-bootnode-enr')
|
|
35
|
+
.summary('Generates the encoded ENR record for a bootnode.')
|
|
36
|
+
.description('Generates the encoded ENR record for a bootnode.')
|
|
37
|
+
.argument('<privateKey>', 'The peer id private key of the bootnode')
|
|
38
|
+
.argument('<udpAnnounceAddress>', 'The bootnode UDP announce address')
|
|
39
|
+
.addOption(l1ChainIdOption)
|
|
40
|
+
.action(async (privateKey: string, udpAnnounceAddress: string, options) => {
|
|
41
|
+
const { generateEncodedBootnodeENR } = await import('./generate_bootnode_enr.js');
|
|
42
|
+
await generateEncodedBootnodeENR(privateKey, udpAnnounceAddress, options.l1ChainId, log);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
program
|
|
46
|
+
.command('decode-enr')
|
|
47
|
+
.summary('Decodes an ENR record')
|
|
48
|
+
.description('Decodes and ENR record')
|
|
49
|
+
.argument('<enr>', 'The encoded ENR string')
|
|
50
|
+
.action(async (enr: string) => {
|
|
51
|
+
await printENR(enr, log);
|
|
52
|
+
});
|
|
53
|
+
|
|
32
54
|
program
|
|
33
55
|
.command('example-contracts')
|
|
34
56
|
.description('Lists the example contracts available to deploy from @aztec/noir-contracts.js')
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DefaultWaitOpts, type EthAddress,
|
|
2
|
-
import { FEE_JUICE_INITIAL_MINT
|
|
3
|
-
import {
|
|
1
|
+
import { DefaultWaitOpts, type EthAddress, FeeJuicePaymentMethod, type Wallet } from '@aztec/aztec.js';
|
|
2
|
+
import { FEE_JUICE_INITIAL_MINT } from '@aztec/constants';
|
|
3
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
4
4
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
|
+
import { Gas } from '@aztec/stdlib/gas';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Deploys the contract to pay for gas on L2.
|
|
@@ -25,9 +26,10 @@ export async function setupCanonicalL2FeeJuice(
|
|
|
25
26
|
|
|
26
27
|
if (portalAddress.isZero()) {
|
|
27
28
|
log('setupCanonicalL2FeeJuice: Calling initialize on fee juice contract...');
|
|
29
|
+
const paymentMethod = new FeeJuicePaymentMethod(ProtocolContractAddress.FeeJuice);
|
|
28
30
|
await feeJuiceContract.methods
|
|
29
31
|
.initialize(feeJuicePortalAddress, FEE_JUICE_INITIAL_MINT)
|
|
30
|
-
.send({ fee: { paymentMethod
|
|
32
|
+
.send({ fee: { paymentMethod, gasSettings: { teardownGasLimits: Gas.empty() } } })
|
|
31
33
|
.wait(waitOpts);
|
|
32
34
|
} else {
|
|
33
35
|
log(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
2
2
|
import { parseNoirPackageConfig } from '@aztec/foundation/noir';
|
|
3
3
|
|
|
4
4
|
import TOML from '@iarna/toml';
|
|
5
5
|
import { readFile } from 'fs/promises';
|
|
6
6
|
import { join, relative, resolve } from 'path';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import type { DependencyChanges } from './common.js';
|
|
9
9
|
import { atomicUpdateFile, prettyPrintNargoToml } from './utils.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from 'child_process';
|
|
4
4
|
import { existsSync } from 'fs';
|
|
@@ -6,7 +6,7 @@ import { readFile } from 'fs/promises';
|
|
|
6
6
|
import { join, relative, resolve } from 'path';
|
|
7
7
|
import { type SemVer, parse } from 'semver';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import type { DependencyChanges } from './common.js';
|
|
10
10
|
import { atomicUpdateFile } from './utils.js';
|
|
11
11
|
|
|
12
12
|
const deprecatedNpmPackages = new Set<string>(['@aztec/cli', '@aztec/aztec-sandbox']);
|
package/src/cmds/misc/update.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
2
|
-
import {
|
|
2
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
import { relative, resolve } from 'path';
|
|
5
5
|
import { parse } from 'semver';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type { DependencyChanges } from './update/common.js';
|
|
8
8
|
import { GITHUB_TAG_PREFIX } from './update/github.js';
|
|
9
9
|
import { updateAztecNr } from './update/noir.js';
|
|
10
10
|
import { getNewestVersion, updateAztecDeps, updateLockfile } from './update/npm.js';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AztecAddress, type ContractInstanceWithAddress, type Fr, getContractClassFromArtifact } from '@aztec/aztec.js';
|
|
2
2
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
3
|
-
import {
|
|
4
|
-
import { computeContractAddressFromInstance } from '@aztec/
|
|
5
|
-
import {
|
|
3
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
4
|
+
import { computeContractAddressFromInstance } from '@aztec/stdlib/contract';
|
|
5
|
+
import { PublicKeys } from '@aztec/stdlib/keys';
|
|
6
6
|
|
|
7
7
|
import { getContractArtifact } from '../../utils/aztec.js';
|
|
8
8
|
|
|
@@ -18,11 +18,13 @@ export async function addContract(
|
|
|
18
18
|
log: LogFn,
|
|
19
19
|
) {
|
|
20
20
|
const artifact = await getContractArtifact(contractArtifactPath, log);
|
|
21
|
+
const contractClass = await getContractClassFromArtifact(artifact);
|
|
21
22
|
const instance: ContractInstanceWithAddress = {
|
|
22
23
|
version: 1,
|
|
23
24
|
salt,
|
|
24
25
|
initializationHash,
|
|
25
|
-
|
|
26
|
+
currentContractClassId: contractClass.id,
|
|
27
|
+
originalContractClassId: contractClass.id,
|
|
26
28
|
publicKeys: publicKeys ?? PublicKeys.default(),
|
|
27
29
|
address,
|
|
28
30
|
deployer: deployer ?? AztecAddress.ZERO,
|
|
@@ -35,5 +37,5 @@ export async function addContract(
|
|
|
35
37
|
const client = await createCompatibleClient(rpcUrl, debugLogger);
|
|
36
38
|
|
|
37
39
|
await client.registerContract({ artifact, instance });
|
|
38
|
-
log(`\nContract added to PXE at ${address.toString()} with class ${instance.
|
|
40
|
+
log(`\nContract added to PXE at ${address.toString()} with class ${instance.currentContractClassId.toString()}\n`);
|
|
39
41
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export async function blockNumber(rpcUrl: string, debugLogger: Logger, log: LogFn) {
|
|
5
5
|
const client = await createCompatibleClient(rpcUrl, debugLogger);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AztecAddress } from '@aztec/aztec.js';
|
|
2
2
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
5
|
export async function getAccount(aztecAddress: AztecAddress, rpcUrl: string, debugLogger: Logger, log: LogFn) {
|
|
6
6
|
const client = await createCompatibleClient(rpcUrl, debugLogger);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AztecAddress } from '@aztec/aztec.js';
|
|
2
2
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
5
|
export async function getContractData(
|
|
6
6
|
rpcUrl: string,
|
|
@@ -16,7 +16,9 @@ export async function getContractData(
|
|
|
16
16
|
isContractPubliclyDeployed: isPubliclyDeployed,
|
|
17
17
|
} = await client.getContractMetadata(contractAddress);
|
|
18
18
|
const contractClass =
|
|
19
|
-
includeBytecode &&
|
|
19
|
+
includeBytecode &&
|
|
20
|
+
instance &&
|
|
21
|
+
(await client.getContractClassMetadata(instance?.currentContractClassId)).contractClass;
|
|
20
22
|
|
|
21
23
|
const isPrivatelyDeployed = !!instance;
|
|
22
24
|
const initStr = isInitialized ? 'initialized' : 'not initialized';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
2
2
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
3
|
-
import {
|
|
3
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
5
5
|
export async function getCurrentBaseFee(rpcUrl: string, debugLogger: Logger, log: LogFn) {
|
|
6
6
|
const client = await createCompatibleClient(rpcUrl, debugLogger);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AztecAddress, type Fr, createCompatibleClient } from '@aztec/aztec.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export async function getL1ToL2MessageWitness(
|
|
5
5
|
rpcUrl: string,
|
package/src/cmds/pxe/get_logs.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AztecAddress, LogFilter, LogId, TxHash } from '@aztec/aztec.js';
|
|
2
2
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
4
4
|
import { sleep } from '@aztec/foundation/sleep';
|
|
5
5
|
|
|
6
6
|
export async function getLogs(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AztecNode, type PXE, createAztecNodeClient, createCompatibleClient } from '@aztec/aztec.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export async function getNodeInfo(
|
|
5
5
|
rpcUrl: string,
|
|
@@ -34,7 +34,7 @@ export async function getNodeInfo(
|
|
|
34
34
|
rewardDistributor: info.l1ContractAddresses.rewardDistributorAddress.toString(),
|
|
35
35
|
governanceProposer: info.l1ContractAddresses.governanceProposerAddress.toString(),
|
|
36
36
|
governance: info.l1ContractAddresses.governanceAddress.toString(),
|
|
37
|
-
slashFactory: info.l1ContractAddresses.slashFactoryAddress
|
|
37
|
+
slashFactory: info.l1ContractAddresses.slashFactoryAddress?.toString(),
|
|
38
38
|
},
|
|
39
39
|
protocolContractAddresses: {
|
|
40
40
|
classRegisterer: info.protocolContractAddresses.classRegisterer.toString(),
|
|
@@ -60,7 +60,7 @@ export async function getNodeInfo(
|
|
|
60
60
|
log(` RewardDistributor Address: ${info.l1ContractAddresses.rewardDistributorAddress.toString()}`);
|
|
61
61
|
log(` GovernanceProposer Address: ${info.l1ContractAddresses.governanceProposerAddress.toString()}`);
|
|
62
62
|
log(` Governance Address: ${info.l1ContractAddresses.governanceAddress.toString()}`);
|
|
63
|
-
log(` SlashFactory Address: ${info.l1ContractAddresses.slashFactoryAddress
|
|
63
|
+
log(` SlashFactory Address: ${info.l1ContractAddresses.slashFactoryAddress?.toString()}`);
|
|
64
64
|
|
|
65
65
|
log(`L2 Contract Addresses:`);
|
|
66
66
|
log(` Class Registerer: ${info.protocolContractAddresses.classRegisterer.toString()}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCompatibleClient } from '@aztec/aztec.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export async function getPXEInfo(rpcUrl: string, debugLogger: Logger, log: LogFn) {
|
|
5
5
|
const client = await createCompatibleClient(rpcUrl, debugLogger);
|
package/src/cmds/pxe/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Fr } from '@aztec/
|
|
2
|
-
import {
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { Command } from 'commander';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
logJson,
|
package/src/utils/aztec.ts
CHANGED
|
@@ -1,25 +1,15 @@
|
|
|
1
|
+
import type { EthAddress, PXE } from '@aztec/aztec.js';
|
|
1
2
|
import { type ContractArtifact, type FunctionArtifact, loadContractArtifact } from '@aztec/aztec.js/abi';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { type LogFn, type Logger } from '@aztec/foundation/log';
|
|
7
|
-
import { type NoirPackageConfig } from '@aztec/foundation/noir';
|
|
8
|
-
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
3
|
+
import type { DeployL1ContractsReturnType, L1ContractsConfig, RollupContract } from '@aztec/ethereum';
|
|
4
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import type { LogFn, Logger } from '@aztec/foundation/log';
|
|
6
|
+
import type { NoirPackageConfig } from '@aztec/foundation/noir';
|
|
9
7
|
import { ProtocolContractAddress, protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
8
|
+
import { FunctionType } from '@aztec/stdlib/abi';
|
|
10
9
|
|
|
11
10
|
import TOML from '@iarna/toml';
|
|
12
11
|
import { readFile } from 'fs/promises';
|
|
13
12
|
import { gtr, ltr, satisfies, valid } from 'semver';
|
|
14
|
-
import {
|
|
15
|
-
type Account,
|
|
16
|
-
type Chain,
|
|
17
|
-
type HttpTransport,
|
|
18
|
-
type WalletClient,
|
|
19
|
-
getAddress,
|
|
20
|
-
getContract,
|
|
21
|
-
publicActions,
|
|
22
|
-
} from 'viem';
|
|
23
13
|
|
|
24
14
|
import { encodeArgs } from './encoding.js';
|
|
25
15
|
|
|
@@ -39,55 +29,95 @@ export function getFunctionArtifact(artifact: ContractArtifact, fnName: string):
|
|
|
39
29
|
|
|
40
30
|
/**
|
|
41
31
|
* Function to execute the 'deployRollupContracts' command.
|
|
42
|
-
* @param
|
|
32
|
+
* @param rpcUrls - The RPC URL of the ethereum node.
|
|
43
33
|
* @param chainId - The chain ID of the L1 host.
|
|
44
34
|
* @param privateKey - The private key to be used in contract deployment.
|
|
45
35
|
* @param mnemonic - The mnemonic to be used in contract deployment.
|
|
46
36
|
*/
|
|
47
37
|
export async function deployAztecContracts(
|
|
48
|
-
|
|
38
|
+
rpcUrls: string[],
|
|
49
39
|
chainId: number,
|
|
50
40
|
privateKey: string | undefined,
|
|
51
41
|
mnemonic: string,
|
|
52
42
|
mnemonicIndex: number,
|
|
53
43
|
salt: number | undefined,
|
|
54
44
|
initialValidators: EthAddress[],
|
|
45
|
+
genesisArchiveRoot: Fr,
|
|
46
|
+
genesisBlockHash: Fr,
|
|
55
47
|
config: L1ContractsConfig,
|
|
56
48
|
debugLogger: Logger,
|
|
57
|
-
): Promise<
|
|
49
|
+
): Promise<DeployL1ContractsReturnType> {
|
|
58
50
|
const { createEthereumChain, deployL1Contracts } = await import('@aztec/ethereum');
|
|
59
51
|
const { mnemonicToAccount, privateKeyToAccount } = await import('viem/accounts');
|
|
60
52
|
|
|
61
53
|
const account = !privateKey
|
|
62
54
|
? mnemonicToAccount(mnemonic!, { addressIndex: mnemonicIndex })
|
|
63
55
|
: privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`);
|
|
64
|
-
const chain = createEthereumChain(
|
|
65
|
-
|
|
66
|
-
const { getVKTreeRoot } = await import('@aztec/noir-protocol-circuits-types/
|
|
67
|
-
|
|
68
|
-
return await deployL1Contracts(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
const chain = createEthereumChain(rpcUrls, chainId);
|
|
57
|
+
|
|
58
|
+
const { getVKTreeRoot } = await import('@aztec/noir-protocol-circuits-types/vk-tree');
|
|
59
|
+
|
|
60
|
+
return await deployL1Contracts(
|
|
61
|
+
chain.rpcUrls,
|
|
62
|
+
account,
|
|
63
|
+
chain.chainInfo,
|
|
64
|
+
debugLogger,
|
|
65
|
+
{
|
|
66
|
+
l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice.toField(),
|
|
67
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
68
|
+
protocolContractTreeRoot,
|
|
69
|
+
genesisArchiveRoot,
|
|
70
|
+
genesisBlockHash,
|
|
71
|
+
salt,
|
|
72
|
+
initialValidators,
|
|
73
|
+
...config,
|
|
74
|
+
},
|
|
75
|
+
config,
|
|
76
|
+
);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
export async function deployNewRollupContracts(
|
|
80
|
+
registryAddress: EthAddress,
|
|
81
|
+
rpcUrls: string[],
|
|
82
|
+
chainId: number,
|
|
83
|
+
privateKey: string | undefined,
|
|
84
|
+
mnemonic: string,
|
|
85
|
+
mnemonicIndex: number,
|
|
86
|
+
salt: number | undefined,
|
|
87
|
+
initialValidators: EthAddress[],
|
|
88
|
+
genesisArchiveRoot: Fr,
|
|
89
|
+
genesisBlockHash: Fr,
|
|
90
|
+
config: L1ContractsConfig,
|
|
91
|
+
logger: Logger,
|
|
92
|
+
): Promise<{ payloadAddress: EthAddress; rollup: RollupContract }> {
|
|
93
|
+
const { createEthereumChain, deployRollupAndPeriphery, createL1Clients } = await import('@aztec/ethereum');
|
|
94
|
+
const { mnemonicToAccount, privateKeyToAccount } = await import('viem/accounts');
|
|
95
|
+
const { getVKTreeRoot } = await import('@aztec/noir-protocol-circuits-types/vk-tree');
|
|
96
|
+
|
|
97
|
+
const account = !privateKey
|
|
98
|
+
? mnemonicToAccount(mnemonic!, { addressIndex: mnemonicIndex })
|
|
99
|
+
: privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`);
|
|
100
|
+
const chain = createEthereumChain(rpcUrls, chainId);
|
|
101
|
+
const clients = createL1Clients(rpcUrls, account, chain.chainInfo, mnemonicIndex);
|
|
102
|
+
|
|
103
|
+
const { payloadAddress, rollup } = await deployRollupAndPeriphery(
|
|
104
|
+
clients,
|
|
105
|
+
{
|
|
106
|
+
salt,
|
|
107
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
108
|
+
protocolContractTreeRoot,
|
|
109
|
+
l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice.toField(),
|
|
110
|
+
genesisArchiveRoot,
|
|
111
|
+
genesisBlockHash,
|
|
112
|
+
initialValidators,
|
|
113
|
+
...config,
|
|
114
|
+
},
|
|
115
|
+
registryAddress,
|
|
116
|
+
logger,
|
|
117
|
+
config,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return { payloadAddress, rollup };
|
|
91
121
|
}
|
|
92
122
|
|
|
93
123
|
/**
|