@typeberry/lib 0.6.2-9d23bc2 → 0.7.0-4f16a18
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.
|
@@ -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
|
@@ -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,uBAiGxF"}
|
|
@@ -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,9 +8,35 @@ 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",
|
|
@@ -20,7 +47,9 @@ export function getFuzzDetails() {
|
|
|
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,13 +80,11 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
|
|
|
51
80
|
runningNode = null;
|
|
52
81
|
await finish;
|
|
53
82
|
}
|
|
54
|
-
|
|
55
|
-
const newNode = await mainImporter({
|
|
83
|
+
const buildNode = (databaseBasePath) => mainImporter({
|
|
56
84
|
...config,
|
|
57
85
|
node: {
|
|
58
86
|
...config.node,
|
|
59
|
-
|
|
60
|
-
databaseBasePath: undefined,
|
|
87
|
+
databaseBasePath,
|
|
61
88
|
chainSpec: {
|
|
62
89
|
...config.node.chainSpec,
|
|
63
90
|
genesisHeader: Encoder.encodeObject(Header.Codec, header, chainSpec),
|
|
@@ -71,9 +98,30 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
|
|
|
71
98
|
dummyFinalityDepth: 10_000,
|
|
72
99
|
pruneBlocks: true,
|
|
73
100
|
});
|
|
74
|
-
|
|
75
|
-
|
|
101
|
+
if (fuzzDbBase !== undefined) {
|
|
102
|
+
// Each reset starts a fresh session from the genesis the fuzzer just sent,
|
|
103
|
+
// so the on-disk db must be empty: otherwise initializeDatabase sees an
|
|
104
|
+
// already-initialized db and silently resumes the previous run's state.
|
|
105
|
+
await wipeFuzzDb(fuzzDbBase);
|
|
106
|
+
try {
|
|
107
|
+
runningNode = await buildNode(fuzzDbBase);
|
|
108
|
+
return await runningNode.getBestStateRootHash();
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
// A partially-opened db may leak on failure; acceptable for this degraded fallback (proper cleanup belongs in mainImporter).
|
|
112
|
+
logger.warn `Failed to open persistent fuzz db at ${fuzzDbBase}, falling back to in-memory: ${e}`;
|
|
113
|
+
runningNode = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
runningNode = await buildNode(undefined);
|
|
117
|
+
return await runningNode.getBestStateRootHash();
|
|
76
118
|
},
|
|
77
119
|
});
|
|
78
|
-
return
|
|
120
|
+
return () => {
|
|
121
|
+
closeFuzzTarget();
|
|
122
|
+
if (fuzzDbBase !== undefined) {
|
|
123
|
+
// best-effort cleanup on shutdown; ignore failures (dir may already be gone).
|
|
124
|
+
wipeFuzzDb(fuzzDbBase).catch(() => { });
|
|
125
|
+
}
|
|
126
|
+
};
|
|
79
127
|
}
|
|
@@ -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
|
+
});
|