@typeberry/lib 0.6.2-9d23bc2 → 0.7.0-366a4ad
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/bin/lib/scripts/build-lib.js +8 -9
- package/package.json +1 -1
- package/packages/jam/database-lmdb/root.d.ts +1 -1
- package/packages/jam/database-lmdb/root.d.ts.map +1 -1
- package/packages/jam/database-lmdb/root.js +9 -4
- package/packages/jam/fuzz-proto/v1/types.d.ts.map +1 -1
- package/packages/jam/fuzz-proto/v1/types.js +4 -1
- package/packages/jam/fuzz-proto/v1/types.test.js +12 -0
- package/packages/jam/node/main-fuzz.d.ts +12 -0
- package/packages/jam/node/main-fuzz.d.ts.map +1 -1
- package/packages/jam/node/main-fuzz.js +79 -23
- package/packages/jam/node/main-fuzz.test.js +30 -1
- package/packages/jam/node/main-importer.d.ts +2 -0
- package/packages/jam/node/main-importer.d.ts.map +1 -1
- package/packages/jam/node/main-importer.js +1 -0
- package/packages/workers/api-node/config.d.ts +3 -1
- package/packages/workers/api-node/config.d.ts.map +1 -1
- package/packages/workers/api-node/config.js +10 -4
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
* └── workers/
|
|
61
61
|
* ```
|
|
62
62
|
*/
|
|
63
|
-
import { execSync } from "node:child_process";
|
|
64
63
|
import fs from "node:fs";
|
|
65
64
|
import path from "node:path";
|
|
66
65
|
import { fileURLToPath } from "node:url";
|
|
@@ -71,26 +70,26 @@ const DIST_DIR = path.resolve(ROOT_DIR, "dist/lib");
|
|
|
71
70
|
/**
|
|
72
71
|
* Get the version string for the package
|
|
73
72
|
*
|
|
74
|
-
* If
|
|
75
|
-
*
|
|
73
|
+
* If the VERSION_SHA environment variable is set (e.g. CI builds), appends it to
|
|
74
|
+
* the base version to create a unique, non-release version. Otherwise (release
|
|
75
|
+
* behavior) the base version from package.json is used as-is.
|
|
76
76
|
*
|
|
77
77
|
* @param baseVersion - The base version from package.json
|
|
78
78
|
* @returns The version string to use for publishing
|
|
79
79
|
*
|
|
80
80
|
* @example
|
|
81
|
-
* // When
|
|
81
|
+
* // When VERSION_SHA=abc1234
|
|
82
82
|
* getVersion("0.5.1") // Returns "0.5.1-abc1234"
|
|
83
83
|
*
|
|
84
|
-
* // When
|
|
84
|
+
* // When VERSION_SHA is not set
|
|
85
85
|
* getVersion("0.5.1") // Returns "0.5.1"
|
|
86
86
|
*/
|
|
87
87
|
function getVersion(baseVersion) {
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
88
|
+
const versionSha = process.env.VERSION_SHA;
|
|
89
|
+
if (versionSha === undefined || versionSha === "") {
|
|
90
90
|
return baseVersion;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
return `${baseVersion}-${commitHash}`;
|
|
92
|
+
return `${baseVersion}-${versionSha}`;
|
|
94
93
|
}
|
|
95
94
|
/**
|
|
96
95
|
* Build a map of package names to their workspace paths
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ export type SubDb = lmdb.Database<Uint8Array, lmdb.Key>;
|
|
|
3
3
|
/** A thin abstraction over lmdb database interface. */
|
|
4
4
|
export declare class LmdbRoot {
|
|
5
5
|
readonly db: lmdb.RootDatabase<Uint8Array, lmdb.Key>;
|
|
6
|
-
static new(dbPath: string, readOnly?: boolean): LmdbRoot;
|
|
6
|
+
static new(dbPath: string, readOnly?: boolean, ephemeral?: boolean): LmdbRoot;
|
|
7
7
|
private constructor();
|
|
8
8
|
/** Open a sub-database under the same path. */
|
|
9
9
|
subDb(name: string): SubDb;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-lmdb/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAExD,uDAAuD;AACvD,qBAAa,QAAQ;IACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAErD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ;
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-lmdb/root.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAExD,uDAAuD;AACvD,qBAAa,QAAQ;IACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAErD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,UAAQ,EAAE,SAAS,UAAQ;IAI9D,OAAO;IAcP,+CAA+C;IAC/C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAI1B,gDAAgD;IAC1C,KAAK;CAGZ"}
|
|
@@ -2,12 +2,17 @@ import * as lmdb from "lmdb";
|
|
|
2
2
|
/** A thin abstraction over lmdb database interface. */
|
|
3
3
|
export class LmdbRoot {
|
|
4
4
|
db;
|
|
5
|
-
static new(dbPath, readOnly = false) {
|
|
6
|
-
return new LmdbRoot(dbPath, readOnly);
|
|
5
|
+
static new(dbPath, readOnly = false, ephemeral = false) {
|
|
6
|
+
return new LmdbRoot(dbPath, readOnly, ephemeral);
|
|
7
7
|
}
|
|
8
|
-
constructor(dbPath, readOnly = false) {
|
|
8
|
+
constructor(dbPath, readOnly = false, ephemeral = false) {
|
|
9
9
|
this.db = lmdb.open(dbPath, {
|
|
10
|
-
|
|
10
|
+
// For ephemeral databases (e.g. the fuzz target, which wipes on every reset)
|
|
11
|
+
// durability is pointless, so we skip fsync and skip compressing the large
|
|
12
|
+
// per-block leaf blobs. Both are pure overhead there and dominate the cost.
|
|
13
|
+
// This trades disk space (uncompressed) and crash-durability for speed.
|
|
14
|
+
compression: !ephemeral,
|
|
15
|
+
noSync: ephemeral,
|
|
11
16
|
keyEncoding: "binary",
|
|
12
17
|
encoding: "binary",
|
|
13
18
|
readOnly,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/fuzz-proto/v1/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,KAAK,WAAW,EAAS,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAW,KAAK,EAAE,EAAE,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;;GAMG;AACH,qBAAa,OAAQ,SAAQ,SAAS;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/fuzz-proto/v1/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,10 @@ export class Version extends WithDebug {
|
|
|
22
22
|
static tryFromString(str) {
|
|
23
23
|
const parse = (v) => tryAsU8(Number(v));
|
|
24
24
|
try {
|
|
25
|
-
|
|
25
|
+
// strip any semver pre-release / build metadata (e.g. "-15ccd70", "+build.42")
|
|
26
|
+
// so that only `major.minor.patch` is parsed.
|
|
27
|
+
const core = str.trim().split(/[-+]/)[0];
|
|
28
|
+
const [major, minor, patch] = core.split(".").map(parse);
|
|
26
29
|
return Version.create({
|
|
27
30
|
major,
|
|
28
31
|
minor,
|
|
@@ -41,6 +41,18 @@ describe("Fuzzer V1 Data Structures", () => {
|
|
|
41
41
|
assert.strictEqual(version.minor, 2);
|
|
42
42
|
assert.strictEqual(version.patch, 3);
|
|
43
43
|
});
|
|
44
|
+
it("should ignore the git hash / pre-release suffix", () => {
|
|
45
|
+
const version = Version.tryFromString("0.7.0-15ccd70");
|
|
46
|
+
assert.strictEqual(version.major, 0);
|
|
47
|
+
assert.strictEqual(version.minor, 7);
|
|
48
|
+
assert.strictEqual(version.patch, 0);
|
|
49
|
+
});
|
|
50
|
+
it("should ignore the build metadata suffix", () => {
|
|
51
|
+
const version = Version.tryFromString("1.2.3+build.42");
|
|
52
|
+
assert.strictEqual(version.major, 1);
|
|
53
|
+
assert.strictEqual(version.minor, 2);
|
|
54
|
+
assert.strictEqual(version.patch, 3);
|
|
55
|
+
});
|
|
44
56
|
});
|
|
45
57
|
describe("PeerInfo", () => {
|
|
46
58
|
it("should encode and decode peer info with features", () => {
|
|
@@ -7,6 +7,18 @@ export type FuzzConfig = {
|
|
|
7
7
|
socket: string | null;
|
|
8
8
|
initGenesisFromAncestry: boolean;
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the directory the fuzzer should use for its on-disk database, or
|
|
12
|
+
* `undefined` for an in-memory database. The dedicated `FUZZ_DB_SUBDIR` is
|
|
13
|
+
* appended so we only ever wipe a directory the fuzzer owns, never the base
|
|
14
|
+
* path the harness handed us.
|
|
15
|
+
*
|
|
16
|
+
* The empty / "undefined" guards are defensive: the env flow already normalizes via fuzzDatabaseBasePath,
|
|
17
|
+
* but the CLI fuzz-target path can set databaseBasePath directly without going through fuzz-env's normalization.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveFuzzDbBase(configured: string | undefined): string | undefined;
|
|
20
|
+
/** Recursively remove the fuzzer's database directory. No-op if it is absent. */
|
|
21
|
+
export declare function wipeFuzzDb(base: string): Promise<void>;
|
|
10
22
|
export declare function getFuzzDetails(): {
|
|
11
23
|
nodeName: string;
|
|
12
24
|
nodeVersion: fuzzV1.Version;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main-fuzz.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-fuzz.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main-fuzz.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-fuzz.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,WAAW,EAAmB,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAOrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,aAAa,EAAE,SAAS,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uBAAuB,EAAE,OAAO,CAAC;CAClC,CAAC;AAOF;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASpF;AAED,iFAAiF;AACjF,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,wBAAgB,cAAc;;;;EAM7B;AAED,wBAAsB,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,uBAwGxF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
1
2
|
import { Header } from "#@typeberry/block";
|
|
2
3
|
import { Bytes } from "#@typeberry/bytes";
|
|
3
4
|
import { Encoder } from "#@typeberry/codec";
|
|
@@ -7,20 +8,48 @@ import { v1 as fuzzV1 } from "#@typeberry/fuzz-proto";
|
|
|
7
8
|
import { HASH_SIZE } from "#@typeberry/hash";
|
|
8
9
|
import { Logger } from "#@typeberry/logger";
|
|
9
10
|
import { CURRENT_VERSION, Result, version } from "#@typeberry/utils";
|
|
11
|
+
import { logHostEnvironment } from "#@typeberry/workers-api-node";
|
|
10
12
|
import { getChainSpec } from "./common.js";
|
|
11
13
|
import { mainImporter } from "./main-importer.js";
|
|
12
14
|
const logger = Logger.new(import.meta.filename, "fuzztarget");
|
|
15
|
+
/** Dedicated subdirectory under the configured base path that the fuzzer owns and wipes. */
|
|
16
|
+
const FUZZ_DB_SUBDIR = "typeberry-fuzz-db";
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the directory the fuzzer should use for its on-disk database, or
|
|
19
|
+
* `undefined` for an in-memory database. The dedicated `FUZZ_DB_SUBDIR` is
|
|
20
|
+
* appended so we only ever wipe a directory the fuzzer owns, never the base
|
|
21
|
+
* path the harness handed us.
|
|
22
|
+
*
|
|
23
|
+
* The empty / "undefined" guards are defensive: the env flow already normalizes via fuzzDatabaseBasePath,
|
|
24
|
+
* but the CLI fuzz-target path can set databaseBasePath directly without going through fuzz-env's normalization.
|
|
25
|
+
*/
|
|
26
|
+
export function resolveFuzzDbBase(configured) {
|
|
27
|
+
if (configured === undefined) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const trimmed = configured.trim();
|
|
31
|
+
if (trimmed === "" || trimmed.toLowerCase() === "undefined") {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return `${trimmed}/${FUZZ_DB_SUBDIR}`;
|
|
35
|
+
}
|
|
36
|
+
/** Recursively remove the fuzzer's database directory. No-op if it is absent. */
|
|
37
|
+
export async function wipeFuzzDb(base) {
|
|
38
|
+
await rm(base, { recursive: true, force: true });
|
|
39
|
+
}
|
|
13
40
|
export function getFuzzDetails() {
|
|
14
41
|
return {
|
|
15
42
|
nodeName: "@typeberry/jam",
|
|
16
43
|
nodeVersion: fuzzV1.Version.tryFromString(version),
|
|
17
|
-
gpVersion: fuzzV1.Version.tryFromString(CURRENT_VERSION
|
|
44
|
+
gpVersion: fuzzV1.Version.tryFromString(CURRENT_VERSION),
|
|
18
45
|
};
|
|
19
46
|
}
|
|
20
47
|
export async function mainFuzz(fuzzConfig, withRelPath) {
|
|
21
48
|
logger.info `💨 Fuzzer V${fuzzConfig.version} starting up.`;
|
|
22
49
|
logger.info `🖥️ PVM Backend: ${PvmBackend[fuzzConfig.jamNodeConfig.pvmBackend]}.`;
|
|
50
|
+
logHostEnvironment(logger);
|
|
23
51
|
const { jamNodeConfig: config } = fuzzConfig;
|
|
52
|
+
const fuzzDbBase = resolveFuzzDbBase(config.node.databaseBasePath);
|
|
24
53
|
let runningNode = null;
|
|
25
54
|
const chainSpec = getChainSpec(config.node.flavor);
|
|
26
55
|
const closeFuzzTarget = startFuzzTarget(fuzzConfig.version, fuzzConfig.socket, {
|
|
@@ -51,29 +80,56 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
|
|
|
51
80
|
runningNode = null;
|
|
52
81
|
await finish;
|
|
53
82
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
const buildNode = (databaseBasePath) => {
|
|
84
|
+
// Enable state/blocks pruning only when running in memory.
|
|
85
|
+
// For disk backend, we store everything.
|
|
86
|
+
const isPersistent = databaseBasePath !== undefined;
|
|
87
|
+
return mainImporter({
|
|
88
|
+
...config,
|
|
89
|
+
node: {
|
|
90
|
+
...config.node,
|
|
91
|
+
databaseBasePath,
|
|
92
|
+
chainSpec: {
|
|
93
|
+
...config.node.chainSpec,
|
|
94
|
+
genesisHeader: Encoder.encodeObject(Header.Codec, header, chainSpec),
|
|
95
|
+
genesisState: new Map(state),
|
|
96
|
+
},
|
|
65
97
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
98
|
+
ancestry,
|
|
99
|
+
network: null,
|
|
100
|
+
}, withRelPath, {
|
|
101
|
+
initGenesisFromAncestry: fuzzConfig.initGenesisFromAncestry,
|
|
102
|
+
dummyFinalityDepth: isPersistent ? 0 : 10_000,
|
|
103
|
+
pruneBlocks: !isPersistent,
|
|
104
|
+
// The fuzz db is wiped on every reset, so durability is pointless:
|
|
105
|
+
// skip fsync + compression to cut the per-block leaf write cost.
|
|
106
|
+
ephemeralDb: isPersistent,
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
if (fuzzDbBase !== undefined) {
|
|
110
|
+
// Each reset starts a fresh session from the genesis the fuzzer just sent,
|
|
111
|
+
// so the on-disk db must be empty: otherwise initializeDatabase sees an
|
|
112
|
+
// already-initialized db and silently resumes the previous run's state.
|
|
113
|
+
await wipeFuzzDb(fuzzDbBase);
|
|
114
|
+
try {
|
|
115
|
+
runningNode = await buildNode(fuzzDbBase);
|
|
116
|
+
return await runningNode.getBestStateRootHash();
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
// A partially-opened db may leak on failure; acceptable for this degraded fallback (proper cleanup belongs in mainImporter).
|
|
120
|
+
logger.warn `Failed to open persistent fuzz db at ${fuzzDbBase}, falling back to in-memory: ${e}`;
|
|
121
|
+
runningNode = null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
runningNode = await buildNode(undefined);
|
|
125
|
+
return await runningNode.getBestStateRootHash();
|
|
76
126
|
},
|
|
77
127
|
});
|
|
78
|
-
return
|
|
128
|
+
return () => {
|
|
129
|
+
closeFuzzTarget();
|
|
130
|
+
if (fuzzDbBase !== undefined) {
|
|
131
|
+
// best-effort cleanup on shutdown; ignore failures (dir may already be gone).
|
|
132
|
+
wipeFuzzDb(fuzzDbBase).catch(() => { });
|
|
133
|
+
}
|
|
134
|
+
};
|
|
79
135
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import * as fs from "node:fs";
|
|
1
3
|
import { describe, it } from "node:test";
|
|
2
4
|
import { tryAsU8 } from "#@typeberry/numbers";
|
|
3
5
|
import { CURRENT_VERSION, deepEqual, version } from "#@typeberry/utils";
|
|
4
|
-
import { getFuzzDetails } from "./main-fuzz.js";
|
|
6
|
+
import { getFuzzDetails, resolveFuzzDbBase, wipeFuzzDb } from "./main-fuzz.js";
|
|
5
7
|
describe("fuzzing config", () => {
|
|
6
8
|
it("should create config from current version", () => {
|
|
7
9
|
const [m, i, p] = version.split(".").map((x) => Number.parseInt(x, 10));
|
|
@@ -22,3 +24,30 @@ describe("fuzzing config", () => {
|
|
|
22
24
|
}, { ignore: ["nodeVersion.patch"] });
|
|
23
25
|
});
|
|
24
26
|
});
|
|
27
|
+
describe("resolveFuzzDbBase", () => {
|
|
28
|
+
it("returns undefined when no base path is configured", () => {
|
|
29
|
+
assert.strictEqual(resolveFuzzDbBase(undefined), undefined);
|
|
30
|
+
});
|
|
31
|
+
it("returns undefined for empty and the 'undefined' sentinel", () => {
|
|
32
|
+
assert.strictEqual(resolveFuzzDbBase(""), undefined);
|
|
33
|
+
assert.strictEqual(resolveFuzzDbBase(" undefined "), undefined);
|
|
34
|
+
});
|
|
35
|
+
it("appends the dedicated fuzz subdir for a real path", () => {
|
|
36
|
+
assert.strictEqual(resolveFuzzDbBase("/tmp/jam-data"), "/tmp/jam-data/typeberry-fuzz-db");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("wipeFuzzDb", () => {
|
|
40
|
+
it("removes an existing directory and its contents", async () => {
|
|
41
|
+
const dir = fs.mkdtempSync("typeberry-fuzz-wipe-");
|
|
42
|
+
fs.writeFileSync(`${dir}/marker`, "x");
|
|
43
|
+
await wipeFuzzDb(dir);
|
|
44
|
+
assert.strictEqual(fs.existsSync(dir), false);
|
|
45
|
+
});
|
|
46
|
+
it("is a no-op when the directory does not exist", async () => {
|
|
47
|
+
const dir = fs.mkdtempSync("typeberry-fuzz-wipe-");
|
|
48
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
49
|
+
// must not throw
|
|
50
|
+
await wipeFuzzDb(dir);
|
|
51
|
+
assert.strictEqual(fs.existsSync(dir), false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -4,6 +4,8 @@ export type ImporterOptions = {
|
|
|
4
4
|
initGenesisFromAncestry?: boolean;
|
|
5
5
|
dummyFinalityDepth?: number;
|
|
6
6
|
pruneBlocks?: boolean;
|
|
7
|
+
/** Open the LMDB database without fsync/compression. Only safe for throwaway dbs (e.g. fuzzing). */
|
|
8
|
+
ephemeralDb?: boolean;
|
|
7
9
|
};
|
|
8
10
|
export declare function mainImporter(config: JamConfig, withRelPath: (v: string) => string, options?: ImporterOptions): Promise<NodeApi>;
|
|
9
11
|
//# sourceMappingURL=main-importer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oGAAoG;IACpG,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAiFlB"}
|
|
@@ -37,6 +37,7 @@ export async function mainImporter(config, withRelPath, options = {}) {
|
|
|
37
37
|
blake2b,
|
|
38
38
|
dbPath,
|
|
39
39
|
workerParams,
|
|
40
|
+
ephemeral: options.ephemeralDb ?? false,
|
|
40
41
|
});
|
|
41
42
|
// Initialize the database with genesis state and block if there isn't one.
|
|
42
43
|
logger.info `🛢️ Opening database at ${dbPath}`;
|
|
@@ -13,13 +13,15 @@ export declare class LmdbWorkerConfig<T = void> implements WorkerConfig<T, Block
|
|
|
13
13
|
readonly dbPath: string;
|
|
14
14
|
readonly blake2b: Blake2b;
|
|
15
15
|
readonly ports: Map<string, ThreadPort>;
|
|
16
|
-
|
|
16
|
+
readonly ephemeral: boolean;
|
|
17
|
+
static new<T>({ nodeName, chainSpec, workerParams, dbPath, blake2b, ports, ephemeral, }: {
|
|
17
18
|
nodeName: string;
|
|
18
19
|
chainSpec: ChainSpec;
|
|
19
20
|
workerParams: T;
|
|
20
21
|
dbPath: string;
|
|
21
22
|
blake2b: Blake2b;
|
|
22
23
|
ports?: Map<string, ThreadPort>;
|
|
24
|
+
ephemeral?: boolean;
|
|
23
25
|
}): LmdbWorkerConfig<T>;
|
|
24
26
|
/** Restore node config from a transferable config object. */
|
|
25
27
|
static fromTransferable<T>(decodeParams: Decode<T>, config: TransferableConfig): Promise<LmdbWorkerConfig<T>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,KAAK,MAAM,EAAW,KAAK,MAAM,EAAW,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EACL,KAAK,QAAQ,EAGb,KAAK,MAAM,EACX,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE9D,+EAA+E;AAC/E,qBAAa,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAE,YAAW,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api-node/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,8 +12,9 @@ export class LmdbWorkerConfig {
|
|
|
12
12
|
dbPath;
|
|
13
13
|
blake2b;
|
|
14
14
|
ports;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
ephemeral;
|
|
16
|
+
static new({ nodeName, chainSpec, workerParams, dbPath, blake2b, ports = new Map(), ephemeral = false, }) {
|
|
17
|
+
return new LmdbWorkerConfig(nodeName, chainSpec, workerParams, dbPath, blake2b, ports, ephemeral);
|
|
17
18
|
}
|
|
18
19
|
/** Restore node config from a transferable config object. */
|
|
19
20
|
static async fromTransferable(decodeParams, config) {
|
|
@@ -30,16 +31,21 @@ export class LmdbWorkerConfig {
|
|
|
30
31
|
ports,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
constructor(nodeName, chainSpec, workerParams, dbPath, blake2b, ports
|
|
34
|
+
constructor(nodeName, chainSpec, workerParams, dbPath, blake2b, ports,
|
|
35
|
+
// When set, the underlying LMDB skips fsync and compression. Only safe for
|
|
36
|
+
// throwaway databases (the fuzz target wipes on reset). Not transferred to
|
|
37
|
+
// worker threads, so the durable main node path always gets the default.
|
|
38
|
+
ephemeral = false) {
|
|
34
39
|
this.nodeName = nodeName;
|
|
35
40
|
this.chainSpec = chainSpec;
|
|
36
41
|
this.workerParams = workerParams;
|
|
37
42
|
this.dbPath = dbPath;
|
|
38
43
|
this.blake2b = blake2b;
|
|
39
44
|
this.ports = ports;
|
|
45
|
+
this.ephemeral = ephemeral;
|
|
40
46
|
}
|
|
41
47
|
openDatabase(options = { readonly: true }) {
|
|
42
|
-
const lmdb = LmdbRoot.new(this.dbPath, options.readonly);
|
|
48
|
+
const lmdb = LmdbRoot.new(this.dbPath, options.readonly, this.ephemeral);
|
|
43
49
|
return {
|
|
44
50
|
getBlocksDb: () => LmdbBlocks.new(this.chainSpec, lmdb),
|
|
45
51
|
getStatesDb: () => LmdbStates.new(this.chainSpec, this.blake2b, lmdb),
|