@claw-network/core 0.1.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/dist/crypto/aes.d.ts +8 -0
- package/dist/crypto/aes.d.ts.map +1 -0
- package/dist/crypto/aes.js +29 -0
- package/dist/crypto/aes.js.map +1 -0
- package/dist/crypto/ed25519.d.ts +11 -0
- package/dist/crypto/ed25519.d.ts.map +1 -0
- package/dist/crypto/ed25519.js +25 -0
- package/dist/crypto/ed25519.js.map +1 -0
- package/dist/crypto/hash.d.ts +5 -0
- package/dist/crypto/hash.d.ts.map +1 -0
- package/dist/crypto/hash.js +16 -0
- package/dist/crypto/hash.js.map +1 -0
- package/dist/crypto/hkdf.d.ts +2 -0
- package/dist/crypto/hkdf.d.ts.map +1 -0
- package/dist/crypto/hkdf.js +6 -0
- package/dist/crypto/hkdf.js.map +1 -0
- package/dist/crypto/index.d.ts +10 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +10 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/jcs.d.ts +3 -0
- package/dist/crypto/jcs.d.ts.map +1 -0
- package/dist/crypto/jcs.js +14 -0
- package/dist/crypto/jcs.js.map +1 -0
- package/dist/crypto/mnemonic.d.ts +9 -0
- package/dist/crypto/mnemonic.d.ts.map +1 -0
- package/dist/crypto/mnemonic.js +22 -0
- package/dist/crypto/mnemonic.js.map +1 -0
- package/dist/crypto/rotation.d.ts +20 -0
- package/dist/crypto/rotation.d.ts.map +1 -0
- package/dist/crypto/rotation.js +37 -0
- package/dist/crypto/rotation.js.map +1 -0
- package/dist/crypto/shamir.d.ts +3 -0
- package/dist/crypto/shamir.d.ts.map +1 -0
- package/dist/crypto/shamir.js +125 -0
- package/dist/crypto/shamir.js.map +1 -0
- package/dist/crypto/x25519.d.ts +8 -0
- package/dist/crypto/x25519.d.ts.map +1 -0
- package/dist/crypto/x25519.js +13 -0
- package/dist/crypto/x25519.js.map +1 -0
- package/dist/encoding/base58.d.ts +5 -0
- package/dist/encoding/base58.d.ts.map +1 -0
- package/dist/encoding/base58.js +63 -0
- package/dist/encoding/base58.js.map +1 -0
- package/dist/encoding/index.d.ts +2 -0
- package/dist/encoding/index.d.ts.map +1 -0
- package/dist/encoding/index.js +2 -0
- package/dist/encoding/index.js.map +1 -0
- package/dist/identity/did.d.ts +6 -0
- package/dist/identity/did.d.ts.map +1 -0
- package/dist/identity/did.js +48 -0
- package/dist/identity/did.js.map +1 -0
- package/dist/identity/index.d.ts +2 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +2 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/p2p/config.d.ts +26 -0
- package/dist/p2p/config.d.ts.map +1 -0
- package/dist/p2p/config.js +14 -0
- package/dist/p2p/config.js.map +1 -0
- package/dist/p2p/index.d.ts +4 -0
- package/dist/p2p/index.d.ts.map +1 -0
- package/dist/p2p/index.js +4 -0
- package/dist/p2p/index.js.map +1 -0
- package/dist/p2p/node.d.ts +44 -0
- package/dist/p2p/node.d.ts.map +1 -0
- package/dist/p2p/node.js +299 -0
- package/dist/p2p/node.js.map +1 -0
- package/dist/p2p/topics.d.ts +6 -0
- package/dist/p2p/topics.d.ts.map +1 -0
- package/dist/p2p/topics.js +6 -0
- package/dist/p2p/topics.js.map +1 -0
- package/dist/protocol/constants.d.ts +3 -0
- package/dist/protocol/constants.d.ts.map +1 -0
- package/dist/protocol/constants.js +3 -0
- package/dist/protocol/constants.js.map +1 -0
- package/dist/protocol/credentials.d.ts +30 -0
- package/dist/protocol/credentials.d.ts.map +1 -0
- package/dist/protocol/credentials.js +61 -0
- package/dist/protocol/credentials.js.map +1 -0
- package/dist/protocol/event-hash.d.ts +10 -0
- package/dist/protocol/event-hash.d.ts.map +1 -0
- package/dist/protocol/event-hash.js +32 -0
- package/dist/protocol/event-hash.js.map +1 -0
- package/dist/protocol/index.d.ts +5 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +5 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/key-rotation.d.ts +23 -0
- package/dist/protocol/key-rotation.d.ts.map +1 -0
- package/dist/protocol/key-rotation.js +34 -0
- package/dist/protocol/key-rotation.js.map +1 -0
- package/dist/storage/config.d.ts +22 -0
- package/dist/storage/config.d.ts.map +1 -0
- package/dist/storage/config.js +63 -0
- package/dist/storage/config.js.map +1 -0
- package/dist/storage/event-store.d.ts +49 -0
- package/dist/storage/event-store.d.ts.map +1 -0
- package/dist/storage/event-store.js +329 -0
- package/dist/storage/event-store.js.map +1 -0
- package/dist/storage/health.d.ts +9 -0
- package/dist/storage/health.d.ts.map +1 -0
- package/dist/storage/health.js +25 -0
- package/dist/storage/health.js.map +1 -0
- package/dist/storage/index.d.ts +13 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/keystore.d.ts +36 -0
- package/dist/storage/keystore.d.ts.map +1 -0
- package/dist/storage/keystore.js +129 -0
- package/dist/storage/keystore.js.map +1 -0
- package/dist/storage/kv.d.ts +11 -0
- package/dist/storage/kv.d.ts.map +1 -0
- package/dist/storage/kv.js +2 -0
- package/dist/storage/kv.js.map +1 -0
- package/dist/storage/level.d.ts +17 -0
- package/dist/storage/level.d.ts.map +1 -0
- package/dist/storage/level.js +57 -0
- package/dist/storage/level.js.map +1 -0
- package/dist/storage/memory.d.ts +12 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +20 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/migrations.d.ts +11 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +47 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/paths.d.ts +14 -0
- package/dist/storage/paths.d.ts.map +1 -0
- package/dist/storage/paths.js +30 -0
- package/dist/storage/paths.js.map +1 -0
- package/dist/storage/snapshot-scheduler.d.ts +16 -0
- package/dist/storage/snapshot-scheduler.d.ts.map +1 -0
- package/dist/storage/snapshot-scheduler.js +43 -0
- package/dist/storage/snapshot-scheduler.js.map +1 -0
- package/dist/storage/snapshots.d.ts +53 -0
- package/dist/storage/snapshots.d.ts.map +1 -0
- package/dist/storage/snapshots.js +192 -0
- package/dist/storage/snapshots.js.map +1 -0
- package/dist/storage/state-store.d.ts +14 -0
- package/dist/storage/state-store.d.ts.map +1 -0
- package/dist/storage/state-store.js +38 -0
- package/dist/storage/state-store.js.map +1 -0
- package/dist/utils/PromiseWithResolvers.d.ts +2 -0
- package/dist/utils/PromiseWithResolvers.d.ts.map +1 -0
- package/dist/utils/PromiseWithResolvers.js +18 -0
- package/dist/utils/PromiseWithResolvers.js.map +1 -0
- package/dist/utils/bytes.d.ts +8 -0
- package/dist/utils/bytes.d.ts.map +1 -0
- package/dist/utils/bytes.js +40 -0
- package/dist/utils/bytes.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Level } from 'level';
|
|
2
|
+
function toUint8Array(value) {
|
|
3
|
+
if (value instanceof Uint8Array) {
|
|
4
|
+
if (Buffer.isBuffer(value)) {
|
|
5
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
return new Uint8Array(value);
|
|
10
|
+
}
|
|
11
|
+
export class LevelStore {
|
|
12
|
+
db;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.db = new Level(options.path, { valueEncoding: 'view' });
|
|
15
|
+
}
|
|
16
|
+
async get(key) {
|
|
17
|
+
try {
|
|
18
|
+
const value = await this.db.get(key);
|
|
19
|
+
if (value === undefined || value === null) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return toUint8Array(value);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code === 'LEVEL_NOT_FOUND') {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async put(key, value) {
|
|
32
|
+
await this.db.put(key, value);
|
|
33
|
+
}
|
|
34
|
+
async del(key) {
|
|
35
|
+
await this.db.del(key);
|
|
36
|
+
}
|
|
37
|
+
async *iterator(prefix = '') {
|
|
38
|
+
const hasPrefix = prefix.length > 0;
|
|
39
|
+
const options = hasPrefix
|
|
40
|
+
? {
|
|
41
|
+
gte: prefix,
|
|
42
|
+
lt: `${prefix}\xff`,
|
|
43
|
+
}
|
|
44
|
+
: {};
|
|
45
|
+
const iterator = this.db.iterator(options);
|
|
46
|
+
for await (const [key, value] of iterator) {
|
|
47
|
+
if (value === undefined || value === null) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
yield { key, value: toUint8Array(value) };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async close() {
|
|
54
|
+
await this.db.close();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=level.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"level.js","sourceRoot":"","sources":["../../src/storage/level.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAO9B,SAAS,YAAY,CAAC,KAAwC;IAC5D,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,OAAO,UAAU;IACJ,EAAE,CAA4B;IAE/C,YAAY,OAA0B;QACpC,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC1C,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,YAAY,CAAC,KAA0C,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA2B,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBAC5D,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAiB;QACtC,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;QACzB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,SAAS;YACvB,CAAC,CAAC;gBACE,GAAG,EAAE,MAAM;gBACX,EAAE,EAAE,GAAG,MAAM,MAAM;aACpB;YACH,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE3C,IAAI,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC1C,SAAS;YACX,CAAC;YACD,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,KAA0C,CAAC,EAAE,CAAC;QACjF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { KVStore } from './kv.js';
|
|
2
|
+
export declare class MemoryStore implements KVStore {
|
|
3
|
+
private store;
|
|
4
|
+
get(key: string): Promise<Uint8Array | undefined>;
|
|
5
|
+
put(key: string, value: Uint8Array): Promise<void>;
|
|
6
|
+
del(key: string): Promise<void>;
|
|
7
|
+
iterator(prefix?: string): AsyncIterable<{
|
|
8
|
+
key: string;
|
|
9
|
+
value: Uint8Array;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/storage/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,qBAAa,WAAY,YAAW,OAAO;IACzC,OAAO,CAAC,KAAK,CAAiC;IAExC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9B,QAAQ,CAAC,MAAM,SAAK,GAAG,aAAa,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;CAOhF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class MemoryStore {
|
|
2
|
+
store = new Map();
|
|
3
|
+
async get(key) {
|
|
4
|
+
return this.store.get(key);
|
|
5
|
+
}
|
|
6
|
+
async put(key, value) {
|
|
7
|
+
this.store.set(key, value);
|
|
8
|
+
}
|
|
9
|
+
async del(key) {
|
|
10
|
+
this.store.delete(key);
|
|
11
|
+
}
|
|
12
|
+
async *iterator(prefix = '') {
|
|
13
|
+
for (const [key, value] of this.store.entries()) {
|
|
14
|
+
if (!prefix || key.startsWith(prefix)) {
|
|
15
|
+
yield { key, value };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/storage/memory.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IACd,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE9C,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAiB;QACtC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;QACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { KVStore } from './kv.js';
|
|
2
|
+
export declare const META_SCHEMA_VERSION_KEY = "meta:version";
|
|
3
|
+
export declare const DEFAULT_SCHEMA_VERSION = 1;
|
|
4
|
+
export interface StorageMigration {
|
|
5
|
+
version: number;
|
|
6
|
+
up: (store: KVStore) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function getSchemaVersion(store: KVStore): Promise<number | null>;
|
|
9
|
+
export declare function setSchemaVersion(store: KVStore, version: number): Promise<void>;
|
|
10
|
+
export declare function ensureSchemaVersion(store: KVStore, targetVersion?: number, migrations?: StorageMigration[]): Promise<number>;
|
|
11
|
+
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/storage/migrations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAWD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG7E;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErF;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,aAAa,GAAE,MAA+B,EAC9C,UAAU,GAAE,gBAAgB,EAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { bytesToUtf8, utf8ToBytes } from '../utils/bytes.js';
|
|
2
|
+
export const META_SCHEMA_VERSION_KEY = 'meta:version';
|
|
3
|
+
export const DEFAULT_SCHEMA_VERSION = 1;
|
|
4
|
+
function encodeNumber(value) {
|
|
5
|
+
return utf8ToBytes(JSON.stringify(value));
|
|
6
|
+
}
|
|
7
|
+
function decodeNumber(value) {
|
|
8
|
+
if (!value)
|
|
9
|
+
return null;
|
|
10
|
+
return JSON.parse(bytesToUtf8(value));
|
|
11
|
+
}
|
|
12
|
+
export async function getSchemaVersion(store) {
|
|
13
|
+
const raw = await store.get(META_SCHEMA_VERSION_KEY);
|
|
14
|
+
return decodeNumber(raw);
|
|
15
|
+
}
|
|
16
|
+
export async function setSchemaVersion(store, version) {
|
|
17
|
+
await store.put(META_SCHEMA_VERSION_KEY, encodeNumber(version));
|
|
18
|
+
}
|
|
19
|
+
export async function ensureSchemaVersion(store, targetVersion = DEFAULT_SCHEMA_VERSION, migrations = []) {
|
|
20
|
+
const current = (await getSchemaVersion(store)) ?? 0;
|
|
21
|
+
if (current > targetVersion) {
|
|
22
|
+
throw new Error(`Refuse downgrade schema from ${current} to ${targetVersion}`);
|
|
23
|
+
}
|
|
24
|
+
const ordered = [...migrations].sort((a, b) => a.version - b.version);
|
|
25
|
+
let latest = current;
|
|
26
|
+
for (const migration of ordered) {
|
|
27
|
+
if (migration.version <= latest) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (migration.version > targetVersion) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
await migration.up(store);
|
|
34
|
+
await setSchemaVersion(store, migration.version);
|
|
35
|
+
latest = migration.version;
|
|
36
|
+
}
|
|
37
|
+
if (latest === 0 && targetVersion === DEFAULT_SCHEMA_VERSION && ordered.length === 0) {
|
|
38
|
+
await setSchemaVersion(store, targetVersion);
|
|
39
|
+
return targetVersion;
|
|
40
|
+
}
|
|
41
|
+
if (latest < targetVersion && ordered.length === 0) {
|
|
42
|
+
await setSchemaVersion(store, targetVersion);
|
|
43
|
+
return targetVersion;
|
|
44
|
+
}
|
|
45
|
+
return (await getSchemaVersion(store)) ?? latest;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/storage/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC;AACtD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAOxC,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,YAAY,CAAC,KAAkB;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAW,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAc;IACnD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrD,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAc,EAAE,OAAe;IACpE,MAAM,KAAK,CAAC,GAAG,CAAC,uBAAuB,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAc,EACd,gBAAwB,sBAAsB,EAC9C,aAAiC,EAAE;IAEnC,MAAM,OAAO,GAAG,CAAC,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,OAAO,GAAG,aAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,OAAO,aAAa,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IACtE,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QAChC,IAAI,SAAS,CAAC,OAAO,IAAI,MAAM,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,OAAO,GAAG,aAAa,EAAE,CAAC;YACtC,MAAM;QACR,CAAC;QACD,MAAM,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM,KAAK,CAAC,IAAI,aAAa,KAAK,sBAAsB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrF,MAAM,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAC7C,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI,MAAM,GAAG,aAAa,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAC7C,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,OAAO,CAAC,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface StoragePaths {
|
|
2
|
+
root: string;
|
|
3
|
+
data: string;
|
|
4
|
+
logs: string;
|
|
5
|
+
keys: string;
|
|
6
|
+
snapshots: string;
|
|
7
|
+
eventsDb: string;
|
|
8
|
+
stateDb: string;
|
|
9
|
+
configFile: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function defaultStorageRoot(): string;
|
|
12
|
+
export declare function resolveStoragePaths(root?: string): StoragePaths;
|
|
13
|
+
export declare function ensureStorageDirs(paths: StoragePaths): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,MAA6B,GAAG,YAAY,CAgBrF;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mkdir } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
export function defaultStorageRoot() {
|
|
5
|
+
return process.env.CLAWNET_HOME ?? resolve(homedir(), '.clawnet');
|
|
6
|
+
}
|
|
7
|
+
export function resolveStoragePaths(root = defaultStorageRoot()) {
|
|
8
|
+
const data = resolve(root, 'data');
|
|
9
|
+
const logs = resolve(root, 'logs');
|
|
10
|
+
const keys = resolve(root, 'keys');
|
|
11
|
+
const snapshots = resolve(data, 'snapshots');
|
|
12
|
+
return {
|
|
13
|
+
root,
|
|
14
|
+
data,
|
|
15
|
+
logs,
|
|
16
|
+
keys,
|
|
17
|
+
snapshots,
|
|
18
|
+
eventsDb: resolve(data, 'events.db'),
|
|
19
|
+
stateDb: resolve(data, 'state.db'),
|
|
20
|
+
configFile: resolve(root, 'config.yaml'),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export async function ensureStorageDirs(paths) {
|
|
24
|
+
await mkdir(paths.root, { recursive: true });
|
|
25
|
+
await mkdir(paths.data, { recursive: true });
|
|
26
|
+
await mkdir(paths.logs, { recursive: true });
|
|
27
|
+
await mkdir(paths.keys, { recursive: true });
|
|
28
|
+
await mkdir(paths.snapshots, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/storage/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,kBAAkB,EAAE;IACrE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE7C,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,SAAS;QACT,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC;QACpC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC;QAClC,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAmB;IACzD,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventStore } from './event-store.js';
|
|
2
|
+
import { SnapshotStore } from './snapshots.js';
|
|
3
|
+
export interface SnapshotSchedulePolicy {
|
|
4
|
+
maxEvents: number;
|
|
5
|
+
maxAgeMs: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_SNAPSHOT_POLICY: SnapshotSchedulePolicy;
|
|
8
|
+
export declare class SnapshotScheduler {
|
|
9
|
+
private readonly eventStore;
|
|
10
|
+
private readonly snapshotStore;
|
|
11
|
+
private readonly policy;
|
|
12
|
+
private readonly startedAt;
|
|
13
|
+
constructor(eventStore: EventStore, snapshotStore: SnapshotStore, policy?: SnapshotSchedulePolicy);
|
|
14
|
+
shouldSnapshot(now?: number): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=snapshot-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-scheduler.d.ts","sourceRoot":"","sources":["../../src/storage/snapshot-scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,uBAAuB,EAAE,sBAGrC,CAAC;AAEF,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,EAC5B,MAAM,GAAE,sBAAgD;IAKrE,cAAc,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CA8BjE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const DEFAULT_SNAPSHOT_POLICY = {
|
|
2
|
+
maxEvents: 10_000,
|
|
3
|
+
maxAgeMs: 60 * 60 * 1000,
|
|
4
|
+
};
|
|
5
|
+
export class SnapshotScheduler {
|
|
6
|
+
eventStore;
|
|
7
|
+
snapshotStore;
|
|
8
|
+
policy;
|
|
9
|
+
startedAt;
|
|
10
|
+
constructor(eventStore, snapshotStore, policy = DEFAULT_SNAPSHOT_POLICY) {
|
|
11
|
+
this.eventStore = eventStore;
|
|
12
|
+
this.snapshotStore = snapshotStore;
|
|
13
|
+
this.policy = policy;
|
|
14
|
+
this.startedAt = Date.now();
|
|
15
|
+
}
|
|
16
|
+
async shouldSnapshot(now = Date.now()) {
|
|
17
|
+
const logLength = await this.eventStore.getLogLength();
|
|
18
|
+
if (logLength <= 0) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const latestSnapshot = await this.snapshotStore.loadLatestSnapshot();
|
|
22
|
+
if (!latestSnapshot) {
|
|
23
|
+
const ageMs = now - this.startedAt;
|
|
24
|
+
return logLength >= this.policy.maxEvents || ageMs >= this.policy.maxAgeMs;
|
|
25
|
+
}
|
|
26
|
+
const seq = await this.eventStore.getEventSeq(latestSnapshot.at);
|
|
27
|
+
if (seq !== null) {
|
|
28
|
+
const eventsSince = logLength - (seq + 1);
|
|
29
|
+
if (eventsSince >= this.policy.maxEvents) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const meta = await this.snapshotStore.loadLatestSnapshotMeta();
|
|
34
|
+
if (meta?.createdAt) {
|
|
35
|
+
const ageMs = now - Date.parse(meta.createdAt);
|
|
36
|
+
if (ageMs >= this.policy.maxAgeMs) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=snapshot-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-scheduler.js","sourceRoot":"","sources":["../../src/storage/snapshot-scheduler.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,uBAAuB,GAA2B;IAC7D,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;CACzB,CAAC;AAEF,MAAM,OAAO,iBAAiB;IAIT;IACA;IACA;IALF,SAAS,CAAS;IAEnC,YACmB,UAAsB,EACtB,aAA4B,EAC5B,SAAiC,uBAAuB;QAFxD,eAAU,GAAV,UAAU,CAAY;QACtB,kBAAa,GAAb,aAAa,CAAe;QAC5B,WAAM,GAAN,MAAM,CAAkD;QAEzE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;QAC3C,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC;QACvD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC;QACrE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;YACnC,OAAO,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC7E,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACjE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,MAAM,WAAW,GAAG,SAAS,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAC1C,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,sBAAsB,EAAE,CAAC;QAC/D,IAAI,IAAI,EAAE,SAAS,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/C,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { StoragePaths } from './paths.js';
|
|
2
|
+
export interface SnapshotSignature {
|
|
3
|
+
peer: string;
|
|
4
|
+
sig: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SnapshotRecord {
|
|
7
|
+
v: number;
|
|
8
|
+
at: string;
|
|
9
|
+
prev: string | null;
|
|
10
|
+
state: Record<string, unknown>;
|
|
11
|
+
hash: string;
|
|
12
|
+
signatures: SnapshotSignature[];
|
|
13
|
+
}
|
|
14
|
+
export declare const SNAPSHOT_DOMAIN_PREFIX = "clawnet:snapshot:v1:";
|
|
15
|
+
export declare function snapshotBody(snapshot: SnapshotRecord): {
|
|
16
|
+
v: number;
|
|
17
|
+
at: string;
|
|
18
|
+
prev: string | null;
|
|
19
|
+
state: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
export declare function snapshotHashHex(snapshot: SnapshotRecord): string;
|
|
22
|
+
export declare function snapshotSigningBytesFromHash(hash: string): Uint8Array;
|
|
23
|
+
export declare function snapshotSigningBytes(snapshot: SnapshotRecord): Uint8Array;
|
|
24
|
+
export declare function verifySnapshotHash(snapshot: SnapshotRecord): boolean;
|
|
25
|
+
export declare function signSnapshot(snapshot: SnapshotRecord, peerId: string, privateKey: Uint8Array): Promise<SnapshotRecord>;
|
|
26
|
+
export declare function verifySnapshotSignatures(snapshot: SnapshotRecord, resolvePeerPublicKey: (peerId: string) => Promise<Uint8Array | null>, options?: {
|
|
27
|
+
minSignatures?: number;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
ok: boolean;
|
|
30
|
+
validPeers: string[];
|
|
31
|
+
}>;
|
|
32
|
+
export declare class SnapshotStore {
|
|
33
|
+
private readonly dir;
|
|
34
|
+
private readonly latestFile;
|
|
35
|
+
private readonly latestMetaFile;
|
|
36
|
+
constructor(paths: StoragePaths);
|
|
37
|
+
saveSnapshot(snapshot: SnapshotRecord): Promise<void>;
|
|
38
|
+
loadSnapshot(hash: string): Promise<SnapshotRecord | null>;
|
|
39
|
+
loadSnapshotBytes(hash: string): Promise<Uint8Array | null>;
|
|
40
|
+
loadLatestSnapshot(): Promise<SnapshotRecord | null>;
|
|
41
|
+
loadLatestSnapshotBytes(): Promise<{
|
|
42
|
+
hash: string;
|
|
43
|
+
bytes: Uint8Array;
|
|
44
|
+
} | null>;
|
|
45
|
+
loadLatestSnapshotMeta(): Promise<{
|
|
46
|
+
hash: string;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
} | null>;
|
|
49
|
+
private snapshotPath;
|
|
50
|
+
private readLatestHash;
|
|
51
|
+
private findLatestSnapshotFile;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=snapshots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshots.d.ts","sourceRoot":"","sources":["../../src/storage/snapshots.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAE7D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG;IACtD,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAOA;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAGhE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAErE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,UAAU,CAEzE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAEpE;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,cAAc,EACxB,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,EACpE,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAoBhD;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,KAAK,EAAE,YAAY;IAMzB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAY1D,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU3D,kBAAkB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAYpD,uBAAuB,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IAoB9E,sBAAsB,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAwBnF,OAAO,CAAC,YAAY;YAIN,cAAc;YAUd,sBAAsB;CAqBrC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { canonicalizeBytes } from '../crypto/jcs.js';
|
|
4
|
+
import { sha256Hex } from '../crypto/hash.js';
|
|
5
|
+
import { signBase58, verifyBase58 } from '../crypto/ed25519.js';
|
|
6
|
+
import { concatBytes, utf8ToBytes, bytesToUtf8 } from '../utils/bytes.js';
|
|
7
|
+
export const SNAPSHOT_DOMAIN_PREFIX = 'clawnet:snapshot:v1:';
|
|
8
|
+
export function snapshotBody(snapshot) {
|
|
9
|
+
return {
|
|
10
|
+
v: snapshot.v,
|
|
11
|
+
at: snapshot.at,
|
|
12
|
+
prev: snapshot.prev,
|
|
13
|
+
state: snapshot.state,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function snapshotHashHex(snapshot) {
|
|
17
|
+
const canonical = canonicalizeBytes(snapshotBody(snapshot));
|
|
18
|
+
return sha256Hex(canonical);
|
|
19
|
+
}
|
|
20
|
+
export function snapshotSigningBytesFromHash(hash) {
|
|
21
|
+
return concatBytes(utf8ToBytes(SNAPSHOT_DOMAIN_PREFIX), utf8ToBytes(hash));
|
|
22
|
+
}
|
|
23
|
+
export function snapshotSigningBytes(snapshot) {
|
|
24
|
+
return snapshotSigningBytesFromHash(snapshotHashHex(snapshot));
|
|
25
|
+
}
|
|
26
|
+
export function verifySnapshotHash(snapshot) {
|
|
27
|
+
return snapshot.hash === snapshotHashHex(snapshot);
|
|
28
|
+
}
|
|
29
|
+
export async function signSnapshot(snapshot, peerId, privateKey) {
|
|
30
|
+
const hash = snapshotHashHex(snapshot);
|
|
31
|
+
const sig = await signBase58(snapshotSigningBytesFromHash(hash), privateKey);
|
|
32
|
+
const signatures = [...(snapshot.signatures ?? []), { peer: peerId, sig }];
|
|
33
|
+
return {
|
|
34
|
+
...snapshot,
|
|
35
|
+
hash,
|
|
36
|
+
signatures,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function verifySnapshotSignatures(snapshot, resolvePeerPublicKey, options = {}) {
|
|
40
|
+
const minSignatures = options.minSignatures ?? 1;
|
|
41
|
+
const signingBytes = snapshotSigningBytesFromHash(snapshot.hash);
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
const validPeers = [];
|
|
44
|
+
for (const entry of snapshot.signatures ?? []) {
|
|
45
|
+
if (!entry?.peer || !entry?.sig || seen.has(entry.peer)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const publicKey = await resolvePeerPublicKey(entry.peer);
|
|
49
|
+
if (!publicKey) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const ok = await verifyBase58(entry.sig, signingBytes, publicKey);
|
|
53
|
+
if (ok) {
|
|
54
|
+
seen.add(entry.peer);
|
|
55
|
+
validPeers.push(entry.peer);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { ok: validPeers.length >= minSignatures, validPeers };
|
|
59
|
+
}
|
|
60
|
+
export class SnapshotStore {
|
|
61
|
+
dir;
|
|
62
|
+
latestFile;
|
|
63
|
+
latestMetaFile;
|
|
64
|
+
constructor(paths) {
|
|
65
|
+
this.dir = paths.snapshots;
|
|
66
|
+
this.latestFile = join(this.dir, 'latest');
|
|
67
|
+
this.latestMetaFile = join(this.dir, 'latest.meta.json');
|
|
68
|
+
}
|
|
69
|
+
async saveSnapshot(snapshot) {
|
|
70
|
+
await mkdir(this.dir, { recursive: true });
|
|
71
|
+
const path = this.snapshotPath(snapshot.hash);
|
|
72
|
+
await writeFile(path, JSON.stringify(snapshot), 'utf8');
|
|
73
|
+
await writeFile(this.latestFile, snapshot.hash, 'utf8');
|
|
74
|
+
const meta = {
|
|
75
|
+
hash: snapshot.hash,
|
|
76
|
+
createdAt: new Date().toISOString(),
|
|
77
|
+
};
|
|
78
|
+
await writeFile(this.latestMetaFile, JSON.stringify(meta), 'utf8');
|
|
79
|
+
}
|
|
80
|
+
async loadSnapshot(hash) {
|
|
81
|
+
const bytes = await this.loadSnapshotBytes(hash);
|
|
82
|
+
if (!bytes) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(bytesToUtf8(bytes));
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async loadSnapshotBytes(hash) {
|
|
93
|
+
try {
|
|
94
|
+
const path = this.snapshotPath(hash);
|
|
95
|
+
const buffer = await readFile(path);
|
|
96
|
+
return new Uint8Array(buffer);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async loadLatestSnapshot() {
|
|
103
|
+
const latest = await this.loadLatestSnapshotBytes();
|
|
104
|
+
if (!latest) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(bytesToUtf8(latest.bytes));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async loadLatestSnapshotBytes() {
|
|
115
|
+
const hash = await this.readLatestHash();
|
|
116
|
+
if (hash) {
|
|
117
|
+
const bytes = await this.loadSnapshotBytes(hash);
|
|
118
|
+
if (bytes) {
|
|
119
|
+
return { hash, bytes };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const fallback = await this.findLatestSnapshotFile();
|
|
123
|
+
if (!fallback) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const bytes = await this.loadSnapshotBytes(fallback);
|
|
127
|
+
if (!bytes) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return { hash: fallback, bytes };
|
|
131
|
+
}
|
|
132
|
+
async loadLatestSnapshotMeta() {
|
|
133
|
+
try {
|
|
134
|
+
const raw = await readFile(this.latestMetaFile, 'utf8');
|
|
135
|
+
const parsed = JSON.parse(raw);
|
|
136
|
+
if (parsed.hash && parsed.createdAt) {
|
|
137
|
+
return { hash: parsed.hash, createdAt: parsed.createdAt };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// ignore
|
|
142
|
+
}
|
|
143
|
+
const latest = await this.findLatestSnapshotFile();
|
|
144
|
+
if (!latest) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const path = this.snapshotPath(latest);
|
|
149
|
+
const stats = await stat(path);
|
|
150
|
+
return { hash: latest, createdAt: new Date(stats.mtimeMs).toISOString() };
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
snapshotPath(hash) {
|
|
157
|
+
return join(this.dir, `${hash}.json`);
|
|
158
|
+
}
|
|
159
|
+
async readLatestHash() {
|
|
160
|
+
try {
|
|
161
|
+
const buffer = await readFile(this.latestFile);
|
|
162
|
+
const value = bytesToUtf8(new Uint8Array(buffer)).trim();
|
|
163
|
+
return value.length ? value : null;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async findLatestSnapshotFile() {
|
|
170
|
+
try {
|
|
171
|
+
const entries = await readdir(this.dir);
|
|
172
|
+
let latestHash = null;
|
|
173
|
+
let latestMtime = 0;
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
if (!entry.endsWith('.json')) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const path = join(this.dir, entry);
|
|
179
|
+
const stats = await stat(path);
|
|
180
|
+
if (stats.mtimeMs > latestMtime) {
|
|
181
|
+
latestMtime = stats.mtimeMs;
|
|
182
|
+
latestHash = entry.slice(0, -'.json'.length);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return latestHash;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=snapshots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshots.js","sourceRoot":"","sources":["../../src/storage/snapshots.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { KVStore } from './kv.js';
|
|
2
|
+
export interface ModuleStateRecord<T = unknown> {
|
|
3
|
+
at: string | null;
|
|
4
|
+
state: T;
|
|
5
|
+
}
|
|
6
|
+
export declare class StateStore {
|
|
7
|
+
private readonly store;
|
|
8
|
+
constructor(store: KVStore);
|
|
9
|
+
getModuleState<T = unknown>(module: string): Promise<ModuleStateRecord<T> | null>;
|
|
10
|
+
setModuleState<T = unknown>(module: string, state: T, at: string | null): Promise<void>;
|
|
11
|
+
deleteModuleState(module: string): Promise<void>;
|
|
12
|
+
listModules(): Promise<string[]>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=state-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/storage/state-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIlC,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO;IAC5C,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,CAAC,CAAC;CACV;AAWD,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,OAAO;IAErC,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAQjF,cAAc,CAAC,CAAC,GAAG,OAAO,EAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,EACR,EAAE,EAAE,MAAM,GAAG,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC;IAKV,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAOvC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { bytesToUtf8, utf8ToBytes } from '../utils/bytes.js';
|
|
2
|
+
const PREFIX_STATE = 'st:';
|
|
3
|
+
function encodeJson(value) {
|
|
4
|
+
return utf8ToBytes(JSON.stringify(value));
|
|
5
|
+
}
|
|
6
|
+
function decodeJson(value, fallback) {
|
|
7
|
+
if (!value)
|
|
8
|
+
return fallback;
|
|
9
|
+
return JSON.parse(bytesToUtf8(value));
|
|
10
|
+
}
|
|
11
|
+
export class StateStore {
|
|
12
|
+
store;
|
|
13
|
+
constructor(store) {
|
|
14
|
+
this.store = store;
|
|
15
|
+
}
|
|
16
|
+
async getModuleState(module) {
|
|
17
|
+
const value = await this.store.get(`${PREFIX_STATE}${module}`);
|
|
18
|
+
if (!value) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return decodeJson(value, null);
|
|
22
|
+
}
|
|
23
|
+
async setModuleState(module, state, at) {
|
|
24
|
+
const record = { at, state };
|
|
25
|
+
await this.store.put(`${PREFIX_STATE}${module}`, encodeJson(record));
|
|
26
|
+
}
|
|
27
|
+
async deleteModuleState(module) {
|
|
28
|
+
await this.store.del(`${PREFIX_STATE}${module}`);
|
|
29
|
+
}
|
|
30
|
+
async listModules() {
|
|
31
|
+
const modules = [];
|
|
32
|
+
for await (const { key } of this.store.iterator(PREFIX_STATE)) {
|
|
33
|
+
modules.push(key.slice(PREFIX_STATE.length));
|
|
34
|
+
}
|
|
35
|
+
return modules;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=state-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-store.js","sourceRoot":"","sources":["../../src/storage/state-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG7D,MAAM,YAAY,GAAG,KAAK,CAAC;AAO3B,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU,CAAI,KAA6B,EAAE,QAAW;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAM,CAAC;AAC7C,CAAC;AAED,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,KAAc;QAAd,UAAK,GAAL,KAAK,CAAS;IAAG,CAAC;IAE/C,KAAK,CAAC,cAAc,CAAc,MAAc;QAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,MAAM,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,UAAU,CAAC,KAAK,EAAE,IAAmC,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,MAAc,EACd,KAAQ,EACR,EAAiB;QAEjB,MAAM,MAAM,GAAyB,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QACnD,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,MAAM,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAAc;QACpC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromiseWithResolvers.d.ts","sourceRoot":"","sources":["../../src/utils/PromiseWithResolvers.ts"],"names":[],"mappings":""}
|