@totemsdk/core 1.2.6 → 1.2.8
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/MiniNumber.js +9 -1
- package/dist/canonical.d.ts +3 -0
- package/dist/canonical.js +22 -0
- package/dist/cjs/MiniNumber.d.ts +47 -0
- package/dist/cjs/MiniNumber.js +310 -0
- package/dist/cjs/Streamable.d.ts +268 -0
- package/dist/cjs/Streamable.js +439 -0
- package/dist/cjs/adapters/index.d.ts +190 -0
- package/dist/cjs/adapters/index.js +118 -0
- package/dist/cjs/adapters/types.d.ts +150 -0
- package/dist/cjs/adapters/types.js +81 -0
- package/dist/cjs/binio.d.ts +9 -0
- package/dist/cjs/binio.js +25 -0
- package/dist/cjs/bip39.d.ts +91 -0
- package/dist/cjs/bip39.js +434 -0
- package/dist/cjs/canonical.d.ts +3 -0
- package/dist/cjs/canonical.js +27 -0
- package/dist/cjs/derive.d.ts +2 -0
- package/dist/cjs/derive.js +13 -0
- package/dist/cjs/index.d.ts +49 -0
- package/dist/cjs/index.js +231 -0
- package/dist/cjs/javaStreamables.d.ts +254 -0
- package/dist/cjs/javaStreamables.js +391 -0
- package/dist/cjs/lease/LeaseMonitor.d.ts +44 -0
- package/dist/cjs/lease/LeaseMonitor.js +115 -0
- package/dist/cjs/lease/LeaseStore.d.ts +58 -0
- package/dist/cjs/lease/LeaseStore.js +151 -0
- package/dist/cjs/lease/WatermarkStore.d.ts +61 -0
- package/dist/cjs/lease/WatermarkStore.js +209 -0
- package/dist/cjs/lease/index.d.ts +14 -0
- package/dist/cjs/lease/index.js +22 -0
- package/dist/cjs/lease-client.d.ts +31 -0
- package/dist/cjs/lease-client.js +44 -0
- package/dist/cjs/legacy.d.ts +23 -0
- package/dist/cjs/legacy.js +163 -0
- package/dist/cjs/minima32.d.ts +18 -0
- package/dist/cjs/minima32.js +121 -0
- package/dist/cjs/minimaWireSerializer.d.ts +60 -0
- package/dist/cjs/minimaWireSerializer.js +77 -0
- package/dist/cjs/mmr.d.ts +157 -0
- package/dist/cjs/mmr.js +352 -0
- package/dist/cjs/mx.d.ts +1 -0
- package/dist/cjs/mx.js +10 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/params.d.ts +29 -0
- package/dist/cjs/params.js +20 -0
- package/dist/cjs/script.d.ts +7 -0
- package/dist/cjs/script.js +27 -0
- package/dist/cjs/scripts/contract-helpers.d.ts +252 -0
- package/dist/cjs/scripts/contract-helpers.js +407 -0
- package/dist/cjs/scripts/dapp-types.d.ts +119 -0
- package/dist/cjs/scripts/dapp-types.js +77 -0
- package/dist/cjs/scripts/index.d.ts +4 -0
- package/dist/cjs/scripts/index.js +38 -0
- package/dist/cjs/scripts/types.d.ts +81 -0
- package/dist/cjs/scripts/types.js +159 -0
- package/dist/cjs/scripts/witness-serializer.d.ts +29 -0
- package/dist/cjs/scripts/witness-serializer.js +306 -0
- package/dist/cjs/transaction.d.ts +106 -0
- package/dist/cjs/transaction.js +293 -0
- package/dist/cjs/treekey.d.ts +399 -0
- package/dist/cjs/treekey.js +827 -0
- package/dist/cjs/tx/TransactionLifecycle.d.ts +55 -0
- package/dist/cjs/tx/TransactionLifecycle.js +205 -0
- package/dist/cjs/tx/TransactionReceiptStore.d.ts +36 -0
- package/dist/cjs/tx/TransactionReceiptStore.js +93 -0
- package/dist/cjs/tx/TransactionService.d.ts +50 -0
- package/dist/cjs/tx/TransactionService.js +186 -0
- package/dist/cjs/tx/index.d.ts +13 -0
- package/dist/cjs/tx/index.js +20 -0
- package/dist/cjs/tx/types.d.ts +115 -0
- package/dist/cjs/tx/types.js +6 -0
- package/dist/cjs/util.d.ts +1 -0
- package/dist/cjs/util.js +5 -0
- package/dist/cjs/utils.d.ts +8 -0
- package/dist/cjs/utils.js +42 -0
- package/dist/cjs/verify.d.ts +18 -0
- package/dist/cjs/verify.js +174 -0
- package/dist/cjs/version.d.ts +12 -0
- package/dist/cjs/version.js +15 -0
- package/dist/cjs/wasm-sync.d.ts +71 -0
- package/dist/cjs/wasm-sync.js +97 -0
- package/dist/cjs/wots.d.ts +232 -0
- package/dist/cjs/wots.js +589 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +25 -2
- package/dist/minimaWireSerializer.js +2 -2
- package/dist/mmr.js +1 -1
- package/dist/transaction.js +10 -10
- package/dist/treekey.js +14 -0
- package/dist/wasm-sync.d.ts +2 -2
- package/dist/wasm-sync.js +3 -1
- package/dist/wots.d.ts +1 -1
- package/package.json +84 -45
- package/dist/wasm-bridge.d.ts +0 -54
- package/dist/wasm-bridge.js +0 -303
package/dist/cjs/mmr.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deserializeMMRProof = exports.MMRTree = exports.serializeRealMMRProof = void 0;
|
|
4
|
+
exports.serializeMMRProof = serializeMMRProof;
|
|
5
|
+
exports.mmrLeafExact = mmrLeafExact;
|
|
6
|
+
exports.mmrRootFromSingleLeaf = mmrRootFromSingleLeaf;
|
|
7
|
+
exports.createMMRDataLeafNode = createMMRDataLeafNode;
|
|
8
|
+
exports.createMMRDataParentNode = createMMRDataParentNode;
|
|
9
|
+
exports.calculateProofRoot = calculateProofRoot;
|
|
10
|
+
exports.verifyMMRProof = verifyMMRProof;
|
|
11
|
+
exports.parseMMRProofFromHex = parseMMRProofFromHex;
|
|
12
|
+
// packages/core/src/mmr.ts
|
|
13
|
+
// Full MMR implementation matching Minima's MMR.java, MMRData.java, and TreeKeyNode.java
|
|
14
|
+
const wasm_sync_js_1 = require("./wasm-sync.js");
|
|
15
|
+
const javaStreamables_js_1 = require("./javaStreamables.js");
|
|
16
|
+
// Import canonical wire serialization from Streamable.ts (single source of truth)
|
|
17
|
+
const Streamable_js_1 = require("./Streamable.js");
|
|
18
|
+
// Re-export for API compatibility (existing code imports from mmr.ts)
|
|
19
|
+
// Using a wrapper function for better compatibility with dynamic imports
|
|
20
|
+
function serializeMMRProof(proof, blockTime = 0n) {
|
|
21
|
+
// Convert to Streamable format and serialize
|
|
22
|
+
const streamableProof = {
|
|
23
|
+
blockTime: blockTime,
|
|
24
|
+
chunks: proof.chunks.map(c => ({
|
|
25
|
+
isLeft: c.isLeft,
|
|
26
|
+
mmrData: { data: c.mmrData.data, value: c.mmrData.value }
|
|
27
|
+
}))
|
|
28
|
+
};
|
|
29
|
+
return (0, Streamable_js_1.writeMMRProof)(streamableProof);
|
|
30
|
+
}
|
|
31
|
+
exports.serializeRealMMRProof = serializeMMRProof;
|
|
32
|
+
/** SHA3-256 helper returning 32 bytes */
|
|
33
|
+
function sha3(data) {
|
|
34
|
+
return (0, wasm_sync_js_1.sha3_256)(data);
|
|
35
|
+
}
|
|
36
|
+
/** concat utility */
|
|
37
|
+
function concat(...parts) {
|
|
38
|
+
const total = parts.reduce((n, p) => n + p.length, 0);
|
|
39
|
+
const out = new Uint8Array(total);
|
|
40
|
+
let off = 0;
|
|
41
|
+
for (const p of parts) {
|
|
42
|
+
out.set(p, off);
|
|
43
|
+
off += p.length;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** big-endian u32 */
|
|
48
|
+
const u32be = (n) => new Uint8Array([(n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff]);
|
|
49
|
+
/**
|
|
50
|
+
* EXACT MiniNumber.ZERO wire format from Java:
|
|
51
|
+
* scale (1 byte) = 0x00
|
|
52
|
+
* length (1 byte) = 0x01
|
|
53
|
+
* unscaled bytes (length=1) = 0x00
|
|
54
|
+
* => 00 01 00
|
|
55
|
+
*/
|
|
56
|
+
function encodeMiniNumberZERO() {
|
|
57
|
+
return new Uint8Array([0x00, 0x01, 0x00]);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* EXACT MiniString wire format (MiniData of UTF-8):
|
|
61
|
+
* 4-byte big-endian length
|
|
62
|
+
* raw UTF-8 bytes
|
|
63
|
+
*/
|
|
64
|
+
function encodeMiniStringUTF8(text) {
|
|
65
|
+
const utf8 = new TextEncoder().encode(text);
|
|
66
|
+
const len = u32be(utf8.length);
|
|
67
|
+
return concat(len, utf8);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Byte-exact one-leaf MMR leaf used by Minima Address.java path:
|
|
71
|
+
* sha3( MiniNumber.ZERO || MiniString(script) || MiniNumber.ZERO )
|
|
72
|
+
*/
|
|
73
|
+
function mmrLeafExact(script) {
|
|
74
|
+
const zero = encodeMiniNumberZERO();
|
|
75
|
+
const mstr = encodeMiniStringUTF8(script);
|
|
76
|
+
const all = concat(zero, mstr, zero);
|
|
77
|
+
return sha3(all); // 32-byte leaf hash
|
|
78
|
+
}
|
|
79
|
+
/** In a single-leaf MMR the root equals the leaf commitment. */
|
|
80
|
+
function mmrRootFromSingleLeaf(script) {
|
|
81
|
+
return mmrLeafExact(script);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create MMRData leaf node matching Minima's MMRData.CreateMMRDataLeafNode
|
|
85
|
+
*
|
|
86
|
+
* From MMRData.java:
|
|
87
|
+
* MiniData hash = Crypto.getInstance().hashAllObjects(MiniNumber.ZERO, zData, zSumValue);
|
|
88
|
+
*
|
|
89
|
+
* CRITICAL: Crypto.hashAllObjects uses writeDataStream for Streamables:
|
|
90
|
+
* - MiniNumber: scale + len + data (see serializeMiniNumber)
|
|
91
|
+
* - MiniData: 4-byte length + data (see serializeMiniData)
|
|
92
|
+
*
|
|
93
|
+
* For TreeKeyNode, zData is the Winternitz public key (MiniData) and zSumValue is ZERO
|
|
94
|
+
*
|
|
95
|
+
* Serialization order:
|
|
96
|
+
* 1. MiniNumber.ZERO: [0x00, 0x01, 0x00]
|
|
97
|
+
* 2. MiniData (pubkey): [4-byte length] + [bytes] (writeDataStream, NOT writeHashToStream)
|
|
98
|
+
* 3. MiniNumber.ZERO: [0x00, 0x01, 0x00]
|
|
99
|
+
*/
|
|
100
|
+
function createMMRDataLeafNode(pubkey, sumValue = 0n) {
|
|
101
|
+
// Use cached ZERO serialization for efficiency
|
|
102
|
+
const zero = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
|
|
103
|
+
// IMPORTANT: hashAllObjects uses writeDataStream which is 4-byte length prefixed
|
|
104
|
+
const pubkeySerialized = (0, javaStreamables_js_1.serializeMiniData)(pubkey);
|
|
105
|
+
// For sumValue, serialize as MiniNumber
|
|
106
|
+
let sumSerialized;
|
|
107
|
+
if (sumValue === 0n) {
|
|
108
|
+
sumSerialized = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
sumSerialized = (0, javaStreamables_js_1.serializeMiniNumber)(Number(sumValue));
|
|
112
|
+
}
|
|
113
|
+
const hash = (0, javaStreamables_js_1.javaHashAllObjects)(zero, pubkeySerialized, sumSerialized);
|
|
114
|
+
return { data: hash, value: sumValue };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create MMRData parent node matching Minima's MMRData.CreateMMRDataParentNode
|
|
118
|
+
*
|
|
119
|
+
* From MMRData.java:
|
|
120
|
+
* MiniNumber sumvalue = zLeft.getValue().add(zRight.getValue());
|
|
121
|
+
* MiniData combinedhash = Crypto.getInstance().hashAllObjects(
|
|
122
|
+
* MiniNumber.ONE, zLeft.getData(), zRight.getData(), sumvalue);
|
|
123
|
+
*
|
|
124
|
+
* CRITICAL: The getData() returns MiniData (the hash), which is serialized
|
|
125
|
+
* with writeDataStream (4-byte length) in hashAllObjects.
|
|
126
|
+
*
|
|
127
|
+
* Serialization order:
|
|
128
|
+
* 1. MiniNumber.ONE: [0x00, 0x01, 0x01]
|
|
129
|
+
* 2. MiniData (left.data): [4-byte length] + [bytes]
|
|
130
|
+
* 3. MiniData (right.data): [4-byte length] + [bytes]
|
|
131
|
+
* 4. MiniNumber (sumvalue): serialized MiniNumber
|
|
132
|
+
*/
|
|
133
|
+
function createMMRDataParentNode(left, right) {
|
|
134
|
+
const sumValue = left.value + right.value;
|
|
135
|
+
// MiniNumber.ONE: [0x00, 0x01, 0x01]
|
|
136
|
+
const one = new Uint8Array([0x00, 0x01, 0x01]);
|
|
137
|
+
// Serialize left and right data as MiniData (4-byte length-prefixed)
|
|
138
|
+
const leftDataSerialized = (0, javaStreamables_js_1.serializeMiniData)(left.data);
|
|
139
|
+
const rightDataSerialized = (0, javaStreamables_js_1.serializeMiniData)(right.data);
|
|
140
|
+
// Serialize sum value
|
|
141
|
+
let sumSerialized;
|
|
142
|
+
if (sumValue === 0n) {
|
|
143
|
+
sumSerialized = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
sumSerialized = (0, javaStreamables_js_1.serializeMiniNumber)(Number(sumValue));
|
|
147
|
+
}
|
|
148
|
+
const hash = (0, javaStreamables_js_1.javaHashAllObjects)(one, leftDataSerialized, rightDataSerialized, sumSerialized);
|
|
149
|
+
return { data: hash, value: sumValue };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Simple MMR Tree for TreeKeyNode
|
|
153
|
+
* Builds a perfect binary tree from N entries (N must be power of 2 for simplicity)
|
|
154
|
+
*
|
|
155
|
+
* This matches TreeKeyNode.java which always uses 64 leaves (2^6)
|
|
156
|
+
*/
|
|
157
|
+
class MMRTree {
|
|
158
|
+
entries = new Map();
|
|
159
|
+
leafCount = 0;
|
|
160
|
+
maxRow = 0;
|
|
161
|
+
getKey(row, entryNumber) {
|
|
162
|
+
return `${row}:${entryNumber}`;
|
|
163
|
+
}
|
|
164
|
+
setEntry(row, entryNumber, data) {
|
|
165
|
+
const entry = { row, entryNumber, mmrData: data };
|
|
166
|
+
this.entries.set(this.getKey(row, entryNumber), entry);
|
|
167
|
+
if (row > this.maxRow)
|
|
168
|
+
this.maxRow = row;
|
|
169
|
+
return entry;
|
|
170
|
+
}
|
|
171
|
+
getEntry(row, entryNumber) {
|
|
172
|
+
return this.entries.get(this.getKey(row, entryNumber));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Add a leaf entry to the MMR
|
|
176
|
+
* Matches MMR.java addEntry() but simplified for power-of-2 trees
|
|
177
|
+
*/
|
|
178
|
+
addLeaf(data) {
|
|
179
|
+
const entryNumber = BigInt(this.leafCount);
|
|
180
|
+
const entry = this.setEntry(0, entryNumber, data);
|
|
181
|
+
this.leafCount++;
|
|
182
|
+
// Propagate up the tree
|
|
183
|
+
let current = entry;
|
|
184
|
+
while (current.entryNumber % 2n === 1n) { // Is right child
|
|
185
|
+
const siblingNumber = current.entryNumber - 1n;
|
|
186
|
+
const sibling = this.getEntry(current.row, siblingNumber);
|
|
187
|
+
if (!sibling)
|
|
188
|
+
break;
|
|
189
|
+
// Create parent node
|
|
190
|
+
const parentData = createMMRDataParentNode(sibling.mmrData, current.mmrData);
|
|
191
|
+
const parentRow = current.row + 1;
|
|
192
|
+
const parentEntry = current.entryNumber / 2n;
|
|
193
|
+
current = this.setEntry(parentRow, parentEntry, parentData);
|
|
194
|
+
}
|
|
195
|
+
return entry;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Build tree from array of Winternitz public keys
|
|
199
|
+
* Used by TreeKeyNode to compute wallet public key
|
|
200
|
+
*/
|
|
201
|
+
static fromPublicKeys(pubkeys) {
|
|
202
|
+
const tree = new MMRTree();
|
|
203
|
+
for (const pk of pubkeys) {
|
|
204
|
+
const leafData = createMMRDataLeafNode(pk, 0n);
|
|
205
|
+
tree.addLeaf(leafData);
|
|
206
|
+
}
|
|
207
|
+
return tree;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the root of the tree
|
|
211
|
+
* For a perfect binary tree with N leaves, root is at row log2(N), entry 0
|
|
212
|
+
*/
|
|
213
|
+
getRoot() {
|
|
214
|
+
if (this.leafCount === 0)
|
|
215
|
+
return null;
|
|
216
|
+
// For power of 2 leaves, there's exactly one peak at the top
|
|
217
|
+
const topRow = Math.floor(Math.log2(this.leafCount));
|
|
218
|
+
const root = this.getEntry(topRow, 0n);
|
|
219
|
+
return root?.mmrData || null;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get proof for a leaf at given index
|
|
223
|
+
* Matches MMR.java getProofToPeak()
|
|
224
|
+
*/
|
|
225
|
+
getProof(leafIndex) {
|
|
226
|
+
const chunks = [];
|
|
227
|
+
let row = 0;
|
|
228
|
+
let entryNumber = BigInt(leafIndex);
|
|
229
|
+
// Walk up the tree collecting siblings
|
|
230
|
+
while (row < this.maxRow) {
|
|
231
|
+
const siblingNumber = entryNumber % 2n === 0n
|
|
232
|
+
? entryNumber + 1n // Current is left, sibling is right
|
|
233
|
+
: entryNumber - 1n; // Current is right, sibling is left
|
|
234
|
+
const sibling = this.getEntry(row, siblingNumber);
|
|
235
|
+
if (!sibling)
|
|
236
|
+
break;
|
|
237
|
+
const isLeft = siblingNumber < entryNumber;
|
|
238
|
+
chunks.push({ isLeft, mmrData: sibling.mmrData });
|
|
239
|
+
// Move to parent
|
|
240
|
+
row++;
|
|
241
|
+
entryNumber = entryNumber / 2n;
|
|
242
|
+
}
|
|
243
|
+
return { chunks };
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get the leaf MMRData at a specific index
|
|
247
|
+
*/
|
|
248
|
+
getLeaf(index) {
|
|
249
|
+
const entry = this.getEntry(0, BigInt(index));
|
|
250
|
+
return entry?.mmrData || null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.MMRTree = MMRTree;
|
|
254
|
+
/**
|
|
255
|
+
* Calculate root from leaf data and proof
|
|
256
|
+
* Matches SignatureProof.getRootPublicKey() in Java
|
|
257
|
+
*
|
|
258
|
+
* From SignatureProof.java:
|
|
259
|
+
* MMRData pubentry = MMRData.CreateMMRDataLeafNode(mPublicKey, MiniNumber.ZERO);
|
|
260
|
+
* return mProof.calculateProof(pubentry).getData();
|
|
261
|
+
*/
|
|
262
|
+
function calculateProofRoot(leafData, proof) {
|
|
263
|
+
let current = leafData;
|
|
264
|
+
for (const chunk of proof.chunks) {
|
|
265
|
+
if (chunk.isLeft) {
|
|
266
|
+
// Sibling is on the left, current is on the right
|
|
267
|
+
current = createMMRDataParentNode(chunk.mmrData, current);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// Sibling is on the right, current is on the left
|
|
271
|
+
current = createMMRDataParentNode(current, chunk.mmrData);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return current.data;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Verify a proof: check that leaf + proof computes to expected root
|
|
278
|
+
*/
|
|
279
|
+
function verifyMMRProof(leafPubkey, proof, expectedRoot) {
|
|
280
|
+
const leafData = createMMRDataLeafNode(leafPubkey, 0n);
|
|
281
|
+
const computedRoot = calculateProofRoot(leafData, proof);
|
|
282
|
+
if (computedRoot.length !== expectedRoot.length)
|
|
283
|
+
return false;
|
|
284
|
+
for (let i = 0; i < computedRoot.length; i++) {
|
|
285
|
+
if (computedRoot[i] !== expectedRoot[i])
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
// NOTE: serializeMMRProof is now imported from minimaWireSerializer.ts and re-exported above
|
|
291
|
+
// This consolidates wire format serialization into a single source of truth.
|
|
292
|
+
/**
|
|
293
|
+
* Deserialize MMRProof from bytes matching Minima's MMRProof.readDataStream()
|
|
294
|
+
*
|
|
295
|
+
* Format:
|
|
296
|
+
* 1. blockTime (MiniNumber)
|
|
297
|
+
* 2. chain length (MiniNumber)
|
|
298
|
+
* 3. Each chunk: isLeft (1 byte) + MMRData (hash with 4-byte length prefix + value MiniNumber)
|
|
299
|
+
*
|
|
300
|
+
* CRITICAL: Java MMRData.readDataStream uses mData.readHashFromStream() which reads
|
|
301
|
+
* a 4-byte big-endian length prefix followed by the hash bytes.
|
|
302
|
+
*
|
|
303
|
+
* @returns { proof: MMRProof, blockTime: bigint }
|
|
304
|
+
*/
|
|
305
|
+
function parseMMRProofFromHex(data) {
|
|
306
|
+
let offset = 0;
|
|
307
|
+
// Read blockTime as MiniNumber
|
|
308
|
+
const { value: blockTime, bytesRead: btRead } = readMiniNumber(data, offset);
|
|
309
|
+
offset += btRead;
|
|
310
|
+
// Read chain length as MiniNumber
|
|
311
|
+
const { value: numChunks, bytesRead: ncRead } = readMiniNumber(data, offset);
|
|
312
|
+
offset += ncRead;
|
|
313
|
+
const chunks = [];
|
|
314
|
+
for (let i = 0; i < Number(numChunks); i++) {
|
|
315
|
+
// isLeft flag (1 byte)
|
|
316
|
+
const isLeft = data[offset] === 1;
|
|
317
|
+
offset += 1;
|
|
318
|
+
// MMRData: hash (4-byte length prefix + hash bytes) + value (MiniNumber)
|
|
319
|
+
// Read 4-byte big-endian length
|
|
320
|
+
const hashLength = (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3];
|
|
321
|
+
offset += 4;
|
|
322
|
+
const hashData = data.slice(offset, offset + hashLength);
|
|
323
|
+
offset += hashLength;
|
|
324
|
+
const { value: chunkValue, bytesRead: cvRead } = readMiniNumber(data, offset);
|
|
325
|
+
offset += cvRead;
|
|
326
|
+
chunks.push({ isLeft, mmrData: { data: hashData, value: chunkValue } });
|
|
327
|
+
}
|
|
328
|
+
return { proof: { chunks }, blockTime, bytesRead: offset };
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Read a MiniNumber from bytes at the given offset
|
|
332
|
+
* Format: [scale: 1 byte] [length: 1 byte] [data: N bytes]
|
|
333
|
+
*/
|
|
334
|
+
function readMiniNumber(data, offset) {
|
|
335
|
+
const scale = data[offset];
|
|
336
|
+
const length = data[offset + 1];
|
|
337
|
+
if (length === 0) {
|
|
338
|
+
// Zero value (shouldn't happen with proper serialization)
|
|
339
|
+
return { value: 0n, bytesRead: 2 };
|
|
340
|
+
}
|
|
341
|
+
const dataBytes = data.slice(offset + 2, offset + 2 + length);
|
|
342
|
+
// Convert bytes to bigint
|
|
343
|
+
let value = 0n;
|
|
344
|
+
for (let i = 0; i < dataBytes.length; i++) {
|
|
345
|
+
value = (value << 8n) | BigInt(dataBytes[i]);
|
|
346
|
+
}
|
|
347
|
+
// Apply scale if non-zero (for decimal numbers)
|
|
348
|
+
// For TreeKey MMR, scale is always 0
|
|
349
|
+
return { value, bytesRead: 2 + length };
|
|
350
|
+
}
|
|
351
|
+
/** @deprecated Use parseMMRProofFromHex */
|
|
352
|
+
exports.deserializeMMRProof = parseMMRProofFromHex;
|
package/dist/cjs/mx.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { hexToMx, mxToHex, makeMinimaAddress, convertMinimaAddress, encodeMx, decodeMx } from './minima32.js';
|
package/dist/cjs/mx.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeMx = exports.encodeMx = exports.convertMinimaAddress = exports.makeMinimaAddress = exports.mxToHex = exports.hexToMx = void 0;
|
|
4
|
+
var minima32_js_1 = require("./minima32.js");
|
|
5
|
+
Object.defineProperty(exports, "hexToMx", { enumerable: true, get: function () { return minima32_js_1.hexToMx; } });
|
|
6
|
+
Object.defineProperty(exports, "mxToHex", { enumerable: true, get: function () { return minima32_js_1.mxToHex; } });
|
|
7
|
+
Object.defineProperty(exports, "makeMinimaAddress", { enumerable: true, get: function () { return minima32_js_1.makeMinimaAddress; } });
|
|
8
|
+
Object.defineProperty(exports, "convertMinimaAddress", { enumerable: true, get: function () { return minima32_js_1.convertMinimaAddress; } });
|
|
9
|
+
Object.defineProperty(exports, "encodeMx", { enumerable: true, get: function () { return minima32_js_1.encodeMx; } });
|
|
10
|
+
Object.defineProperty(exports, "decodeMx", { enumerable: true, get: function () { return minima32_js_1.decodeMx; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WOTS Parameter Set - BouncyCastle Compatible (w=8)
|
|
3
|
+
*
|
|
4
|
+
* Matches Minima Java implementation which uses BouncyCastle:
|
|
5
|
+
* - Winternitz.java: WINTERNITZ_VALUE = 8
|
|
6
|
+
* - WinternitzOTSignature.java: w=8 means 8 BITS per digit (not base-8)
|
|
7
|
+
* - SHA3-256 hash function (mdsize = 32 bytes)
|
|
8
|
+
*
|
|
9
|
+
* Chain count calculation (from WinternitzOTSignature constructor):
|
|
10
|
+
* messagesize = ((mdsize << 3) + w - 1) / w = (256 + 7) / 8 = 32
|
|
11
|
+
* checksumsize = getLog((messagesize << w) + 1) = getLog(8193) = 14 bits
|
|
12
|
+
* keysize = messagesize + (checksumsize + w - 1) / w = 32 + (14 + 7) / 8 = 34
|
|
13
|
+
*
|
|
14
|
+
* So L = 34 chains total, each chain value is 0-255 (8-bit digit)
|
|
15
|
+
*/
|
|
16
|
+
export type ParamSet = {
|
|
17
|
+
name: 'minima';
|
|
18
|
+
n: 256;
|
|
19
|
+
w: 8;
|
|
20
|
+
L: 34;
|
|
21
|
+
messageSize: 32;
|
|
22
|
+
checksumSize: 14;
|
|
23
|
+
checksumDigits: 2;
|
|
24
|
+
maxDigit: 255;
|
|
25
|
+
};
|
|
26
|
+
export declare const WOTS_MINIMA: ParamSet;
|
|
27
|
+
export declare const WOTS_V1_DEV: ParamSet;
|
|
28
|
+
export declare const WOTS_V2_SPEC: ParamSet;
|
|
29
|
+
export declare function getParamSet(_env?: string): ParamSet;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WOTS_V2_SPEC = exports.WOTS_V1_DEV = exports.WOTS_MINIMA = void 0;
|
|
4
|
+
exports.getParamSet = getParamSet;
|
|
5
|
+
exports.WOTS_MINIMA = {
|
|
6
|
+
name: 'minima',
|
|
7
|
+
n: 256,
|
|
8
|
+
w: 8,
|
|
9
|
+
L: 34,
|
|
10
|
+
messageSize: 32,
|
|
11
|
+
checksumSize: 14,
|
|
12
|
+
checksumDigits: 2,
|
|
13
|
+
maxDigit: 255,
|
|
14
|
+
};
|
|
15
|
+
// Legacy aliases for backwards compatibility during migration
|
|
16
|
+
exports.WOTS_V1_DEV = exports.WOTS_MINIMA;
|
|
17
|
+
exports.WOTS_V2_SPEC = exports.WOTS_MINIMA;
|
|
18
|
+
function getParamSet(_env) {
|
|
19
|
+
return exports.WOTS_MINIMA;
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WotsKeypair } from "./wots.js";
|
|
2
|
+
/** Produce KISSVM script that authorizes with a WOTS PK digest (32 bytes). */
|
|
3
|
+
export declare function scriptFromWotsPk(pkDigest32: Uint8Array): string;
|
|
4
|
+
/** Address from WOTS keypair (client-only): script -> MMR leaf -> Mx */
|
|
5
|
+
export declare function wotsAddressFromKeypair(kp: WotsKeypair): string;
|
|
6
|
+
/** tiny utils */
|
|
7
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scriptFromWotsPk = scriptFromWotsPk;
|
|
4
|
+
exports.wotsAddressFromKeypair = wotsAddressFromKeypair;
|
|
5
|
+
exports.hexToBytes = hexToBytes;
|
|
6
|
+
const util_js_1 = require("./util.js");
|
|
7
|
+
const derive_js_1 = require("./derive.js");
|
|
8
|
+
/** Produce KISSVM script that authorizes with a WOTS PK digest (32 bytes). */
|
|
9
|
+
function scriptFromWotsPk(pkDigest32) {
|
|
10
|
+
// Minima uses SHA3-256 in SIGNEDBY paths; here we embed the digest as hex.
|
|
11
|
+
return `RETURN SIGNEDBY(${(0, util_js_1.bytesToHex)(pkDigest32)})`;
|
|
12
|
+
}
|
|
13
|
+
/** Address from WOTS keypair (client-only): script -> MMR leaf -> Mx */
|
|
14
|
+
function wotsAddressFromKeypair(kp) {
|
|
15
|
+
const script = scriptFromWotsPk(kp.pk);
|
|
16
|
+
return (0, derive_js_1.scriptToAddress)(script);
|
|
17
|
+
}
|
|
18
|
+
/** tiny utils */
|
|
19
|
+
function hexToBytes(hex) {
|
|
20
|
+
let h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
21
|
+
if (h.length % 2)
|
|
22
|
+
h = "0" + h;
|
|
23
|
+
const out = new Uint8Array(h.length / 2);
|
|
24
|
+
for (let i = 0; i < out.length; i++)
|
|
25
|
+
out[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
26
|
+
return out;
|
|
27
|
+
}
|