@aztec/aztec 0.0.1-commit.fce3e4f → 0.0.1-commit.ff7989d6c
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/bin/index.js +8 -3
- package/dest/cli/admin_api_key_store.d.ts +45 -0
- package/dest/cli/admin_api_key_store.d.ts.map +1 -0
- package/dest/cli/admin_api_key_store.js +98 -0
- package/dest/cli/aztec_start_action.d.ts +1 -1
- package/dest/cli/aztec_start_action.d.ts.map +1 -1
- package/dest/cli/aztec_start_action.js +50 -13
- package/dest/cli/aztec_start_options.d.ts +1 -1
- package/dest/cli/aztec_start_options.d.ts.map +1 -1
- package/dest/cli/aztec_start_options.js +39 -33
- package/dest/cli/cli.d.ts +1 -1
- package/dest/cli/cli.d.ts.map +1 -1
- package/dest/cli/cli.js +4 -37
- package/dest/cli/cmds/compile.d.ts +4 -0
- package/dest/cli/cmds/compile.d.ts.map +1 -0
- package/dest/cli/cmds/compile.js +95 -0
- package/dest/cli/cmds/migrate_ha_db.d.ts +3 -0
- package/dest/cli/cmds/migrate_ha_db.d.ts.map +1 -0
- package/dest/cli/cmds/migrate_ha_db.js +27 -0
- package/dest/cli/cmds/start_archiver.d.ts +1 -1
- package/dest/cli/cmds/start_archiver.d.ts.map +1 -1
- package/dest/cli/cmds/start_archiver.js +11 -13
- package/dest/cli/cmds/start_bot.d.ts +3 -3
- package/dest/cli/cmds/start_bot.d.ts.map +1 -1
- package/dest/cli/cmds/start_bot.js +10 -6
- package/dest/cli/cmds/start_node.d.ts +1 -1
- package/dest/cli/cmds/start_node.d.ts.map +1 -1
- package/dest/cli/cmds/start_node.js +64 -12
- package/dest/cli/cmds/start_p2p_bootstrap.d.ts +2 -2
- package/dest/cli/cmds/start_p2p_bootstrap.d.ts.map +1 -1
- package/dest/cli/cmds/start_p2p_bootstrap.js +2 -3
- package/dest/cli/cmds/start_prover_agent.d.ts +1 -1
- package/dest/cli/cmds/start_prover_agent.d.ts.map +1 -1
- package/dest/cli/cmds/start_prover_agent.js +4 -4
- package/dest/cli/cmds/start_prover_broker.d.ts +1 -1
- package/dest/cli/cmds/start_prover_broker.d.ts.map +1 -1
- package/dest/cli/cmds/start_prover_broker.js +4 -4
- package/dest/cli/util.d.ts +8 -17
- package/dest/cli/util.d.ts.map +1 -1
- package/dest/cli/util.js +13 -8
- package/dest/examples/token.js +5 -5
- package/dest/examples/util.d.ts +2 -2
- package/dest/examples/util.d.ts.map +1 -1
- package/dest/local-network/banana_fpc.d.ts +1 -1
- package/dest/local-network/banana_fpc.d.ts.map +1 -1
- package/dest/local-network/banana_fpc.js +3 -3
- package/dest/local-network/local-network.d.ts +13 -14
- package/dest/local-network/local-network.d.ts.map +1 -1
- package/dest/local-network/local-network.js +68 -38
- package/dest/testing/anvil_test_watcher.d.ts +10 -2
- package/dest/testing/anvil_test_watcher.d.ts.map +1 -1
- package/dest/testing/anvil_test_watcher.js +53 -16
- package/dest/testing/cheat_codes.d.ts +3 -1
- package/dest/testing/cheat_codes.d.ts.map +1 -1
- package/dest/testing/epoch_test_settler.d.ts +19 -0
- package/dest/testing/epoch_test_settler.d.ts.map +1 -0
- package/dest/testing/epoch_test_settler.js +62 -0
- package/dest/testing/index.d.ts +2 -1
- package/dest/testing/index.d.ts.map +1 -1
- package/dest/testing/index.js +1 -0
- package/package.json +37 -35
- package/scripts/aztec.sh +14 -8
- package/src/bin/index.ts +9 -3
- package/src/cli/admin_api_key_store.ts +128 -0
- package/src/cli/aztec_start_action.ts +53 -8
- package/src/cli/aztec_start_options.ts +40 -32
- package/src/cli/cli.ts +4 -37
- package/src/cli/cmds/compile.ts +107 -0
- package/src/cli/cmds/migrate_ha_db.ts +43 -0
- package/src/cli/cmds/start_archiver.ts +7 -18
- package/src/cli/cmds/start_bot.ts +9 -6
- package/src/cli/cmds/start_node.ts +53 -11
- package/src/cli/cmds/start_p2p_bootstrap.ts +3 -3
- package/src/cli/cmds/start_prover_agent.ts +4 -12
- package/src/cli/cmds/start_prover_broker.ts +7 -3
- package/src/cli/util.ts +20 -25
- package/src/examples/token.ts +5 -7
- package/src/examples/util.ts +1 -1
- package/src/local-network/banana_fpc.ts +11 -7
- package/src/local-network/local-network.ts +107 -82
- package/src/testing/anvil_test_watcher.ts +61 -17
- package/src/testing/cheat_codes.ts +3 -2
- package/src/testing/epoch_test_settler.ts +71 -0
- package/src/testing/index.ts +1 -0
- package/dest/cli/cmds/start_blob_sink.d.ts +0 -3
- package/dest/cli/cmds/start_blob_sink.d.ts.map +0 -1
- package/dest/cli/cmds/start_blob_sink.js +0 -33
- package/dest/cli/cmds/start_prover_node.d.ts +0 -7
- package/dest/cli/cmds/start_prover_node.d.ts.map +0 -1
- package/dest/cli/cmds/start_prover_node.js +0 -108
- package/scripts/compile.sh +0 -44
- package/src/cli/cmds/start_blob_sink.ts +0 -57
- package/src/cli/cmds/start_prover_node.ts +0 -124
|
@@ -1,40 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-warnings
|
|
2
2
|
import { getInitialTestAccountsData } from '@aztec/accounts/testing';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { AztecNodeService } from '@aztec/aztec-node';
|
|
4
|
+
import { type AztecNodeConfig, getConfigEnvVars } from '@aztec/aztec-node/config';
|
|
5
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
6
|
+
import { createLogger } from '@aztec/aztec.js/log';
|
|
7
|
+
import { type BlobClientInterface, createBlobClient } from '@aztec/blob-client/client';
|
|
6
8
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
getL1ContractsConfigEnvVars,
|
|
13
|
-
waitForPublicClient,
|
|
14
|
-
} from '@aztec/ethereum';
|
|
9
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
10
|
+
import { waitForPublicClient } from '@aztec/ethereum/client';
|
|
11
|
+
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
12
|
+
import { NULL_KEY } from '@aztec/ethereum/constants';
|
|
13
|
+
import { deployAztecL1Contracts } from '@aztec/ethereum/deploy-aztec-l1-contracts';
|
|
15
14
|
import { EthCheatCodes } from '@aztec/ethereum/test';
|
|
16
15
|
import { SecretValue } from '@aztec/foundation/config';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
16
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
17
|
+
import type { LogFn } from '@aztec/foundation/log';
|
|
19
18
|
import { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
|
|
20
19
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
21
20
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
21
|
+
import { SequencerState } from '@aztec/sequencer-client';
|
|
22
|
+
import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
|
|
22
23
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
23
24
|
import {
|
|
24
25
|
type TelemetryClient,
|
|
25
26
|
getConfigEnvVars as getTelemetryClientConfig,
|
|
26
27
|
initTelemetryClient,
|
|
27
28
|
} from '@aztec/telemetry-client';
|
|
28
|
-
import {
|
|
29
|
+
import { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
30
|
+
import { deployFundedSchnorrAccounts } from '@aztec/wallets/testing';
|
|
29
31
|
import { getGenesisValues } from '@aztec/world-state/testing';
|
|
30
32
|
|
|
31
|
-
import { type
|
|
33
|
+
import { type Hex, createPublicClient, fallback, http as httpViemTransport } from 'viem';
|
|
32
34
|
import { mnemonicToAccount, privateKeyToAddress } from 'viem/accounts';
|
|
33
35
|
import { foundry } from 'viem/chains';
|
|
34
36
|
|
|
35
37
|
import { createAccountLogs } from '../cli/util.js';
|
|
36
38
|
import { DefaultMnemonic } from '../mnemonic.js';
|
|
37
39
|
import { AnvilTestWatcher } from '../testing/anvil_test_watcher.js';
|
|
40
|
+
import { EpochTestSettler } from '../testing/epoch_test_settler.js';
|
|
38
41
|
import { getBananaFPCAddress, setupBananaFPC } from './banana_fpc.js';
|
|
39
42
|
import { getSponsoredFPCAddress } from './sponsored_fpc.js';
|
|
40
43
|
|
|
@@ -49,42 +52,25 @@ const localAnvil = foundry;
|
|
|
49
52
|
*/
|
|
50
53
|
export async function deployContractsToL1(
|
|
51
54
|
aztecNodeConfig: AztecNodeConfig,
|
|
52
|
-
|
|
53
|
-
contractDeployLogger = logger,
|
|
55
|
+
privateKey: Hex,
|
|
54
56
|
opts: {
|
|
55
|
-
assumeProvenThroughBlockNumber?: number;
|
|
56
|
-
salt?: number;
|
|
57
57
|
genesisArchiveRoot?: Fr;
|
|
58
58
|
feeJuicePortalInitialBalance?: bigint;
|
|
59
59
|
} = {},
|
|
60
60
|
) {
|
|
61
|
-
const chain =
|
|
62
|
-
aztecNodeConfig.l1RpcUrls.length > 0
|
|
63
|
-
? createEthereumChain(aztecNodeConfig.l1RpcUrls, aztecNodeConfig.l1ChainId)
|
|
64
|
-
: { chainInfo: localAnvil };
|
|
65
|
-
|
|
66
61
|
await waitForPublicClient(aztecNodeConfig);
|
|
67
62
|
|
|
68
|
-
const l1Contracts = await
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
salt: opts.salt,
|
|
80
|
-
feeJuicePortalInitialBalance: opts.feeJuicePortalInitialBalance,
|
|
81
|
-
aztecTargetCommitteeSize: 0, // no committee in local network
|
|
82
|
-
slasherFlavor: 'none', // no slashing in local network
|
|
83
|
-
realVerifier: false,
|
|
84
|
-
},
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
await deployMulticall3(l1Contracts.l1Client, logger);
|
|
63
|
+
const l1Contracts = await deployAztecL1Contracts(aztecNodeConfig.l1RpcUrls[0], privateKey, foundry.id, {
|
|
64
|
+
...getL1ContractsConfigEnvVars(), // TODO: We should not need to be loading config from env again, caller should handle this
|
|
65
|
+
...aztecNodeConfig,
|
|
66
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
67
|
+
protocolContractsHash,
|
|
68
|
+
genesisArchiveRoot: opts.genesisArchiveRoot ?? new Fr(GENESIS_ARCHIVE_ROOT),
|
|
69
|
+
feeJuicePortalInitialBalance: opts.feeJuicePortalInitialBalance,
|
|
70
|
+
aztecTargetCommitteeSize: 0, // no committee in local network
|
|
71
|
+
slasherFlavor: 'none', // no slashing in local network
|
|
72
|
+
realVerifier: false,
|
|
73
|
+
});
|
|
88
74
|
|
|
89
75
|
aztecNodeConfig.l1Contracts = l1Contracts.l1ContractAddresses;
|
|
90
76
|
aztecNodeConfig.rollupVersion = l1Contracts.rollupVersion;
|
|
@@ -96,8 +82,6 @@ export async function deployContractsToL1(
|
|
|
96
82
|
export type LocalNetworkConfig = AztecNodeConfig & {
|
|
97
83
|
/** Mnemonic used to derive the L1 deployer private key.*/
|
|
98
84
|
l1Mnemonic: string;
|
|
99
|
-
/** Salt used to deploy L1 contracts.*/
|
|
100
|
-
deployAztecContractsSalt: string;
|
|
101
85
|
/** Whether to deploy test accounts on local network start.*/
|
|
102
86
|
testAccounts: boolean;
|
|
103
87
|
};
|
|
@@ -116,15 +100,21 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
116
100
|
if ((config.l1RpcUrls?.length || 0) > 1) {
|
|
117
101
|
logger.warn(`Multiple L1 RPC URLs provided. Local networks will only use the first one: ${l1RpcUrl}`);
|
|
118
102
|
}
|
|
119
|
-
|
|
103
|
+
|
|
104
|
+
const aztecNodeConfig: AztecNodeConfig = {
|
|
105
|
+
...getConfigEnvVars(),
|
|
106
|
+
...config,
|
|
107
|
+
};
|
|
120
108
|
const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic);
|
|
121
109
|
if (
|
|
122
|
-
aztecNodeConfig.
|
|
123
|
-
!aztecNodeConfig.
|
|
124
|
-
aztecNodeConfig.
|
|
110
|
+
aztecNodeConfig.sequencerPublisherPrivateKeys == undefined ||
|
|
111
|
+
!aztecNodeConfig.sequencerPublisherPrivateKeys.length ||
|
|
112
|
+
aztecNodeConfig.sequencerPublisherPrivateKeys[0].getValue() === NULL_KEY
|
|
125
113
|
) {
|
|
126
114
|
const privKey = hdAccount.getHdKey().privateKey;
|
|
127
|
-
aztecNodeConfig.
|
|
115
|
+
aztecNodeConfig.sequencerPublisherPrivateKeys = [
|
|
116
|
+
new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const),
|
|
117
|
+
];
|
|
128
118
|
}
|
|
129
119
|
if (!aztecNodeConfig.validatorPrivateKeys?.getValue().length) {
|
|
130
120
|
const privKey = hdAccount.getHdKey().privateKey;
|
|
@@ -153,15 +143,20 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
153
143
|
: [];
|
|
154
144
|
const { genesisArchiveRoot, prefilledPublicData, fundingNeeded } = await getGenesisValues(fundedAddresses);
|
|
155
145
|
|
|
156
|
-
let watcher: AnvilTestWatcher | undefined = undefined;
|
|
157
146
|
const dateProvider = new TestDateProvider();
|
|
147
|
+
|
|
148
|
+
let cheatcodes: EthCheatCodes | undefined;
|
|
149
|
+
let rollupAddress: EthAddress | undefined;
|
|
150
|
+
let watcher: AnvilTestWatcher | undefined;
|
|
158
151
|
if (!aztecNodeConfig.p2pEnabled) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
152
|
+
({ rollupAddress } = await deployContractsToL1(
|
|
153
|
+
aztecNodeConfig,
|
|
154
|
+
aztecNodeConfig.validatorPrivateKeys.getValue()[0],
|
|
155
|
+
{
|
|
156
|
+
genesisArchiveRoot,
|
|
157
|
+
feeJuicePortalInitialBalance: fundingNeeded,
|
|
158
|
+
},
|
|
159
|
+
));
|
|
165
160
|
|
|
166
161
|
const chain =
|
|
167
162
|
aztecNodeConfig.l1RpcUrls.length > 0
|
|
@@ -173,36 +168,56 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
173
168
|
transport: fallback([httpViemTransport(l1RpcUrl)]) as any,
|
|
174
169
|
});
|
|
175
170
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
publicClient,
|
|
180
|
-
dateProvider,
|
|
181
|
-
);
|
|
171
|
+
cheatcodes = new EthCheatCodes([l1RpcUrl], dateProvider);
|
|
172
|
+
|
|
173
|
+
watcher = new AnvilTestWatcher(cheatcodes, rollupAddress, publicClient, dateProvider);
|
|
182
174
|
watcher.setisLocalNetwork(true);
|
|
175
|
+
watcher.setIsMarkingAsProven(false); // Do not mark as proven in the watcher. It's marked in the epochTestSettler after the out hash is set.
|
|
176
|
+
|
|
183
177
|
await watcher.start();
|
|
184
178
|
}
|
|
185
179
|
|
|
186
|
-
const telemetry = initTelemetryClient(getTelemetryClientConfig());
|
|
187
|
-
// Create a local blob
|
|
188
|
-
const
|
|
189
|
-
const node = await createAztecNode(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
180
|
+
const telemetry = await initTelemetryClient(getTelemetryClientConfig());
|
|
181
|
+
// Create a local blob client client inside the local network, no http connectivity
|
|
182
|
+
const blobClient = createBlobClient();
|
|
183
|
+
const node = await createAztecNode(aztecNodeConfig, { telemetry, blobClient, dateProvider }, { prefilledPublicData });
|
|
184
|
+
|
|
185
|
+
// Now that the node is up, let the watcher check for pending txs so it can skip unfilled slots faster when
|
|
186
|
+
// transactions are waiting in the mempool. Also let it check if the sequencer is actively building, to avoid
|
|
187
|
+
// warping time out from under an in-progress block.
|
|
188
|
+
watcher?.setGetPendingTxCount(() => node.getPendingTxCount());
|
|
189
|
+
const sequencer = node.getSequencer()?.getSequencer();
|
|
190
|
+
if (sequencer) {
|
|
191
|
+
const idleStates: Set<string> = new Set([
|
|
192
|
+
SequencerState.STOPPED,
|
|
193
|
+
SequencerState.STOPPING,
|
|
194
|
+
SequencerState.IDLE,
|
|
195
|
+
SequencerState.SYNCHRONIZING,
|
|
196
|
+
]);
|
|
197
|
+
watcher?.setIsSequencerBuilding(() => !idleStates.has(sequencer.getState()));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let epochTestSettler: EpochTestSettler | undefined;
|
|
201
|
+
if (!aztecNodeConfig.p2pEnabled) {
|
|
202
|
+
epochTestSettler = new EpochTestSettler(
|
|
203
|
+
cheatcodes!,
|
|
204
|
+
rollupAddress!,
|
|
205
|
+
node.getBlockSource(),
|
|
206
|
+
logger.createChild('epoch-settler'),
|
|
207
|
+
{ pollingIntervalMs: 200 },
|
|
208
|
+
);
|
|
209
|
+
await epochTestSettler.start();
|
|
210
|
+
}
|
|
194
211
|
|
|
195
212
|
if (initialAccounts.length) {
|
|
196
|
-
const
|
|
197
|
-
|
|
213
|
+
const wallet = await EmbeddedWallet.create(node, {
|
|
214
|
+
pxeConfig: { proverEnabled: aztecNodeConfig.realProofs },
|
|
215
|
+
ephemeral: true,
|
|
216
|
+
});
|
|
198
217
|
|
|
199
218
|
userLog('Setting up funded test accounts...');
|
|
200
|
-
const accountManagers = await deployFundedSchnorrAccounts(wallet,
|
|
201
|
-
const
|
|
202
|
-
account: manager,
|
|
203
|
-
secretKey: initialAccounts[i].secret,
|
|
204
|
-
}));
|
|
205
|
-
const accLogs = await createAccountLogs(accountsWithSecrets, wallet);
|
|
219
|
+
const accountManagers = await deployFundedSchnorrAccounts(wallet, initialAccounts);
|
|
220
|
+
const accLogs = await createAccountLogs(accountManagers, wallet);
|
|
206
221
|
userLog(accLogs.join(''));
|
|
207
222
|
|
|
208
223
|
await setupBananaFPC(initialAccounts, wallet, userLog);
|
|
@@ -216,6 +231,7 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
216
231
|
const stop = async () => {
|
|
217
232
|
await node.stop();
|
|
218
233
|
await watcher?.stop();
|
|
234
|
+
await epochTestSettler?.stop();
|
|
219
235
|
};
|
|
220
236
|
|
|
221
237
|
return { node, stop };
|
|
@@ -227,7 +243,12 @@ export async function createLocalNetwork(config: Partial<LocalNetworkConfig> = {
|
|
|
227
243
|
*/
|
|
228
244
|
export async function createAztecNode(
|
|
229
245
|
config: Partial<AztecNodeConfig> = {},
|
|
230
|
-
deps: {
|
|
246
|
+
deps: {
|
|
247
|
+
telemetry?: TelemetryClient;
|
|
248
|
+
blobClient?: BlobClientInterface;
|
|
249
|
+
dateProvider?: DateProvider;
|
|
250
|
+
proverBroker?: ProvingJobBroker;
|
|
251
|
+
} = {},
|
|
231
252
|
options: { prefilledPublicData?: PublicDataTreeLeaf[] } = {},
|
|
232
253
|
) {
|
|
233
254
|
// TODO(#12272): will clean this up. This is criminal.
|
|
@@ -237,6 +258,10 @@ export async function createAztecNode(
|
|
|
237
258
|
...config,
|
|
238
259
|
l1Contracts: { ...l1Contracts, ...config.l1Contracts },
|
|
239
260
|
};
|
|
240
|
-
const node = await AztecNodeService.createAndSync(
|
|
261
|
+
const node = await AztecNodeService.createAndSync(
|
|
262
|
+
aztecNodeConfig,
|
|
263
|
+
{ ...deps, proverNodeDeps: { broker: deps.proverBroker } },
|
|
264
|
+
options,
|
|
265
|
+
);
|
|
241
266
|
return node;
|
|
242
267
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ViemClient } from '@aztec/ethereum';
|
|
2
1
|
import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
|
|
2
|
+
import type { ViemClient } from '@aztec/ethereum/types';
|
|
3
3
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
5
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
@@ -31,6 +31,15 @@ export class AnvilTestWatcher {
|
|
|
31
31
|
|
|
32
32
|
private isMarkingAsProven = true;
|
|
33
33
|
|
|
34
|
+
// Optional callback to check if there are pending txs in the mempool.
|
|
35
|
+
private getPendingTxCount?: () => Promise<number>;
|
|
36
|
+
|
|
37
|
+
// Optional callback to check if the sequencer is actively building a block.
|
|
38
|
+
private isSequencerBuilding?: () => boolean;
|
|
39
|
+
|
|
40
|
+
// Tracks when we first observed the current unfilled slot with pending txs (real wall time).
|
|
41
|
+
private unfilledSlotFirstSeen?: { slot: number; realTime: number };
|
|
42
|
+
|
|
34
43
|
constructor(
|
|
35
44
|
private cheatcodes: EthCheatCodes,
|
|
36
45
|
rollupAddress: EthAddress,
|
|
@@ -59,6 +68,16 @@ export class AnvilTestWatcher {
|
|
|
59
68
|
this.isLocalNetwork = isLocalNetwork;
|
|
60
69
|
}
|
|
61
70
|
|
|
71
|
+
/** Sets a callback to check for pending txs, used to skip unfilled slots faster when txs are waiting. */
|
|
72
|
+
setGetPendingTxCount(fn: () => Promise<number>) {
|
|
73
|
+
this.getPendingTxCount = fn;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Sets a callback to check if the sequencer is actively building, to avoid warping while it works. */
|
|
77
|
+
setIsSequencerBuilding(fn: () => boolean) {
|
|
78
|
+
this.isSequencerBuilding = fn;
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
async start() {
|
|
63
82
|
if (this.filledRunningPromise) {
|
|
64
83
|
throw new Error('Watcher already watching for filled slot');
|
|
@@ -125,21 +144,14 @@ export class AnvilTestWatcher {
|
|
|
125
144
|
async warpTimeIfNeeded() {
|
|
126
145
|
try {
|
|
127
146
|
const currentSlot = SlotNumber.fromBigInt(await this.rollup.read.getCurrentSlot());
|
|
128
|
-
const pendingCheckpointNumber =
|
|
147
|
+
const pendingCheckpointNumber = await this.rollup.read.getPendingCheckpointNumber();
|
|
129
148
|
const checkpointLog = await this.rollup.read.getCheckpoint([pendingCheckpointNumber]);
|
|
130
149
|
const nextSlot = SlotNumber(currentSlot + 1);
|
|
131
150
|
const nextSlotTimestamp = Number(await this.rollup.read.getTimestampForSlot([BigInt(nextSlot)]));
|
|
132
151
|
|
|
133
152
|
if (BigInt(currentSlot) === checkpointLog.slotNumber) {
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
await this.cheatcodes.warp(nextSlotTimestamp, {
|
|
137
|
-
resetBlockInterval: true,
|
|
138
|
-
});
|
|
139
|
-
} catch (e) {
|
|
140
|
-
this.logger.error(`Failed to warp to timestamp ${nextSlotTimestamp}: ${e}`);
|
|
141
|
-
}
|
|
142
|
-
|
|
153
|
+
// The current slot has been filled, we should jump to the next slot.
|
|
154
|
+
await this.warpToTimestamp(nextSlotTimestamp);
|
|
143
155
|
this.logger.info(`Slot ${currentSlot} was filled, jumped to next slot`);
|
|
144
156
|
return;
|
|
145
157
|
}
|
|
@@ -149,18 +161,50 @@ export class AnvilTestWatcher {
|
|
|
149
161
|
return;
|
|
150
162
|
}
|
|
151
163
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
// If there are pending txs and the sequencer missed them, warp quickly (after a 2s real-time debounce) so the
|
|
165
|
+
// sequencer can retry in the next slot. Without this, we'd have to wait a full real-time slot duration (~36s) for
|
|
166
|
+
// the dateProvider to catch up to the next slot timestamp. We skip the warp if the sequencer is actively building
|
|
167
|
+
// to avoid invalidating its in-progress work.
|
|
168
|
+
if (this.getPendingTxCount) {
|
|
169
|
+
const pendingTxs = await this.getPendingTxCount();
|
|
170
|
+
if (pendingTxs > 0) {
|
|
171
|
+
if (this.isSequencerBuilding?.()) {
|
|
172
|
+
this.unfilledSlotFirstSeen = undefined;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const realNow = Date.now();
|
|
177
|
+
if (!this.unfilledSlotFirstSeen || this.unfilledSlotFirstSeen.slot !== currentSlot) {
|
|
178
|
+
this.unfilledSlotFirstSeen = { slot: currentSlot, realTime: realNow };
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (realNow - this.unfilledSlotFirstSeen.realTime > 2000) {
|
|
183
|
+
await this.warpToTimestamp(nextSlotTimestamp);
|
|
184
|
+
this.unfilledSlotFirstSeen = undefined;
|
|
185
|
+
this.logger.info(`Slot ${currentSlot} was missed with pending txs, jumped to next slot`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return;
|
|
158
189
|
}
|
|
190
|
+
}
|
|
159
191
|
|
|
192
|
+
// Fallback: warp when the dateProvider time has passed the next slot timestamp.
|
|
193
|
+
const currentTimestamp = this.dateProvider?.now() ?? Date.now();
|
|
194
|
+
if (currentTimestamp > nextSlotTimestamp * 1000) {
|
|
195
|
+
await this.warpToTimestamp(nextSlotTimestamp);
|
|
160
196
|
this.logger.info(`Slot ${currentSlot} was missed, jumped to next slot`);
|
|
161
197
|
}
|
|
162
198
|
} catch {
|
|
163
199
|
this.logger.error('mineIfSlotFilled failed');
|
|
164
200
|
}
|
|
165
201
|
}
|
|
202
|
+
|
|
203
|
+
private async warpToTimestamp(timestamp: number) {
|
|
204
|
+
try {
|
|
205
|
+
await this.cheatcodes.warp(timestamp, { resetBlockInterval: true });
|
|
206
|
+
} catch (e) {
|
|
207
|
+
this.logger.error(`Failed to warp to timestamp ${timestamp}: ${e}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
166
210
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
3
4
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import type { SequencerClient } from '@aztec/sequencer-client';
|
|
@@ -37,7 +38,7 @@ export class CheatCodes {
|
|
|
37
38
|
* @param targetTimestamp - The target timestamp to warp to (in seconds)
|
|
38
39
|
*/
|
|
39
40
|
async warpL2TimeAtLeastTo(sequencerClient: SequencerClient, node: AztecNode, targetTimestamp: bigint | number) {
|
|
40
|
-
const currentL2BlockNumber = await node.getBlockNumber();
|
|
41
|
+
const currentL2BlockNumber: BlockNumber = await node.getBlockNumber();
|
|
41
42
|
|
|
42
43
|
// We warp the L1 timestamp
|
|
43
44
|
await this.eth.warp(targetTimestamp, { resetBlockInterval: true });
|
|
@@ -49,7 +50,7 @@ export class CheatCodes {
|
|
|
49
50
|
|
|
50
51
|
await retryUntil(
|
|
51
52
|
async () => {
|
|
52
|
-
const newL2BlockNumber = await node.getBlockNumber();
|
|
53
|
+
const newL2BlockNumber: BlockNumber = await node.getBlockNumber();
|
|
53
54
|
return newL2BlockNumber > currentL2BlockNumber;
|
|
54
55
|
},
|
|
55
56
|
'new block after warping L2 time',
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Fr } from '@aztec/aztec.js/fields';
|
|
2
|
+
import { type EthCheatCodes, RollupCheatCodes } from '@aztec/ethereum/test';
|
|
3
|
+
import { type EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
5
|
+
import { EpochMonitor } from '@aztec/prover-node';
|
|
6
|
+
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
7
|
+
import { computeL2ToL1MembershipWitnessFromMessagesInEpoch } from '@aztec/stdlib/messaging';
|
|
8
|
+
|
|
9
|
+
export class EpochTestSettler {
|
|
10
|
+
private rollupCheatCodes: RollupCheatCodes;
|
|
11
|
+
private epochMonitor?: EpochMonitor;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
cheatcodes: EthCheatCodes,
|
|
15
|
+
rollupAddress: EthAddress,
|
|
16
|
+
private l2BlockSource: L2BlockSource,
|
|
17
|
+
private log: Logger,
|
|
18
|
+
private options: { pollingIntervalMs: number; provingDelayMs?: number },
|
|
19
|
+
) {
|
|
20
|
+
this.rollupCheatCodes = new RollupCheatCodes(cheatcodes, { rollupAddress });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async start() {
|
|
24
|
+
const { epochDuration } = await this.rollupCheatCodes.getConfig();
|
|
25
|
+
this.epochMonitor = new EpochMonitor(this.l2BlockSource, { epochDuration: Number(epochDuration) }, this.options);
|
|
26
|
+
this.epochMonitor.start(this);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async stop() {
|
|
30
|
+
await this.epochMonitor?.stop();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async handleEpochReadyToProve(epoch: EpochNumber): Promise<boolean> {
|
|
34
|
+
const checkpointedBlocks = await this.l2BlockSource.getCheckpointedBlocksForEpoch(epoch);
|
|
35
|
+
const blocks = checkpointedBlocks.map(b => b.block);
|
|
36
|
+
this.log.info(
|
|
37
|
+
`Settling epoch ${epoch} with blocks ${blocks[0]?.header.getBlockNumber()} to ${blocks.at(-1)?.header.getBlockNumber()}`,
|
|
38
|
+
{ blocks: blocks.map(b => b.toBlockInfo()) },
|
|
39
|
+
);
|
|
40
|
+
const messagesInEpoch: Fr[][][][] = [];
|
|
41
|
+
let previousSlotNumber = SlotNumber.ZERO;
|
|
42
|
+
let checkpointIndex = -1;
|
|
43
|
+
|
|
44
|
+
for (const block of blocks) {
|
|
45
|
+
const slotNumber = block.header.globalVariables.slotNumber;
|
|
46
|
+
if (slotNumber !== previousSlotNumber) {
|
|
47
|
+
checkpointIndex++;
|
|
48
|
+
messagesInEpoch[checkpointIndex] = [];
|
|
49
|
+
previousSlotNumber = slotNumber;
|
|
50
|
+
}
|
|
51
|
+
messagesInEpoch[checkpointIndex].push(block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const [firstMessage] = messagesInEpoch.flat(3);
|
|
55
|
+
if (firstMessage) {
|
|
56
|
+
const { root: outHash } = computeL2ToL1MembershipWitnessFromMessagesInEpoch(messagesInEpoch, firstMessage);
|
|
57
|
+
await this.rollupCheatCodes.insertOutbox(epoch, outHash.toBigInt());
|
|
58
|
+
} else {
|
|
59
|
+
this.log.info(`No L2 to L1 messages in epoch ${epoch}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const lastCheckpoint = checkpointedBlocks.at(-1)?.checkpointNumber;
|
|
63
|
+
if (lastCheckpoint !== undefined) {
|
|
64
|
+
await this.rollupCheatCodes.markAsProven(lastCheckpoint);
|
|
65
|
+
} else {
|
|
66
|
+
this.log.warn(`No checkpoint found for epoch ${epoch}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/testing/index.ts
CHANGED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { LogFn } from '@aztec/foundation/log';
|
|
2
|
-
export declare function startBlobSink(options: any, signalHandlers: (() => Promise<void>)[], userLog: LogFn): Promise<void>;
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfYmxvYl9zaW5rLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2xpL2NtZHMvc3RhcnRfYmxvYl9zaW5rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBS25ELHdCQUFzQixhQUFhLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsQ0FBQyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssaUJBNEN4RyJ9
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start_blob_sink.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/start_blob_sink.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAKnD,wBAAsB,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,iBA4CxG"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { blobSinkConfigMappings, createBlobSinkServer, getBlobSinkConfigFromEnv } from '@aztec/blob-sink/server';
|
|
2
|
-
import { getL1Config } from '@aztec/cli/config';
|
|
3
|
-
import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } from '@aztec/telemetry-client';
|
|
4
|
-
import { extractRelevantOptions } from '../util.js';
|
|
5
|
-
export async function startBlobSink(options, signalHandlers, userLog) {
|
|
6
|
-
if (options.prover || options.node || options.sequencer || options.pxe || options.p2pBootstrap || options.txe) {
|
|
7
|
-
userLog(`Starting a blob sink with --node, --sequencer, --pxe, --p2p-bootstrap, --prover or --txe is not supported.`);
|
|
8
|
-
process.exit(1);
|
|
9
|
-
}
|
|
10
|
-
let blobSinkConfig = {
|
|
11
|
-
...getBlobSinkConfigFromEnv(),
|
|
12
|
-
...extractRelevantOptions(options, blobSinkConfigMappings, 'blobSink')
|
|
13
|
-
};
|
|
14
|
-
if (!blobSinkConfig.l1Contracts?.registryAddress || blobSinkConfig.l1Contracts.registryAddress.isZero()) {
|
|
15
|
-
throw new Error('REGISTRY_CONTRACT_ADDRESS not set');
|
|
16
|
-
}
|
|
17
|
-
if (!blobSinkConfig.l1RpcUrls || blobSinkConfig.l1RpcUrls.length === 0) {
|
|
18
|
-
throw new Error('ETHEREUM_HOSTS not set');
|
|
19
|
-
}
|
|
20
|
-
if (typeof blobSinkConfig.l1ChainId !== 'number') {
|
|
21
|
-
throw new Error('L1_CHAIN_ID');
|
|
22
|
-
}
|
|
23
|
-
const telemetry = initTelemetryClient(getTelemetryClientConfig());
|
|
24
|
-
const { config: chainConfig, addresses } = await getL1Config(blobSinkConfig.l1Contracts.registryAddress, blobSinkConfig.l1RpcUrls, blobSinkConfig.l1ChainId, blobSinkConfig.rollupVersion);
|
|
25
|
-
blobSinkConfig = {
|
|
26
|
-
...blobSinkConfig,
|
|
27
|
-
l1Contracts: addresses,
|
|
28
|
-
...chainConfig
|
|
29
|
-
};
|
|
30
|
-
const blobSink = await createBlobSinkServer(blobSinkConfig, telemetry);
|
|
31
|
-
signalHandlers.push(blobSink.stop.bind(blobSink));
|
|
32
|
-
await blobSink.start();
|
|
33
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
|
|
2
|
-
import type { LogFn } from '@aztec/foundation/log';
|
|
3
|
-
import { type ProverNodeConfig } from '@aztec/prover-node';
|
|
4
|
-
export declare function startProverNode(options: any, signalHandlers: (() => Promise<void>)[], services: NamespacedApiHandlers, userLog: LogFn): Promise<{
|
|
5
|
-
config: ProverNodeConfig;
|
|
6
|
-
}>;
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfcHJvdmVyX25vZGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGkvY21kcy9zdGFydF9wcm92ZXJfbm9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEtBQUssRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRS9FLE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRW5ELE9BQU8sRUFDTCxLQUFLLGdCQUFnQixFQUl0QixNQUFNLG9CQUFvQixDQUFDO0FBUzVCLHdCQUFzQixlQUFlLENBQ25DLE9BQU8sRUFBRSxHQUFHLEVBQ1osY0FBYyxFQUFFLENBQUMsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUN2QyxRQUFRLEVBQUUscUJBQXFCLEVBQy9CLE9BQU8sRUFBRSxLQUFLLEdBQ2IsT0FBTyxDQUFDO0lBQUUsTUFBTSxFQUFFLGdCQUFnQixDQUFBO0NBQUUsQ0FBQyxDQStGdkMifQ==
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start_prover_node.d.ts","sourceRoot":"","sources":["../../../src/cli/cmds/start_prover_node.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,oBAAoB,CAAC;AAS5B,wBAAsB,eAAe,CACnC,OAAO,EAAE,GAAG,EACZ,cAAc,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EACvC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,KAAK,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA+FvC"}
|