@typeberry/lib 0.8.3 → 0.8.4-70b1490
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 +6 -4
- package/packages/configs/index.d.ts +30 -1
- package/packages/configs/index.d.ts.map +1 -1
- package/packages/configs/index.js +4 -2
- package/packages/configs/typeberry-dev-full.json +29 -0
- package/packages/core/bytes/bytes.d.ts +1 -0
- package/packages/core/bytes/bytes.d.ts.map +1 -1
- package/packages/core/bytes/bytes.js +8 -0
- package/packages/core/utils/debug.d.ts +16 -4
- package/packages/core/utils/debug.d.ts.map +1 -1
- package/packages/core/utils/debug.js +39 -17
- package/packages/core/utils/debug.test.js +12 -6
- package/packages/jam/config-node/node-config.d.ts +2 -1
- package/packages/jam/config-node/node-config.d.ts.map +1 -1
- package/packages/jam/config-node/node-config.js +8 -3
- package/packages/jam/config-node/node-config.test.js +3 -3
- package/packages/jam/database/states.d.ts +7 -0
- package/packages/jam/database/states.d.ts.map +1 -1
- package/packages/jam/database-fjall/hybrid-states.d.ts +45 -0
- package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -0
- package/packages/jam/database-fjall/hybrid-states.js +113 -0
- package/packages/jam/database-fjall/hybrid-states.test.d.ts +2 -0
- package/packages/jam/database-fjall/hybrid-states.test.d.ts.map +1 -0
- package/packages/jam/database-fjall/hybrid-states.test.js +83 -0
- package/packages/jam/database-fjall/index.d.ts +3 -0
- package/packages/jam/database-fjall/index.d.ts.map +1 -0
- package/packages/jam/database-fjall/index.js +2 -0
- package/packages/jam/database-fjall/root.d.ts +52 -0
- package/packages/jam/database-fjall/root.d.ts.map +1 -0
- package/packages/jam/database-fjall/root.js +85 -0
- package/packages/jam/database-lmdb/hybrid-states.d.ts +3 -1
- package/packages/jam/database-lmdb/hybrid-states.d.ts.map +1 -1
- package/packages/jam/database-lmdb/hybrid-states.js +5 -2
- package/packages/jam/database-lmdb/root.d.ts +14 -1
- package/packages/jam/database-lmdb/root.d.ts.map +1 -1
- package/packages/jam/database-lmdb/root.js +25 -5
- package/packages/jam/database-lmdb/states.d.ts +1 -0
- package/packages/jam/database-lmdb/states.d.ts.map +1 -1
- package/packages/jam/database-lmdb/states.js +3 -0
- package/packages/jam/database-lmdb/states.test.js +4 -4
- package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts +18 -10
- package/packages/jam/jamnp-s/tasks/ticket-distribution.d.ts.map +1 -1
- package/packages/jam/jamnp-s/tasks/ticket-distribution.js +44 -68
- package/packages/jam/jamnp-s/tasks/ticket-distribution.test.js +30 -8
- package/packages/jam/node/main-fuzz.d.ts.map +1 -1
- package/packages/jam/node/main-fuzz.js +21 -4
- package/packages/jam/node/main-importer.d.ts +7 -4
- package/packages/jam/node/main-importer.d.ts.map +1 -1
- package/packages/jam/node/main-importer.js +10 -4
- package/packages/jam/safrole/bandersnatch-vrf.d.ts +24 -4
- package/packages/jam/safrole/bandersnatch-vrf.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-vrf.js +92 -40
- package/packages/jam/safrole/bandersnatch-vrf.test.js +12 -9
- package/packages/jam/safrole/bandersnatch-wasm.d.ts +10 -0
- package/packages/jam/safrole/bandersnatch-wasm.d.ts.map +1 -1
- package/packages/jam/safrole/bandersnatch-wasm.js +12 -0
- package/packages/jam/safrole/safrole.js +5 -5
- package/packages/jam/safrole/safrole.test.js +13 -13
- package/packages/jam/ticket-pool/index.d.ts +4 -0
- package/packages/jam/ticket-pool/index.d.ts.map +1 -0
- package/packages/jam/ticket-pool/index.js +3 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.d.ts +30 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.d.ts.map +1 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.js +56 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts +2 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/pending-ticket-pool.test.js +67 -0
- package/packages/jam/ticket-pool/ticket-validator.d.ts +47 -0
- package/packages/jam/ticket-pool/ticket-validator.d.ts.map +1 -0
- package/packages/jam/ticket-pool/ticket-validator.js +34 -0
- package/packages/jam/ticket-pool/ticket-validator.test.d.ts +2 -0
- package/packages/jam/ticket-pool/ticket-validator.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/ticket-validator.test.js +35 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts +26 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.d.ts.map +1 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.js +41 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts +2 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.d.ts.map +1 -0
- package/packages/jam/ticket-pool/verified-ticket-pool.test.js +54 -0
- package/packages/jam/transition/chain-stf.d.ts +2 -1
- package/packages/jam/transition/chain-stf.d.ts.map +1 -1
- package/packages/jam/transition/chain-stf.js +15 -3
- package/packages/workers/api-node/config.d.ts +14 -5
- package/packages/workers/api-node/config.d.ts.map +1 -1
- package/packages/workers/api-node/config.js +29 -20
- package/packages/workers/api-node/config.test.js +38 -1
- package/packages/workers/block-authorship/{generator.d.ts → block-generator.d.ts} +5 -5
- package/packages/workers/block-authorship/block-generator.d.ts.map +1 -0
- package/packages/workers/block-authorship/{generator.js → block-generator.js} +3 -3
- package/packages/workers/block-authorship/block-generator.test.d.ts +2 -0
- package/packages/workers/block-authorship/block-generator.test.d.ts.map +1 -0
- package/packages/workers/block-authorship/{generator.test.js → block-generator.test.js} +8 -8
- package/packages/workers/block-authorship/epoch-authoring-slots.d.ts +35 -0
- package/packages/workers/block-authorship/epoch-authoring-slots.d.ts.map +1 -0
- package/packages/workers/block-authorship/epoch-authoring-slots.js +86 -0
- package/packages/workers/block-authorship/epoch-tracker.d.ts +29 -0
- package/packages/workers/block-authorship/epoch-tracker.d.ts.map +1 -0
- package/packages/workers/block-authorship/epoch-tracker.js +80 -0
- package/packages/workers/block-authorship/index.d.ts.map +1 -1
- package/packages/workers/block-authorship/index.js +1 -1
- package/packages/workers/block-authorship/main.d.ts +3 -0
- package/packages/workers/block-authorship/main.d.ts.map +1 -1
- package/packages/workers/block-authorship/main.js +197 -315
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts +2 -0
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/bootstrap-main.js +23 -0
- package/packages/workers/block-authorship/ticket-generator/index.d.ts +16 -0
- package/packages/workers/block-authorship/ticket-generator/index.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/index.js +62 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.d.ts +50 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/protocol.js +54 -0
- package/packages/workers/block-authorship/{ticket-generator.d.ts → ticket-generator/ticket-generator.d.ts} +4 -0
- package/packages/workers/block-authorship/ticket-generator/ticket-generator.d.ts.map +1 -0
- package/packages/workers/block-authorship/{ticket-generator.js → ticket-generator/ticket-generator.js} +19 -9
- package/packages/workers/block-authorship/ticket-generator/ticket-generator.test.d.ts.map +1 -0
- package/packages/workers/block-authorship/{ticket-generator.test.js → ticket-generator/ticket-generator.test.js} +13 -9
- package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts +36 -0
- package/packages/workers/block-authorship/ticket-generator/worker-pool.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-generator/worker-pool.js +111 -0
- package/packages/workers/block-authorship/ticket-validator.d.ts +31 -0
- package/packages/workers/block-authorship/ticket-validator.d.ts.map +1 -0
- package/packages/workers/block-authorship/ticket-validator.js +59 -0
- package/packages/workers/comms-authorship-network/protocol.d.ts +14 -4
- package/packages/workers/comms-authorship-network/protocol.d.ts.map +1 -1
- package/packages/workers/comms-authorship-network/protocol.js +12 -6
- package/packages/workers/comms-authorship-network/tickets-message.d.ts +0 -14
- package/packages/workers/comms-authorship-network/tickets-message.d.ts.map +1 -1
- package/packages/workers/comms-authorship-network/tickets-message.js +0 -17
- package/packages/workers/importer/importer.d.ts +5 -3
- package/packages/workers/importer/importer.d.ts.map +1 -1
- package/packages/workers/importer/importer.js +43 -35
- package/packages/workers/importer/stats.d.ts +36 -0
- package/packages/workers/importer/stats.d.ts.map +1 -0
- package/packages/workers/importer/stats.js +69 -0
- package/packages/workers/jam-network/main.d.ts.map +1 -1
- package/packages/workers/jam-network/main.js +25 -4
- package/packages/workers/block-authorship/generator.d.ts.map +0 -1
- package/packages/workers/block-authorship/generator.test.d.ts +0 -2
- package/packages/workers/block-authorship/generator.test.d.ts.map +0 -1
- package/packages/workers/block-authorship/ticket-generator.d.ts.map +0 -1
- package/packages/workers/block-authorship/ticket-generator.test.d.ts.map +0 -1
- /package/packages/configs/{typeberry-dev.json → typeberry-dev-tiny.json} +0 -0
- /package/packages/workers/block-authorship/{ticket-generator.test.d.ts → ticket-generator/ticket-generator.test.d.ts} +0 -0
|
@@ -71,6 +71,7 @@ export declare class Bytes<T extends number> extends BytesBlob {
|
|
|
71
71
|
isEqualTo(other: Bytes<T>): boolean;
|
|
72
72
|
/** Converts current type into some opaque extension. */
|
|
73
73
|
asOpaque<R>(): Opaque<Bytes<T>, TokenOf<R, Bytes<T>>>;
|
|
74
|
+
toStringTruncated(): string;
|
|
74
75
|
}
|
|
75
76
|
export declare const bytesBlobComparator: Comparator<BytesBlob>;
|
|
76
77
|
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../../../../packages/core/bytes/bytes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../../../../packages/core/bytes/bytes.ts"],"names":[],"mappings":"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"}
|
|
@@ -197,6 +197,14 @@ export class Bytes extends BytesBlob {
|
|
|
197
197
|
asOpaque() {
|
|
198
198
|
return asOpaqueType(this);
|
|
199
199
|
}
|
|
200
|
+
toStringTruncated() {
|
|
201
|
+
if (this.raw.length > 8) {
|
|
202
|
+
const start = bytesToHexString(this.raw.subarray(0, 2));
|
|
203
|
+
const end = bytesToHexString(this.raw.subarray(this.raw.length - 2));
|
|
204
|
+
return `${start}...${end.substring(2)}`;
|
|
205
|
+
}
|
|
206
|
+
return `${this.toString()}`;
|
|
207
|
+
}
|
|
200
208
|
}
|
|
201
209
|
function byteFromString(s) {
|
|
202
210
|
check `${s.length === 2} Two-character string expected`;
|
|
@@ -39,8 +39,18 @@ export declare function assertNever(value: never): never;
|
|
|
39
39
|
export declare function assertEmpty<T extends Record<string, never>>(value: T): void;
|
|
40
40
|
/** Debug print an object. */
|
|
41
41
|
export declare function inspect<T>(val: T): string;
|
|
42
|
-
/**
|
|
43
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Utility function to measure time taken for some operation [ms].
|
|
44
|
+
*
|
|
45
|
+
* To reduce allocations, each timer can only track one entry.
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
export declare function measure(id: string): () => {
|
|
49
|
+
id: string;
|
|
50
|
+
start: number;
|
|
51
|
+
duration(): number;
|
|
52
|
+
toString(): string;
|
|
53
|
+
};
|
|
44
54
|
/**
|
|
45
55
|
* Format current process memory usage as a human readable string.
|
|
46
56
|
*
|
|
@@ -49,9 +59,11 @@ export declare function measure(id: string): () => string;
|
|
|
49
59
|
* `arrayBuffers` should allow tracking WASM memory, since every instance backs its
|
|
50
60
|
* memory with `ArrayBuffer`.
|
|
51
61
|
*/
|
|
52
|
-
export declare function memoryUsage(): string;
|
|
62
|
+
export declare function memoryUsage(withDetails: boolean): string;
|
|
53
63
|
/** Create a stateful memory usage reporter. */
|
|
54
|
-
export declare function memoryTracker(
|
|
64
|
+
export declare function memoryTracker(withDetails: boolean): {
|
|
65
|
+
toString(): string;
|
|
66
|
+
};
|
|
55
67
|
/** A class that adds `toString` method that prints all properties of an object. */
|
|
56
68
|
export declare abstract class WithDebug {
|
|
57
69
|
toString(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../../../packages/core/utils/debug.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,YAExB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,cAA6F,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,OAAO,EAClB,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,SAAS,IAAI,IAAI,CAO3B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,QAKpE;AAED,6BAA6B;AAC7B,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAEzC;AAkED
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../../../packages/core/utils/debug.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,YAExB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,cAA6F,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,OAAO,EAClB,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,SAAS,IAAI,IAAI,CAO3B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,QAKpE;AAED,6BAA6B;AAC7B,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAEzC;AAkED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM;;;;;EAgBjC;AAcD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,CAUxD;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,WAAW,EAAE,OAAO,GAAG;IAAE,QAAQ,IAAI,MAAM,CAAA;CAAE,CAgB1E;AAED,mFAAmF;AACnF,8BAAsB,SAAS;IAC7B,QAAQ;CAGT;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;;EAMpC"}
|
|
@@ -108,14 +108,31 @@ function inspectInternal(val, seen) {
|
|
|
108
108
|
v += oneLine ? "}" : "\n}";
|
|
109
109
|
return v;
|
|
110
110
|
}
|
|
111
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Utility function to measure time taken for some operation [ms].
|
|
113
|
+
*
|
|
114
|
+
* To reduce allocations, each timer can only track one entry.
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
112
117
|
export function measure(id) {
|
|
113
|
-
const
|
|
114
|
-
|
|
118
|
+
const response = {
|
|
119
|
+
id,
|
|
120
|
+
start: 0,
|
|
121
|
+
duration() {
|
|
122
|
+
return now() - this.start;
|
|
123
|
+
},
|
|
124
|
+
toString() {
|
|
125
|
+
return `${this.id} took ${(this.duration()).toFixed(2)}ms`;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
return () => {
|
|
129
|
+
response.start = now();
|
|
130
|
+
return response;
|
|
131
|
+
};
|
|
115
132
|
}
|
|
116
133
|
const BYTES_IN_MB = 1024 * 1024;
|
|
117
134
|
const toMb = (bytes) => (bytes / BYTES_IN_MB).toFixed(1);
|
|
118
|
-
const signedMb = (bytes) => `${bytes >= 0 ? "+" : "
|
|
135
|
+
const signedMb = (bytes) => `${bytes >= 0 ? "+" : ""}${toMb(bytes)}`;
|
|
119
136
|
/** Raw process memory usage, or `null` in environments without `process` (e.g. browser). */
|
|
120
137
|
function rawMemoryUsage() {
|
|
121
138
|
if (isBrowser() || typeof process.memoryUsage !== "function") {
|
|
@@ -131,26 +148,31 @@ function rawMemoryUsage() {
|
|
|
131
148
|
* `arrayBuffers` should allow tracking WASM memory, since every instance backs its
|
|
132
149
|
* memory with `ArrayBuffer`.
|
|
133
150
|
*/
|
|
134
|
-
export function memoryUsage() {
|
|
151
|
+
export function memoryUsage(withDetails) {
|
|
135
152
|
const m = rawMemoryUsage();
|
|
136
153
|
if (m === null) {
|
|
137
154
|
return "";
|
|
138
155
|
}
|
|
139
|
-
|
|
156
|
+
if (withDetails) {
|
|
157
|
+
return `rss=${toMb(m.rss)}MB heap=${toMb(m.heapUsed)}/${toMb(m.heapTotal)}MB external=${toMb(m.external)}MB arrayBuffers=${toMb(m.arrayBuffers)}MB`;
|
|
158
|
+
}
|
|
159
|
+
return `rss=${toMb(m.rss)}MB heap=${toMb(m.heapUsed)}/${toMb(m.heapTotal)}MB`;
|
|
140
160
|
}
|
|
141
161
|
/** Create a stateful memory usage reporter. */
|
|
142
|
-
export function memoryTracker() {
|
|
162
|
+
export function memoryTracker(withDetails) {
|
|
143
163
|
let prev = null;
|
|
144
|
-
return
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
return {
|
|
165
|
+
toString() {
|
|
166
|
+
const m = rawMemoryUsage();
|
|
167
|
+
if (m === null) {
|
|
168
|
+
return "";
|
|
169
|
+
}
|
|
170
|
+
const delta = prev === null || withDetails === false
|
|
171
|
+
? ""
|
|
172
|
+
: ` (Δrss=${signedMb(m.rss - prev.rss)}MB ΔarrayBuffers=${signedMb(m.arrayBuffers - prev.arrayBuffers)}MB)`;
|
|
173
|
+
prev = m;
|
|
174
|
+
return `${memoryUsage(withDetails)}${delta}`;
|
|
175
|
+
},
|
|
154
176
|
};
|
|
155
177
|
}
|
|
156
178
|
/** A class that adds `toString` method that prints all properties of an object. */
|
|
@@ -25,21 +25,27 @@ describe("utils::lazyInspect", () => {
|
|
|
25
25
|
});
|
|
26
26
|
describe("utils::memoryUsage", () => {
|
|
27
27
|
it("should report all memory fields", () => {
|
|
28
|
-
const usage = memoryUsage();
|
|
28
|
+
const usage = memoryUsage(true);
|
|
29
29
|
for (const field of ["rss=", "heap=", "external=", "arrayBuffers="]) {
|
|
30
30
|
assert.ok(usage.includes(field), `expected "${field}" in "${usage}"`);
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
|
+
it("should report all memory fields without details", () => {
|
|
34
|
+
const usage = memoryUsage(false);
|
|
35
|
+
for (const field of ["rss=", "heap="]) {
|
|
36
|
+
assert.ok(usage.includes(field), `expected "${field}" in "${usage}"`);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
33
39
|
});
|
|
34
40
|
describe("utils::memoryTracker", () => {
|
|
35
41
|
it("should not include a delta on the first call", () => {
|
|
36
|
-
const tracker = memoryTracker();
|
|
37
|
-
assert.ok(!tracker().includes("Δrss"));
|
|
42
|
+
const tracker = memoryTracker(true);
|
|
43
|
+
assert.ok(!tracker.toString().includes("Δrss"));
|
|
38
44
|
});
|
|
39
45
|
it("should include a delta on subsequent calls", () => {
|
|
40
|
-
const tracker = memoryTracker();
|
|
41
|
-
tracker();
|
|
42
|
-
const second = tracker();
|
|
46
|
+
const tracker = memoryTracker(true);
|
|
47
|
+
tracker.toString();
|
|
48
|
+
const second = tracker.toString();
|
|
43
49
|
assert.ok(second.includes("Δrss="), `expected delta in "${second}"`);
|
|
44
50
|
assert.ok(second.includes("ΔarrayBuffers="), `expected delta in "${second}"`);
|
|
45
51
|
});
|
|
@@ -4,7 +4,8 @@ import { type FromJson } from "#@typeberry/json-parser";
|
|
|
4
4
|
import { AuthorshipOptions } from "./authorship.js";
|
|
5
5
|
import { JipChainSpec } from "./jip-chain-spec.js";
|
|
6
6
|
/** Development config. Will accept unsealed blocks for now. */
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const DEV_TINY_CONFIG = "dev";
|
|
8
|
+
export declare const DEV_FULL_CONFIG = "dev-full";
|
|
8
9
|
/** Default config file. */
|
|
9
10
|
export declare const DEFAULT_CONFIG = "default";
|
|
10
11
|
export declare const NODE_DEFAULTS: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"node-config.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/config-node/node-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,2BAA2B;AAC3B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa;;;;CAIzB,CAAC;AAEF,0BAA0B;AAC1B,oBAAY,cAAc;IACxB,uBAAuB;IACvB,IAAI,SAAS;IACb,uBAAuB;IACvB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,sBAAsB,EAS7B,QAAQ,CAAC,cAAc,CAAC,CAAC;AAE/B,qBAAa,iBAAiB;aAqBV,OAAO,EAAE,MAAM;aACf,OAAO,EAAE,MAAM;aACf,MAAM,EAAE,cAAc;aACtB,SAAS,EAAE,YAAY;IACvC,iEAAiE;aACjD,gBAAgB,EAAE,MAAM,GAAG,SAAS;aACpC,UAAU,EAAE,iBAAiB;IA1B/C,MAAM,CAAC,QAAQ,kFAUb;IAEF,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,iBAAiB,CAAC;IAOlH,OAAO;CASR;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,iBAAiB,CAuDlG"}
|
|
@@ -9,7 +9,8 @@ import { AuthorshipOptions } from "./authorship.js";
|
|
|
9
9
|
import { JipChainSpec } from "./jip-chain-spec.js";
|
|
10
10
|
const logger = Logger.new(import.meta.filename, "config");
|
|
11
11
|
/** Development config. Will accept unsealed blocks for now. */
|
|
12
|
-
export const
|
|
12
|
+
export const DEV_TINY_CONFIG = "dev";
|
|
13
|
+
export const DEV_FULL_CONFIG = "dev-full";
|
|
13
14
|
/** Default config file. */
|
|
14
15
|
export const DEFAULT_CONFIG = "default";
|
|
15
16
|
export const NODE_DEFAULTS = {
|
|
@@ -72,8 +73,12 @@ export function loadConfig(config, withRelPath) {
|
|
|
72
73
|
let mergedJson = {};
|
|
73
74
|
for (const entry of config) {
|
|
74
75
|
logger.log `🔧 Applying '${entry}'`;
|
|
75
|
-
if (entry ===
|
|
76
|
-
mergedJson = structuredClone(configs.
|
|
76
|
+
if (entry === DEV_TINY_CONFIG) {
|
|
77
|
+
mergedJson = structuredClone(configs.devTiny); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (entry === DEV_FULL_CONFIG) {
|
|
81
|
+
mergedJson = structuredClone(configs.devFull); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
|
|
77
82
|
continue;
|
|
78
83
|
}
|
|
79
84
|
if (entry === DEFAULT_CONFIG) {
|
|
@@ -70,7 +70,7 @@ describe("loadConfig", () => {
|
|
|
70
70
|
});
|
|
71
71
|
it("should load dev config", () => {
|
|
72
72
|
const config = loadConfig(["dev"], withRelPath);
|
|
73
|
-
assert.deepStrictEqual(config, parseFromJson(configs.
|
|
73
|
+
assert.deepStrictEqual(config, parseFromJson(configs.devTiny, NodeConfiguration.fromJson));
|
|
74
74
|
});
|
|
75
75
|
it("should parse inline json config and deep merge onto previous entries", () => {
|
|
76
76
|
const config = loadConfig(["default", JSON.stringify({ database_base_path: "/test/path", chain_spec: { bootnodes: [] } })], withRelPath);
|
|
@@ -138,9 +138,9 @@ describe("loadConfig", () => {
|
|
|
138
138
|
`.database_base_path="/test/path-1"`,
|
|
139
139
|
], withRelPath);
|
|
140
140
|
assert.deepStrictEqual(config, parseFromJson({
|
|
141
|
-
...configs.
|
|
141
|
+
...configs.devTiny,
|
|
142
142
|
database_base_path: "/test/path-1",
|
|
143
|
-
chain_spec: { ...configs.
|
|
143
|
+
chain_spec: { ...configs.devTiny.chain_spec, bootnodes: [] },
|
|
144
144
|
}, NodeConfiguration.fromJson));
|
|
145
145
|
});
|
|
146
146
|
it("should throw an error if an invalid json file is provided", () => {
|
|
@@ -35,6 +35,13 @@ export interface StatesDb<T extends State = State> {
|
|
|
35
35
|
getState(header: HeaderHash): T | null;
|
|
36
36
|
/** Mark state as no longer needed. Backend may remove it asynchronously. */
|
|
37
37
|
markUnused(header: HeaderHash): void;
|
|
38
|
+
/**
|
|
39
|
+
* Apparent on-disk size of the database in bytes, used for monitoring.
|
|
40
|
+
*
|
|
41
|
+
* Returns `null` when the size is unknown. Backends that are not persisted
|
|
42
|
+
* (e.g. in-memory) may omit the method entirely.
|
|
43
|
+
*/
|
|
44
|
+
diskSizeInBytes?(): number | null;
|
|
38
45
|
/** Close the database and free resources. */
|
|
39
46
|
close(): Promise<void>;
|
|
40
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAe,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAe,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,0DAA0D;AAC1D,oBAAY,gBAAgB;IAC1B,oDAAoD;IACpD,QAAQ,IAAI;IACZ,iDAAiD;IACjD,MAAM,IAAI;CACX;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,KAAK;IACrC,qEAAqE;IACrE,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK;IAC/C,4CAA4C;IAC5C,YAAY,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C;;;;OAIG;IACH,iBAAiB,CACf,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEzC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC;IAEvC,4EAA4E;IAC5E,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAErC,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,cAAe,YAAW,QAAQ,CAAC,aAAa,CAAC;IAQxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmE;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS;IAI1B,OAAO;IAID,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAgBlC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAKhE,6CAA6C;IACvC,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAM7G,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAStD,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
|
|
1
|
+
{"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database/states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,KAAK,EAAe,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAe,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3D,0DAA0D;AAC1D,oBAAY,gBAAgB;IAC1B,oDAAoD;IACpD,QAAQ,IAAI;IACZ,iDAAiD;IACjD,MAAM,IAAI;CACX;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,KAAK;IACrC,qEAAqE;IACrE,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACpG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK;IAC/C,4CAA4C;IAC5C,YAAY,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C;;;;OAIG;IACH,iBAAiB,CACf,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEzC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC;IAEvC,4EAA4E;IAC5E,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAErC;;;;;OAKG;IACH,eAAe,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;IAElC,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,cAAe,YAAW,QAAQ,CAAC,aAAa,CAAC;IAQxC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmE;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS;IAI1B,OAAO;IAID,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAgBlC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAKhE,6CAA6C;IACvC,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAM7G,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAStD,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI9B,KAAK;CACZ"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { HeaderHash, StateRootHash } from "#@typeberry/block";
|
|
2
|
+
import type { ChainSpec } from "#@typeberry/config";
|
|
3
|
+
import { type InitStatesDb, LeafDb, type StatesDb, StateUpdateError } from "#@typeberry/database";
|
|
4
|
+
import type { Blake2b } from "#@typeberry/hash";
|
|
5
|
+
import type { ServicesUpdate, State } from "#@typeberry/state";
|
|
6
|
+
import { SerializedState, type StateEntries } from "#@typeberry/state-merkleization";
|
|
7
|
+
import { OK, Result } from "#@typeberry/utils";
|
|
8
|
+
/**
|
|
9
|
+
* Hybrid serialized-states db (fjall variant).
|
|
10
|
+
*
|
|
11
|
+
* States (leafs) are kept in-memory, but large values are persisted to fjall.
|
|
12
|
+
* Reads go straight to fjall, which keeps its own (bounded) block cache.
|
|
13
|
+
* Designed for long fuzzing, used with pruning to keep heap usage bounded.
|
|
14
|
+
*
|
|
15
|
+
* Behaviourally identical to the LMDB hybrid db; differences are mechanical:
|
|
16
|
+
* construction is async, and value writes are ordered + flushed explicitly
|
|
17
|
+
* because fjall has no transaction primitive.
|
|
18
|
+
*/
|
|
19
|
+
export declare class HybridSerializedStates implements StatesDb<SerializedState<LeafDb>>, InitStatesDb<StateEntries> {
|
|
20
|
+
private readonly spec;
|
|
21
|
+
private readonly blake2b;
|
|
22
|
+
private readonly root;
|
|
23
|
+
private readonly values;
|
|
24
|
+
static new({ spec, blake2b, dbPath, ephemeral, }: {
|
|
25
|
+
spec: ChainSpec;
|
|
26
|
+
blake2b: Blake2b;
|
|
27
|
+
dbPath: string;
|
|
28
|
+
ephemeral?: boolean;
|
|
29
|
+
}): Promise<HybridSerializedStates>;
|
|
30
|
+
private readonly inMemStates;
|
|
31
|
+
private readonly valuesDb;
|
|
32
|
+
private constructor();
|
|
33
|
+
insertInitialState(headerHash: HeaderHash, entries: StateEntries): Promise<Result<OK, StateUpdateError>>;
|
|
34
|
+
updateAndSetState(header: HeaderHash, state: SerializedState<LeafDb>, update: Partial<State & ServicesUpdate>): Promise<Result<OK, StateUpdateError>>;
|
|
35
|
+
getStateRoot(state: SerializedState<LeafDb>): Promise<StateRootHash>;
|
|
36
|
+
getState(header: HeaderHash): SerializedState<LeafDb> | null;
|
|
37
|
+
markUnused(header: HeaderHash): void;
|
|
38
|
+
diskSizeInBytes(): number | null;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
/** Write new large values to fjall, then flush. */
|
|
41
|
+
private writeValues;
|
|
42
|
+
/** Read a value from fjall. */
|
|
43
|
+
private readValue;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=hybrid-states.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-states.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-fjall/hybrid-states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGlE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,KAAK,YAAY,EACjB,MAAM,EACN,KAAK,QAAQ,EACb,gBAAgB,EAGjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EACL,eAAe,EACf,KAAK,YAAY,EAGlB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK9C;;;;;;;;;;GAUG;AACH,qBAAa,sBAAuB,YAAW,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC;IAsBxG,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;WAxBZ,GAAG,CAAC,EACf,IAAI,EACJ,OAAO,EACP,MAAM,EACN,SAAS,GACV,EAAE;QACD,IAAI,EAAE,SAAS,CAAC;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAMnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyE;IAErG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC,OAAO;IASD,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAcxG,iBAAiB,CACrB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAkBlC,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAI1E,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI;IAS5D,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAMpC,eAAe,IAAI,MAAM,GAAG,IAAI;IAI1B,KAAK;IAIX,mDAAmD;YACrC,WAAW;IAgBzB,+BAA+B;IAC/B,OAAO,CAAC,SAAS;CAOlB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { HashDictionary, SortedSet } from "#@typeberry/collections";
|
|
2
|
+
import { LeafDb, StateUpdateError, updateLeafs, } from "#@typeberry/database";
|
|
3
|
+
import { Logger } from "#@typeberry/logger";
|
|
4
|
+
import { SerializedState, StateEntryUpdateAction, serializeStateUpdate, } from "#@typeberry/state-merkleization";
|
|
5
|
+
import { leafComparator } from "#@typeberry/trie";
|
|
6
|
+
import { OK, Result } from "#@typeberry/utils";
|
|
7
|
+
import { FjallRoot, toUint8Array } from "./root.js";
|
|
8
|
+
const logger = Logger.new(import.meta.filename, "db");
|
|
9
|
+
/**
|
|
10
|
+
* Hybrid serialized-states db (fjall variant).
|
|
11
|
+
*
|
|
12
|
+
* States (leafs) are kept in-memory, but large values are persisted to fjall.
|
|
13
|
+
* Reads go straight to fjall, which keeps its own (bounded) block cache.
|
|
14
|
+
* Designed for long fuzzing, used with pruning to keep heap usage bounded.
|
|
15
|
+
*
|
|
16
|
+
* Behaviourally identical to the LMDB hybrid db; differences are mechanical:
|
|
17
|
+
* construction is async, and value writes are ordered + flushed explicitly
|
|
18
|
+
* because fjall has no transaction primitive.
|
|
19
|
+
*/
|
|
20
|
+
export class HybridSerializedStates {
|
|
21
|
+
spec;
|
|
22
|
+
blake2b;
|
|
23
|
+
root;
|
|
24
|
+
values;
|
|
25
|
+
static async new({ spec, blake2b, dbPath, ephemeral, }) {
|
|
26
|
+
const root = await FjallRoot.open(dbPath, { ephemeral });
|
|
27
|
+
const values = await root.partition("values");
|
|
28
|
+
return new HybridSerializedStates(spec, blake2b, root, values);
|
|
29
|
+
}
|
|
30
|
+
inMemStates = HashDictionary.new();
|
|
31
|
+
// A single shared values accessor reused by every `LeafDb` we hand out.
|
|
32
|
+
valuesDb;
|
|
33
|
+
constructor(spec, blake2b, root, values) {
|
|
34
|
+
this.spec = spec;
|
|
35
|
+
this.blake2b = blake2b;
|
|
36
|
+
this.root = root;
|
|
37
|
+
this.values = values;
|
|
38
|
+
this.valuesDb = { get: (key) => this.readValue(key) };
|
|
39
|
+
}
|
|
40
|
+
async insertInitialState(headerHash, entries) {
|
|
41
|
+
const { values, leafs } = updateLeafs(SortedSet.fromArray(leafComparator, []), this.blake2b, Array.from(entries, (x) => [StateEntryUpdateAction.Insert, x[0], x[1]]));
|
|
42
|
+
const res = await this.writeValues(values);
|
|
43
|
+
if (res.isError) {
|
|
44
|
+
return res;
|
|
45
|
+
}
|
|
46
|
+
this.inMemStates.set(headerHash, leafs);
|
|
47
|
+
return Result.ok(OK);
|
|
48
|
+
}
|
|
49
|
+
async updateAndSetState(header, state, update) {
|
|
50
|
+
const updatedValues = serializeStateUpdate(this.spec, this.blake2b, update);
|
|
51
|
+
// Clone the leaf set before mutating: the previous state keeps using its own.
|
|
52
|
+
const newLeafs = SortedSet.fromSortedArray(leafComparator, state.backend.leafs.array);
|
|
53
|
+
const { values, leafs } = updateLeafs(newLeafs, this.blake2b, updatedValues);
|
|
54
|
+
const res = await this.writeValues(values);
|
|
55
|
+
if (res.isError) {
|
|
56
|
+
// Leave the caller's state untouched: its new leaves would reference
|
|
57
|
+
// values that never reached disk.
|
|
58
|
+
return res;
|
|
59
|
+
}
|
|
60
|
+
// Re-create the lookup with the shared values accessor only once the new
|
|
61
|
+
// values are durably written.
|
|
62
|
+
state.updateBackend(LeafDb.fromLeaves(leafs, this.valuesDb));
|
|
63
|
+
this.inMemStates.set(header, leafs);
|
|
64
|
+
return Result.ok(OK);
|
|
65
|
+
}
|
|
66
|
+
async getStateRoot(state) {
|
|
67
|
+
return state.backend.getStateRoot(this.blake2b);
|
|
68
|
+
}
|
|
69
|
+
getState(header) {
|
|
70
|
+
const leafs = this.inMemStates.get(header);
|
|
71
|
+
if (leafs === undefined) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const leafDb = LeafDb.fromLeaves(leafs, this.valuesDb);
|
|
75
|
+
return SerializedState.new(this.spec, this.blake2b, leafDb);
|
|
76
|
+
}
|
|
77
|
+
markUnused(header) {
|
|
78
|
+
// We only remove the state from memory - values are not pruned at all,
|
|
79
|
+
// but since they are stored on disk we should be safe.
|
|
80
|
+
this.inMemStates.delete(header);
|
|
81
|
+
}
|
|
82
|
+
diskSizeInBytes() {
|
|
83
|
+
return this.root.sizeInBytes();
|
|
84
|
+
}
|
|
85
|
+
async close() {
|
|
86
|
+
await this.root.close();
|
|
87
|
+
}
|
|
88
|
+
/** Write new large values to fjall, then flush. */
|
|
89
|
+
async writeValues(values) {
|
|
90
|
+
if (values.length === 0) {
|
|
91
|
+
return Result.ok(OK);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
for (const [hash, val] of values) {
|
|
95
|
+
await this.values.insert(hash.raw, val.raw);
|
|
96
|
+
}
|
|
97
|
+
await this.root.persist();
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
logger.error `${e}`;
|
|
101
|
+
return Result.error(StateUpdateError.Commit, () => `Failed to commit values: ${e}`);
|
|
102
|
+
}
|
|
103
|
+
return Result.ok(OK);
|
|
104
|
+
}
|
|
105
|
+
/** Read a value from fjall. */
|
|
106
|
+
readValue(key) {
|
|
107
|
+
const val = toUint8Array(this.values.get(key.raw));
|
|
108
|
+
if (val === null) {
|
|
109
|
+
throw new Error(`Missing value at key: ${key}`);
|
|
110
|
+
}
|
|
111
|
+
return val;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-states.test.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-fjall/hybrid-states.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import { afterEach, before, beforeEach, describe, it } from "node:test";
|
|
4
|
+
import { Bytes, BytesBlob } from "#@typeberry/bytes";
|
|
5
|
+
import { tinyChainSpec } from "#@typeberry/config";
|
|
6
|
+
import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
|
|
7
|
+
import { InMemoryState } from "#@typeberry/state";
|
|
8
|
+
import { StateEntries } from "#@typeberry/state-merkleization";
|
|
9
|
+
import { deepEqual, OK, Result } from "#@typeberry/utils";
|
|
10
|
+
import { HybridSerializedStates } from "./hybrid-states.js";
|
|
11
|
+
let blake2b;
|
|
12
|
+
before(async () => {
|
|
13
|
+
blake2b = await Blake2b.createHasher();
|
|
14
|
+
});
|
|
15
|
+
function createTempDir(suffix = "fjall-hybrid") {
|
|
16
|
+
return fs.mkdtempSync(`typeberry-${suffix}`);
|
|
17
|
+
}
|
|
18
|
+
describe("Fjall hybrid serialized states", () => {
|
|
19
|
+
const spec = tinyChainSpec;
|
|
20
|
+
const headerHash = Bytes.zero(HASH_SIZE).asOpaque();
|
|
21
|
+
let dbPath = "";
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
dbPath = createTempDir();
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
fs.rmSync(dbPath, { recursive: true });
|
|
27
|
+
});
|
|
28
|
+
it("round-trips an initial state through the on-disk values store", async () => {
|
|
29
|
+
const states = await HybridSerializedStates.new({ spec, blake2b, dbPath });
|
|
30
|
+
try {
|
|
31
|
+
const empty = InMemoryState.empty(spec);
|
|
32
|
+
const serialized = StateEntries.serializeInMemory(spec, blake2b, empty);
|
|
33
|
+
const expectedRoot = serialized.getRootHash(blake2b);
|
|
34
|
+
const res = await states.insertInitialState(headerHash, serialized);
|
|
35
|
+
deepEqual(res, Result.ok(OK));
|
|
36
|
+
const state = states.getState(headerHash);
|
|
37
|
+
assert.ok(state !== null);
|
|
38
|
+
const stateRoot = await states.getStateRoot(state);
|
|
39
|
+
assert.strictEqual(`${stateRoot}`, `${expectedRoot}`);
|
|
40
|
+
deepEqual(InMemoryState.copyFrom(spec, state, new Map()), empty);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await states.close();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
it("reads large values back from disk", async () => {
|
|
47
|
+
const states = await HybridSerializedStates.new({ spec, blake2b, dbPath });
|
|
48
|
+
try {
|
|
49
|
+
// > 32 bytes => stored in the values db (not embedded in the leaf).
|
|
50
|
+
const big1 = BytesBlob.blobFromString("x".repeat(100));
|
|
51
|
+
const big2 = BytesBlob.blobFromString("y".repeat(100));
|
|
52
|
+
const key1 = Bytes.fill(HASH_SIZE, 1).asOpaque();
|
|
53
|
+
const key2 = Bytes.fill(HASH_SIZE, 2).asOpaque();
|
|
54
|
+
const entries = StateEntries.fromEntriesUnsafe([
|
|
55
|
+
[key1, big1],
|
|
56
|
+
[key2, big2],
|
|
57
|
+
]);
|
|
58
|
+
const res = await states.insertInitialState(headerHash, entries);
|
|
59
|
+
deepEqual(res, Result.ok(OK));
|
|
60
|
+
const state = states.getState(headerHash);
|
|
61
|
+
assert.ok(state !== null);
|
|
62
|
+
assert.strictEqual(`${state.backend.get(key2)}`, `${big2}`);
|
|
63
|
+
assert.strictEqual(`${state.backend.get(key1)}`, `${big1}`);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
await states.close();
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
it("drops the leaf set on markUnused while values stay on disk", async () => {
|
|
70
|
+
const states = await HybridSerializedStates.new({ spec, blake2b, dbPath });
|
|
71
|
+
try {
|
|
72
|
+
const empty = InMemoryState.empty(spec);
|
|
73
|
+
const serialized = StateEntries.serializeInMemory(spec, blake2b, empty);
|
|
74
|
+
await states.insertInitialState(headerHash, serialized);
|
|
75
|
+
assert.ok(states.getState(headerHash) !== null);
|
|
76
|
+
states.markUnused(headerHash);
|
|
77
|
+
assert.strictEqual(states.getState(headerHash), null);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
await states.close();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-fjall/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type Partition } from "@fjall-js/fjall";
|
|
2
|
+
export type { Partition };
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a value read from fjall (a Node `Buffer`) into a plain `Uint8Array`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function toUint8Array(value: Buffer | null): Uint8Array | null;
|
|
7
|
+
export type FjallRootOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* When set, durability flushes (`persist`) are skipped entirely.
|
|
10
|
+
*
|
|
11
|
+
* Only safe for throwaway databases (e.g. the fuzz target, which wipes on
|
|
12
|
+
* every reset). Mirrors LMDB's `noSync`.
|
|
13
|
+
*/
|
|
14
|
+
ephemeral?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A thin abstraction over the fjall keyspace.
|
|
18
|
+
*
|
|
19
|
+
* Unlike LMDB (a memory-mapped B-tree), fjall is an LSM-tree that reads/writes
|
|
20
|
+
* through regular file I/O, so its working set is bounded by an explicit block
|
|
21
|
+
* cache rather than the whole mmap. LMDB has been causing oom issues because
|
|
22
|
+
* of that.
|
|
23
|
+
*/
|
|
24
|
+
export declare class FjallRoot {
|
|
25
|
+
private readonly keyspace;
|
|
26
|
+
/** Path of the underlying keyspace directory, used to report on-disk usage. */
|
|
27
|
+
private readonly dbPath;
|
|
28
|
+
private readonly options;
|
|
29
|
+
private constructor();
|
|
30
|
+
/** Open (or create) a fjall keyspace at the given path. */
|
|
31
|
+
static open(dbPath: string, options: FjallRootOptions): Promise<FjallRoot>;
|
|
32
|
+
/** Open (or create) a partition under this keyspace. */
|
|
33
|
+
partition(name: string): Promise<Partition>;
|
|
34
|
+
/**
|
|
35
|
+
* Flush the journal to disk so prior writes survive a crash.
|
|
36
|
+
*
|
|
37
|
+
* Call after a logically-complete unit of work (one block, one state commit).
|
|
38
|
+
* A no-op for ephemeral databases.
|
|
39
|
+
*/
|
|
40
|
+
persist(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Apparent on-disk size of the keyspace directory, in bytes.
|
|
43
|
+
*
|
|
44
|
+
* Returns `null` if the directory cannot be walked (e.g. not yet created).
|
|
45
|
+
* Unlike LMDB's single `data.mdb`, a fjall keyspace is a directory of
|
|
46
|
+
* partition and journal files, so we sum it recursively.
|
|
47
|
+
*/
|
|
48
|
+
sizeInBytes(): number | null;
|
|
49
|
+
/** Persist with `sync-all` and release the keyspace handle. */
|
|
50
|
+
close(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/database-fjall/root.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtE,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAKpE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO;IAOP,2DAA2D;WAC9C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC;IAKhF,wDAAwD;IAClD,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAIjD;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;;;;;OAMG;IACH,WAAW,IAAI,MAAM,GAAG,IAAI;IAQ5B,+DAA+D;IACzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|