@taquito/timelock 24.3.0-beta.0 → 24.3.0-beta.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.
@@ -1,326 +1,780 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@stablelib/nacl'), require('big-integer'), require('@stablelib/blake2b')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@stablelib/nacl', 'big-integer', '@stablelib/blake2b'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.taquitoTimelock = {}, global.nacl, global.bigInt, global.blake2b));
5
- })(this, (function (exports, nacl, bigInt, blake2b) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@stablelib/nacl'), require('big-integer')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@stablelib/nacl', 'big-integer'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.taquitoTimelock = {}, global.nacl, global.bigInt));
5
+ })(this, (function (exports, nacl, bigInt) { 'use strict';
6
6
 
7
- // globalThis.crypto is available in browsers and Node.js 20+
8
- const defaultRNG$1 = globalThis.crypto;
9
- const RSA_MODULUS = bigInt('25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784406918290641249515082189298559149176184502808489120072844992687392807287776735971418347270261896375014971824691165077613379859095700097330459748808428401797429100642458691817195118746121515172654632282216869987549182422433637259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133844143603833904414952634432190114657544454178424020924616515723350778707749817125772467962926386356373289912154831438167899885040445364023527381951378636564391212010397122822120720357');
10
- function rand(rng = defaultRNG$1) {
11
- const bytes = new Uint8Array(4);
12
- rng.getRandomValues(bytes);
13
- const x = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
14
- return x / Math.pow(2, 32);
15
- }
16
- function randomInteger(rng, bits) {
17
- const bytes = new Uint8Array(bits / 8);
18
- rng.getRandomValues(bytes);
19
- return bigInt.fromArray(Array.from(bytes), 256);
20
- }
21
- function nextPrime(n) {
22
- if (n.compare(2) < 0) {
23
- return bigInt(2);
24
- }
25
- const limit = n.multiply(2);
26
- for (let p = n.next(); p.compare(limit) < 0; p = p.next()) {
27
- // use 25 bases like in GMP mpz_nextprime and thus in Tezos
28
- if (p.isProbablePrime(25, rand)) {
29
- return p;
30
- }
31
- }
32
- throw new Error('!!!nextPrime!!!'); // shouldn't happen
33
- }
34
- function generate(rng, mod) {
35
- const m = mod.subtract(bigInt(2));
36
- return randomInteger(rng, mod.bitLength().toJSNumber()).mod(m).add(bigInt(2));
37
- }
38
- function toLE(x) {
39
- return x.toArray(256).value.reverse();
40
- }
41
- function fromLE(x) {
42
- return bigInt.fromArray(x.reverse(), 256);
43
- }
44
- const HASH_SEPARATOR = [0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00];
45
- function hashToPrime(time, value, key, mod) {
46
- const b = [
47
- ...new TextEncoder().encode(String(time)),
48
- ...HASH_SEPARATOR,
49
- ...toLE(mod),
50
- ...HASH_SEPARATOR,
51
- ...toLE(value),
52
- ...HASH_SEPARATOR,
53
- ...toLE(key),
54
- ];
55
- const sum = blake2b.hash(new Uint8Array(b), 32, { key: new Uint8Array([32]) });
56
- const val = fromLE(Array.from(sum));
57
- return nextPrime(val);
58
- }
59
- function proveWesolowski(time, locked, unlocked, mod) {
60
- const l = hashToPrime(time, locked, unlocked, mod);
61
- let pi = bigInt(1);
62
- let r = bigInt(1);
63
- for (; time > 0; time -= 1) {
64
- const rr = r.multiply(2);
65
- r = rr.mod(l);
66
- const pi2 = pi.multiply(pi).mod(mod);
67
- if (rr.compare(l) >= 0) {
68
- pi = pi2.multiply(locked);
69
- }
70
- else {
71
- pi = pi2;
72
- }
73
- }
74
- return pi.mod(mod);
75
- }
76
- function prove(time, locked, unlocked, mod = RSA_MODULUS) {
77
- return new TimelockProof({
78
- vdfTuple: new Timelock({
79
- lockedValue: locked,
80
- unlockedValue: unlocked,
81
- vdfProof: proveWesolowski(time, locked, unlocked, mod),
82
- modulus: mod,
83
- }),
84
- nonce: bigInt(1),
85
- });
86
- }
87
- function unlockTimelock(time, locked, mod) {
88
- if (locked.compare(bigInt(1)) <= 0) {
89
- return locked;
90
- }
91
- let x = locked;
92
- for (; time > 0; time -= 1) {
93
- x = x.multiply(x).mod(mod);
94
- }
95
- return x;
96
- }
97
- function unlockAndProve(time, locked, mod = RSA_MODULUS) {
98
- const unlocked = unlockTimelock(time, locked, mod);
99
- return prove(time, locked, unlocked, mod);
100
- }
101
- function verifyWesolowski(vdfTuple, time) {
102
- const l = hashToPrime(time, vdfTuple.lockedValue, vdfTuple.unlockedValue, vdfTuple.modulus);
103
- const ll = vdfTuple.vdfProof.modPow(l, vdfTuple.modulus);
104
- const r = bigInt(2).modPow(time, l);
105
- const rr = vdfTuple.lockedValue.modPow(r, vdfTuple.modulus);
106
- const unlocked = ll.multiply(rr).mod(vdfTuple.modulus);
107
- return unlocked.compare(vdfTuple.unlockedValue) === 0;
108
- }
109
- function verify(locked, proof, time) {
110
- const randomizedChallenge = proof.vdfTuple.lockedValue.modPow(proof.nonce, proof.vdfTuple.modulus);
111
- return randomizedChallenge.compare(locked) === 0 && verifyWesolowski(proof.vdfTuple, time);
112
- }
113
- class Timelock {
114
- constructor({ lockedValue, unlockedValue, vdfProof, modulus }) {
115
- this.lockedValue = lockedValue;
116
- this.unlockedValue = unlockedValue;
117
- this.vdfProof = vdfProof;
118
- this.modulus = modulus ?? RSA_MODULUS;
119
- }
120
- static precompute(time, mod = RSA_MODULUS, rng = defaultRNG$1) {
121
- const locked = generate(rng, mod);
122
- const unlocked = unlockTimelock(time, locked, mod);
123
- return new Timelock({
124
- lockedValue: locked,
125
- unlockedValue: unlocked,
126
- vdfProof: proveWesolowski(time, locked, unlocked, mod),
127
- modulus: mod,
128
- });
129
- }
130
- getProof(time, rng = defaultRNG$1) {
131
- if (this.lockedValue.compare(bigInt(1)) < 1 ||
132
- this.unlockedValue.compare(bigInt(0)) < 1 ||
133
- this.vdfProof.compare(bigInt(0)) < 1 ||
134
- this.lockedValue.compare(this.modulus) > 0 ||
135
- this.unlockedValue.compare(this.modulus) > 0 ||
136
- this.vdfProof.compare(this.modulus) >= 0) {
137
- throw new Error('Invalid argument');
138
- }
139
- if (!verifyWesolowski(this, time)) {
140
- throw new Error('Verification error');
141
- }
142
- const nonce = randomInteger(rng, 16 * 8);
143
- const lockedValue = this.lockedValue.modPow(nonce, this.modulus);
144
- return {
145
- lockedValue,
146
- proof: new TimelockProof({
147
- vdfTuple: this,
148
- nonce,
149
- }),
150
- };
151
- }
152
- encode() {
153
- return new Uint8Array([
154
- ...encodeBigInt(this.lockedValue),
155
- ...encodeBigInt(this.unlockedValue),
156
- ...encodeBigInt(this.vdfProof),
157
- ]);
158
- }
159
- static fromArray(buf, mod = RSA_MODULUS) {
160
- let i = 0;
161
- const [lockedValue, n1] = decodeBigInt(buf);
162
- i += n1;
163
- const [unlockedValue, n2] = decodeBigInt(buf.slice(i));
164
- i += n2;
165
- const [vdfProof, n3] = decodeBigInt(buf.slice(i));
166
- i += n3;
167
- return [
168
- new Timelock({
169
- lockedValue,
170
- unlockedValue,
171
- vdfProof,
172
- modulus: mod,
173
- }),
174
- i,
175
- ];
176
- }
177
- }
178
- const KDF_KEY = new TextEncoder().encode('Tezoskdftimelockv1');
179
- class TimelockProof {
180
- constructor({ vdfTuple, nonce }) {
181
- this.vdfTuple = vdfTuple;
182
- this.nonce = nonce;
183
- }
184
- symmetricKey() {
185
- const updated = this.vdfTuple.unlockedValue.modPow(this.nonce, this.vdfTuple.modulus);
186
- return blake2b.hash(new TextEncoder().encode(String(updated)), 32, { key: KDF_KEY });
187
- }
188
- encode() {
189
- return new Uint8Array([...this.vdfTuple.encode(), ...encodeBigInt(this.nonce)]);
190
- }
191
- static fromArray(buf, mod = RSA_MODULUS) {
192
- let i = 0;
193
- const [vdfTuple, n1] = Timelock.fromArray(buf, mod);
194
- i += n1;
195
- const [nonce, n2] = decodeBigInt(buf.slice(i));
196
- i += n2;
197
- return [new TimelockProof({ vdfTuple, nonce }), i];
198
- }
199
- }
200
- function encodeBigInt(v) {
201
- if (v.isNegative()) {
202
- throw new Error('Negative value');
203
- }
204
- const res = [];
205
- for (let i = 0;; i++) {
206
- const x = v.and(bigInt(0x7f)).toJSNumber();
207
- v = v.shiftRight(7);
208
- if (!v.isZero()) {
209
- res.push(x | 0x80);
210
- }
211
- else {
212
- res.push(x);
213
- break;
214
- }
215
- }
216
- return res;
217
- }
218
- function decodeBigInt(buf) {
219
- let shift = 0;
220
- let i = 0;
221
- let res = bigInt(0);
222
- while (i < buf.length) {
223
- const x = buf[i];
224
- res = res.add(bigInt(x & 0x7f).shiftLeft(shift));
225
- shift += 7;
226
- i++;
227
- if ((x & 0x80) === 0)
228
- break;
229
- }
230
- return [res, i];
231
- }
7
+ /**
8
+ * Utilities for hex, bytes, CSPRNG.
9
+ * @module
10
+ */
11
+ /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
12
+ /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
13
+ function isBytes(a) {
14
+ return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
15
+ }
16
+ /** Asserts something is positive integer. */
17
+ function anumber(n, title = '') {
18
+ if (!Number.isSafeInteger(n) || n < 0) {
19
+ const prefix = title && `"${title}" `;
20
+ throw new Error(`${prefix}expected integer >= 0, got ${n}`);
21
+ }
22
+ }
23
+ /** Asserts something is Uint8Array. */
24
+ function abytes(value, length, title = '') {
25
+ const bytes = isBytes(value);
26
+ const len = value?.length;
27
+ const needsLen = length !== undefined;
28
+ if (!bytes || (needsLen && len !== length)) {
29
+ const prefix = title && `"${title}" `;
30
+ const ofLen = needsLen ? ` of length ${length}` : '';
31
+ const got = bytes ? `length=${len}` : `type=${typeof value}`;
32
+ throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
33
+ }
34
+ return value;
35
+ }
36
+ /** Asserts a hash instance has not been destroyed / finished */
37
+ function aexists(instance, checkFinished = true) {
38
+ if (instance.destroyed)
39
+ throw new Error('Hash instance has been destroyed');
40
+ if (checkFinished && instance.finished)
41
+ throw new Error('Hash#digest() has already been called');
42
+ }
43
+ /** Asserts output is properly-sized byte array */
44
+ function aoutput(out, instance) {
45
+ abytes(out, undefined, 'digestInto() output');
46
+ const min = instance.outputLen;
47
+ if (out.length < min) {
48
+ throw new Error('"digestInto() output" expected to be of length >=' + min);
49
+ }
50
+ }
51
+ /** Cast u8 / u16 / u32 to u32. */
52
+ function u32(arr) {
53
+ return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
54
+ }
55
+ /** Zeroize a byte array. Warning: JS provides no guarantees. */
56
+ function clean(...arrays) {
57
+ for (let i = 0; i < arrays.length; i++) {
58
+ arrays[i].fill(0);
59
+ }
60
+ }
61
+ /** Is current platform little-endian? Most are. Big-Endian platform: IBM */
62
+ const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();
63
+ /** The byte swap operation for uint32 */
64
+ function byteSwap(word) {
65
+ return (((word << 24) & 0xff000000) |
66
+ ((word << 8) & 0xff0000) |
67
+ ((word >>> 8) & 0xff00) |
68
+ ((word >>> 24) & 0xff));
69
+ }
70
+ /** Conditionally byte swap if on a big-endian platform */
71
+ const swap8IfBE = isLE
72
+ ? (n) => n
73
+ : (n) => byteSwap(n);
74
+ /** In place byte swap for Uint32Array */
75
+ function byteSwap32(arr) {
76
+ for (let i = 0; i < arr.length; i++) {
77
+ arr[i] = byteSwap(arr[i]);
78
+ }
79
+ return arr;
80
+ }
81
+ const swap32IfBE = isLE
82
+ ? (u) => u
83
+ : byteSwap32;
84
+ /** Creates function with outputLen, blockLen, create properties from a class constructor. */
85
+ function createHasher(hashCons, info = {}) {
86
+ const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
87
+ const tmp = hashCons(undefined);
88
+ hashC.outputLen = tmp.outputLen;
89
+ hashC.blockLen = tmp.blockLen;
90
+ hashC.create = (opts) => hashCons(opts);
91
+ Object.assign(hashC, info);
92
+ return Object.freeze(hashC);
93
+ }
232
94
 
233
- // globalThis.crypto is available in browsers and Node.js 20+
234
- const defaultRNG = globalThis.crypto;
235
- class ChestKey extends TimelockProof {
236
- }
237
- function encrypt(key, text, rng = defaultRNG) {
238
- const nonce = new Uint8Array(24);
239
- rng.getRandomValues(nonce);
240
- const payload = nacl.secretBox(key, nonce, text);
241
- return {
242
- payload,
243
- nonce,
244
- };
245
- }
246
- function decrypt(key, c) {
247
- return nacl.openSecretBox(key, c.nonce, c.payload);
248
- }
249
- class Chest {
250
- constructor({ lockedValue, cipherText }) {
251
- this.lockedValue = lockedValue;
252
- this.cipherText = cipherText;
253
- }
254
- static newChestAndKey(payload, time, mod, rng) {
255
- if (time <= 0) {
256
- throw new Error('Invalid argument');
257
- }
258
- const vdfTuple = Timelock.precompute(time, mod, rng);
259
- return Chest.fromTimelock(payload, time, vdfTuple, rng);
260
- }
261
- static fromTimelock(payload, time, timelock, rng) {
262
- if (time <= 0) {
263
- throw new Error('Invalid argument');
264
- }
265
- const { lockedValue, proof } = timelock.getProof(time, rng);
266
- const symKey = proof.symmetricKey();
267
- const cipherText = encrypt(symKey, payload, rng);
268
- return { chest: new Chest({ lockedValue, cipherText }), key: proof };
269
- }
270
- newKey(time, mod) {
271
- if (time <= 0) {
272
- throw new Error('Invalid argument');
273
- }
274
- return unlockAndProve(time, this.lockedValue, mod);
275
- }
276
- open(key, time) {
277
- if (time <= 0) {
278
- throw new Error('Invalid argument');
279
- }
280
- if (!verify(this.lockedValue, key, time)) {
281
- return null;
282
- }
283
- const symKey = key.symmetricKey();
284
- return decrypt(symKey, this.cipherText);
285
- }
286
- encode() {
287
- const locked = encodeBigInt(this.lockedValue);
288
- const res = new Uint8Array(locked.length + 24 + 4 + this.cipherText.payload.length);
289
- res.set(locked);
290
- let off = locked.length;
291
- res.set(this.cipherText.nonce, off);
292
- off += 24;
293
- new DataView(res.buffer, res.byteOffset, res.byteLength).setUint32(off, this.cipherText.payload.length);
294
- off += 4;
295
- res.set(this.cipherText.payload, off);
296
- return res;
297
- }
298
- static fromArray(buf) {
299
- let i = 0;
300
- const [lockedValue, n] = decodeBigInt(buf);
301
- i += n;
302
- if (buf.length - i < 24 + 4) {
303
- throw new Error('Buffer is too short');
304
- }
305
- const nonce = new Uint8Array(buf.slice(i, i + 24));
306
- i += 24;
307
- const len = new DataView(buf.buffer, buf.byteOffset, buf.byteLength).getUint32(i);
308
- i += 4;
309
- if (buf.length - i < len) {
310
- throw new Error('Buffer is too short');
311
- }
312
- const payload = new Uint8Array(buf.slice(i, i + len));
313
- i += len;
314
- return [new Chest({ lockedValue, cipherText: { nonce, payload } }), i];
315
- }
316
- }
95
+ /**
96
+ * Internal helpers for blake hash.
97
+ * @module
98
+ */
99
+ /**
100
+ * Internal blake variable.
101
+ * For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1].
102
+ */
103
+ // prettier-ignore
104
+ const BSIGMA = /* @__PURE__ */ Uint8Array.from([
105
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
106
+ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
107
+ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
108
+ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
109
+ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
110
+ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
111
+ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
112
+ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
113
+ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
114
+ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
115
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
116
+ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
117
+ // Blake1, unused in others
118
+ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
119
+ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
120
+ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
121
+ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
122
+ ]);
317
123
 
318
- exports.Chest = Chest;
319
- exports.ChestKey = ChestKey;
320
- exports.Timelock = Timelock;
321
- exports.TimelockProof = TimelockProof;
322
- exports.decrypt = decrypt;
323
- exports.encrypt = encrypt;
124
+ /**
125
+ * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.
126
+ * @todo re-check https://issues.chromium.org/issues/42212588
127
+ * @module
128
+ */
129
+ const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
130
+ const _32n = /* @__PURE__ */ BigInt(32);
131
+ function fromBig(n, le = false) {
132
+ if (le)
133
+ return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
134
+ return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
135
+ }
136
+ // Right rotate for Shift in [1, 32)
137
+ const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
138
+ const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
139
+ // Right rotate for Shift in (32, 64), NOTE: 32 is special case.
140
+ const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
141
+ const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
142
+ // Right rotate for shift===32 (just swaps l&h)
143
+ const rotr32H = (_h, l) => l;
144
+ const rotr32L = (h, _l) => h;
145
+ // JS uses 32-bit signed integers for bitwise operations which means we cannot
146
+ // simple take carry out of low bit sum by shift, we need to use division.
147
+ function add(Ah, Al, Bh, Bl) {
148
+ const l = (Al >>> 0) + (Bl >>> 0);
149
+ return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
150
+ }
151
+ // Addition with more than 2 elements
152
+ const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
153
+ const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
154
+
155
+ /**
156
+ * blake2b (64-bit) & blake2s (8 to 32-bit) hash functions.
157
+ * b could have been faster, but there is no fast u64 in js, so s is 1.5x faster.
158
+ * @module
159
+ */
160
+ // Same as SHA512_IV, but swapped endianness: LE instead of BE. iv[1] is iv[0], etc.
161
+ const B2B_IV = /* @__PURE__ */ Uint32Array.from([
162
+ 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a,
163
+ 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19,
164
+ ]);
165
+ // Temporary buffer
166
+ const BBUF = /* @__PURE__ */ new Uint32Array(32);
167
+ // Mixing function G splitted in two halfs
168
+ function G1b(a, b, c, d, msg, x) {
169
+ // NOTE: V is LE here
170
+ const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
171
+ let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
172
+ let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
173
+ let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
174
+ let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
175
+ // v[a] = (v[a] + v[b] + x) | 0;
176
+ let ll = add3L(Al, Bl, Xl);
177
+ Ah = add3H(ll, Ah, Bh, Xh);
178
+ Al = ll | 0;
179
+ // v[d] = rotr(v[d] ^ v[a], 32)
180
+ ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
181
+ ({ Dh, Dl } = { Dh: rotr32H(Dh, Dl), Dl: rotr32L(Dh) });
182
+ // v[c] = (v[c] + v[d]) | 0;
183
+ ({ h: Ch, l: Cl } = add(Ch, Cl, Dh, Dl));
184
+ // v[b] = rotr(v[b] ^ v[c], 24)
185
+ ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
186
+ ({ Bh, Bl } = { Bh: rotrSH(Bh, Bl, 24), Bl: rotrSL(Bh, Bl, 24) });
187
+ ((BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah));
188
+ ((BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh));
189
+ ((BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch));
190
+ ((BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh));
191
+ }
192
+ function G2b(a, b, c, d, msg, x) {
193
+ // NOTE: V is LE here
194
+ const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
195
+ let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
196
+ let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
197
+ let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
198
+ let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
199
+ // v[a] = (v[a] + v[b] + x) | 0;
200
+ let ll = add3L(Al, Bl, Xl);
201
+ Ah = add3H(ll, Ah, Bh, Xh);
202
+ Al = ll | 0;
203
+ // v[d] = rotr(v[d] ^ v[a], 16)
204
+ ({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
205
+ ({ Dh, Dl } = { Dh: rotrSH(Dh, Dl, 16), Dl: rotrSL(Dh, Dl, 16) });
206
+ // v[c] = (v[c] + v[d]) | 0;
207
+ ({ h: Ch, l: Cl } = add(Ch, Cl, Dh, Dl));
208
+ // v[b] = rotr(v[b] ^ v[c], 63)
209
+ ({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
210
+ ({ Bh, Bl } = { Bh: rotrBH(Bh, Bl, 63), Bl: rotrBL(Bh, Bl, 63) });
211
+ ((BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah));
212
+ ((BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh));
213
+ ((BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch));
214
+ ((BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh));
215
+ }
216
+ function checkBlake2Opts(outputLen, opts = {}, keyLen, saltLen, persLen) {
217
+ anumber(keyLen);
218
+ if (outputLen < 0 || outputLen > keyLen)
219
+ throw new Error('outputLen bigger than keyLen');
220
+ const { key, salt, personalization } = opts;
221
+ if (key !== undefined && (key.length < 1 || key.length > keyLen))
222
+ throw new Error('"key" expected to be undefined or of length=1..' + keyLen);
223
+ if (salt !== undefined)
224
+ abytes(salt, saltLen, 'salt');
225
+ if (personalization !== undefined)
226
+ abytes(personalization, persLen, 'personalization');
227
+ }
228
+ /** Internal base class for BLAKE2. */
229
+ class _BLAKE2 {
230
+ buffer;
231
+ buffer32;
232
+ finished = false;
233
+ destroyed = false;
234
+ length = 0;
235
+ pos = 0;
236
+ blockLen;
237
+ outputLen;
238
+ constructor(blockLen, outputLen) {
239
+ anumber(blockLen);
240
+ anumber(outputLen);
241
+ this.blockLen = blockLen;
242
+ this.outputLen = outputLen;
243
+ this.buffer = new Uint8Array(blockLen);
244
+ this.buffer32 = u32(this.buffer);
245
+ }
246
+ update(data) {
247
+ aexists(this);
248
+ abytes(data);
249
+ // Main difference with other hashes: there is flag for last block,
250
+ // so we cannot process current block before we know that there
251
+ // is the next one. This significantly complicates logic and reduces ability
252
+ // to do zero-copy processing
253
+ const { blockLen, buffer, buffer32 } = this;
254
+ const len = data.length;
255
+ const offset = data.byteOffset;
256
+ const buf = data.buffer;
257
+ for (let pos = 0; pos < len;) {
258
+ // If buffer is full and we still have input (don't process last block, same as blake2s)
259
+ if (this.pos === blockLen) {
260
+ swap32IfBE(buffer32);
261
+ this.compress(buffer32, 0, false);
262
+ swap32IfBE(buffer32);
263
+ this.pos = 0;
264
+ }
265
+ const take = Math.min(blockLen - this.pos, len - pos);
266
+ const dataOffset = offset + pos;
267
+ // full block && aligned to 4 bytes && not last in input
268
+ if (take === blockLen && !(dataOffset % 4) && pos + take < len) {
269
+ const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4));
270
+ swap32IfBE(data32);
271
+ for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) {
272
+ this.length += blockLen;
273
+ this.compress(data32, pos32, false);
274
+ }
275
+ swap32IfBE(data32);
276
+ continue;
277
+ }
278
+ buffer.set(data.subarray(pos, pos + take), this.pos);
279
+ this.pos += take;
280
+ this.length += take;
281
+ pos += take;
282
+ }
283
+ return this;
284
+ }
285
+ digestInto(out) {
286
+ aexists(this);
287
+ aoutput(out, this);
288
+ const { pos, buffer32 } = this;
289
+ this.finished = true;
290
+ // Padding
291
+ clean(this.buffer.subarray(pos));
292
+ swap32IfBE(buffer32);
293
+ this.compress(buffer32, 0, true);
294
+ swap32IfBE(buffer32);
295
+ const out32 = u32(out);
296
+ this.get().forEach((v, i) => (out32[i] = swap8IfBE(v)));
297
+ }
298
+ digest() {
299
+ const { buffer, outputLen } = this;
300
+ this.digestInto(buffer);
301
+ const res = buffer.slice(0, outputLen);
302
+ this.destroy();
303
+ return res;
304
+ }
305
+ _cloneInto(to) {
306
+ const { buffer, length, finished, destroyed, outputLen, pos } = this;
307
+ to ||= new this.constructor({ dkLen: outputLen });
308
+ to.set(...this.get());
309
+ to.buffer.set(buffer);
310
+ to.destroyed = destroyed;
311
+ to.finished = finished;
312
+ to.length = length;
313
+ to.pos = pos;
314
+ // @ts-ignore
315
+ to.outputLen = outputLen;
316
+ return to;
317
+ }
318
+ clone() {
319
+ return this._cloneInto();
320
+ }
321
+ }
322
+ /** Internal blake2b hash class. */
323
+ class _BLAKE2b extends _BLAKE2 {
324
+ // Same as SHA-512, but LE
325
+ v0l = B2B_IV[0] | 0;
326
+ v0h = B2B_IV[1] | 0;
327
+ v1l = B2B_IV[2] | 0;
328
+ v1h = B2B_IV[3] | 0;
329
+ v2l = B2B_IV[4] | 0;
330
+ v2h = B2B_IV[5] | 0;
331
+ v3l = B2B_IV[6] | 0;
332
+ v3h = B2B_IV[7] | 0;
333
+ v4l = B2B_IV[8] | 0;
334
+ v4h = B2B_IV[9] | 0;
335
+ v5l = B2B_IV[10] | 0;
336
+ v5h = B2B_IV[11] | 0;
337
+ v6l = B2B_IV[12] | 0;
338
+ v6h = B2B_IV[13] | 0;
339
+ v7l = B2B_IV[14] | 0;
340
+ v7h = B2B_IV[15] | 0;
341
+ constructor(opts = {}) {
342
+ const olen = opts.dkLen === undefined ? 64 : opts.dkLen;
343
+ super(128, olen);
344
+ checkBlake2Opts(olen, opts, 64, 16, 16);
345
+ let { key, personalization, salt } = opts;
346
+ let keyLength = 0;
347
+ if (key !== undefined) {
348
+ abytes(key, undefined, 'key');
349
+ keyLength = key.length;
350
+ }
351
+ this.v0l ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24);
352
+ if (salt !== undefined) {
353
+ abytes(salt, undefined, 'salt');
354
+ const slt = u32(salt);
355
+ this.v4l ^= swap8IfBE(slt[0]);
356
+ this.v4h ^= swap8IfBE(slt[1]);
357
+ this.v5l ^= swap8IfBE(slt[2]);
358
+ this.v5h ^= swap8IfBE(slt[3]);
359
+ }
360
+ if (personalization !== undefined) {
361
+ abytes(personalization, undefined, 'personalization');
362
+ const pers = u32(personalization);
363
+ this.v6l ^= swap8IfBE(pers[0]);
364
+ this.v6h ^= swap8IfBE(pers[1]);
365
+ this.v7l ^= swap8IfBE(pers[2]);
366
+ this.v7h ^= swap8IfBE(pers[3]);
367
+ }
368
+ if (key !== undefined) {
369
+ // Pad to blockLen and update
370
+ const tmp = new Uint8Array(this.blockLen);
371
+ tmp.set(key);
372
+ this.update(tmp);
373
+ }
374
+ }
375
+ // prettier-ignore
376
+ get() {
377
+ let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this;
378
+ return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h];
379
+ }
380
+ // prettier-ignore
381
+ set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) {
382
+ this.v0l = v0l | 0;
383
+ this.v0h = v0h | 0;
384
+ this.v1l = v1l | 0;
385
+ this.v1h = v1h | 0;
386
+ this.v2l = v2l | 0;
387
+ this.v2h = v2h | 0;
388
+ this.v3l = v3l | 0;
389
+ this.v3h = v3h | 0;
390
+ this.v4l = v4l | 0;
391
+ this.v4h = v4h | 0;
392
+ this.v5l = v5l | 0;
393
+ this.v5h = v5h | 0;
394
+ this.v6l = v6l | 0;
395
+ this.v6h = v6h | 0;
396
+ this.v7l = v7l | 0;
397
+ this.v7h = v7h | 0;
398
+ }
399
+ compress(msg, offset, isLast) {
400
+ this.get().forEach((v, i) => (BBUF[i] = v)); // First half from state.
401
+ BBUF.set(B2B_IV, 16); // Second half from IV.
402
+ let { h, l } = fromBig(BigInt(this.length));
403
+ BBUF[24] = B2B_IV[8] ^ l; // Low word of the offset.
404
+ BBUF[25] = B2B_IV[9] ^ h; // High word.
405
+ // Invert all bits for last block
406
+ if (isLast) {
407
+ BBUF[28] = ~BBUF[28];
408
+ BBUF[29] = ~BBUF[29];
409
+ }
410
+ let j = 0;
411
+ const s = BSIGMA;
412
+ for (let i = 0; i < 12; i++) {
413
+ G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]);
414
+ G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]);
415
+ G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]);
416
+ G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]);
417
+ G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]);
418
+ G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]);
419
+ G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]);
420
+ G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]);
421
+ G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]);
422
+ G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]);
423
+ G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]);
424
+ G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]);
425
+ G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]);
426
+ G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]);
427
+ G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]);
428
+ G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]);
429
+ }
430
+ this.v0l ^= BBUF[0] ^ BBUF[16];
431
+ this.v0h ^= BBUF[1] ^ BBUF[17];
432
+ this.v1l ^= BBUF[2] ^ BBUF[18];
433
+ this.v1h ^= BBUF[3] ^ BBUF[19];
434
+ this.v2l ^= BBUF[4] ^ BBUF[20];
435
+ this.v2h ^= BBUF[5] ^ BBUF[21];
436
+ this.v3l ^= BBUF[6] ^ BBUF[22];
437
+ this.v3h ^= BBUF[7] ^ BBUF[23];
438
+ this.v4l ^= BBUF[8] ^ BBUF[24];
439
+ this.v4h ^= BBUF[9] ^ BBUF[25];
440
+ this.v5l ^= BBUF[10] ^ BBUF[26];
441
+ this.v5h ^= BBUF[11] ^ BBUF[27];
442
+ this.v6l ^= BBUF[12] ^ BBUF[28];
443
+ this.v6h ^= BBUF[13] ^ BBUF[29];
444
+ this.v7l ^= BBUF[14] ^ BBUF[30];
445
+ this.v7h ^= BBUF[15] ^ BBUF[31];
446
+ clean(BBUF);
447
+ }
448
+ destroy() {
449
+ this.destroyed = true;
450
+ clean(this.buffer32);
451
+ this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
452
+ }
453
+ }
454
+ /**
455
+ * Blake2b hash function. 64-bit. 1.5x slower than blake2s in JS.
456
+ * @param msg - message that would be hashed
457
+ * @param opts - dkLen output length, key for MAC mode, salt, personalization
458
+ */
459
+ const blake2b = /* @__PURE__ */ createHasher((opts) => new _BLAKE2b(opts));
460
+
461
+ // globalThis.crypto is available in browsers and Node.js 20+
462
+ const defaultRNG$1 = globalThis.crypto;
463
+ const RSA_MODULUS = bigInt('25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784406918290641249515082189298559149176184502808489120072844992687392807287776735971418347270261896375014971824691165077613379859095700097330459748808428401797429100642458691817195118746121515172654632282216869987549182422433637259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133844143603833904414952634432190114657544454178424020924616515723350778707749817125772467962926386356373289912154831438167899885040445364023527381951378636564391212010397122822120720357');
464
+ function rand(rng = defaultRNG$1) {
465
+ const bytes = new Uint8Array(4);
466
+ rng.getRandomValues(bytes);
467
+ const x = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
468
+ return x / Math.pow(2, 32);
469
+ }
470
+ function randomInteger(rng, bits) {
471
+ const bytes = new Uint8Array(bits / 8);
472
+ rng.getRandomValues(bytes);
473
+ return bigInt.fromArray(Array.from(bytes), 256);
474
+ }
475
+ function nextPrime(n) {
476
+ if (n.compare(2) < 0) {
477
+ return bigInt(2);
478
+ }
479
+ const limit = n.multiply(2);
480
+ for (let p = n.next(); p.compare(limit) < 0; p = p.next()) {
481
+ // use 25 bases like in GMP mpz_nextprime and thus in Tezos
482
+ if (p.isProbablePrime(25, rand)) {
483
+ return p;
484
+ }
485
+ }
486
+ throw new Error('!!!nextPrime!!!'); // shouldn't happen
487
+ }
488
+ function generate(rng, mod) {
489
+ const m = mod.subtract(bigInt(2));
490
+ return randomInteger(rng, mod.bitLength().toJSNumber()).mod(m).add(bigInt(2));
491
+ }
492
+ function toLE(x) {
493
+ return x.toArray(256).value.reverse();
494
+ }
495
+ function fromLE(x) {
496
+ return bigInt.fromArray(x.reverse(), 256);
497
+ }
498
+ const HASH_SEPARATOR = [0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00];
499
+ function hashToPrime(time, value, key, mod) {
500
+ const b = [
501
+ ...new TextEncoder().encode(String(time)),
502
+ ...HASH_SEPARATOR,
503
+ ...toLE(mod),
504
+ ...HASH_SEPARATOR,
505
+ ...toLE(value),
506
+ ...HASH_SEPARATOR,
507
+ ...toLE(key),
508
+ ];
509
+ const sum = blake2b(new Uint8Array(b), { dkLen: 32, key: new Uint8Array([32]) });
510
+ const val = fromLE(Array.from(sum));
511
+ return nextPrime(val);
512
+ }
513
+ function proveWesolowski(time, locked, unlocked, mod) {
514
+ const l = hashToPrime(time, locked, unlocked, mod);
515
+ let pi = bigInt(1);
516
+ let r = bigInt(1);
517
+ for (; time > 0; time -= 1) {
518
+ const rr = r.multiply(2);
519
+ r = rr.mod(l);
520
+ const pi2 = pi.multiply(pi).mod(mod);
521
+ if (rr.compare(l) >= 0) {
522
+ pi = pi2.multiply(locked);
523
+ }
524
+ else {
525
+ pi = pi2;
526
+ }
527
+ }
528
+ return pi.mod(mod);
529
+ }
530
+ function prove(time, locked, unlocked, mod = RSA_MODULUS) {
531
+ return new TimelockProof({
532
+ vdfTuple: new Timelock({
533
+ lockedValue: locked,
534
+ unlockedValue: unlocked,
535
+ vdfProof: proveWesolowski(time, locked, unlocked, mod),
536
+ modulus: mod,
537
+ }),
538
+ nonce: bigInt(1),
539
+ });
540
+ }
541
+ function unlockTimelock(time, locked, mod) {
542
+ if (locked.compare(bigInt(1)) <= 0) {
543
+ return locked;
544
+ }
545
+ let x = locked;
546
+ for (; time > 0; time -= 1) {
547
+ x = x.multiply(x).mod(mod);
548
+ }
549
+ return x;
550
+ }
551
+ function unlockAndProve(time, locked, mod = RSA_MODULUS) {
552
+ const unlocked = unlockTimelock(time, locked, mod);
553
+ return prove(time, locked, unlocked, mod);
554
+ }
555
+ function verifyWesolowski(vdfTuple, time) {
556
+ const l = hashToPrime(time, vdfTuple.lockedValue, vdfTuple.unlockedValue, vdfTuple.modulus);
557
+ const ll = vdfTuple.vdfProof.modPow(l, vdfTuple.modulus);
558
+ const r = bigInt(2).modPow(time, l);
559
+ const rr = vdfTuple.lockedValue.modPow(r, vdfTuple.modulus);
560
+ const unlocked = ll.multiply(rr).mod(vdfTuple.modulus);
561
+ return unlocked.compare(vdfTuple.unlockedValue) === 0;
562
+ }
563
+ function verify(locked, proof, time) {
564
+ const randomizedChallenge = proof.vdfTuple.lockedValue.modPow(proof.nonce, proof.vdfTuple.modulus);
565
+ return randomizedChallenge.compare(locked) === 0 && verifyWesolowski(proof.vdfTuple, time);
566
+ }
567
+ class Timelock {
568
+ constructor({ lockedValue, unlockedValue, vdfProof, modulus }) {
569
+ this.lockedValue = lockedValue;
570
+ this.unlockedValue = unlockedValue;
571
+ this.vdfProof = vdfProof;
572
+ this.modulus = modulus ?? RSA_MODULUS;
573
+ }
574
+ static precompute(time, mod = RSA_MODULUS, rng = defaultRNG$1) {
575
+ const locked = generate(rng, mod);
576
+ const unlocked = unlockTimelock(time, locked, mod);
577
+ return new Timelock({
578
+ lockedValue: locked,
579
+ unlockedValue: unlocked,
580
+ vdfProof: proveWesolowski(time, locked, unlocked, mod),
581
+ modulus: mod,
582
+ });
583
+ }
584
+ getProof(time, rng = defaultRNG$1) {
585
+ if (this.lockedValue.compare(bigInt(1)) < 1 ||
586
+ this.unlockedValue.compare(bigInt(0)) < 1 ||
587
+ this.vdfProof.compare(bigInt(0)) < 1 ||
588
+ this.lockedValue.compare(this.modulus) > 0 ||
589
+ this.unlockedValue.compare(this.modulus) > 0 ||
590
+ this.vdfProof.compare(this.modulus) >= 0) {
591
+ throw new Error('Invalid argument');
592
+ }
593
+ if (!verifyWesolowski(this, time)) {
594
+ throw new Error('Verification error');
595
+ }
596
+ const nonce = randomInteger(rng, 16 * 8);
597
+ const lockedValue = this.lockedValue.modPow(nonce, this.modulus);
598
+ return {
599
+ lockedValue,
600
+ proof: new TimelockProof({
601
+ vdfTuple: this,
602
+ nonce,
603
+ }),
604
+ };
605
+ }
606
+ encode() {
607
+ return new Uint8Array([
608
+ ...encodeBigInt(this.lockedValue),
609
+ ...encodeBigInt(this.unlockedValue),
610
+ ...encodeBigInt(this.vdfProof),
611
+ ]);
612
+ }
613
+ static fromArray(buf, mod = RSA_MODULUS) {
614
+ let i = 0;
615
+ const [lockedValue, n1] = decodeBigInt(buf);
616
+ i += n1;
617
+ const [unlockedValue, n2] = decodeBigInt(buf.slice(i));
618
+ i += n2;
619
+ const [vdfProof, n3] = decodeBigInt(buf.slice(i));
620
+ i += n3;
621
+ return [
622
+ new Timelock({
623
+ lockedValue,
624
+ unlockedValue,
625
+ vdfProof,
626
+ modulus: mod,
627
+ }),
628
+ i,
629
+ ];
630
+ }
631
+ }
632
+ const KDF_KEY = new TextEncoder().encode('Tezoskdftimelockv1');
633
+ class TimelockProof {
634
+ constructor({ vdfTuple, nonce }) {
635
+ this.vdfTuple = vdfTuple;
636
+ this.nonce = nonce;
637
+ }
638
+ symmetricKey() {
639
+ const updated = this.vdfTuple.unlockedValue.modPow(this.nonce, this.vdfTuple.modulus);
640
+ return blake2b(new TextEncoder().encode(String(updated)), { dkLen: 32, key: KDF_KEY });
641
+ }
642
+ encode() {
643
+ return new Uint8Array([...this.vdfTuple.encode(), ...encodeBigInt(this.nonce)]);
644
+ }
645
+ static fromArray(buf, mod = RSA_MODULUS) {
646
+ let i = 0;
647
+ const [vdfTuple, n1] = Timelock.fromArray(buf, mod);
648
+ i += n1;
649
+ const [nonce, n2] = decodeBigInt(buf.slice(i));
650
+ i += n2;
651
+ return [new TimelockProof({ vdfTuple, nonce }), i];
652
+ }
653
+ }
654
+ function encodeBigInt(v) {
655
+ if (v.isNegative()) {
656
+ throw new Error('Negative value');
657
+ }
658
+ const res = [];
659
+ for (let i = 0;; i++) {
660
+ const x = v.and(bigInt(0x7f)).toJSNumber();
661
+ v = v.shiftRight(7);
662
+ if (!v.isZero()) {
663
+ res.push(x | 0x80);
664
+ }
665
+ else {
666
+ res.push(x);
667
+ break;
668
+ }
669
+ }
670
+ return res;
671
+ }
672
+ function decodeBigInt(buf) {
673
+ let shift = 0;
674
+ let i = 0;
675
+ let res = bigInt(0);
676
+ while (i < buf.length) {
677
+ const x = buf[i];
678
+ res = res.add(bigInt(x & 0x7f).shiftLeft(shift));
679
+ shift += 7;
680
+ i++;
681
+ if ((x & 0x80) === 0)
682
+ break;
683
+ }
684
+ return [res, i];
685
+ }
686
+
687
+ // globalThis.crypto is available in browsers and Node.js 20+
688
+ const defaultRNG = globalThis.crypto;
689
+ class ChestKey extends TimelockProof {
690
+ }
691
+ function encrypt(key, text, rng = defaultRNG) {
692
+ const nonce = new Uint8Array(24);
693
+ rng.getRandomValues(nonce);
694
+ const payload = nacl.secretBox(key, nonce, text);
695
+ return {
696
+ payload,
697
+ nonce,
698
+ };
699
+ }
700
+ function decrypt(key, c) {
701
+ return nacl.openSecretBox(key, c.nonce, c.payload);
702
+ }
703
+ class Chest {
704
+ constructor({ lockedValue, cipherText }) {
705
+ this.lockedValue = lockedValue;
706
+ this.cipherText = cipherText;
707
+ }
708
+ static newChestAndKey(payload, time, mod, rng) {
709
+ if (time <= 0) {
710
+ throw new Error('Invalid argument');
711
+ }
712
+ const vdfTuple = Timelock.precompute(time, mod, rng);
713
+ return Chest.fromTimelock(payload, time, vdfTuple, rng);
714
+ }
715
+ static fromTimelock(payload, time, timelock, rng) {
716
+ if (time <= 0) {
717
+ throw new Error('Invalid argument');
718
+ }
719
+ const { lockedValue, proof } = timelock.getProof(time, rng);
720
+ const symKey = proof.symmetricKey();
721
+ const cipherText = encrypt(symKey, payload, rng);
722
+ return { chest: new Chest({ lockedValue, cipherText }), key: proof };
723
+ }
724
+ newKey(time, mod) {
725
+ if (time <= 0) {
726
+ throw new Error('Invalid argument');
727
+ }
728
+ return unlockAndProve(time, this.lockedValue, mod);
729
+ }
730
+ open(key, time) {
731
+ if (time <= 0) {
732
+ throw new Error('Invalid argument');
733
+ }
734
+ if (!verify(this.lockedValue, key, time)) {
735
+ return null;
736
+ }
737
+ const symKey = key.symmetricKey();
738
+ return decrypt(symKey, this.cipherText);
739
+ }
740
+ encode() {
741
+ const locked = encodeBigInt(this.lockedValue);
742
+ const res = new Uint8Array(locked.length + 24 + 4 + this.cipherText.payload.length);
743
+ res.set(locked);
744
+ let off = locked.length;
745
+ res.set(this.cipherText.nonce, off);
746
+ off += 24;
747
+ new DataView(res.buffer, res.byteOffset, res.byteLength).setUint32(off, this.cipherText.payload.length);
748
+ off += 4;
749
+ res.set(this.cipherText.payload, off);
750
+ return res;
751
+ }
752
+ static fromArray(buf) {
753
+ let i = 0;
754
+ const [lockedValue, n] = decodeBigInt(buf);
755
+ i += n;
756
+ if (buf.length - i < 24 + 4) {
757
+ throw new Error('Buffer is too short');
758
+ }
759
+ const nonce = new Uint8Array(buf.slice(i, i + 24));
760
+ i += 24;
761
+ const len = new DataView(buf.buffer, buf.byteOffset, buf.byteLength).getUint32(i);
762
+ i += 4;
763
+ if (buf.length - i < len) {
764
+ throw new Error('Buffer is too short');
765
+ }
766
+ const payload = new Uint8Array(buf.slice(i, i + len));
767
+ i += len;
768
+ return [new Chest({ lockedValue, cipherText: { nonce, payload } }), i];
769
+ }
770
+ }
771
+
772
+ exports.Chest = Chest;
773
+ exports.ChestKey = ChestKey;
774
+ exports.Timelock = Timelock;
775
+ exports.TimelockProof = TimelockProof;
776
+ exports.decrypt = decrypt;
777
+ exports.encrypt = encrypt;
324
778
 
325
779
  }));
326
780
  //# sourceMappingURL=taquito-timelock.umd.js.map