@hashtree/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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bep52.d.ts +179 -0
  3. package/dist/bep52.d.ts.map +1 -0
  4. package/dist/bep52.js +384 -0
  5. package/dist/bep52.js.map +1 -0
  6. package/dist/builder.d.ts +137 -0
  7. package/dist/builder.d.ts.map +1 -0
  8. package/dist/builder.js +281 -0
  9. package/dist/builder.js.map +1 -0
  10. package/dist/codec.d.ts +37 -0
  11. package/dist/codec.d.ts.map +1 -0
  12. package/dist/codec.js +109 -0
  13. package/dist/codec.js.map +1 -0
  14. package/dist/crypto.d.ts +92 -0
  15. package/dist/crypto.d.ts.map +1 -0
  16. package/dist/crypto.js +212 -0
  17. package/dist/crypto.js.map +1 -0
  18. package/dist/encrypted.d.ts +114 -0
  19. package/dist/encrypted.d.ts.map +1 -0
  20. package/dist/encrypted.js +446 -0
  21. package/dist/encrypted.js.map +1 -0
  22. package/dist/hash.d.ts +14 -0
  23. package/dist/hash.d.ts.map +1 -0
  24. package/dist/hash.js +27 -0
  25. package/dist/hash.js.map +1 -0
  26. package/dist/hashtree.d.ts +237 -0
  27. package/dist/hashtree.d.ts.map +1 -0
  28. package/dist/hashtree.js +557 -0
  29. package/dist/hashtree.js.map +1 -0
  30. package/dist/index.d.ts +27 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +44 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/nhash.d.ts +94 -0
  35. package/dist/nhash.d.ts.map +1 -0
  36. package/dist/nhash.js +293 -0
  37. package/dist/nhash.js.map +1 -0
  38. package/dist/resolver/index.d.ts +5 -0
  39. package/dist/resolver/index.d.ts.map +1 -0
  40. package/dist/resolver/index.js +5 -0
  41. package/dist/resolver/index.js.map +1 -0
  42. package/dist/resolver/nostr.d.ts +82 -0
  43. package/dist/resolver/nostr.d.ts.map +1 -0
  44. package/dist/resolver/nostr.js +868 -0
  45. package/dist/resolver/nostr.js.map +1 -0
  46. package/dist/store/blossom.d.ts +100 -0
  47. package/dist/store/blossom.d.ts.map +1 -0
  48. package/dist/store/blossom.js +355 -0
  49. package/dist/store/blossom.js.map +1 -0
  50. package/dist/store/dexie.d.ts +44 -0
  51. package/dist/store/dexie.d.ts.map +1 -0
  52. package/dist/store/dexie.js +196 -0
  53. package/dist/store/dexie.js.map +1 -0
  54. package/dist/store/fallback.d.ts +40 -0
  55. package/dist/store/fallback.d.ts.map +1 -0
  56. package/dist/store/fallback.js +71 -0
  57. package/dist/store/fallback.js.map +1 -0
  58. package/dist/store/index.d.ts +6 -0
  59. package/dist/store/index.d.ts.map +1 -0
  60. package/dist/store/index.js +6 -0
  61. package/dist/store/index.js.map +1 -0
  62. package/dist/store/memory.d.ts +29 -0
  63. package/dist/store/memory.d.ts.map +1 -0
  64. package/dist/store/memory.js +66 -0
  65. package/dist/store/memory.js.map +1 -0
  66. package/dist/store/opfs.d.ts +56 -0
  67. package/dist/store/opfs.d.ts.map +1 -0
  68. package/dist/store/opfs.js +200 -0
  69. package/dist/store/opfs.js.map +1 -0
  70. package/dist/streaming.d.ts +74 -0
  71. package/dist/streaming.d.ts.map +1 -0
  72. package/dist/streaming.js +199 -0
  73. package/dist/streaming.js.map +1 -0
  74. package/dist/tree/create.d.ts +35 -0
  75. package/dist/tree/create.d.ts.map +1 -0
  76. package/dist/tree/create.js +90 -0
  77. package/dist/tree/create.js.map +1 -0
  78. package/dist/tree/edit.d.ts +28 -0
  79. package/dist/tree/edit.d.ts.map +1 -0
  80. package/dist/tree/edit.js +115 -0
  81. package/dist/tree/edit.js.map +1 -0
  82. package/dist/tree/editEncrypted.d.ts +46 -0
  83. package/dist/tree/editEncrypted.d.ts.map +1 -0
  84. package/dist/tree/editEncrypted.js +225 -0
  85. package/dist/tree/editEncrypted.js.map +1 -0
  86. package/dist/tree/index.d.ts +7 -0
  87. package/dist/tree/index.d.ts.map +1 -0
  88. package/dist/tree/index.js +7 -0
  89. package/dist/tree/index.js.map +1 -0
  90. package/dist/tree/read.d.ts +75 -0
  91. package/dist/tree/read.d.ts.map +1 -0
  92. package/dist/tree/read.js +389 -0
  93. package/dist/tree/read.js.map +1 -0
  94. package/dist/tree/writeAt.d.ts +44 -0
  95. package/dist/tree/writeAt.d.ts.map +1 -0
  96. package/dist/tree/writeAt.js +282 -0
  97. package/dist/tree/writeAt.js.map +1 -0
  98. package/dist/types.d.ts +274 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +47 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/verify.d.ts +12 -0
  103. package/dist/verify.d.ts.map +1 -0
  104. package/dist/verify.js +32 -0
  105. package/dist/verify.js.map +1 -0
  106. package/dist/visibility.d.ts +50 -0
  107. package/dist/visibility.d.ts.map +1 -0
  108. package/dist/visibility.js +111 -0
  109. package/dist/visibility.js.map +1 -0
  110. package/dist/webrtc/index.d.ts +4 -0
  111. package/dist/webrtc/index.d.ts.map +1 -0
  112. package/dist/webrtc/index.js +4 -0
  113. package/dist/webrtc/index.js.map +1 -0
  114. package/dist/webrtc/lruCache.d.ts +20 -0
  115. package/dist/webrtc/lruCache.d.ts.map +1 -0
  116. package/dist/webrtc/lruCache.js +59 -0
  117. package/dist/webrtc/lruCache.js.map +1 -0
  118. package/dist/webrtc/peer.d.ts +122 -0
  119. package/dist/webrtc/peer.d.ts.map +1 -0
  120. package/dist/webrtc/peer.js +583 -0
  121. package/dist/webrtc/peer.js.map +1 -0
  122. package/dist/webrtc/protocol.d.ts +76 -0
  123. package/dist/webrtc/protocol.d.ts.map +1 -0
  124. package/dist/webrtc/protocol.js +167 -0
  125. package/dist/webrtc/protocol.js.map +1 -0
  126. package/dist/webrtc/store.d.ts +190 -0
  127. package/dist/webrtc/store.d.ts.map +1 -0
  128. package/dist/webrtc/store.js +1043 -0
  129. package/dist/webrtc/store.js.map +1 -0
  130. package/dist/webrtc/types.d.ts +196 -0
  131. package/dist/webrtc/types.d.ts.map +1 -0
  132. package/dist/webrtc/types.js +46 -0
  133. package/dist/webrtc/types.js.map +1 -0
  134. package/dist/worker/protocol.d.ts +493 -0
  135. package/dist/worker/protocol.d.ts.map +1 -0
  136. package/dist/worker/protocol.js +15 -0
  137. package/dist/worker/protocol.js.map +1 -0
  138. package/package.json +59 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sirius Business Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,179 @@
1
+ /**
2
+ * BEP52 (BitTorrent v2) compatible merkle tree implementation
3
+ *
4
+ * Key differences from default hashtree:
5
+ * - 16 KiB block size (vs 256KB default)
6
+ * - Binary tree (2 children per node, not variable fanout)
7
+ * - Zero-padding for incomplete trees (pads to power of 2)
8
+ * - SHA256 hash algorithm
9
+ * - Piece layers: intermediate hash layers at piece boundaries
10
+ *
11
+ * @see https://www.bittorrent.org/beps/bep_0052.html
12
+ */
13
+ import { Hash, Store } from './types.js';
14
+ /**
15
+ * BEP52 block size: 16 KiB
16
+ */
17
+ export declare const BEP52_BLOCK_SIZE: number;
18
+ /**
19
+ * Zero hash (32 bytes of zeros) used for padding
20
+ */
21
+ export declare const ZERO_HASH: Hash;
22
+ /**
23
+ * Result of building a BEP52 merkle tree
24
+ */
25
+ export interface Bep52Result {
26
+ /** Root hash (pieces root) */
27
+ root: Hash;
28
+ /** Total file size in bytes */
29
+ size: number;
30
+ /** Number of 16KB blocks */
31
+ blockCount: number;
32
+ /** Leaf hashes (one per block) */
33
+ leafHashes: Hash[];
34
+ /**
35
+ * Piece layer hashes at specified piece size
36
+ * Only populated if pieceSize > blockSize
37
+ */
38
+ pieceLayers?: Hash[];
39
+ }
40
+ /**
41
+ * Configuration for BEP52 tree building
42
+ */
43
+ export interface Bep52Config {
44
+ /** Store for persisting blocks (optional - if not provided, only computes hashes) */
45
+ store?: Store;
46
+ /**
47
+ * Piece size for piece layers (must be power of 2, >= 16KB)
48
+ * Common values: 16KB (same as block), 32KB, 64KB, 128KB, 256KB, 512KB, 1MB, etc.
49
+ * If not specified, no piece layers are computed.
50
+ */
51
+ pieceSize?: number;
52
+ }
53
+ /**
54
+ * Compute the number of leaves needed (rounds up to power of 2)
55
+ */
56
+ export declare function merkleNumLeafs(blocks: number): number;
57
+ /**
58
+ * Get parent index in flat tree representation
59
+ * Tree layout: [0=root, 1=left, 2=right, 3=left-left, 4=left-right, ...]
60
+ */
61
+ export declare function merkleGetParent(idx: number): number;
62
+ /**
63
+ * Get sibling index
64
+ */
65
+ export declare function merkleGetSibling(idx: number): number;
66
+ /**
67
+ * Get first child index
68
+ */
69
+ export declare function merkleGetFirstChild(idx: number): number;
70
+ /**
71
+ * Get index of first leaf given number of leaves
72
+ */
73
+ export declare function merkleFirstLeaf(numLeafs: number): number;
74
+ /**
75
+ * Get total number of nodes in tree given number of leaves
76
+ */
77
+ export declare function merkleNumNodes(numLeafs: number): number;
78
+ /**
79
+ * Compute hash of two concatenated hashes (parent = H(left || right))
80
+ */
81
+ export declare function merkleHashPair(left: Hash, right: Hash): Promise<Hash>;
82
+ /**
83
+ * Compute the pad hash for a given depth
84
+ * pad(0) = zero hash
85
+ * pad(n) = H(pad(n-1) || pad(n-1))
86
+ */
87
+ export declare function merklePadHash(depth: number): Promise<Hash>;
88
+ /**
89
+ * Compute merkle root from leaf hashes with zero-padding
90
+ *
91
+ * @param leaves - Array of leaf hashes (one per 16KB block)
92
+ * @param numLeafs - Number of leaves in balanced tree (power of 2)
93
+ * @returns Root hash
94
+ */
95
+ export declare function merkleRoot(leaves: Hash[], numLeafs?: number): Promise<Hash>;
96
+ /**
97
+ * Build full merkle tree from leaves, returning all nodes
98
+ *
99
+ * @param leaves - Leaf hashes
100
+ * @returns Flat array of tree nodes [root, layer1..., leaves]
101
+ */
102
+ export declare function merkleBuildTree(leaves: Hash[]): Promise<Hash[]>;
103
+ /**
104
+ * Generate uncle hashes (proof) for a leaf
105
+ *
106
+ * @param tree - Full merkle tree
107
+ * @param leafIndex - Index of leaf in leaf layer (0-based)
108
+ * @param numLeafs - Number of leaves in tree
109
+ * @returns Array of uncle hashes from leaf to root
110
+ */
111
+ export declare function merkleGetProof(tree: Hash[], leafIndex: number, numLeafs: number): Hash[];
112
+ /**
113
+ * Verify a merkle proof
114
+ *
115
+ * @param leaf - Leaf hash to verify
116
+ * @param leafIndex - Position of leaf (0-based)
117
+ * @param proof - Uncle hashes from leaf to root
118
+ * @param root - Expected root hash
119
+ * @param numLeafs - Number of leaves in tree
120
+ * @returns True if proof is valid
121
+ */
122
+ export declare function merkleVerifyProof(leaf: Hash, leafIndex: number, proof: Hash[], root: Hash, numLeafs: number): Promise<boolean>;
123
+ /**
124
+ * BEP52 Tree Builder
125
+ *
126
+ * Builds a binary merkle tree compatible with BitTorrent v2.
127
+ */
128
+ export declare class Bep52TreeBuilder {
129
+ private store?;
130
+ private pieceSize;
131
+ private blocksPerPiece;
132
+ constructor(config?: Bep52Config);
133
+ /**
134
+ * Build BEP52 merkle tree from file data
135
+ *
136
+ * @param data - File content
137
+ * @returns Tree result with root, leaf hashes, and optional piece layers
138
+ */
139
+ buildFromData(data: Uint8Array): Promise<Bep52Result>;
140
+ /**
141
+ * Compute piece layer hashes
142
+ * Each piece layer hash is the root of a subtree covering blocksPerPiece blocks
143
+ */
144
+ private computePieceLayers;
145
+ /**
146
+ * Build tree from pre-computed leaf hashes
147
+ */
148
+ buildFromHashes(leafHashes: Hash[], size: number): Promise<Bep52Result>;
149
+ }
150
+ /**
151
+ * Streaming BEP52 tree builder
152
+ * Allows incremental hashing without loading entire file into memory
153
+ */
154
+ export declare class Bep52StreamBuilder {
155
+ private store?;
156
+ private buffer;
157
+ private bufferOffset;
158
+ private leafHashes;
159
+ private totalSize;
160
+ constructor(config?: Bep52Config);
161
+ /**
162
+ * Append data to the stream
163
+ */
164
+ append(data: Uint8Array): Promise<void>;
165
+ private flushBlock;
166
+ /**
167
+ * Finalize and return the tree result
168
+ */
169
+ finalize(): Promise<Bep52Result>;
170
+ /**
171
+ * Get current stats
172
+ */
173
+ get stats(): {
174
+ blocks: number;
175
+ buffered: number;
176
+ totalSize: number;
177
+ };
178
+ }
179
+ //# sourceMappingURL=bep52.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bep52.d.ts","sourceRoot":"","sources":["../src/bep52.ts"],"names":[],"mappings":"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"}
package/dist/bep52.js ADDED
@@ -0,0 +1,384 @@
1
+ /**
2
+ * BEP52 (BitTorrent v2) compatible merkle tree implementation
3
+ *
4
+ * Key differences from default hashtree:
5
+ * - 16 KiB block size (vs 256KB default)
6
+ * - Binary tree (2 children per node, not variable fanout)
7
+ * - Zero-padding for incomplete trees (pads to power of 2)
8
+ * - SHA256 hash algorithm
9
+ * - Piece layers: intermediate hash layers at piece boundaries
10
+ *
11
+ * @see https://www.bittorrent.org/beps/bep_0052.html
12
+ */
13
+ import { hashEquals } from './types.js';
14
+ import { sha256 } from './hash.js';
15
+ /**
16
+ * BEP52 block size: 16 KiB
17
+ */
18
+ export const BEP52_BLOCK_SIZE = 16 * 1024;
19
+ /**
20
+ * Zero hash (32 bytes of zeros) used for padding
21
+ */
22
+ export const ZERO_HASH = new Uint8Array(32);
23
+ /**
24
+ * Compute the number of leaves needed (rounds up to power of 2)
25
+ */
26
+ export function merkleNumLeafs(blocks) {
27
+ if (blocks <= 0)
28
+ return 0;
29
+ let n = 1;
30
+ while (n < blocks)
31
+ n <<= 1;
32
+ return n;
33
+ }
34
+ /**
35
+ * Get parent index in flat tree representation
36
+ * Tree layout: [0=root, 1=left, 2=right, 3=left-left, 4=left-right, ...]
37
+ */
38
+ export function merkleGetParent(idx) {
39
+ return Math.floor((idx - 1) / 2);
40
+ }
41
+ /**
42
+ * Get sibling index
43
+ */
44
+ export function merkleGetSibling(idx) {
45
+ // Even indices have sibling to left, odd to right
46
+ return idx + ((idx & 1) ? 1 : -1);
47
+ }
48
+ /**
49
+ * Get first child index
50
+ */
51
+ export function merkleGetFirstChild(idx) {
52
+ return idx * 2 + 1;
53
+ }
54
+ /**
55
+ * Get index of first leaf given number of leaves
56
+ */
57
+ export function merkleFirstLeaf(numLeafs) {
58
+ return numLeafs - 1;
59
+ }
60
+ /**
61
+ * Get total number of nodes in tree given number of leaves
62
+ */
63
+ export function merkleNumNodes(numLeafs) {
64
+ return numLeafs * 2 - 1;
65
+ }
66
+ /**
67
+ * Compute hash of two concatenated hashes (parent = H(left || right))
68
+ */
69
+ export async function merkleHashPair(left, right) {
70
+ const combined = new Uint8Array(64);
71
+ combined.set(left, 0);
72
+ combined.set(right, 32);
73
+ return sha256(combined);
74
+ }
75
+ /**
76
+ * Compute the pad hash for a given depth
77
+ * pad(0) = zero hash
78
+ * pad(n) = H(pad(n-1) || pad(n-1))
79
+ */
80
+ export async function merklePadHash(depth) {
81
+ let pad = ZERO_HASH;
82
+ for (let i = 0; i < depth; i++) {
83
+ pad = await merkleHashPair(pad, pad);
84
+ }
85
+ return pad;
86
+ }
87
+ /**
88
+ * Compute merkle root from leaf hashes with zero-padding
89
+ *
90
+ * @param leaves - Array of leaf hashes (one per 16KB block)
91
+ * @param numLeafs - Number of leaves in balanced tree (power of 2)
92
+ * @returns Root hash
93
+ */
94
+ export async function merkleRoot(leaves, numLeafs) {
95
+ if (leaves.length === 0) {
96
+ return ZERO_HASH;
97
+ }
98
+ if (leaves.length === 1 && (numLeafs === undefined || numLeafs === 1)) {
99
+ return leaves[0];
100
+ }
101
+ const targetLeafs = numLeafs ?? merkleNumLeafs(leaves.length);
102
+ // Build tree bottom-up using scratch space
103
+ // This matches libtorrent's merkle_root_scratch approach
104
+ let current = leaves.slice();
105
+ let padHash = ZERO_HASH;
106
+ let levelSize = targetLeafs;
107
+ while (levelSize > 1) {
108
+ const nextLevel = [];
109
+ for (let i = 0; i < current.length; i += 2) {
110
+ if (i + 1 < current.length) {
111
+ // Both children present
112
+ nextLevel.push(await merkleHashPair(current[i], current[i + 1]));
113
+ }
114
+ else {
115
+ // Odd leaf - pair with pad
116
+ nextLevel.push(await merkleHashPair(current[i], padHash));
117
+ }
118
+ }
119
+ // Compute next level's pad hash (H(pad || pad))
120
+ padHash = await merkleHashPair(padHash, padHash);
121
+ current = nextLevel;
122
+ levelSize = levelSize / 2;
123
+ }
124
+ return current[0];
125
+ }
126
+ /**
127
+ * Build full merkle tree from leaves, returning all nodes
128
+ *
129
+ * @param leaves - Leaf hashes
130
+ * @returns Flat array of tree nodes [root, layer1..., leaves]
131
+ */
132
+ export async function merkleBuildTree(leaves) {
133
+ if (leaves.length === 0) {
134
+ return [ZERO_HASH];
135
+ }
136
+ const numLeafs = merkleNumLeafs(leaves.length);
137
+ const numNodes = merkleNumNodes(numLeafs);
138
+ const tree = new Array(numNodes);
139
+ // Fill leaves (with zero-padding)
140
+ const firstLeaf = merkleFirstLeaf(numLeafs);
141
+ for (let i = 0; i < numLeafs; i++) {
142
+ tree[firstLeaf + i] = i < leaves.length ? leaves[i] : ZERO_HASH;
143
+ }
144
+ // Build parents bottom-up
145
+ let levelStart = firstLeaf;
146
+ let levelSize = numLeafs;
147
+ while (levelSize > 1) {
148
+ let parent = merkleGetParent(levelStart);
149
+ for (let i = levelStart; i < levelStart + levelSize; i += 2) {
150
+ tree[parent] = await merkleHashPair(tree[i], tree[i + 1]);
151
+ parent++;
152
+ }
153
+ levelStart = merkleGetParent(levelStart);
154
+ levelSize = levelSize / 2;
155
+ }
156
+ return tree;
157
+ }
158
+ /**
159
+ * Generate uncle hashes (proof) for a leaf
160
+ *
161
+ * @param tree - Full merkle tree
162
+ * @param leafIndex - Index of leaf in leaf layer (0-based)
163
+ * @param numLeafs - Number of leaves in tree
164
+ * @returns Array of uncle hashes from leaf to root
165
+ */
166
+ export function merkleGetProof(tree, leafIndex, numLeafs) {
167
+ const proofs = [];
168
+ let idx = merkleFirstLeaf(numLeafs) + leafIndex;
169
+ while (idx > 0) {
170
+ const siblingIdx = merkleGetSibling(idx);
171
+ proofs.push(tree[siblingIdx]);
172
+ idx = merkleGetParent(idx);
173
+ }
174
+ return proofs;
175
+ }
176
+ /**
177
+ * Verify a merkle proof
178
+ *
179
+ * @param leaf - Leaf hash to verify
180
+ * @param leafIndex - Position of leaf (0-based)
181
+ * @param proof - Uncle hashes from leaf to root
182
+ * @param root - Expected root hash
183
+ * @param numLeafs - Number of leaves in tree
184
+ * @returns True if proof is valid
185
+ */
186
+ export async function merkleVerifyProof(leaf, leafIndex, proof, root, numLeafs) {
187
+ let hash = leaf;
188
+ let idx = merkleFirstLeaf(numLeafs) + leafIndex;
189
+ for (const uncle of proof) {
190
+ // In flat tree: children of parent P are at 2P+1 (left) and 2P+2 (right)
191
+ // So odd indices are LEFT children, even indices are RIGHT children
192
+ if (idx & 1) {
193
+ // Odd index - we're on the left, uncle is on right
194
+ hash = await merkleHashPair(hash, uncle);
195
+ }
196
+ else {
197
+ // Even index - we're on the right, uncle is on left
198
+ hash = await merkleHashPair(uncle, hash);
199
+ }
200
+ idx = merkleGetParent(idx);
201
+ }
202
+ return hashEquals(hash, root);
203
+ }
204
+ /**
205
+ * BEP52 Tree Builder
206
+ *
207
+ * Builds a binary merkle tree compatible with BitTorrent v2.
208
+ */
209
+ export class Bep52TreeBuilder {
210
+ store;
211
+ pieceSize;
212
+ blocksPerPiece;
213
+ constructor(config = {}) {
214
+ this.store = config.store;
215
+ this.pieceSize = config.pieceSize ?? BEP52_BLOCK_SIZE;
216
+ if (this.pieceSize < BEP52_BLOCK_SIZE) {
217
+ throw new Error(`Piece size must be >= ${BEP52_BLOCK_SIZE} (16KB)`);
218
+ }
219
+ if ((this.pieceSize & (this.pieceSize - 1)) !== 0) {
220
+ throw new Error('Piece size must be a power of 2');
221
+ }
222
+ this.blocksPerPiece = this.pieceSize / BEP52_BLOCK_SIZE;
223
+ }
224
+ /**
225
+ * Build BEP52 merkle tree from file data
226
+ *
227
+ * @param data - File content
228
+ * @returns Tree result with root, leaf hashes, and optional piece layers
229
+ */
230
+ async buildFromData(data) {
231
+ const size = data.length;
232
+ const blockCount = Math.ceil(size / BEP52_BLOCK_SIZE);
233
+ if (blockCount === 0) {
234
+ return {
235
+ root: ZERO_HASH,
236
+ size: 0,
237
+ blockCount: 0,
238
+ leafHashes: [],
239
+ };
240
+ }
241
+ // Hash each 16KB block
242
+ const leafHashes = [];
243
+ for (let i = 0; i < blockCount; i++) {
244
+ const start = i * BEP52_BLOCK_SIZE;
245
+ const end = Math.min(start + BEP52_BLOCK_SIZE, size);
246
+ const block = data.slice(start, end);
247
+ // Store block if store is provided
248
+ const hash = await sha256(block);
249
+ if (this.store) {
250
+ await this.store.put(hash, block);
251
+ }
252
+ leafHashes.push(hash);
253
+ }
254
+ // Compute root
255
+ const numLeafs = merkleNumLeafs(blockCount);
256
+ const root = await merkleRoot(leafHashes, numLeafs);
257
+ // Compute piece layers if piece size > block size
258
+ let pieceLayers;
259
+ if (this.pieceSize > BEP52_BLOCK_SIZE) {
260
+ pieceLayers = await this.computePieceLayers(leafHashes, numLeafs);
261
+ }
262
+ return {
263
+ root,
264
+ size,
265
+ blockCount,
266
+ leafHashes,
267
+ pieceLayers,
268
+ };
269
+ }
270
+ /**
271
+ * Compute piece layer hashes
272
+ * Each piece layer hash is the root of a subtree covering blocksPerPiece blocks
273
+ */
274
+ async computePieceLayers(leafHashes, _numLeafs) {
275
+ const pieceCount = Math.ceil(leafHashes.length / this.blocksPerPiece);
276
+ const layers = [];
277
+ for (let p = 0; p < pieceCount; p++) {
278
+ const start = p * this.blocksPerPiece;
279
+ const end = Math.min(start + this.blocksPerPiece, leafHashes.length);
280
+ const pieceLeaves = leafHashes.slice(start, end);
281
+ // Compute subtree root for this piece
282
+ const pieceRoot = await merkleRoot(pieceLeaves, this.blocksPerPiece);
283
+ layers.push(pieceRoot);
284
+ }
285
+ return layers;
286
+ }
287
+ /**
288
+ * Build tree from pre-computed leaf hashes
289
+ */
290
+ async buildFromHashes(leafHashes, size) {
291
+ const blockCount = leafHashes.length;
292
+ const numLeafs = merkleNumLeafs(blockCount);
293
+ const root = await merkleRoot(leafHashes, numLeafs);
294
+ let pieceLayers;
295
+ if (this.pieceSize > BEP52_BLOCK_SIZE) {
296
+ pieceLayers = await this.computePieceLayers(leafHashes, numLeafs);
297
+ }
298
+ return {
299
+ root,
300
+ size,
301
+ blockCount,
302
+ leafHashes,
303
+ pieceLayers,
304
+ };
305
+ }
306
+ }
307
+ /**
308
+ * Streaming BEP52 tree builder
309
+ * Allows incremental hashing without loading entire file into memory
310
+ */
311
+ export class Bep52StreamBuilder {
312
+ store;
313
+ buffer;
314
+ bufferOffset = 0;
315
+ leafHashes = [];
316
+ totalSize = 0;
317
+ constructor(config = {}) {
318
+ this.store = config.store;
319
+ this.buffer = new Uint8Array(BEP52_BLOCK_SIZE);
320
+ }
321
+ /**
322
+ * Append data to the stream
323
+ */
324
+ async append(data) {
325
+ let offset = 0;
326
+ while (offset < data.length) {
327
+ const space = BEP52_BLOCK_SIZE - this.bufferOffset;
328
+ const toWrite = Math.min(space, data.length - offset);
329
+ this.buffer.set(data.subarray(offset, offset + toWrite), this.bufferOffset);
330
+ this.bufferOffset += toWrite;
331
+ offset += toWrite;
332
+ if (this.bufferOffset === BEP52_BLOCK_SIZE) {
333
+ await this.flushBlock();
334
+ }
335
+ }
336
+ this.totalSize += data.length;
337
+ }
338
+ async flushBlock() {
339
+ if (this.bufferOffset === 0)
340
+ return;
341
+ const block = this.buffer.slice(0, this.bufferOffset);
342
+ const hash = await sha256(block);
343
+ if (this.store) {
344
+ await this.store.put(hash, new Uint8Array(block));
345
+ }
346
+ this.leafHashes.push(hash);
347
+ this.bufferOffset = 0;
348
+ }
349
+ /**
350
+ * Finalize and return the tree result
351
+ */
352
+ async finalize() {
353
+ // Flush any remaining data
354
+ await this.flushBlock();
355
+ const blockCount = this.leafHashes.length;
356
+ if (blockCount === 0) {
357
+ return {
358
+ root: ZERO_HASH,
359
+ size: 0,
360
+ blockCount: 0,
361
+ leafHashes: [],
362
+ };
363
+ }
364
+ const numLeafs = merkleNumLeafs(blockCount);
365
+ const root = await merkleRoot(this.leafHashes, numLeafs);
366
+ return {
367
+ root,
368
+ size: this.totalSize,
369
+ blockCount,
370
+ leafHashes: this.leafHashes,
371
+ };
372
+ }
373
+ /**
374
+ * Get current stats
375
+ */
376
+ get stats() {
377
+ return {
378
+ blocks: this.leafHashes.length,
379
+ buffered: this.bufferOffset,
380
+ totalSize: this.totalSize,
381
+ };
382
+ }
383
+ }
384
+ //# sourceMappingURL=bep52.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bep52.js","sourceRoot":"","sources":["../src/bep52.ts"],"names":[],"mappings":"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"}