@totemsdk/wots-lease 1.0.1 → 1.0.2

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.
Files changed (55) hide show
  1. package/LICENSE +202 -21
  2. package/NOTICE +60 -0
  3. package/dist/axia.js +21 -25
  4. package/dist/certificate.js +7 -12
  5. package/dist/cjs/axia.d.ts +33 -0
  6. package/dist/cjs/axia.js +145 -0
  7. package/dist/cjs/certificate.d.ts +37 -0
  8. package/dist/cjs/certificate.js +74 -0
  9. package/dist/cjs/device.d.ts +18 -0
  10. package/dist/cjs/device.js +34 -0
  11. package/dist/cjs/errors.d.ts +71 -0
  12. package/dist/cjs/errors.js +135 -0
  13. package/dist/cjs/hybrid.d.ts +37 -0
  14. package/dist/cjs/hybrid.js +145 -0
  15. package/dist/cjs/index.d.ts +17 -0
  16. package/dist/cjs/index.js +45 -0
  17. package/dist/cjs/journal.d.ts +30 -0
  18. package/dist/cjs/journal.js +369 -0
  19. package/dist/cjs/local.d.ts +83 -0
  20. package/dist/cjs/local.js +440 -0
  21. package/dist/cjs/onchain.d.ts +54 -0
  22. package/dist/cjs/onchain.js +314 -0
  23. package/dist/cjs/package.json +1 -0
  24. package/dist/cjs/quorum.d.ts +75 -0
  25. package/dist/cjs/quorum.js +307 -0
  26. package/dist/cjs/replicated-backup.d.ts +30 -0
  27. package/dist/cjs/replicated-backup.js +52 -0
  28. package/dist/cjs/seed.d.ts +41 -0
  29. package/dist/cjs/seed.js +84 -0
  30. package/dist/cjs/stubs.d.ts +50 -0
  31. package/dist/cjs/stubs.js +125 -0
  32. package/dist/cjs/types.d.ts +272 -0
  33. package/dist/cjs/types.js +5 -0
  34. package/dist/cjs/watermark.d.ts +51 -0
  35. package/dist/cjs/watermark.js +328 -0
  36. package/dist/device.js +2 -6
  37. package/dist/errors.js +14 -31
  38. package/dist/hybrid.js +4 -8
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +12 -43
  41. package/dist/journal.js +35 -38
  42. package/dist/local.js +29 -33
  43. package/dist/onchain.js +23 -27
  44. package/dist/quorum.js +9 -13
  45. package/dist/replicated-backup.d.ts +30 -0
  46. package/dist/replicated-backup.js +48 -0
  47. package/dist/seed.js +7 -11
  48. package/dist/stubs.js +5 -11
  49. package/dist/types.js +1 -2
  50. package/dist/watermark.js +11 -18
  51. package/package.json +22 -13
  52. package/rust/pkg/package.json +2 -2
  53. package/rust/pkg/wots_lease_wasm_bg.wasm +0 -0
  54. package/rust/pkg-node/package.json +2 -2
  55. package/rust/pkg-node/wots_lease_wasm_bg.wasm +0 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * RFC-057 — replicated WOTS lease-journal backup.
3
+ *
4
+ * The local `LeaseJournal` remains authoritative for allocation. This adapter
5
+ * mirrors the physically append-only journal into a replicated log for audit
6
+ * and disaster recovery, and restores entries into a local journal in order.
7
+ * It never allocates or advances a signing slot.
8
+ */
9
+ import type { ReplicatedLog } from '@totemsdk/replication';
10
+ import type { JournalEntry } from './types.js';
11
+ export interface LeaseJournalRestoreTarget {
12
+ append(entry: JournalEntry): Promise<void>;
13
+ }
14
+ export declare class ReplicatedLeaseJournalBackup {
15
+ private readonly log;
16
+ constructor(log: ReplicatedLog<JournalEntry>);
17
+ /** Mirror one local journal entry. */
18
+ append(entry: JournalEntry): Promise<{
19
+ length: number;
20
+ head: string;
21
+ }>;
22
+ /** Read all mirrored entries, verifying the local hash-chain links in order. */
23
+ readAll(): Promise<JournalEntry[]>;
24
+ /**
25
+ * Restore into a local journal. The local journal's own duplicate-slot and
26
+ * reservation checks remain the final guard; this method only preserves the
27
+ * replicated order and links.
28
+ */
29
+ restoreInto(target: LeaseJournalRestoreTarget): Promise<number>;
30
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * RFC-057 — replicated WOTS lease-journal backup.
3
+ *
4
+ * The local `LeaseJournal` remains authoritative for allocation. This adapter
5
+ * mirrors the physically append-only journal into a replicated log for audit
6
+ * and disaster recovery, and restores entries into a local journal in order.
7
+ * It never allocates or advances a signing slot.
8
+ */
9
+ import { StorageError } from '@totemsdk/storage/errors';
10
+ export class ReplicatedLeaseJournalBackup {
11
+ constructor(log) {
12
+ this.log = log;
13
+ }
14
+ /** Mirror one local journal entry. */
15
+ async append(entry) {
16
+ return this.log.append(entry);
17
+ }
18
+ /** Read all mirrored entries, verifying the local hash-chain links in order. */
19
+ async readAll() {
20
+ const entries = [];
21
+ for await (const entry of this.log.readSince())
22
+ entries.push(entry.record);
23
+ let previous;
24
+ for (const [index, entry] of entries.entries()) {
25
+ if (index === 0) {
26
+ if (entry.previousHash !== undefined) {
27
+ throw new StorageError('replicated lease journal first entry has previousHash', 'corrupt');
28
+ }
29
+ }
30
+ else if (entry.previousHash !== previous?.hash) {
31
+ throw new StorageError(`replicated lease journal chain mismatch at ${index}`, 'corrupt');
32
+ }
33
+ previous = entry;
34
+ }
35
+ return entries;
36
+ }
37
+ /**
38
+ * Restore into a local journal. The local journal's own duplicate-slot and
39
+ * reservation checks remain the final guard; this method only preserves the
40
+ * replicated order and links.
41
+ */
42
+ async restoreInto(target) {
43
+ const entries = await this.readAll();
44
+ for (const entry of entries)
45
+ await target.append(entry);
46
+ return entries.length;
47
+ }
48
+ }
package/dist/seed.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @module @totemsdk/wots-lease/seed
4
3
  *
@@ -13,13 +12,10 @@
13
12
  * If none is available and the caller has not declared the keyspace fresh,
14
13
  * seeding **fails closed** — starting at 0 would reissue spent leaves.
15
14
  */
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.seedLeaseWatermark = seedLeaseWatermark;
18
- exports.exportLeaseWatermark = exportLeaseWatermark;
19
- const watermark_js_1 = require("./watermark.js");
20
- const errors_js_1 = require("./errors.js");
15
+ import { flatIndex, fromFlatIndex } from './watermark.js';
16
+ import { WatermarkSeedRequiredError } from './errors.js';
21
17
  function flatOf(w) {
22
- return (0, watermark_js_1.flatIndex)({ addressIndex: w.addressCursor, l1: w.l1Cursor, l2: w.l2Cursor });
18
+ return flatIndex({ addressIndex: w.addressCursor, l1: w.l1Cursor, l2: w.l2Cursor });
23
19
  }
24
20
  /**
25
21
  * Seed a local watermark from the best available source, requiring at least one
@@ -30,7 +26,7 @@ function flatOf(w) {
30
26
  * @throws {WatermarkSeedRegressionError} when a supplied seed is behind the
31
27
  * current cursor.
32
28
  */
33
- async function seedLeaseWatermark(params) {
29
+ export async function seedLeaseWatermark(params) {
34
30
  const { local, treeId } = params;
35
31
  // 1. On-chain cursor — advances the same local watermark (monotonic).
36
32
  if (params.onchain) {
@@ -53,7 +49,7 @@ async function seedLeaseWatermark(params) {
53
49
  }
54
50
  // 3. Operator high-water mark.
55
51
  if (params.operatorHighWaterMark !== undefined) {
56
- const indices = (0, watermark_js_1.fromFlatIndex)(params.operatorHighWaterMark);
52
+ const indices = fromFlatIndex(params.operatorHighWaterMark);
57
53
  const candidate = {
58
54
  version: 1,
59
55
  treeId,
@@ -74,11 +70,11 @@ async function seedLeaseWatermark(params) {
74
70
  !params.exported &&
75
71
  params.operatorHighWaterMark === undefined &&
76
72
  !params.fresh) {
77
- throw new errors_js_1.WatermarkSeedRequiredError(treeId);
73
+ throw new WatermarkSeedRequiredError(treeId);
78
74
  }
79
75
  return local.getLocalWatermark(treeId);
80
76
  }
81
77
  /** Export a portable watermark blob for backup/restore. */
82
- function exportLeaseWatermark(local, treeId) {
78
+ export function exportLeaseWatermark(local, treeId) {
83
79
  return local.exportWatermark(treeId);
84
80
  }
package/dist/stubs.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Implementations for Layers 3–5 of the WotsLeaseProvider hierarchy.
4
3
  *
@@ -9,13 +8,9 @@
9
8
  * Layers 4–5 (P2PQuorumLeaseProvider, OnchainWatermarkProvider) — implemented in
10
9
  * quorum.ts and onchain.ts; re-exported here for backward compatibility.
11
10
  */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.PersonalLeaseNodeProvider = exports.OnchainWatermarkProvider = exports.P2PQuorumLeaseProvider = void 0;
14
- const certificate_js_1 = require("./certificate.js");
15
- var quorum_js_1 = require("./quorum.js");
16
- Object.defineProperty(exports, "P2PQuorumLeaseProvider", { enumerable: true, get: function () { return quorum_js_1.P2PQuorumLeaseProvider; } });
17
- var onchain_js_1 = require("./onchain.js");
18
- Object.defineProperty(exports, "OnchainWatermarkProvider", { enumerable: true, get: function () { return onchain_js_1.OnchainWatermarkProvider; } });
11
+ import { certificateSignatureVerified } from './certificate.js';
12
+ export { P2PQuorumLeaseProvider } from './quorum.js';
13
+ export { OnchainWatermarkProvider } from './onchain.js';
19
14
  /**
20
15
  * Layer 3 — personal lookup-node lease coordinator.
21
16
  *
@@ -35,7 +30,7 @@ Object.defineProperty(exports, "OnchainWatermarkProvider", { enumerable: true, g
35
30
  * });
36
31
  * ```
37
32
  */
38
- class PersonalLeaseNodeProvider {
33
+ export class PersonalLeaseNodeProvider {
39
34
  constructor(config) {
40
35
  this.baseUrl = config.nodeUrl.replace(/\/$/, '');
41
36
  this.nodePubkey = config.nodePubkey;
@@ -119,7 +114,6 @@ class PersonalLeaseNodeProvider {
119
114
  verify: this.verify,
120
115
  }
121
116
  : undefined;
122
- return (0, certificate_js_1.certificateSignatureVerified)(cert, signer);
117
+ return certificateSignatureVerified(cert, signer);
123
118
  }
124
119
  }
125
- exports.PersonalLeaseNodeProvider = PersonalLeaseNodeProvider;
package/dist/types.js CHANGED
@@ -1,5 +1,4 @@
1
- "use strict";
2
1
  /**
3
2
  * @totemsdk/wots-lease — canonical v3 watermark types and WotsLeaseProvider interface
4
3
  */
5
- Object.defineProperty(exports, "__esModule", { value: true });
4
+ export {};
package/dist/watermark.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * WotsWatermarkStore — canonical v3 implementation
4
3
  *
@@ -7,22 +6,17 @@
7
6
  * - Enforces monotonicity: unavailable map can only grow, cursors can only advance.
8
7
  * - Storage key unchanged ('totem_wots_watermark') to avoid storage churn.
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.WotsWatermarkStore = void 0;
12
- exports.flatIndex = flatIndex;
13
- exports.fromFlatIndex = fromFlatIndex;
14
- exports.assertValidSigningIndices = assertValidSigningIndices;
15
- const core_1 = require("@totemsdk/core");
16
- const errors_js_1 = require("./errors.js");
9
+ import { NoopLogger } from '@totemsdk/core';
10
+ import { WatermarkMonotonicityError, WatermarkExhaustedError, WatermarkSeedRegressionError, } from './errors.js';
17
11
  const STORAGE_KEY = 'totem_wots_watermark';
18
12
  const MAX_L = 64;
19
13
  const CAPACITY_PER_TREE = MAX_L * MAX_L * MAX_L;
20
14
  const DEFAULT_TREE = 'default';
21
- function flatIndex(idx) {
15
+ export function flatIndex(idx) {
22
16
  assertValidSigningIndices(idx);
23
17
  return idx.addressIndex * MAX_L * MAX_L + idx.l1 * MAX_L + idx.l2;
24
18
  }
25
- function fromFlatIndex(flat) {
19
+ export function fromFlatIndex(flat) {
26
20
  if (!Number.isSafeInteger(flat) || flat < 0 || flat >= CAPACITY_PER_TREE) {
27
21
  throw new RangeError(`WOTS flat index must be an integer in [0, ${CAPACITY_PER_TREE - 1}]`);
28
22
  }
@@ -32,7 +26,7 @@ function fromFlatIndex(flat) {
32
26
  const l2 = rem % MAX_L;
33
27
  return { addressIndex, l1, l2 };
34
28
  }
35
- function assertValidSigningIndices(indices) {
29
+ export function assertValidSigningIndices(indices) {
36
30
  for (const name of ['addressIndex', 'l1', 'l2']) {
37
31
  const value = indices[name];
38
32
  if (!Number.isSafeInteger(value) || value < 0 || value >= MAX_L) {
@@ -131,8 +125,8 @@ function migrateToV3(raw) {
131
125
  tree.l2Cursor = v1.next_l2 ?? 0;
132
126
  return { version: 3, trees: { [DEFAULT_TREE]: tree } };
133
127
  }
134
- class WotsWatermarkStore {
135
- constructor(storage, logger = new core_1.NoopLogger()) {
128
+ export class WotsWatermarkStore {
129
+ constructor(storage, logger = new NoopLogger()) {
136
130
  this.storage = storage;
137
131
  this.state = null;
138
132
  this._initialized = false;
@@ -194,7 +188,7 @@ class WotsWatermarkStore {
194
188
  cur = nxt;
195
189
  attempts++;
196
190
  }
197
- throw new errors_js_1.WatermarkExhaustedError(treeId);
191
+ throw new WatermarkExhaustedError(treeId);
198
192
  }
199
193
  async markUnavailable(treeId, indices, reason) {
200
194
  const tree = this.getOrCreateTree(treeId);
@@ -232,12 +226,12 @@ class WotsWatermarkStore {
232
226
  const existingFlat = flatIndex({ addressIndex: existing.addressCursor, l1: existing.l1Cursor, l2: existing.l2Cursor });
233
227
  const newFlat = flatIndex({ addressIndex: merged.addressCursor, l1: merged.l1Cursor, l2: merged.l2Cursor });
234
228
  if (newFlat < existingFlat) {
235
- throw new errors_js_1.WatermarkMonotonicityError(`Cannot decrease watermark cursor for ${treeId}: ${existingFlat} → ${newFlat}`);
229
+ throw new WatermarkMonotonicityError(`Cannot decrease watermark cursor for ${treeId}: ${existingFlat} → ${newFlat}`);
236
230
  }
237
231
  const existingUnavailCount = Object.keys(existing.unavailable).length;
238
232
  const newUnavailCount = Object.keys(merged.unavailable).length;
239
233
  if (newUnavailCount < existingUnavailCount) {
240
- throw new errors_js_1.WatermarkMonotonicityError(`Cannot shrink unavailable map for ${treeId}: ${existingUnavailCount} → ${newUnavailCount}`);
234
+ throw new WatermarkMonotonicityError(`Cannot shrink unavailable map for ${treeId}: ${existingUnavailCount} → ${newUnavailCount}`);
241
235
  }
242
236
  s.trees[treeId] = merged;
243
237
  await this.persist();
@@ -295,7 +289,7 @@ class WotsWatermarkStore {
295
289
  l2: existing.l2Cursor,
296
290
  });
297
291
  if (!options.allowRegression && seedCursor < existingCursor) {
298
- throw new errors_js_1.WatermarkSeedRegressionError(seed.treeId, existingCursor, seedCursor);
292
+ throw new WatermarkSeedRegressionError(seed.treeId, existingCursor, seedCursor);
299
293
  }
300
294
  const unavailable = { ...existing.unavailable };
301
295
  for (const flat of seed.unavailable ?? []) {
@@ -325,4 +319,3 @@ class WotsWatermarkStore {
325
319
  await this.storage.remove(STORAGE_KEY);
326
320
  }
327
321
  }
328
- exports.WotsWatermarkStore = WotsWatermarkStore;
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "@totemsdk/wots-lease",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "WOTS key-use coordination — canonical v3 watermark, provider-based lease safety layers",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "dist/cjs/index.js",
6
+ "types": "dist/cjs/index.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
- "types": "./dist/index.d.ts",
10
- "require": "./dist/index.js",
11
- "import": "./dist/index.js"
9
+ "import": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "require": {
14
+ "types": "./dist/cjs/index.d.ts",
15
+ "default": "./dist/cjs/index.js"
16
+ }
12
17
  }
13
18
  },
14
19
  "files": [
@@ -16,13 +21,16 @@
16
21
  "rust/pkg/",
17
22
  "rust/pkg-node/",
18
23
  "README.md",
19
- "LICENSE"
24
+ "LICENSE",
25
+ "NOTICE"
20
26
  ],
21
27
  "dependencies": {
22
- "@totemsdk/core": "^1.2.11",
23
- "@totemsdk/lookup-protocol": "^0.2.0",
24
- "@totemsdk/txpow": "^1.0.2",
25
- "@totemsdk/storage": "^0.1.0"
28
+ "@noble/hashes": "^1.8.0",
29
+ "@totemsdk/core": "^1.4.2",
30
+ "@totemsdk/txpow": "^1.1.1",
31
+ "@totemsdk/replication": "^0.2.0",
32
+ "@totemsdk/lookup-protocol": "^0.3.0",
33
+ "@totemsdk/storage": "^0.2.2"
26
34
  },
27
35
  "devDependencies": {
28
36
  "@types/jest": "^30.0.0",
@@ -37,7 +45,7 @@
37
45
  "publishConfig": {
38
46
  "access": "public"
39
47
  },
40
- "license": "MIT",
48
+ "license": "Apache-2.0",
41
49
  "author": "Totem SDK",
42
50
  "homepage": "https://docs.totem.ing",
43
51
  "bugs": {
@@ -57,8 +65,9 @@
57
65
  "wots",
58
66
  "utxo"
59
67
  ],
68
+ "type": "module",
60
69
  "scripts": {
61
- "build": "npm run build:wasm && tsc && node ../../scripts/clean-wasm-output-ignores.mjs",
70
+ "build": "tsc && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'})+'\\n')\"",
62
71
  "build:wasm": "cd rust && wasm-pack build --target bundler --out-dir pkg && wasm-pack build --target nodejs --out-dir pkg-node",
63
72
  "clean": "rm -rf dist rust/pkg rust/pkg-node rust/target",
64
73
  "test": "jest"
@@ -6,7 +6,7 @@
6
6
  ],
7
7
  "description": "WOTS key-use coordination — canonical v3 watermark, flat index computation, monotonicity enforcement, device keyspace partitioning (Rust/WASM)",
8
8
  "version": "0.1.0",
9
- "license": "MIT",
9
+ "license": "Apache-2.0",
10
10
  "repository": {
11
11
  "type": "git",
12
12
  "url": "https://github.com/Totem-Edge/totem-sdk"
@@ -24,4 +24,4 @@
24
24
  "./wots_lease_wasm.js",
25
25
  "./snippets/*"
26
26
  ]
27
- }
27
+ }
Binary file
@@ -5,7 +5,7 @@
5
5
  ],
6
6
  "description": "WOTS key-use coordination — canonical v3 watermark, flat index computation, monotonicity enforcement, device keyspace partitioning (Rust/WASM)",
7
7
  "version": "0.1.0",
8
- "license": "MIT",
8
+ "license": "Apache-2.0",
9
9
  "repository": {
10
10
  "type": "git",
11
11
  "url": "https://github.com/Totem-Edge/totem-sdk"
@@ -18,4 +18,4 @@
18
18
  "main": "wots_lease_wasm.js",
19
19
  "homepage": "https://totem.ing",
20
20
  "types": "wots_lease_wasm.d.ts"
21
- }
21
+ }