@aztec/node-lib 0.0.1-fake-c83136db25

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.
Files changed (50) hide show
  1. package/README.md +3 -0
  2. package/dest/actions/build-snapshot-metadata.d.ts +5 -0
  3. package/dest/actions/build-snapshot-metadata.d.ts.map +1 -0
  4. package/dest/actions/build-snapshot-metadata.js +19 -0
  5. package/dest/actions/create-backups.d.ts +6 -0
  6. package/dest/actions/create-backups.d.ts.map +1 -0
  7. package/dest/actions/create-backups.js +32 -0
  8. package/dest/actions/index.d.ts +5 -0
  9. package/dest/actions/index.d.ts.map +1 -0
  10. package/dest/actions/index.js +4 -0
  11. package/dest/actions/snapshot-sync.d.ts +27 -0
  12. package/dest/actions/snapshot-sync.d.ts.map +1 -0
  13. package/dest/actions/snapshot-sync.js +236 -0
  14. package/dest/actions/upload-snapshot.d.ts +12 -0
  15. package/dest/actions/upload-snapshot.d.ts.map +1 -0
  16. package/dest/actions/upload-snapshot.js +38 -0
  17. package/dest/config/index.d.ts +19 -0
  18. package/dest/config/index.d.ts.map +1 -0
  19. package/dest/config/index.js +41 -0
  20. package/dest/factories/index.d.ts +2 -0
  21. package/dest/factories/index.d.ts.map +1 -0
  22. package/dest/factories/index.js +1 -0
  23. package/dest/factories/l1_tx_utils.d.ts +53 -0
  24. package/dest/factories/l1_tx_utils.d.ts.map +1 -0
  25. package/dest/factories/l1_tx_utils.js +50 -0
  26. package/dest/metrics/index.d.ts +2 -0
  27. package/dest/metrics/index.d.ts.map +1 -0
  28. package/dest/metrics/index.js +1 -0
  29. package/dest/metrics/l1_tx_metrics.d.ts +29 -0
  30. package/dest/metrics/l1_tx_metrics.d.ts.map +1 -0
  31. package/dest/metrics/l1_tx_metrics.js +138 -0
  32. package/dest/stores/index.d.ts +2 -0
  33. package/dest/stores/index.d.ts.map +1 -0
  34. package/dest/stores/index.js +1 -0
  35. package/dest/stores/l1_tx_store.d.ts +89 -0
  36. package/dest/stores/l1_tx_store.d.ts.map +1 -0
  37. package/dest/stores/l1_tx_store.js +264 -0
  38. package/package.json +99 -0
  39. package/src/actions/build-snapshot-metadata.ts +29 -0
  40. package/src/actions/create-backups.ts +41 -0
  41. package/src/actions/index.ts +4 -0
  42. package/src/actions/snapshot-sync.ts +277 -0
  43. package/src/actions/upload-snapshot.ts +50 -0
  44. package/src/config/index.ts +64 -0
  45. package/src/factories/index.ts +1 -0
  46. package/src/factories/l1_tx_utils.ts +122 -0
  47. package/src/metrics/index.ts +1 -0
  48. package/src/metrics/l1_tx_metrics.ts +169 -0
  49. package/src/stores/index.ts +1 -0
  50. package/src/stores/l1_tx_store.ts +387 -0
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Node Lib
2
+
3
+ Shared code for Aztec Nodes and Prover Nodes.
@@ -0,0 +1,5 @@
1
+ import type { Archiver } from '@aztec/archiver';
2
+ import type { UploadSnapshotMetadata } from '@aztec/stdlib/snapshots';
3
+ import type { UploadSnapshotConfig } from './upload-snapshot.js';
4
+ export declare function buildSnapshotMetadata(archiver: Archiver, config: UploadSnapshotConfig): Promise<UploadSnapshotMetadata>;
5
+ //# sourceMappingURL=build-snapshot-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-snapshot-metadata.d.ts","sourceRoot":"","sources":["../../src/actions/build-snapshot-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAoBjC"}
@@ -0,0 +1,19 @@
1
+ export async function buildSnapshotMetadata(archiver, config) {
2
+ const [rollupAddress, l1BlockNumber, { latest }] = await Promise.all([
3
+ archiver.getRollupAddress(),
4
+ archiver.getL1BlockNumber(),
5
+ archiver.getL2Tips()
6
+ ]);
7
+ const { number: l2BlockNumber, hash: l2BlockHash } = latest;
8
+ if (!l2BlockHash) {
9
+ throw new Error(`Failed to get L2 block hash from archiver.`);
10
+ }
11
+ return {
12
+ l1ChainId: config.l1ChainId,
13
+ rollupVersion: config.rollupVersion,
14
+ rollupAddress,
15
+ l2BlockNumber,
16
+ l2BlockHash,
17
+ l1BlockNumber: Number(l1BlockNumber)
18
+ };
19
+ }
@@ -0,0 +1,6 @@
1
+ import type { Archiver } from '@aztec/archiver';
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
4
+ import type { SnapshotDataUrls } from '@aztec/stdlib/snapshots';
5
+ export declare function createBackups(backupDir: string, archiver: Archiver, worldState: WorldStateSynchronizer, log: Logger): Promise<SnapshotDataUrls>;
6
+ //# sourceMappingURL=create-backups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-backups.d.ts","sourceRoot":"","sources":["../../src/actions/create-backups.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,sBAAsB,EAClC,GAAG,EAAE,MAAM,6BA4BZ"}
@@ -0,0 +1,32 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path/posix';
3
+ export async function createBackups(backupDir, archiver, worldState, log) {
4
+ try {
5
+ log.info(`Pausing archiver and world state sync to start snapshot upload`);
6
+ await archiver.stop();
7
+ await worldState.stopSync();
8
+ log.info(`Creating backups of lmdb environments to ${backupDir}`);
9
+ const [archiverPath, worldStatePaths] = await Promise.all([
10
+ archiver.backupTo(join(backupDir, 'archiver')),
11
+ worldState.backupTo(join(backupDir, 'world-state'))
12
+ ]);
13
+ const paths = {
14
+ ...worldStatePaths,
15
+ archiver: archiverPath
16
+ };
17
+ const missing = Object.entries(paths).filter(([_key, path])=>!path || !existsSync(path));
18
+ if (missing.length > 0) {
19
+ throw new Error(`Missing backup files: ${missing.map(([key, path])=>`${path} (${key})`).join(', ')}`);
20
+ }
21
+ log.info(`Data stores backed up to ${backupDir}`, {
22
+ paths
23
+ });
24
+ return paths;
25
+ } catch (err) {
26
+ throw new Error(`Error creating backups for snapshot upload: ${err}`);
27
+ } finally{
28
+ log.info(`Resuming archiver and world state sync`);
29
+ worldState.resumeSync();
30
+ archiver.resume();
31
+ }
32
+ }
@@ -0,0 +1,5 @@
1
+ export * from './snapshot-sync.js';
2
+ export * from './upload-snapshot.js';
3
+ export * from './create-backups.js';
4
+ export * from './build-snapshot-metadata.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './snapshot-sync.js';
2
+ export * from './upload-snapshot.js';
3
+ export * from './create-backups.js';
4
+ export * from './build-snapshot-metadata.js';
@@ -0,0 +1,27 @@
1
+ import { type ArchiverConfig } from '@aztec/archiver';
2
+ import { type EthereumClientConfig } from '@aztec/ethereum';
3
+ import type { EthAddress } from '@aztec/foundation/eth-address';
4
+ import type { Logger } from '@aztec/foundation/log';
5
+ import type { DataStoreConfig } from '@aztec/kv-store/config';
6
+ import type { ChainConfig } from '@aztec/stdlib/config';
7
+ import { type SnapshotMetadata } from '@aztec/stdlib/snapshots';
8
+ import type { SharedNodeConfig } from '../config/index.js';
9
+ type SnapshotSyncConfig = Pick<SharedNodeConfig, 'syncMode'> & Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'> & Pick<ArchiverConfig, 'archiverStoreMapSizeKb' | 'maxLogs'> & Required<DataStoreConfig> & EthereumClientConfig & {
10
+ snapshotsUrls?: string[];
11
+ minL1BlocksToTriggerReplace?: number;
12
+ };
13
+ /**
14
+ * Connects to a remote snapshot index and downloads the latest snapshot if the local archiver is behind.
15
+ * Behaviour depends on syncing mode.
16
+ */
17
+ export declare function trySnapshotSync(config: SnapshotSyncConfig, log: Logger): Promise<boolean>;
18
+ /**
19
+ * Downloads the given snapshot replacing any local data stores.
20
+ */
21
+ export declare function snapshotSync(snapshot: Pick<SnapshotMetadata, 'dataUrls'>, log: Logger, config: {
22
+ dataDirectory: string;
23
+ rollupAddress: EthAddress;
24
+ snapshotsUrl: string;
25
+ }): Promise<void>;
26
+ export {};
27
+ //# sourceMappingURL=snapshot-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-sync.d.ts","sourceRoot":"","sources":["../../src/actions/snapshot-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AAErH,OAAO,EAAE,KAAK,oBAAoB,EAAmB,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EACL,KAAK,gBAAgB,EAKtB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAK3D,KAAK,kBAAkB,GAAG,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,GAC1D,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,eAAe,CAAC,GAChD,IAAI,CAAC,cAAc,EAAE,wBAAwB,GAAG,SAAS,CAAC,GAC1D,QAAQ,CAAC,eAAe,CAAC,GACzB,oBAAoB,GAAG;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC,CAAC;AAEJ;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,oBAiK5E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,EAC5C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,iBAqDnF"}
@@ -0,0 +1,236 @@
1
+ import { ARCHIVER_DB_VERSION, ARCHIVER_STORE_NAME, createArchiverStore } from '@aztec/archiver';
2
+ import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
3
+ import { getPublicClient } from '@aztec/ethereum';
4
+ import { tryRmDir } from '@aztec/foundation/fs';
5
+ import { P2P_STORE_NAME } from '@aztec/p2p';
6
+ import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
7
+ import { createReadOnlyFileStore } from '@aztec/stdlib/file-store';
8
+ import { downloadSnapshot, getLatestSnapshotMetadata, makeSnapshotPaths } from '@aztec/stdlib/snapshots';
9
+ import { NATIVE_WORLD_STATE_DBS, WORLD_STATE_DB_VERSION, WORLD_STATE_DIR } from '@aztec/world-state';
10
+ import { mkdir, mkdtemp, rename } from 'fs/promises';
11
+ import { join } from 'path';
12
+ // Half day worth of L1 blocks
13
+ const MIN_L1_BLOCKS_TO_TRIGGER_REPLACE = 86400 / 2 / 12;
14
+ /**
15
+ * Connects to a remote snapshot index and downloads the latest snapshot if the local archiver is behind.
16
+ * Behaviour depends on syncing mode.
17
+ */ export async function trySnapshotSync(config, log) {
18
+ const { syncMode, snapshotsUrls, dataDirectory, l1ChainId, rollupVersion, l1Contracts } = config;
19
+ if (syncMode === 'full') {
20
+ log.debug('Snapshot sync is disabled. Running full sync.', {
21
+ syncMode: syncMode
22
+ });
23
+ return false;
24
+ }
25
+ if (!snapshotsUrls || snapshotsUrls.length === 0) {
26
+ log.verbose('Snapshot sync is disabled. No snapshots URLs provided.');
27
+ return false;
28
+ }
29
+ if (!dataDirectory) {
30
+ log.verbose('Snapshot sync is disabled. No local data directory defined.');
31
+ return false;
32
+ }
33
+ // Create an archiver store to check the current state (do this only once)
34
+ log.verbose(`Creating temporary archiver data store`);
35
+ const archiverStore = await createArchiverStore(config);
36
+ let archiverL1BlockNumber;
37
+ let archiverL2BlockNumber;
38
+ try {
39
+ [archiverL1BlockNumber, archiverL2BlockNumber] = await Promise.all([
40
+ archiverStore.getSynchPoint().then((s)=>s.blocksSynchedTo),
41
+ archiverStore.getSynchedL2BlockNumber()
42
+ ]);
43
+ } finally{
44
+ log.verbose(`Closing temporary archiver data store`, {
45
+ archiverL1BlockNumber,
46
+ archiverL2BlockNumber
47
+ });
48
+ await archiverStore.close();
49
+ }
50
+ const minL1BlocksToTriggerReplace = config.minL1BlocksToTriggerReplace ?? MIN_L1_BLOCKS_TO_TRIGGER_REPLACE;
51
+ if (syncMode === 'snapshot' && archiverL2BlockNumber !== undefined && archiverL2BlockNumber >= INITIAL_L2_BLOCK_NUM) {
52
+ log.verbose(`Skipping non-forced snapshot sync as archiver is already synced to L2 block ${archiverL2BlockNumber}.`);
53
+ return false;
54
+ }
55
+ const currentL1BlockNumber = await getPublicClient(config).getBlockNumber();
56
+ if (archiverL1BlockNumber && currentL1BlockNumber - archiverL1BlockNumber < minL1BlocksToTriggerReplace) {
57
+ log.verbose(`Skipping snapshot sync as archiver is less than ${currentL1BlockNumber - archiverL1BlockNumber} L1 blocks behind.`, {
58
+ archiverL1BlockNumber,
59
+ currentL1BlockNumber,
60
+ minL1BlocksToTriggerReplace
61
+ });
62
+ return false;
63
+ }
64
+ const indexMetadata = {
65
+ l1ChainId,
66
+ rollupVersion,
67
+ rollupAddress: l1Contracts.rollupAddress
68
+ };
69
+ const snapshotCandidates = [];
70
+ for (const snapshotsUrl of snapshotsUrls){
71
+ let fileStore;
72
+ try {
73
+ fileStore = await createReadOnlyFileStore(snapshotsUrl, log);
74
+ } catch (err) {
75
+ log.error(`Invalid config for downloading snapshots from ${snapshotsUrl}`, err);
76
+ continue;
77
+ }
78
+ let snapshot;
79
+ try {
80
+ snapshot = await getLatestSnapshotMetadata(indexMetadata, fileStore);
81
+ } catch (err) {
82
+ log.error(`Failed to get latest snapshot metadata from ${snapshotsUrl}. Skipping this URL.`, err, {
83
+ ...indexMetadata,
84
+ snapshotsUrl
85
+ });
86
+ continue;
87
+ }
88
+ if (!snapshot) {
89
+ log.verbose(`No snapshot found at ${snapshotsUrl}. Skipping this URL.`, {
90
+ ...indexMetadata,
91
+ snapshotsUrl
92
+ });
93
+ continue;
94
+ }
95
+ if (snapshot.schemaVersions.archiver !== ARCHIVER_DB_VERSION) {
96
+ log.warn(`Skipping snapshot from ${snapshotsUrl} as it has schema version ${snapshot.schemaVersions.archiver} but expected ${ARCHIVER_DB_VERSION}.`, snapshot);
97
+ continue;
98
+ }
99
+ if (snapshot.schemaVersions.worldState !== WORLD_STATE_DB_VERSION) {
100
+ log.warn(`Skipping snapshot from ${snapshotsUrl} as it has world state schema version ${snapshot.schemaVersions.worldState} but we expected ${WORLD_STATE_DB_VERSION}.`, snapshot);
101
+ continue;
102
+ }
103
+ if (archiverL1BlockNumber && snapshot.l1BlockNumber < archiverL1BlockNumber) {
104
+ log.verbose(`Skipping snapshot from ${snapshotsUrl} since local archiver is at L1 block ${archiverL1BlockNumber} which is further than snapshot at ${snapshot.l1BlockNumber}`, {
105
+ snapshot,
106
+ archiverL1BlockNumber,
107
+ snapshotsUrl
108
+ });
109
+ continue;
110
+ }
111
+ if (archiverL1BlockNumber && snapshot.l1BlockNumber - Number(archiverL1BlockNumber) < minL1BlocksToTriggerReplace) {
112
+ log.verbose(`Skipping snapshot from ${snapshotsUrl} as archiver is less than ${snapshot.l1BlockNumber - Number(archiverL1BlockNumber)} L1 blocks behind this snapshot.`, {
113
+ snapshot,
114
+ archiverL1BlockNumber,
115
+ snapshotsUrl
116
+ });
117
+ continue;
118
+ }
119
+ snapshotCandidates.push({
120
+ snapshot,
121
+ url: snapshotsUrl,
122
+ fileStore
123
+ });
124
+ }
125
+ if (snapshotCandidates.length === 0) {
126
+ log.verbose(`No valid snapshots found from any URL. Skipping snapshot sync.`, {
127
+ ...indexMetadata,
128
+ snapshotsUrls
129
+ });
130
+ return false;
131
+ }
132
+ // Sort candidates by L1 block number (highest first)
133
+ snapshotCandidates.sort((a, b)=>b.snapshot.l1BlockNumber - a.snapshot.l1BlockNumber);
134
+ // Try each candidate in order until one succeeds
135
+ for (const { snapshot, url } of snapshotCandidates){
136
+ const { l1BlockNumber, l2BlockNumber } = snapshot;
137
+ log.info(`Attempting to sync from snapshot at L1 block ${l1BlockNumber} L2 block ${l2BlockNumber}`, {
138
+ snapshot,
139
+ snapshotsUrl: url
140
+ });
141
+ try {
142
+ await snapshotSync(snapshot, log, {
143
+ dataDirectory: config.dataDirectory,
144
+ rollupAddress: config.l1Contracts.rollupAddress,
145
+ snapshotsUrl: url
146
+ });
147
+ log.info(`Snapshot synced to L1 block ${l1BlockNumber} L2 block ${l2BlockNumber}`, {
148
+ snapshot,
149
+ snapshotsUrl: url
150
+ });
151
+ return true;
152
+ } catch (err) {
153
+ log.error(`Failed to download snapshot from ${url}. Trying next candidate.`, err, {
154
+ snapshot,
155
+ snapshotsUrl: url
156
+ });
157
+ continue;
158
+ }
159
+ }
160
+ log.error(`Failed to download snapshot from all URLs.`, {
161
+ snapshotsUrls
162
+ });
163
+ return false;
164
+ }
165
+ /**
166
+ * Downloads the given snapshot replacing any local data stores.
167
+ */ export async function snapshotSync(snapshot, log, config) {
168
+ const { dataDirectory, rollupAddress } = config;
169
+ if (!dataDirectory) {
170
+ throw new Error(`No local data directory defined. Cannot sync snapshot.`);
171
+ }
172
+ const fileStore = await createReadOnlyFileStore(config.snapshotsUrl, log);
173
+ let downloadDir;
174
+ try {
175
+ // Download the snapshot to a temp location.
176
+ await mkdir(dataDirectory, {
177
+ recursive: true
178
+ });
179
+ downloadDir = await mkdtemp(join(dataDirectory, 'download-'));
180
+ const downloadPaths = makeSnapshotPaths(downloadDir);
181
+ log.info(`Downloading snapshot to ${downloadDir}`, {
182
+ snapshot,
183
+ downloadPaths
184
+ });
185
+ await downloadSnapshot(snapshot, downloadPaths, fileStore);
186
+ log.info(`Snapshot downloaded at ${downloadDir}`, {
187
+ snapshot,
188
+ downloadPaths
189
+ });
190
+ // If download was successful, clear lock and version, and move download there
191
+ const archiverPath = join(dataDirectory, ARCHIVER_STORE_NAME);
192
+ await prepareTarget(archiverPath, ARCHIVER_DB_VERSION, rollupAddress);
193
+ await rename(downloadPaths.archiver, join(archiverPath, 'data.mdb'));
194
+ log.info(`Archiver database set up from snapshot`, {
195
+ path: archiverPath,
196
+ dbVersion: ARCHIVER_DB_VERSION,
197
+ rollupAddress
198
+ });
199
+ // Same for the world state dbs, only that we do not close them, since we assume they are not yet in use
200
+ const worldStateBasePath = join(dataDirectory, WORLD_STATE_DIR);
201
+ await prepareTarget(worldStateBasePath, WORLD_STATE_DB_VERSION, rollupAddress);
202
+ for (const [name, dir] of NATIVE_WORLD_STATE_DBS){
203
+ const path = join(worldStateBasePath, dir);
204
+ await mkdir(path, {
205
+ recursive: true
206
+ });
207
+ await rename(downloadPaths[name], join(path, 'data.mdb'));
208
+ log.info(`World state database ${name} set up from snapshot`, {
209
+ path,
210
+ dbVersion: WORLD_STATE_DB_VERSION,
211
+ rollupAddress
212
+ });
213
+ }
214
+ // And clear the p2p db altogether
215
+ const p2pPath = join(dataDirectory, P2P_STORE_NAME);
216
+ await tryRmDir(p2pPath, log);
217
+ log.info(`P2P database cleared`, {
218
+ path: p2pPath
219
+ });
220
+ } finally{
221
+ if (downloadDir) {
222
+ await tryRmDir(downloadDir, log);
223
+ }
224
+ }
225
+ }
226
+ /** Deletes target dir and writes the new version file. */ async function prepareTarget(target, schemaVersion, rollupAddress) {
227
+ const noOpen = ()=>Promise.resolve(undefined);
228
+ const versionManager = new DatabaseVersionManager({
229
+ schemaVersion,
230
+ rollupAddress,
231
+ dataDirectory: target,
232
+ onOpen: noOpen
233
+ });
234
+ await versionManager.resetDataDirectory();
235
+ await versionManager.writeVersion();
236
+ }
@@ -0,0 +1,12 @@
1
+ import { type Archiver } from '@aztec/archiver';
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import type { DataStoreConfig } from '@aztec/kv-store/config';
4
+ import type { ChainConfig } from '@aztec/stdlib/config';
5
+ import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
6
+ export type UploadSnapshotConfig = Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'> & Pick<DataStoreConfig, 'dataDirectory'>;
7
+ /**
8
+ * Pauses the archiver and world state sync, creates backups of the archiver and world state lmdb environments,
9
+ * and uploads them to the specified location. Location must be a URL supported by our file store (eg `gs://bucketname/path`).
10
+ */
11
+ export declare function uploadSnapshot(location: string, archiver: Archiver, worldState: WorldStateSynchronizer, config: UploadSnapshotConfig, log: Logger): Promise<void>;
12
+ //# sourceMappingURL=upload-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-snapshot.d.ts","sourceRoot":"","sources":["../../src/actions/upload-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAW9E,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,eAAe,CAAC,GACjF,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,sBAAsB,EAClC,MAAM,EAAE,oBAAoB,EAC5B,GAAG,EAAE,MAAM,iBAoBZ"}
@@ -0,0 +1,38 @@
1
+ import { ARCHIVER_DB_VERSION } from '@aztec/archiver';
2
+ import { tryRmDir } from '@aztec/foundation/fs';
3
+ import { createFileStore } from '@aztec/stdlib/file-store';
4
+ import { uploadSnapshotToIndex } from '@aztec/stdlib/snapshots';
5
+ import { WORLD_STATE_DB_VERSION } from '@aztec/world-state';
6
+ import { mkdtemp } from 'fs/promises';
7
+ import { tmpdir } from 'os';
8
+ import { join } from 'path';
9
+ import { buildSnapshotMetadata } from './build-snapshot-metadata.js';
10
+ import { createBackups } from './create-backups.js';
11
+ /**
12
+ * Pauses the archiver and world state sync, creates backups of the archiver and world state lmdb environments,
13
+ * and uploads them to the specified location. Location must be a URL supported by our file store (eg `gs://bucketname/path`).
14
+ */ export async function uploadSnapshot(location, archiver, worldState, config, log) {
15
+ const store = await createFileStore(location);
16
+ if (!store) {
17
+ throw new Error(`Failed to create file store for snapshot upload for location ${location}.`);
18
+ }
19
+ const backupDir = await mkdtemp(join(config.dataDirectory ?? tmpdir(), 'snapshot-'));
20
+ try {
21
+ const paths = await createBackups(backupDir, archiver, worldState, log);
22
+ const versions = {
23
+ archiver: ARCHIVER_DB_VERSION,
24
+ worldState: WORLD_STATE_DB_VERSION
25
+ };
26
+ const metadata = await buildSnapshotMetadata(archiver, config);
27
+ log.info(`Uploading snapshot to ${location}`, {
28
+ snapshot: metadata
29
+ });
30
+ const snapshot = await uploadSnapshotToIndex(paths, versions, metadata, store);
31
+ log.info(`Snapshot uploaded successfully`, {
32
+ snapshot
33
+ });
34
+ } finally{
35
+ log.info(`Cleaning up backup dir ${backupDir}`);
36
+ await tryRmDir(backupDir, log);
37
+ }
38
+ }
@@ -0,0 +1,19 @@
1
+ import { type ConfigMappingsType } from '@aztec/foundation/config';
2
+ export type SharedNodeConfig = {
3
+ /** Whether to populate the genesis state with initial fee juice for the test accounts */
4
+ testAccounts: boolean;
5
+ /** Whether to populate the genesis state with initial fee juice for the sponsored FPC */
6
+ sponsoredFPC: boolean;
7
+ /** Sync mode: full to always sync via L1, snapshot to download a snapshot if there is no local data, force-snapshot to download even if there is local data. */
8
+ syncMode: 'full' | 'snapshot' | 'force-snapshot';
9
+ /** Base URLs for snapshots index. Index file will be searched at `SNAPSHOTS_BASE_URL/aztec-L1_CHAIN_ID-VERSION-ROLLUP_ADDRESS/index.json` */
10
+ snapshotsUrls?: string[];
11
+ /** Auto update mode: disabled - to completely ignore remote signals to update the node. enabled - to respect the signals (potentially shutting this node down). log - check for updates but log a warning instead of applying them*/
12
+ autoUpdate?: 'disabled' | 'notify' | 'config' | 'config-and-version';
13
+ /** The base URL against which to check for updates */
14
+ autoUpdateUrl?: string;
15
+ /** URL of the Web3Signer instance */
16
+ web3SignerUrl?: string;
17
+ };
18
+ export declare const sharedNodeConfigMappings: ConfigMappingsType<SharedNodeConfig>;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAuB,MAAM,0BAA0B,CAAC;AAExF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,yFAAyF;IACzF,YAAY,EAAE,OAAO,CAAC;IACtB,yFAAyF;IACzF,YAAY,EAAE,OAAO,CAAC;IACtB,gKAAgK;IAChK,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACjD,6IAA6I;IAC7I,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,qOAAqO;IACrO,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,oBAAoB,CAAC;IACrE,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,kBAAkB,CAAC,gBAAgB,CA0CzE,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { booleanConfigHelper } from '@aztec/foundation/config';
2
+ export const sharedNodeConfigMappings = {
3
+ testAccounts: {
4
+ env: 'TEST_ACCOUNTS',
5
+ description: 'Whether to populate the genesis state with initial fee juice for the test accounts.',
6
+ ...booleanConfigHelper()
7
+ },
8
+ sponsoredFPC: {
9
+ env: 'SPONSORED_FPC',
10
+ description: 'Whether to populate the genesis state with initial fee juice for the sponsored FPC.',
11
+ ...booleanConfigHelper(false)
12
+ },
13
+ syncMode: {
14
+ env: 'SYNC_MODE',
15
+ description: 'Set sync mode to `full` to always sync via L1, `snapshot` to download a snapshot if there is no local data, `force-snapshot` to download even if there is local data.',
16
+ defaultValue: 'snapshot'
17
+ },
18
+ snapshotsUrls: {
19
+ env: 'SYNC_SNAPSHOTS_URLS',
20
+ description: 'Base URLs for snapshots index, comma-separated.',
21
+ parseEnv: (val)=>val.split(',').map((url)=>url.trim()).filter((url)=>url.length > 0),
22
+ fallback: [
23
+ 'SYNC_SNAPSHOTS_URL'
24
+ ],
25
+ defaultValue: []
26
+ },
27
+ autoUpdate: {
28
+ env: 'AUTO_UPDATE',
29
+ description: 'The auto update mode for this node',
30
+ defaultValue: 'disabled'
31
+ },
32
+ autoUpdateUrl: {
33
+ env: 'AUTO_UPDATE_URL',
34
+ description: 'Base URL to check for updates'
35
+ },
36
+ web3SignerUrl: {
37
+ env: 'WEB3_SIGNER_URL',
38
+ description: 'URL of the Web3Signer instance',
39
+ parseEnv: (val)=>val.trim()
40
+ }
41
+ };
@@ -0,0 +1,2 @@
1
+ export * from './l1_tx_utils.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factories/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './l1_tx_utils.js';
@@ -0,0 +1,53 @@
1
+ import type { EthSigner, ExtendedViemWalletClient, L1TxUtilsConfig, ViemClient } from '@aztec/ethereum';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import type { DateProvider } from '@aztec/foundation/timer';
4
+ import type { DataStoreConfig } from '@aztec/kv-store/config';
5
+ import type { TelemetryClient } from '@aztec/telemetry-client';
6
+ import type { L1TxScope } from '../metrics/l1_tx_metrics.js';
7
+ /**
8
+ * Creates L1TxUtils with blobs from multiple Viem wallets, sharing store and metrics.
9
+ */
10
+ export declare function createL1TxUtilsWithBlobsFromViemWallet(clients: ExtendedViemWalletClient[], config: DataStoreConfig & Partial<L1TxUtilsConfig> & {
11
+ debugMaxGasLimit?: boolean;
12
+ scope?: L1TxScope;
13
+ }, deps: {
14
+ telemetry: TelemetryClient;
15
+ logger?: ReturnType<typeof createLogger>;
16
+ dateProvider?: DateProvider;
17
+ }): Promise<import("@aztec/ethereum/l1-tx-utils-with-blobs").L1TxUtilsWithBlobs[]>;
18
+ /**
19
+ * Creates L1TxUtils with blobs from multiple EthSigners, sharing store and metrics.
20
+ */
21
+ export declare function createL1TxUtilsWithBlobsFromEthSigner(client: ViemClient, signers: EthSigner[], config: DataStoreConfig & Partial<L1TxUtilsConfig> & {
22
+ debugMaxGasLimit?: boolean;
23
+ scope?: L1TxScope;
24
+ }, deps: {
25
+ telemetry: TelemetryClient;
26
+ logger?: ReturnType<typeof createLogger>;
27
+ dateProvider?: DateProvider;
28
+ }): Promise<import("@aztec/ethereum/l1-tx-utils-with-blobs").L1TxUtilsWithBlobs[]>;
29
+ /**
30
+ * Creates L1TxUtils (without blobs) from multiple Viem wallets, sharing store and metrics.
31
+ */
32
+ export declare function createL1TxUtilsFromViemWalletWithStore(clients: ExtendedViemWalletClient[], config: DataStoreConfig & Partial<L1TxUtilsConfig> & {
33
+ debugMaxGasLimit?: boolean;
34
+ scope?: L1TxScope;
35
+ }, deps: {
36
+ telemetry: TelemetryClient;
37
+ logger?: ReturnType<typeof createLogger>;
38
+ dateProvider?: DateProvider;
39
+ scope?: L1TxScope;
40
+ }): Promise<import("@aztec/ethereum").L1TxUtils[]>;
41
+ /**
42
+ * Creates L1TxUtils (without blobs) from multiple EthSigners, sharing store and metrics.
43
+ */
44
+ export declare function createL1TxUtilsFromEthSignerWithStore(client: ViemClient, signers: EthSigner[], config: DataStoreConfig & Partial<L1TxUtilsConfig> & {
45
+ debugMaxGasLimit?: boolean;
46
+ scope?: L1TxScope;
47
+ }, deps: {
48
+ telemetry: TelemetryClient;
49
+ logger?: ReturnType<typeof createLogger>;
50
+ dateProvider?: DateProvider;
51
+ scope?: L1TxScope;
52
+ }): Promise<import("@aztec/ethereum").L1TxUtils[]>;
53
+ //# sourceMappingURL=l1_tx_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"l1_tx_utils.d.ts","sourceRoot":"","sources":["../../src/factories/l1_tx_utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,wBAAwB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMxG,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA+B7D;;GAEG;AACH,wBAAsB,sCAAsC,CAC1D,OAAO,EAAE,wBAAwB,EAAE,EACnC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,EACtG,IAAI,EAAE;IACJ,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,kFAOF;AAED;;GAEG;AACH,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,SAAS,EAAE,EACpB,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,EACtG,IAAI,EAAE;IACJ,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,kFAOF;AAED;;GAEG;AACH,wBAAsB,sCAAsC,CAC1D,OAAO,EAAE,wBAAwB,EAAE,EACnC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,EACtG,IAAI,EAAE;IACJ,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,kDAKF;AAED;;GAEG;AACH,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,SAAS,EAAE,EACpB,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,EACtG,IAAI,EAAE;IACJ,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,kDAKF"}
@@ -0,0 +1,50 @@
1
+ import { createL1TxUtilsFromEthSigner as createL1TxUtilsFromEthSignerBase, createL1TxUtilsFromViemWallet as createL1TxUtilsFromViemWalletBase } from '@aztec/ethereum';
2
+ import { createL1TxUtilsWithBlobsFromEthSigner as createL1TxUtilsWithBlobsFromEthSignerBase, createL1TxUtilsWithBlobsFromViemWallet as createL1TxUtilsWithBlobsFromViemWalletBase } from '@aztec/ethereum/l1-tx-utils-with-blobs';
3
+ import { omit } from '@aztec/foundation/collection';
4
+ import { createLogger } from '@aztec/foundation/log';
5
+ import { createStore } from '@aztec/kv-store/lmdb-v2';
6
+ import { L1TxMetrics } from '../metrics/l1_tx_metrics.js';
7
+ import { L1TxStore } from '../stores/l1_tx_store.js';
8
+ const L1_TX_STORE_NAME = 'l1-tx-utils';
9
+ /**
10
+ * Creates shared dependencies (logger, store, metrics) for L1TxUtils instances.
11
+ */ async function createSharedDeps(config, deps) {
12
+ const logger = deps.logger ?? createLogger('l1-tx-utils');
13
+ // Note that we do NOT bind them to the rollup address, since we still need to
14
+ // monitor and cancel txs for previous rollups to free up our nonces.
15
+ const noRollupConfig = omit(config, 'l1Contracts');
16
+ const kvStore = await createStore(L1_TX_STORE_NAME, L1TxStore.SCHEMA_VERSION, noRollupConfig, logger);
17
+ const store = new L1TxStore(kvStore, logger);
18
+ const meter = deps.telemetry.getMeter('L1TxUtils');
19
+ const metrics = new L1TxMetrics(meter, config.scope ?? 'other', logger);
20
+ return {
21
+ logger,
22
+ store,
23
+ metrics,
24
+ dateProvider: deps.dateProvider
25
+ };
26
+ }
27
+ /**
28
+ * Creates L1TxUtils with blobs from multiple Viem wallets, sharing store and metrics.
29
+ */ export async function createL1TxUtilsWithBlobsFromViemWallet(clients, config, deps) {
30
+ const sharedDeps = await createSharedDeps(config, deps);
31
+ return clients.map((client)=>createL1TxUtilsWithBlobsFromViemWalletBase(client, sharedDeps, config, config.debugMaxGasLimit));
32
+ }
33
+ /**
34
+ * Creates L1TxUtils with blobs from multiple EthSigners, sharing store and metrics.
35
+ */ export async function createL1TxUtilsWithBlobsFromEthSigner(client, signers, config, deps) {
36
+ const sharedDeps = await createSharedDeps(config, deps);
37
+ return signers.map((signer)=>createL1TxUtilsWithBlobsFromEthSignerBase(client, signer, sharedDeps, config, config.debugMaxGasLimit));
38
+ }
39
+ /**
40
+ * Creates L1TxUtils (without blobs) from multiple Viem wallets, sharing store and metrics.
41
+ */ export async function createL1TxUtilsFromViemWalletWithStore(clients, config, deps) {
42
+ const sharedDeps = await createSharedDeps(config, deps);
43
+ return clients.map((client)=>createL1TxUtilsFromViemWalletBase(client, sharedDeps, config));
44
+ }
45
+ /**
46
+ * Creates L1TxUtils (without blobs) from multiple EthSigners, sharing store and metrics.
47
+ */ export async function createL1TxUtilsFromEthSignerWithStore(client, signers, config, deps) {
48
+ const sharedDeps = await createSharedDeps(config, deps);
49
+ return signers.map((signer)=>createL1TxUtilsFromEthSignerBase(client, signer, sharedDeps, config));
50
+ }
@@ -0,0 +1,2 @@
1
+ export * from './l1_tx_metrics.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './l1_tx_metrics.js';