@totemsdk/core 1.0.9 → 1.0.11
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/LICENSE +21 -0
- package/README.md +5 -5
- package/dist/Streamable.js +54 -31
- package/dist/adapters/index.js +18 -8
- package/dist/adapters/types.js +19 -8
- package/dist/binio.js +5 -1
- package/dist/bip39.js +24 -14
- package/dist/derive.js +11 -7
- package/dist/index.js +130 -22
- package/dist/javaStreamables.js +49 -30
- package/dist/lease/LeaseMonitor.js +7 -3
- package/dist/lease/LeaseStore.js +7 -3
- package/dist/lease/WatermarkStore.js +7 -3
- package/dist/lease/index.js +13 -4
- package/dist/lease-client.js +8 -3
- package/dist/minima32.js +22 -13
- package/dist/minimaWireSerializer.js +20 -14
- package/dist/mmr.js +35 -23
- package/dist/mx.js +10 -1
- package/dist/params.js +9 -5
- package/dist/script.js +12 -7
- package/dist/scripts/contract-helpers.js +37 -26
- package/dist/scripts/dapp-types.js +11 -6
- package/dist/scripts/index.js +38 -4
- package/dist/scripts/types.js +26 -12
- package/dist/scripts/witness-serializer.js +48 -30
- package/dist/transaction.js +55 -46
- package/dist/treekey.js +74 -58
- package/dist/tx/TransactionLifecycle.js +11 -5
- package/dist/tx/TransactionReceiptStore.js +7 -3
- package/dist/tx/TransactionService.js +14 -10
- package/dist/tx/index.js +11 -3
- package/dist/tx/types.js +2 -1
- package/dist/util.js +5 -1
- package/dist/utils.js +12 -5
- package/dist/verify.js +36 -25
- package/dist/version.js +5 -2
- package/dist/wots.d.ts +2 -2
- package/dist/wots.js +94 -64
- package/package.json +50 -6
- package/src/Streamable.d.ts +0 -268
- package/src/Streamable.js +0 -416
- package/src/Streamable.ts +0 -567
- package/src/__tests__/Streamable.parity.test.ts +0 -422
- package/src/__tests__/perAddressDerivation.parity.test.ts +0 -152
- package/src/__tests__/roottree-prepare.test.ts +0 -101
- package/src/__tests__/wots-parity.test.ts +0 -289
- package/src/adapters/index.d.ts +0 -190
- package/src/adapters/index.js +0 -117
- package/src/adapters/index.ts +0 -301
- package/src/adapters/types.ts +0 -235
- package/src/addr.oracle.test.ts +0 -25
- package/src/address.test.ts +0 -55
- package/src/binio.ts +0 -21
- package/src/bip39.d.ts +0 -91
- package/src/bip39.js +0 -427
- package/src/bip39.ts +0 -432
- package/src/derive.d.ts +0 -2
- package/src/derive.js +0 -13
- package/src/derive.ts +0 -11
- package/src/index.d.ts +0 -26
- package/src/index.js +0 -128
- package/src/index.test.ts +0 -5
- package/src/index.ts +0 -221
- package/src/javaStreamables.d.ts +0 -233
- package/src/javaStreamables.js +0 -332
- package/src/javaStreamables.ts +0 -403
- package/src/lease/LeaseMonitor.d.ts +0 -44
- package/src/lease/LeaseMonitor.js +0 -111
- package/src/lease/LeaseMonitor.ts +0 -157
- package/src/lease/LeaseStore.d.ts +0 -57
- package/src/lease/LeaseStore.js +0 -148
- package/src/lease/LeaseStore.ts +0 -203
- package/src/lease/WatermarkStore.d.ts +0 -61
- package/src/lease/WatermarkStore.js +0 -206
- package/src/lease/WatermarkStore.ts +0 -270
- package/src/lease/index.d.ts +0 -14
- package/src/lease/index.js +0 -22
- package/src/lease/index.ts +0 -41
- package/src/lease-client.d.ts +0 -31
- package/src/lease-client.js +0 -44
- package/src/lease-client.ts +0 -69
- package/src/minima32.d.ts +0 -10
- package/src/minima32.js +0 -113
- package/src/minima32.test.ts +0 -11
- package/src/minima32.ts +0 -127
- package/src/minimaWireSerializer.d.ts +0 -189
- package/src/minimaWireSerializer.js +0 -311
- package/src/minimaWireSerializer.test.ts +0 -466
- package/src/minimaWireSerializer.ts +0 -117
- package/src/mmr.d.ts +0 -157
- package/src/mmr.js +0 -340
- package/src/mmr.oracle.test.ts +0 -28
- package/src/mmr.ts +0 -429
- package/src/mx.test.ts +0 -25
- package/src/mx.ts +0 -1
- package/src/params.d.ts +0 -29
- package/src/params.d.ts.map +0 -1
- package/src/params.js +0 -20
- package/src/params.js.map +0 -1
- package/src/params.ts +0 -44
- package/src/script.d.ts +0 -7
- package/src/script.js +0 -27
- package/src/script.ts +0 -24
- package/src/scripts/contract-helpers.ts +0 -609
- package/src/scripts/dapp-types.ts +0 -240
- package/src/scripts/index.ts +0 -22
- package/src/scripts/types.d.ts +0 -81
- package/src/scripts/types.js +0 -145
- package/src/scripts/types.ts +0 -247
- package/src/scripts/witness-serializer.ts +0 -384
- package/src/transaction.ts +0 -430
- package/src/treekey.d.ts +0 -383
- package/src/treekey.js +0 -774
- package/src/treekey.parity.test.ts +0 -459
- package/src/treekey.ts +0 -975
- package/src/tx/TransactionLifecycle.d.ts +0 -55
- package/src/tx/TransactionLifecycle.js +0 -188
- package/src/tx/TransactionLifecycle.ts +0 -280
- package/src/tx/TransactionReceiptStore.d.ts +0 -36
- package/src/tx/TransactionReceiptStore.js +0 -89
- package/src/tx/TransactionReceiptStore.ts +0 -112
- package/src/tx/TransactionService.d.ts +0 -31
- package/src/tx/TransactionService.js +0 -140
- package/src/tx/TransactionService.ts +0 -252
- package/src/tx/index.d.ts +0 -13
- package/src/tx/index.js +0 -20
- package/src/tx/index.ts +0 -44
- package/src/tx/types.d.ts +0 -80
- package/src/tx/types.js +0 -6
- package/src/tx/types.ts +0 -130
- package/src/util.d.ts +0 -1
- package/src/util.js +0 -5
- package/src/util.ts +0 -1
- package/src/utils.d.ts +0 -8
- package/src/utils.js +0 -42
- package/src/utils.ts +0 -38
- package/src/verify.ts +0 -210
- package/src/version.ts +0 -13
- package/src/wots.d.ts +0 -224
- package/src/wots.d.ts.map +0 -1
- package/src/wots.js +0 -565
- package/src/wots.js.map +0 -1
- package/src/wots.ts +0 -651
- package/test-vectors.json +0 -45
|
@@ -1,466 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for Minima Wire Format Serialization
|
|
3
|
-
*
|
|
4
|
-
* Tests byte-exact compatibility with Java Signature.java and SignatureProof.java
|
|
5
|
-
*/
|
|
6
|
-
import { describe, it, expect } from 'vitest';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
serializeHierarchicalWitness,
|
|
10
|
-
serializeMiniNumber,
|
|
11
|
-
serializeMiniData,
|
|
12
|
-
fromHex,
|
|
13
|
-
toHex,
|
|
14
|
-
} from './minimaWireSerializer';
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
writeMiniNumber,
|
|
18
|
-
writeMiniData,
|
|
19
|
-
writeHashToStream,
|
|
20
|
-
writeMMRData,
|
|
21
|
-
writeMMRProof,
|
|
22
|
-
writeSignatureProof,
|
|
23
|
-
writeSignature,
|
|
24
|
-
hexToBytes,
|
|
25
|
-
bytesToHex,
|
|
26
|
-
type MMRData,
|
|
27
|
-
type MMRProofChunk,
|
|
28
|
-
type MMRProof,
|
|
29
|
-
type SignatureProof,
|
|
30
|
-
type Signature,
|
|
31
|
-
} from './Streamable';
|
|
32
|
-
|
|
33
|
-
// Alias for test compatibility (tests use serialize* naming)
|
|
34
|
-
const serializeMMRData = writeMMRData;
|
|
35
|
-
const serializeMMRProof = writeMMRProof;
|
|
36
|
-
const serializeSignatureProof = writeSignatureProof;
|
|
37
|
-
const serializeSignature = writeSignature;
|
|
38
|
-
|
|
39
|
-
describe('MiniNumber Serialization', () => {
|
|
40
|
-
it('serializes zero correctly', () => {
|
|
41
|
-
const result = serializeMiniNumber(0n);
|
|
42
|
-
expect(Array.from(result)).toEqual([0, 1, 0x00]);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('serializes small positive integers', () => {
|
|
46
|
-
const result = serializeMiniNumber(1n);
|
|
47
|
-
expect(result[0]).toBe(0); // scale
|
|
48
|
-
expect(result[1]).toBe(1); // length
|
|
49
|
-
expect(result[2]).toBe(1); // value
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('serializes count of 3 (typical for hierarchical proofs)', () => {
|
|
53
|
-
const result = serializeMiniNumber(3n);
|
|
54
|
-
expect(Array.from(result)).toEqual([0, 1, 3]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('serializes larger numbers with proper length', () => {
|
|
58
|
-
const result = serializeMiniNumber(256n);
|
|
59
|
-
expect(result[0]).toBe(0); // scale
|
|
60
|
-
expect(result[1]).toBe(2); // length (needs 2 bytes: 0x01 0x00)
|
|
61
|
-
expect(result[2]).toBe(1);
|
|
62
|
-
expect(result[3]).toBe(0);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('adds leading zero for negative sign bit', () => {
|
|
66
|
-
const result = serializeMiniNumber(128n);
|
|
67
|
-
expect(result[0]).toBe(0); // scale
|
|
68
|
-
expect(result[1]).toBe(2); // length (0x80 has high bit set, needs 0x00 prefix)
|
|
69
|
-
expect(result[2]).toBe(0);
|
|
70
|
-
expect(result[3]).toBe(0x80);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe('MiniData Serialization', () => {
|
|
75
|
-
it('serializes empty data with 4-byte zero length', () => {
|
|
76
|
-
const result = serializeMiniData(new Uint8Array(0));
|
|
77
|
-
expect(Array.from(result)).toEqual([0, 0, 0, 0]);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('serializes 32-byte hash with proper length prefix', () => {
|
|
81
|
-
const hash = new Uint8Array(32).fill(0xAB);
|
|
82
|
-
const result = serializeMiniData(hash);
|
|
83
|
-
|
|
84
|
-
expect(result.length).toBe(4 + 32);
|
|
85
|
-
expect(result[0]).toBe(0);
|
|
86
|
-
expect(result[1]).toBe(0);
|
|
87
|
-
expect(result[2]).toBe(0);
|
|
88
|
-
expect(result[3]).toBe(32);
|
|
89
|
-
expect(result[4]).toBe(0xAB);
|
|
90
|
-
expect(result[35]).toBe(0xAB);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('serializes WOTS signature (34*32 = 1088 bytes)', () => {
|
|
94
|
-
const signature = new Uint8Array(1088).fill(0xCD);
|
|
95
|
-
const result = serializeMiniData(signature);
|
|
96
|
-
|
|
97
|
-
expect(result.length).toBe(4 + 1088);
|
|
98
|
-
expect((result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3]).toBe(1088);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('Hash Stream Writing', () => {
|
|
103
|
-
it('writes 32-byte hash with 4-byte length prefix', () => {
|
|
104
|
-
const hash = new Uint8Array(32).fill(0xEF);
|
|
105
|
-
const result = writeHashToStream(hash);
|
|
106
|
-
|
|
107
|
-
// 4-byte prefix + 32 bytes = 36 bytes total
|
|
108
|
-
expect(result.length).toBe(36);
|
|
109
|
-
// First 4 bytes are big-endian length (32 = 0x00000020)
|
|
110
|
-
expect(result[0]).toBe(0);
|
|
111
|
-
expect(result[1]).toBe(0);
|
|
112
|
-
expect(result[2]).toBe(0);
|
|
113
|
-
expect(result[3]).toBe(32);
|
|
114
|
-
// Hash data follows
|
|
115
|
-
expect(result[4]).toBe(0xEF);
|
|
116
|
-
expect(result[35]).toBe(0xEF);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('rejects inputs over 64 bytes (MINIMA_MAX_HASH_LENGTH)', () => {
|
|
120
|
-
expect(() => writeHashToStream(new Uint8Array(65))).toThrow('Hash too long');
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
describe('MMRData Serialization', () => {
|
|
125
|
-
it('serializes MMRData with hash (4-byte prefix) and value', () => {
|
|
126
|
-
const mmrData: MMRData = {
|
|
127
|
-
data: new Uint8Array(32).fill(0x11),
|
|
128
|
-
value: 1n
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const result = serializeMMRData(mmrData);
|
|
132
|
-
// 4-byte length prefix + 32-byte hash + 3-byte MiniNumber = 39 bytes
|
|
133
|
-
expect(result.length).toBe(4 + 32 + 3);
|
|
134
|
-
// Length prefix (32 = 0x00000020)
|
|
135
|
-
expect(result[0]).toBe(0);
|
|
136
|
-
expect(result[1]).toBe(0);
|
|
137
|
-
expect(result[2]).toBe(0);
|
|
138
|
-
expect(result[3]).toBe(32);
|
|
139
|
-
// Hash data
|
|
140
|
-
expect(result[4]).toBe(0x11);
|
|
141
|
-
expect(result[35]).toBe(0x11);
|
|
142
|
-
// MiniNumber value (1)
|
|
143
|
-
expect(result[36]).toBe(0); // scale
|
|
144
|
-
expect(result[37]).toBe(1); // length
|
|
145
|
-
expect(result[38]).toBe(1); // value
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
describe('MMRProof Serialization', () => {
|
|
150
|
-
it('serializes empty proof', () => {
|
|
151
|
-
const proof: MMRProof = { blockTime: 0n, chunks: [] };
|
|
152
|
-
const result = serializeMMRProof(proof);
|
|
153
|
-
|
|
154
|
-
expect(result.length).toBe(6);
|
|
155
|
-
expect(Array.from(result.slice(0, 3))).toEqual([0, 1, 0]);
|
|
156
|
-
expect(Array.from(result.slice(3, 6))).toEqual([0, 1, 0]);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('serializes proof with single chunk', () => {
|
|
160
|
-
const chunk: MMRProofChunk = {
|
|
161
|
-
isLeft: true,
|
|
162
|
-
mmrData: {
|
|
163
|
-
data: new Uint8Array(32).fill(0x22),
|
|
164
|
-
value: 0n
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
const proof: MMRProof = { blockTime: 0n, chunks: [chunk] };
|
|
168
|
-
const result = serializeMMRProof(proof);
|
|
169
|
-
|
|
170
|
-
const blockTimeLen = 3;
|
|
171
|
-
const countLen = 3;
|
|
172
|
-
// Chunk = 1 (isLeft) + 4 (hash length prefix) + 32 (hash) + 3 (MiniNumber.ZERO) = 40 bytes
|
|
173
|
-
const chunkLen = 1 + 4 + 32 + 3;
|
|
174
|
-
expect(result.length).toBe(blockTimeLen + countLen + chunkLen);
|
|
175
|
-
|
|
176
|
-
// isLeft byte
|
|
177
|
-
expect(result[blockTimeLen + countLen]).toBe(1);
|
|
178
|
-
// First byte of hash length prefix (0x00)
|
|
179
|
-
expect(result[blockTimeLen + countLen + 1]).toBe(0);
|
|
180
|
-
// Fifth byte is first byte of hash data
|
|
181
|
-
expect(result[blockTimeLen + countLen + 5]).toBe(0x22);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('serializes isLeft correctly (0 or 1)', () => {
|
|
185
|
-
const leftChunk: MMRProofChunk = {
|
|
186
|
-
isLeft: true,
|
|
187
|
-
mmrData: { data: new Uint8Array(32), value: 0n }
|
|
188
|
-
};
|
|
189
|
-
const rightChunk: MMRProofChunk = {
|
|
190
|
-
isLeft: false,
|
|
191
|
-
mmrData: { data: new Uint8Array(32), value: 0n }
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
const leftProof = serializeMMRProof({ blockTime: 0n, chunks: [leftChunk] });
|
|
195
|
-
const rightProof = serializeMMRProof({ blockTime: 0n, chunks: [rightChunk] });
|
|
196
|
-
|
|
197
|
-
// isLeft byte is at offset 6 (after blockTime[3] + count[3])
|
|
198
|
-
expect(leftProof[6]).toBe(1);
|
|
199
|
-
expect(rightProof[6]).toBe(0);
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
describe('SignatureProof Serialization', () => {
|
|
204
|
-
it('serializes complete SignatureProof', () => {
|
|
205
|
-
const sigProof: SignatureProof = {
|
|
206
|
-
leafPubkey: new Uint8Array(32).fill(0xAA), // 32-byte WOTS digest
|
|
207
|
-
signature: new Uint8Array(1088).fill(0xBB),
|
|
208
|
-
mmrProof: { blockTime: 0n, chunks: [] }
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const result = serializeSignatureProof(sigProof);
|
|
212
|
-
|
|
213
|
-
const pubKeyLen = 4 + 32; // 32-byte digest
|
|
214
|
-
const sigLen = 4 + 1088;
|
|
215
|
-
const proofLen = 6;
|
|
216
|
-
expect(result.length).toBe(pubKeyLen + sigLen + proofLen);
|
|
217
|
-
|
|
218
|
-
expect(result[0]).toBe(0);
|
|
219
|
-
expect(result[3]).toBe(32);
|
|
220
|
-
expect(result[4]).toBe(0xAA);
|
|
221
|
-
|
|
222
|
-
expect(result[pubKeyLen + 3]).toBe(0x20);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
describe('Signature Serialization', () => {
|
|
227
|
-
it('serializes signature with 3 proofs (hierarchical TreeKey)', () => {
|
|
228
|
-
const createProof = (fill: number): SignatureProof => ({
|
|
229
|
-
leafPubkey: new Uint8Array(32).fill(fill), // 32-byte WOTS digest
|
|
230
|
-
signature: new Uint8Array(1088).fill(fill),
|
|
231
|
-
mmrProof: { blockTime: 0n, chunks: [] }
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
const signature: Signature = {
|
|
235
|
-
proofs: [createProof(0x11), createProof(0x22), createProof(0x33)]
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const result = serializeSignature(signature);
|
|
239
|
-
|
|
240
|
-
expect(Array.from(result.slice(0, 3))).toEqual([0, 1, 3]);
|
|
241
|
-
|
|
242
|
-
const proofSize = 4 + 32 + 4 + 1088 + 6; // 32-byte digest, not 1088
|
|
243
|
-
expect(result.length).toBe(3 + 3 * proofSize);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('serializes signature count correctly', () => {
|
|
247
|
-
const createProof = (): SignatureProof => ({
|
|
248
|
-
leafPubkey: new Uint8Array(32), // 32-byte WOTS digest
|
|
249
|
-
signature: new Uint8Array(1088),
|
|
250
|
-
mmrProof: { blockTime: 0n, chunks: [] }
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
const sig1: Signature = { proofs: [createProof()] };
|
|
254
|
-
const sig3: Signature = { proofs: [createProof(), createProof(), createProof()] };
|
|
255
|
-
|
|
256
|
-
expect(serializeSignature(sig1)[2]).toBe(1);
|
|
257
|
-
expect(serializeSignature(sig3)[2]).toBe(3);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
describe('Hex Utilities', () => {
|
|
262
|
-
it('converts hex to bytes', () => {
|
|
263
|
-
const bytes = fromHex('0x0102030405');
|
|
264
|
-
expect(Array.from(bytes)).toEqual([1, 2, 3, 4, 5]);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('converts bytes to hex with 0x prefix', () => {
|
|
268
|
-
const bytes = new Uint8Array([1, 2, 3, 4, 5]);
|
|
269
|
-
expect(toHex(bytes)).toBe('0x0102030405');
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('handles hex without 0x prefix', () => {
|
|
273
|
-
const bytes = fromHex('abcdef');
|
|
274
|
-
expect(Array.from(bytes)).toEqual([0xab, 0xcd, 0xef]);
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
describe('Hierarchical Witness Serialization', () => {
|
|
279
|
-
it('serializes complete hierarchical witness bundle', () => {
|
|
280
|
-
const emptyProof = '0x' + '00010000010000';
|
|
281
|
-
|
|
282
|
-
const bundle = {
|
|
283
|
-
addressIndex: 0,
|
|
284
|
-
l1: 0,
|
|
285
|
-
l2: 0,
|
|
286
|
-
rootPublicKey: '0x' + 'aa'.repeat(32),
|
|
287
|
-
proofs: [
|
|
288
|
-
{
|
|
289
|
-
leafPubkey: '0x' + '11'.repeat(32),
|
|
290
|
-
signature: '0x' + '22'.repeat(1088),
|
|
291
|
-
mmrProof: emptyProof
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
leafPubkey: '0x' + '33'.repeat(32),
|
|
295
|
-
signature: '0x' + '44'.repeat(1088),
|
|
296
|
-
mmrProof: emptyProof
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
leafPubkey: '0x' + '55'.repeat(32),
|
|
300
|
-
signature: '0x' + '66'.repeat(1088),
|
|
301
|
-
mmrProof: emptyProof
|
|
302
|
-
}
|
|
303
|
-
]
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const result = serializeHierarchicalWitness(bundle);
|
|
307
|
-
|
|
308
|
-
expect(result[0]).toBe(0);
|
|
309
|
-
expect(result[1]).toBe(1);
|
|
310
|
-
expect(result[2]).toBe(3);
|
|
311
|
-
|
|
312
|
-
expect(result.length).toBeGreaterThan(3300);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
import {
|
|
317
|
-
serializeMMREntryNumber,
|
|
318
|
-
serializeMMREntry,
|
|
319
|
-
createMMREntryNumber,
|
|
320
|
-
serializeMMRData as serializeMMRDataJava,
|
|
321
|
-
type MMREntry as MMREntryType,
|
|
322
|
-
type MMREntryNumber as MMREntryNumberType,
|
|
323
|
-
type MMRData as MMRDataJavaType,
|
|
324
|
-
} from './javaStreamables';
|
|
325
|
-
|
|
326
|
-
describe('MMREntryNumber Serialization', () => {
|
|
327
|
-
it('serializes ZERO correctly', () => {
|
|
328
|
-
const entry: MMREntryNumberType = { scale: 0, unscaled: 0n };
|
|
329
|
-
const result = serializeMMREntryNumber(entry);
|
|
330
|
-
expect(Array.from(result)).toEqual([
|
|
331
|
-
0, 1, 0, // MiniNumber(scale=0): scale(0) + len(1) + data(0)
|
|
332
|
-
0, 0, 0, 1, 0 // MiniData(unscaled): 4-byte len(1) + data(0)
|
|
333
|
-
]);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('serializes small positive integers', () => {
|
|
337
|
-
const entry = createMMREntryNumber(63n);
|
|
338
|
-
const result = serializeMMREntryNumber(entry);
|
|
339
|
-
expect(result[0]).toBe(0); // scale byte
|
|
340
|
-
expect(result[1]).toBe(1); // length byte
|
|
341
|
-
expect(result[2]).toBe(0); // scale value = 0
|
|
342
|
-
expect(result.slice(3, 7)).toEqual(new Uint8Array([0, 0, 0, 1])); // MiniData length = 1
|
|
343
|
-
expect(result[7]).toBe(63); // unscaled value
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
it('serializes 128 with sign extension', () => {
|
|
347
|
-
const entry = createMMREntryNumber(128n);
|
|
348
|
-
const result = serializeMMREntryNumber(entry);
|
|
349
|
-
expect(result.slice(3, 7)).toEqual(new Uint8Array([0, 0, 0, 2])); // MiniData length = 2
|
|
350
|
-
expect(result[7]).toBe(0); // leading zero for sign
|
|
351
|
-
expect(result[8]).toBe(128); // value
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
describe('MMREntry Serialization', () => {
|
|
356
|
-
it('serializes complete MMREntry', () => {
|
|
357
|
-
const hash = new Uint8Array(32).fill(0xab);
|
|
358
|
-
const entry: MMREntryType = {
|
|
359
|
-
row: 0,
|
|
360
|
-
entryNumber: { scale: 0, unscaled: 5n },
|
|
361
|
-
mmrData: { data: hash, value: 0n }
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const result = serializeMMREntry(entry);
|
|
365
|
-
expect(result[0]).toBe(0); // row scale
|
|
366
|
-
expect(result[1]).toBe(1); // row length
|
|
367
|
-
expect(result[2]).toBe(0); // row value = 0
|
|
368
|
-
|
|
369
|
-
expect(result.length).toBeGreaterThan(40);
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
it('serializes row 3 entry 10 correctly', () => {
|
|
373
|
-
const hash = new Uint8Array(32).fill(0xff);
|
|
374
|
-
const entry: MMREntryType = {
|
|
375
|
-
row: 3,
|
|
376
|
-
entryNumber: { scale: 0, unscaled: 10n },
|
|
377
|
-
mmrData: { data: hash, value: 0n }
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
const result = serializeMMREntry(entry);
|
|
381
|
-
expect(result[0]).toBe(0); // row scale
|
|
382
|
-
expect(result[1]).toBe(1); // row length
|
|
383
|
-
expect(result[2]).toBe(3); // row value = 3
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
describe('MMRData Java Serialization', () => {
|
|
388
|
-
it('serializes MMRData with hash and zero value', () => {
|
|
389
|
-
const hash = new Uint8Array(32).fill(0xcc);
|
|
390
|
-
const mmrData: MMRDataJavaType = { data: hash, value: 0n };
|
|
391
|
-
|
|
392
|
-
const result = serializeMMRDataJava(mmrData);
|
|
393
|
-
expect(result[0]).toBe(0); // 4-byte length prefix
|
|
394
|
-
expect(result[1]).toBe(0);
|
|
395
|
-
expect(result[2]).toBe(0);
|
|
396
|
-
expect(result[3]).toBe(32); // hash length
|
|
397
|
-
expect(result.slice(4, 36)).toEqual(hash);
|
|
398
|
-
expect(result.slice(36)).toEqual(new Uint8Array([0, 1, 0])); // MiniNumber.ZERO
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
describe('MMRProof round-trip', () => {
|
|
403
|
-
it('serializeMMRProof output can be parsed correctly', () => {
|
|
404
|
-
const hash1 = new Uint8Array(32).fill(0xaa);
|
|
405
|
-
const hash2 = new Uint8Array(32).fill(0xbb);
|
|
406
|
-
const proof: MMRProof = {
|
|
407
|
-
blockTime: 0n,
|
|
408
|
-
chunks: [
|
|
409
|
-
{ isLeft: true, mmrData: { data: hash1, value: 0n } },
|
|
410
|
-
{ isLeft: false, mmrData: { data: hash2, value: 0n } }
|
|
411
|
-
]
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
const serialized = serializeMMRProof(proof);
|
|
415
|
-
|
|
416
|
-
expect(serialized[0]).toBe(0); // blockTime scale
|
|
417
|
-
expect(serialized[1]).toBe(1); // blockTime len
|
|
418
|
-
expect(serialized[2]).toBe(0); // blockTime value = 0
|
|
419
|
-
expect(serialized[3]).toBe(0); // chainLength scale
|
|
420
|
-
expect(serialized[4]).toBe(1); // chainLength len
|
|
421
|
-
expect(serialized[5]).toBe(2); // chainLength value = 2 (two chunks)
|
|
422
|
-
|
|
423
|
-
const chunkSize = 1 + 4 + 32 + 3; // isLeft + 4-byte prefix + 32-byte hash + MiniNumber.ZERO
|
|
424
|
-
expect(serialized.length).toBe(6 + chunkSize * 2);
|
|
425
|
-
});
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
describe('SDK consolidation verification', () => {
|
|
429
|
-
it('serializeMMRProof produces consistent output across calls', () => {
|
|
430
|
-
const hash1 = new Uint8Array(32);
|
|
431
|
-
for (let i = 0; i < 32; i++) hash1[i] = i;
|
|
432
|
-
const hash2 = new Uint8Array(32);
|
|
433
|
-
for (let i = 0; i < 32; i++) hash2[i] = 255 - i;
|
|
434
|
-
const hash3 = new Uint8Array(32).fill(0x42);
|
|
435
|
-
|
|
436
|
-
const proof: MMRProof = {
|
|
437
|
-
blockTime: 0n,
|
|
438
|
-
chunks: [
|
|
439
|
-
{ isLeft: true, mmrData: { data: hash1, value: 0n } },
|
|
440
|
-
{ isLeft: false, mmrData: { data: hash2, value: 100n } },
|
|
441
|
-
{ isLeft: true, mmrData: { data: hash3, value: 1000000n } }
|
|
442
|
-
]
|
|
443
|
-
};
|
|
444
|
-
|
|
445
|
-
// Verify serializeMMRProof produces consistent byte-exact output
|
|
446
|
-
const result1 = serializeMMRProof(proof);
|
|
447
|
-
const result2 = serializeMMRProof(proof);
|
|
448
|
-
|
|
449
|
-
expect(toHex(result1)).toBe(toHex(result2));
|
|
450
|
-
expect(result1.length).toBe(result2.length);
|
|
451
|
-
|
|
452
|
-
// Verify basic structure (exact size depends on value encoding)
|
|
453
|
-
// Minimum: blockTime(3) + chainLen(3) + 3 * (isLeft(1) + lengthPrefix(4) + hash(32) + value)
|
|
454
|
-
expect(result1.length).toBeGreaterThan(6 + 3 * (1 + 4 + 32)); // At least header + chunks without values
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
it('canonical serializer exports expected types', () => {
|
|
458
|
-
// Verify the exported types can be used correctly
|
|
459
|
-
const proof: MMRProof = { blockTime: 0n, chunks: [] };
|
|
460
|
-
const result = serializeMMRProof(proof);
|
|
461
|
-
|
|
462
|
-
// Empty proof should have: blockTime(3B) + chainLen(3B) = 6 bytes
|
|
463
|
-
expect(result.length).toBe(6);
|
|
464
|
-
expect(result[5]).toBe(0); // chainLen = 0
|
|
465
|
-
});
|
|
466
|
-
});
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minima Wire Format Serializer
|
|
3
|
-
*
|
|
4
|
-
* High-level serialization for hex-string bundles (used in service.ts).
|
|
5
|
-
* Primitive serialization functions are imported from Streamable.ts.
|
|
6
|
-
*
|
|
7
|
-
* @deprecated (2026-01) - Most functions deprecated. Use Streamable.ts directly for
|
|
8
|
-
* byte-level serialization. This file remains for HierarchicalWitnessBundle hex APIs.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
concat,
|
|
13
|
-
hexToBytes,
|
|
14
|
-
bytesToHex,
|
|
15
|
-
writeMiniNumber,
|
|
16
|
-
writeMiniData,
|
|
17
|
-
type Bytes,
|
|
18
|
-
} from './Streamable.js';
|
|
19
|
-
|
|
20
|
-
// Re-export primitives for backward compatibility
|
|
21
|
-
export { writeMiniNumber as serializeMiniNumber, writeMiniData as serializeMiniData };
|
|
22
|
-
export { hexToBytes as fromHex, bytesToHex as toHex };
|
|
23
|
-
export type { Bytes };
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* SignatureProof with hex strings (for bundle transport)
|
|
27
|
-
*/
|
|
28
|
-
export interface SignatureProofHex {
|
|
29
|
-
leafPubkey: string;
|
|
30
|
-
signature: string;
|
|
31
|
-
mmrProof: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* HierarchicalWitnessBundle - used by service.ts for transaction signing
|
|
36
|
-
* All fields are hex strings for JSON transport
|
|
37
|
-
*/
|
|
38
|
-
export interface HierarchicalWitnessBundle {
|
|
39
|
-
addressIndex: number;
|
|
40
|
-
l1: number;
|
|
41
|
-
l2: number;
|
|
42
|
-
rootPublicKey: string;
|
|
43
|
-
proofs: SignatureProofHex[];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Serialize a SignatureProof from pre-serialized byte arrays
|
|
48
|
-
*
|
|
49
|
-
* This avoids double-serialization by passing MMR proof bytes through directly.
|
|
50
|
-
* Format matches SignatureProof.writeDataStream():
|
|
51
|
-
* 1. MiniData (publicKey) - 4-byte length + bytes
|
|
52
|
-
* 2. MiniData (signature) - 4-byte length + bytes
|
|
53
|
-
* 3. MMRProof bytes (pre-serialized)
|
|
54
|
-
*/
|
|
55
|
-
function serializeSignatureProofFromBytes(
|
|
56
|
-
publicKey: Bytes,
|
|
57
|
-
signature: Bytes,
|
|
58
|
-
mmrProofBytes: Bytes
|
|
59
|
-
): Bytes {
|
|
60
|
-
return concat(
|
|
61
|
-
writeMiniData(publicKey),
|
|
62
|
-
writeMiniData(signature),
|
|
63
|
-
mmrProofBytes // Already serialized - pass through directly
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Serialize hierarchical witness bundle to Minima wire format
|
|
69
|
-
*
|
|
70
|
-
* This converts the HierarchicalWitnessBundle (with hex strings) to
|
|
71
|
-
* the proper Witness signature format matching Witness.java → Signature.java hierarchy.
|
|
72
|
-
*
|
|
73
|
-
* CRITICAL FIX (2026-01): Must use double-nesting to match Java format:
|
|
74
|
-
* - Witness.writeDataStream writes: [signatureCount][Signature[0].writeDataStream()]...
|
|
75
|
-
* - Signature.writeDataStream writes: [proofCount][SignatureProof[0]]...
|
|
76
|
-
*
|
|
77
|
-
* So the final format is:
|
|
78
|
-
* [1] = signatureCount (we have 1 Signature object in Witness)
|
|
79
|
-
* [N] = proofCount inside that Signature (2 for address-based TreeKey)
|
|
80
|
-
* [SignatureProof[0]]
|
|
81
|
-
* [SignatureProof[1]]
|
|
82
|
-
*
|
|
83
|
-
* IMPORTANT: Uses pre-serialized MMR proof bytes directly to avoid
|
|
84
|
-
* double-serialization (deserialize then re-serialize).
|
|
85
|
-
*/
|
|
86
|
-
export function serializeHierarchicalWitness(bundle: HierarchicalWitnessBundle): Bytes {
|
|
87
|
-
const parts: Bytes[] = [];
|
|
88
|
-
|
|
89
|
-
// Witness.signatureCount (MiniNumber) - 1 Signature object containing N proofs
|
|
90
|
-
parts.push(writeMiniNumber(1n));
|
|
91
|
-
|
|
92
|
-
// Signature.proofCount (MiniNumber) - N SignatureProofs inside the Signature
|
|
93
|
-
parts.push(writeMiniNumber(BigInt(bundle.proofs.length)));
|
|
94
|
-
|
|
95
|
-
for (const proofHex of bundle.proofs) {
|
|
96
|
-
const publicKey = hexToBytes(proofHex.leafPubkey);
|
|
97
|
-
const signature = hexToBytes(proofHex.signature);
|
|
98
|
-
const mmrProofBytes = hexToBytes(proofHex.mmrProof); // Already serialized
|
|
99
|
-
|
|
100
|
-
// Serialize SignatureProof with pre-serialized MMR bytes
|
|
101
|
-
parts.push(serializeSignatureProofFromBytes(publicKey, signature, mmrProofBytes));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return concat(...parts);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @deprecated (2026-01) This function's output is NOT used in the main Totem transaction flow.
|
|
109
|
-
* MinimaTransactionBuilder.serializeWitness in the extension handles actual witness serialization.
|
|
110
|
-
* Kept for API compatibility and potential future direct SDK usage.
|
|
111
|
-
*
|
|
112
|
-
* Serialize hierarchical witness bundle to hex string for transport
|
|
113
|
-
*/
|
|
114
|
-
export function serializeHierarchicalWitnessToHex(bundle: HierarchicalWitnessBundle): string {
|
|
115
|
-
const bytes = serializeHierarchicalWitness(bundle);
|
|
116
|
-
return bytesToHex(bytes);
|
|
117
|
-
}
|