@agoric/cosmic-swingset 0.41.4-dev-c6d8a27.0 → 0.41.4-dev-f2445bc.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/cosmic-swingset",
3
- "version": "0.41.4-dev-c6d8a27.0+c6d8a27",
3
+ "version": "0.41.4-dev-f2445bc.0+f2445bc",
4
4
  "description": "Agoric's Cosmos blockchain integration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,15 +22,15 @@
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/assert": "0.6.1-dev-c6d8a27.0+c6d8a27",
26
- "@agoric/cosmos": "0.34.2-dev-c6d8a27.0+c6d8a27",
27
- "@agoric/deploy-script-support": "0.10.4-dev-c6d8a27.0+c6d8a27",
28
- "@agoric/internal": "0.3.3-dev-c6d8a27.0+c6d8a27",
29
- "@agoric/store": "0.9.3-dev-c6d8a27.0+c6d8a27",
30
- "@agoric/swing-store": "0.9.2-dev-c6d8a27.0+c6d8a27",
31
- "@agoric/swingset-vat": "0.32.3-dev-c6d8a27.0+c6d8a27",
32
- "@agoric/telemetry": "0.6.3-dev-c6d8a27.0+c6d8a27",
33
- "@agoric/vm-config": "0.1.1-dev-c6d8a27.0+c6d8a27",
25
+ "@agoric/assert": "0.6.1-dev-f2445bc.0+f2445bc",
26
+ "@agoric/cosmos": "0.34.2-dev-f2445bc.0+f2445bc",
27
+ "@agoric/deploy-script-support": "0.10.4-dev-f2445bc.0+f2445bc",
28
+ "@agoric/internal": "0.3.3-dev-f2445bc.0+f2445bc",
29
+ "@agoric/store": "0.9.3-dev-f2445bc.0+f2445bc",
30
+ "@agoric/swing-store": "0.9.2-dev-f2445bc.0+f2445bc",
31
+ "@agoric/swingset-vat": "0.32.3-dev-f2445bc.0+f2445bc",
32
+ "@agoric/telemetry": "0.6.3-dev-f2445bc.0+f2445bc",
33
+ "@agoric/vm-config": "0.1.1-dev-f2445bc.0+f2445bc",
34
34
  "@endo/bundle-source": "^2.5.2",
35
35
  "@endo/far": "^0.2.19",
36
36
  "@endo/import-bundle": "^0.3.5",
@@ -65,5 +65,5 @@
65
65
  ],
66
66
  "timeout": "20m"
67
67
  },
68
- "gitHead": "c6d8a278ad7d7c0ad758f57c7e4db858d6a67e53"
68
+ "gitHead": "f2445bcb471c26169ea8052d04e96d51ef9f1487"
69
69
  }
@@ -23,30 +23,64 @@ import { makeProcessValue } from './helpers/process-value.js';
23
23
  // with the golang SwingStoreExportsHandler in golang/cosmos/x/swingset/keeper/swing_store_exports_handler.go
24
24
  export const ExportManifestFileName = 'export-manifest.json';
25
25
 
26
- /** @typedef {'current' | 'archival' | 'debug'} SwingStoreExportMode */
26
+ /**
27
+ * @typedef {'none' // No artifacts included
28
+ * | import("@agoric/swing-store").ArtifactMode
29
+ * } SwingStoreArtifactMode
30
+ */
27
31
 
28
32
  /**
29
- * @param {SwingStoreExportMode | undefined} exportMode
33
+ * @typedef {'skip' // Do not include any "export data" (artifacts only)
34
+ * | 'repair-metadata' // Add missing artifact metadata (import only)
35
+ * | 'all' // Include all export data, create new swing-store on import
36
+ * } SwingStoreExportDataMode
37
+ */
38
+
39
+ /**
40
+ * @param {SwingStoreArtifactMode | undefined} artifactMode
30
41
  * @returns {import("@agoric/swing-store").ArtifactMode}
31
42
  */
32
- const getArtifactModeFromExportMode = exportMode => {
33
- switch (exportMode) {
34
- case 'current':
35
- case undefined:
43
+ export const getEffectiveArtifactMode = artifactMode => {
44
+ switch (artifactMode) {
45
+ case 'none':
46
+ case 'operational':
36
47
  return 'operational';
48
+ case undefined:
49
+ case 'replay':
50
+ return 'replay';
37
51
  case 'archival':
38
- return 'archival';
39
52
  case 'debug':
40
- return 'debug';
53
+ return artifactMode;
41
54
  default:
42
- throw Fail`Invalid value ${q(exportMode)} for "export-mode"`;
55
+ throw Fail`Invalid value ${q(artifactMode)} for "artifact-mode"`;
43
56
  }
44
57
  };
45
58
 
59
+ /** @type {(artifactMode: string | undefined) => asserts artifactMode is SwingStoreArtifactMode | undefined} */
60
+ export const checkArtifactMode = getEffectiveArtifactMode;
61
+
46
62
  /**
47
- * @type {(exportMode: string | undefined) => asserts exportMode is SwingStoreExportMode}
63
+ * @param {string | undefined} mode
64
+ * @param {boolean} [isImport]
65
+ * @returns {asserts mode is SwingStoreExportDataMode | undefined}
48
66
  */
49
- const checkExportMode = getArtifactModeFromExportMode;
67
+ export const checkExportDataMode = (mode, isImport = false) => {
68
+ switch (mode) {
69
+ case 'skip':
70
+ case undefined:
71
+ break;
72
+ case 'all':
73
+ break;
74
+ case 'repair-metadata': {
75
+ if (isImport) {
76
+ break;
77
+ }
78
+ // Fall through
79
+ }
80
+ default:
81
+ throw Fail`Invalid value ${q(mode)} for "export-data-mode"`;
82
+ }
83
+ };
50
84
 
51
85
  /**
52
86
  * A state-sync manifest is a representation of the information contained in a
@@ -60,7 +94,7 @@ const checkExportMode = getArtifactModeFromExportMode;
60
94
  *
61
95
  * @typedef {object} StateSyncManifest
62
96
  * @property {number} blockHeight the block height corresponding to this export
63
- * @property {SwingStoreExportMode} [mode]
97
+ * @property {SwingStoreArtifactMode} [artifactMode]
64
98
  * @property {string} [data] file name containing the swingStore "export data"
65
99
  * @property {Array<[artifactName: string, fileName: string]>} artifacts
66
100
  * List of swingStore export artifacts which can be validated by the export data
@@ -79,8 +113,8 @@ const checkExportMode = getArtifactModeFromExportMode;
79
113
  * @property {string} stateDir the directory containing the SwingStore to export
80
114
  * @property {string} exportDir the directory in which to place the exported artifacts and manifest
81
115
  * @property {number} [blockHeight] block height to check for
82
- * @property {SwingStoreExportMode} [exportMode] whether to include historical or debug artifacts in the export
83
- * @property {boolean} [includeExportData] whether to include an artifact for the export data in the export
116
+ * @property {SwingStoreArtifactMode} [artifactMode] the level of artifacts to include in the export
117
+ * @property {SwingStoreExportDataMode} [exportDataMode] include a synthetic artifact for the export data in the export
84
118
  */
85
119
 
86
120
  /**
@@ -96,10 +130,12 @@ export const validateExporterOptions = options => {
96
130
  options.blockHeight == null ||
97
131
  typeof options.blockHeight === 'number' ||
98
132
  Fail`optional blockHeight option not a number`;
99
- checkExportMode(options.exportMode);
100
- options.includeExportData == null ||
101
- typeof options.includeExportData === 'boolean' ||
102
- Fail`optional includeExportData option not a boolean`;
133
+ checkArtifactMode(options.artifactMode);
134
+ checkExportDataMode(options.exportDataMode);
135
+
136
+ options.includeExportData === undefined ||
137
+ Fail`deprecated includeExportData option found`;
138
+ options.exportMode === undefined || Fail`deprecated exportMode option found`;
103
139
  };
104
140
 
105
141
  /**
@@ -113,7 +149,7 @@ export const validateExporterOptions = options => {
113
149
  * @returns {StateSyncExporter}
114
150
  */
115
151
  export const initiateSwingStoreExport = (
116
- { stateDir, exportDir, blockHeight, exportMode, includeExportData },
152
+ { stateDir, exportDir, blockHeight, artifactMode, exportDataMode },
117
153
  {
118
154
  fs: { open, writeFile },
119
155
  pathResolve,
@@ -122,8 +158,7 @@ export const initiateSwingStoreExport = (
122
158
  log = console.log,
123
159
  },
124
160
  ) => {
125
- const artifactMode = getArtifactModeFromExportMode(exportMode);
126
-
161
+ const effectiveArtifactMode = getEffectiveArtifactMode(artifactMode);
127
162
  /** @type {number | undefined} */
128
163
  let savedBlockHeight;
129
164
 
@@ -143,7 +178,9 @@ export const initiateSwingStoreExport = (
143
178
  const manifestFile = await open(manifestPath, 'wx');
144
179
  cleanup.push(async () => manifestFile.close());
145
180
 
146
- const swingStoreExporter = makeExporter(stateDir, { artifactMode });
181
+ const swingStoreExporter = makeExporter(stateDir, {
182
+ artifactMode: effectiveArtifactMode,
183
+ });
147
184
  cleanup.push(async () => swingStoreExporter.close());
148
185
 
149
186
  const { hostStorage } = openDB(stateDir);
@@ -153,7 +190,9 @@ export const initiateSwingStoreExport = (
153
190
 
154
191
  if (blockHeight) {
155
192
  blockHeight === savedBlockHeight ||
156
- Fail`DB at unexpected block height ${savedBlockHeight} (expected ${blockHeight})`;
193
+ Fail`DB at unexpected block height ${q(savedBlockHeight)} (expected ${q(
194
+ blockHeight,
195
+ )})`;
157
196
  }
158
197
 
159
198
  abortIfStopped();
@@ -163,11 +202,11 @@ export const initiateSwingStoreExport = (
163
202
  /** @type {StateSyncManifest} */
164
203
  const manifest = {
165
204
  blockHeight: savedBlockHeight,
166
- mode: exportMode,
205
+ artifactMode: artifactMode || effectiveArtifactMode,
167
206
  artifacts: [],
168
207
  };
169
208
 
170
- if (includeExportData) {
209
+ if (exportDataMode === 'all') {
171
210
  log?.(`Writing Export Data`);
172
211
  const fileName = `export-data.jsonl`;
173
212
  const exportDataFile = await open(pathResolve(exportDir, fileName), 'wx');
@@ -181,14 +220,16 @@ export const initiateSwingStoreExport = (
181
220
  }
182
221
  abortIfStopped();
183
222
 
184
- for await (const artifactName of swingStoreExporter.getArtifactNames()) {
185
- abortIfStopped();
186
- log?.(`Writing artifact: ${artifactName}`);
187
- const artifactData = swingStoreExporter.getArtifact(artifactName);
188
- // Use artifactName as the file name as we trust swingStore to generate
189
- // artifact names that are valid file names.
190
- await writeFile(pathResolve(exportDir, artifactName), artifactData);
191
- manifest.artifacts.push([artifactName, artifactName]);
223
+ if (artifactMode !== 'none') {
224
+ for await (const artifactName of swingStoreExporter.getArtifactNames()) {
225
+ abortIfStopped();
226
+ log?.(`Writing artifact: ${artifactName}`);
227
+ const artifactData = swingStoreExporter.getArtifact(artifactName);
228
+ // Use artifactName as the file name as we trust swingStore to generate
229
+ // artifact names that are valid file names.
230
+ await writeFile(pathResolve(exportDir, artifactName), artifactData);
231
+ manifest.artifacts.push([artifactName, artifactName]);
232
+ }
192
233
  }
193
234
 
194
235
  await manifestFile.write(JSON.stringify(manifest, null, 2));
@@ -272,11 +313,22 @@ export const main = async (
272
313
  /** @type {string} */ (processValue.getFlag('export-dir', '.')),
273
314
  );
274
315
 
275
- const includeExportData = processValue.getBoolean({
276
- flagName: 'include-export-data',
277
- });
278
- const exportMode = processValue.getFlag('export-mode');
279
- checkExportMode(exportMode);
316
+ const artifactMode = /** @type {SwingStoreArtifactMode | undefined} */ (
317
+ processValue.getFlag('artifact-mode')
318
+ );
319
+ checkArtifactMode(artifactMode);
320
+
321
+ const exportDataMode = processValue.getFlag('export-data-mode');
322
+ checkExportDataMode(exportDataMode);
323
+
324
+ if (
325
+ processValue.getBoolean({ flagName: 'include-export-data' }) !== undefined
326
+ ) {
327
+ throw Fail`deprecated "include-export-data" options, use "export-data-mode" instead`;
328
+ }
329
+ if (processValue.getFlag('export-mode') !== undefined) {
330
+ throw Fail`deprecated "export-mode" options, use "artifact-mode" instead`;
331
+ }
280
332
 
281
333
  const checkBlockHeight = processValue.getInteger({
282
334
  flagName: 'check-block-height',
@@ -293,8 +345,8 @@ export const main = async (
293
345
  stateDir,
294
346
  exportDir,
295
347
  blockHeight: checkBlockHeight,
296
- exportMode,
297
- includeExportData,
348
+ artifactMode,
349
+ exportDataMode,
298
350
  },
299
351
  {
300
352
  fs,
@@ -335,7 +387,7 @@ export const main = async (
335
387
  * @returns {StateSyncExporter}
336
388
  */
337
389
  export const spawnSwingStoreExport = (
338
- { stateDir, exportDir, blockHeight, exportMode, includeExportData },
390
+ { stateDir, exportDir, blockHeight, artifactMode, exportDataMode },
339
391
  { fork, verbose },
340
392
  ) => {
341
393
  const args = ['--state-dir', stateDir, '--export-dir', exportDir];
@@ -344,12 +396,12 @@ export const spawnSwingStoreExport = (
344
396
  args.push('--check-block-height', String(blockHeight));
345
397
  }
346
398
 
347
- if (exportMode) {
348
- args.push('--export-mode', exportMode);
399
+ if (artifactMode) {
400
+ args.push('--artifact-mode', artifactMode);
349
401
  }
350
402
 
351
- if (includeExportData) {
352
- args.push('--include-export-data');
403
+ if (exportDataMode) {
404
+ args.push('--export-data-mode', exportDataMode);
353
405
  }
354
406
 
355
407
  if (verbose) {
@@ -401,7 +453,7 @@ export const spawnSwingStoreExport = (
401
453
  }
402
454
  default: {
403
455
  // @ts-expect-error exhaustive check
404
- Fail`Unexpected ${msg.type} message`;
456
+ Fail`Unexpected ${q(msg.type)} message`;
405
457
  }
406
458
  }
407
459
  };
@@ -12,19 +12,24 @@ import fsPromisesPower from 'fs/promises';
12
12
  import pathPower from 'path';
13
13
 
14
14
  import BufferLineTransform from '@agoric/internal/src/node/buffer-line-transform.js';
15
- import { Fail } from '@agoric/assert';
16
- import { importSwingStore } from '@agoric/swing-store';
15
+ import { Fail, q } from '@agoric/assert';
16
+ import { importSwingStore, openSwingStore } from '@agoric/swing-store';
17
17
 
18
18
  import { isEntrypoint } from './helpers/is-entrypoint.js';
19
19
  import { makeProcessValue } from './helpers/process-value.js';
20
- import { ExportManifestFileName } from './export-kernel-db.js';
20
+ import {
21
+ ExportManifestFileName,
22
+ checkExportDataMode,
23
+ checkArtifactMode,
24
+ } from './export-kernel-db.js';
21
25
 
22
26
  /**
23
27
  * @typedef {object} StateSyncImporterOptions
24
28
  * @property {string} stateDir the directory containing the SwingStore to export
25
29
  * @property {string} exportDir the directory where to place the exported artifacts and manifest
26
30
  * @property {number} [blockHeight] block height to check for
27
- * @property {boolean} [includeHistorical] whether to include historical artifacts in the export
31
+ * @property {import('./export-kernel-db.js').SwingStoreExportDataMode} [exportDataMode] how to handle export data
32
+ * @property {import('./export-kernel-db.js').SwingStoreArtifactMode} [artifactMode] the level of historical artifacts to import
28
33
  */
29
34
 
30
35
  /**
@@ -40,9 +45,57 @@ export const validateImporterOptions = options => {
40
45
  options.blockHeight == null ||
41
46
  typeof options.blockHeight === 'number' ||
42
47
  Fail`optional blockHeight option not a number`;
43
- options.includeHistorical == null ||
44
- typeof options.includeHistorical === 'boolean' ||
45
- Fail`optional includeHistorical option not a boolean`;
48
+ checkExportDataMode(options.exportDataMode, true);
49
+ checkArtifactMode(options.artifactMode);
50
+ options.includeHistorical === undefined ||
51
+ Fail`deprecated includeHistorical option found`;
52
+ };
53
+
54
+ /**
55
+ * @param {Pick<StateSyncImporterOptions, 'artifactMode' | 'exportDataMode' >} options
56
+ * @param {Readonly<import('./export-kernel-db.js').StateSyncManifest>} manifest
57
+ * @returns {import('@agoric/swing-store').ImportSwingStoreOptions}
58
+ */
59
+ const checkAndGetImportSwingStoreOptions = (options, manifest) => {
60
+ typeof manifest.blockHeight === 'number' ||
61
+ Fail`Cannot restore snapshot without block height`;
62
+
63
+ manifest.data || Fail`State-sync manifest missing export data`;
64
+
65
+ const { artifactMode = manifest.artifactMode || 'replay' } = options;
66
+
67
+ if (artifactMode === 'none') {
68
+ throw Fail`Cannot import "export data" without at least "operational" artifacts`;
69
+ }
70
+
71
+ manifest.artifacts?.length ||
72
+ Fail`State-sync manifest missing required artifacts`;
73
+
74
+ switch (artifactMode) {
75
+ case 'debug':
76
+ // eslint-disable-next-line no-fallthrough
77
+ case 'operational':
78
+ if (manifest.artifactMode === 'operational') break;
79
+ // eslint-disable-next-line no-fallthrough
80
+ case 'replay':
81
+ if (manifest.artifactMode === 'replay') break;
82
+ // eslint-disable-next-line no-fallthrough
83
+ case 'archival':
84
+ if (manifest.artifactMode === 'archival') break;
85
+ if (
86
+ manifest.artifactMode === undefined ||
87
+ manifest.artifactMode === 'debug'
88
+ ) {
89
+ // assume the export has sufficient data
90
+ break;
91
+ }
92
+ throw Fail`State-sync manifest has insufficient artifacts: requested import artifact mode: ${q(
93
+ artifactMode,
94
+ )}, manifest has ${q(manifest.artifactMode)} artifacts`;
95
+ default:
96
+ throw Fail`Unexpected artifactMode ${q(artifactMode)}`;
97
+ }
98
+ return { artifactMode };
46
99
  };
47
100
 
48
101
  /**
@@ -51,15 +104,17 @@ export const validateImporterOptions = options => {
51
104
  * @param {Pick<import('fs/promises'), 'readFile'> & Pick<import('fs'), 'createReadStream'>} powers.fs
52
105
  * @param {import('path')['resolve']} powers.pathResolve
53
106
  * @param {typeof import('@agoric/swing-store')['importSwingStore']} [powers.importSwingStore]
107
+ * @param {typeof import('@agoric/swing-store')['openSwingStore']} [powers.openSwingStore]
54
108
  * @param {null | ((...args: any[]) => void)} [powers.log]
55
109
  * @returns {Promise<void>}
56
110
  */
57
111
  export const performStateSyncImport = async (
58
- { stateDir, exportDir, blockHeight, includeHistorical },
112
+ { stateDir, exportDir, blockHeight, exportDataMode = 'all', artifactMode },
59
113
  {
60
114
  fs: { createReadStream, readFile },
61
115
  pathResolve,
62
116
  importSwingStore: importDB = importSwingStore,
117
+ openSwingStore: openDB = openSwingStore,
63
118
  log = console.log,
64
119
  },
65
120
  ) => {
@@ -67,7 +122,9 @@ export const performStateSyncImport = async (
67
122
  const safeExportFileResolve = allegedRelativeFilename => {
68
123
  const resolvedPath = pathResolve(exportDir, allegedRelativeFilename);
69
124
  resolvedPath.startsWith(exportDir) ||
70
- Fail`Exported file ${allegedRelativeFilename} must be in export dir ${exportDir}`;
125
+ Fail`Exported file ${q(
126
+ allegedRelativeFilename,
127
+ )} must be in export dir ${q(exportDir)}`;
71
128
  return resolvedPath;
72
129
  };
73
130
 
@@ -78,26 +135,12 @@ export const performStateSyncImport = async (
78
135
  );
79
136
 
80
137
  if (blockHeight !== undefined && manifest.blockHeight !== blockHeight) {
81
- Fail`State-sync manifest for unexpected block height ${manifest.blockHeight} (expected ${blockHeight})`;
82
- }
83
-
84
- if (!manifest.data) {
85
- throw Fail`State-sync manifest missing export data`;
86
- }
87
-
88
- if (!manifest.artifacts) {
89
- throw Fail`State-sync manifest missing required artifacts`;
138
+ Fail`State-sync manifest for unexpected block height ${q(
139
+ manifest.blockHeight,
140
+ )} (expected ${q(blockHeight)})`;
90
141
  }
91
142
 
92
- const artifacts = harden(Object.fromEntries(manifest.artifacts));
93
-
94
- if (
95
- includeHistorical &&
96
- manifest.mode !== 'archival' &&
97
- manifest.mode !== 'debug'
98
- ) {
99
- throw Fail`State-sync manifest missing historical artifacts`;
100
- }
143
+ const artifacts = harden(Object.fromEntries(manifest.artifacts || []));
101
144
 
102
145
  // Represent the data in `exportDir` as a SwingSetExporter object.
103
146
  /** @type {import('@agoric/swing-store').SwingStoreExporter} */
@@ -128,7 +171,7 @@ export const performStateSyncImport = async (
128
171
  log?.(`importing artifact ${name}`);
129
172
  const fileName = artifacts[name];
130
173
  if (!fileName) {
131
- Fail`invalid artifact ${name}`;
174
+ Fail`invalid artifact ${q(name)}`;
132
175
  }
133
176
  const stream = createReadStream(safeExportFileResolve(fileName));
134
177
  yield* stream;
@@ -141,17 +184,47 @@ export const performStateSyncImport = async (
141
184
  },
142
185
  });
143
186
 
144
- const artifactMode = includeHistorical
145
- ? 'debug' // for now don't enforce completeness but allow importing all provided artifacts
146
- : 'operational';
187
+ if (exportDataMode === 'all') {
188
+ const importOptions = checkAndGetImportSwingStoreOptions(
189
+ { artifactMode, exportDataMode },
190
+ manifest,
191
+ );
192
+
193
+ const swingstore = await importDB(exporter, stateDir, importOptions);
194
+
195
+ const { hostStorage } = swingstore;
196
+
197
+ hostStorage.kvStore.set('host.height', String(manifest.blockHeight));
198
+ await hostStorage.commit();
199
+ await hostStorage.close();
200
+ } else if (exportDataMode === 'repair-metadata') {
201
+ blockHeight !== 0 || Fail`repair metadata requires a block height`;
202
+
203
+ manifest.data || Fail`State-sync manifest missing export data`;
204
+
205
+ artifactMode === 'none' ||
206
+ Fail`Cannot restore artifacts while repairing metadata`;
207
+
208
+ const { hostStorage } = openDB(stateDir);
147
209
 
148
- const swingstore = await importDB(exporter, stateDir, { artifactMode });
210
+ const savedBlockHeight =
211
+ Number(hostStorage.kvStore.get('host.height')) || 0;
149
212
 
150
- const { hostStorage } = swingstore;
213
+ if (blockHeight !== savedBlockHeight) {
214
+ throw Fail`block height doesn't match. requested=${q(
215
+ blockHeight,
216
+ )}, current=${q(savedBlockHeight)}`;
217
+ }
151
218
 
152
- hostStorage.kvStore.set('host.height', String(manifest.blockHeight));
153
- await hostStorage.commit();
154
- await hostStorage.close();
219
+ await hostStorage.repairMetadata(exporter);
220
+
221
+ await hostStorage.commit();
222
+ await hostStorage.close();
223
+ } else if (exportDataMode === 'skip') {
224
+ throw Fail`Repopulation of artifacts not yet supported`;
225
+ } else {
226
+ throw Fail`Unknown export-data-mode ${exportDataMode}`;
227
+ }
155
228
  };
156
229
 
157
230
  /**
@@ -186,9 +259,20 @@ export const main = async (
186
259
  /** @type {string} */ (processValue.getFlag('export-dir', '.')),
187
260
  );
188
261
 
189
- const includeHistorical = processValue.getBoolean({
190
- flagName: 'include-historical',
191
- });
262
+ const artifactMode =
263
+ /** @type {import('./export-kernel-db.js').SwingStoreArtifactMode | undefined} */ (
264
+ processValue.getFlag('artifact-mode')
265
+ );
266
+ checkArtifactMode(artifactMode);
267
+
268
+ const exportDataMode = processValue.getFlag('export-data-mode');
269
+ checkExportDataMode(exportDataMode, true);
270
+
271
+ if (
272
+ processValue.getBoolean({ flagName: 'include-historical' }) !== undefined
273
+ ) {
274
+ throw Fail`deprecated "include-historical" options, use "artifact-mode" instead`;
275
+ }
192
276
 
193
277
  const checkBlockHeight = processValue.getInteger({
194
278
  flagName: 'check-block-height',
@@ -203,7 +287,8 @@ export const main = async (
203
287
  stateDir,
204
288
  exportDir,
205
289
  blockHeight: checkBlockHeight,
206
- includeHistorical,
290
+ artifactMode,
291
+ exportDataMode,
207
292
  },
208
293
  {
209
294
  fs,