@btc-vision/btc-runtime 1.4.5 → 1.4.6
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/package.json +2 -2
- package/runtime/buffer/BytesReader.ts +1 -1
- package/runtime/contracts/DeployableOP_20.ts +56 -47
- package/runtime/index.ts +0 -1
- package/runtime/math/bytes.ts +22 -8
- package/runtime/secp256k1/ECPoint.ts +103 -75
- package/runtime/storage/Serializable.ts +13 -10
- package/runtime/storage/arrays/StoredAddressArray.ts +13 -56
- package/runtime/storage/arrays/StoredBooleanArray.ts +17 -64
- package/runtime/storage/arrays/StoredU128Array.ts +13 -60
- package/runtime/storage/arrays/StoredU16Array.ts +11 -57
- package/runtime/storage/arrays/StoredU256Array.ts +23 -63
- package/runtime/storage/arrays/StoredU32Array.ts +11 -23
- package/runtime/storage/arrays/StoredU8Array.ts +11 -56
- package/runtime/types/Address.ts +1 -2
- package/runtime/types/SafeMath.ts +56 -28
- package/runtime/types/SafeMathI128.ts +8 -0
- package/runtime/math/rnd.ts +0 -55
|
@@ -65,7 +65,9 @@ export class StoredU32Array {
|
|
|
65
65
|
*/
|
|
66
66
|
@inline
|
|
67
67
|
public get(index: u64): u32 {
|
|
68
|
-
|
|
68
|
+
if (index >= this._length) {
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
69
71
|
|
|
70
72
|
const slotIndex: u64 = index / 8; // Each slot holds 8 u32s
|
|
71
73
|
const subIndex: u8 = <u8>(index % 8); // 0..7
|
|
@@ -82,7 +84,10 @@ export class StoredU32Array {
|
|
|
82
84
|
*/
|
|
83
85
|
@inline
|
|
84
86
|
public set(index: u64, value: u32): void {
|
|
85
|
-
|
|
87
|
+
if (index > this.MAX_LENGTH) {
|
|
88
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
89
|
+
}
|
|
90
|
+
|
|
86
91
|
const slotIndex: u64 = index / 8;
|
|
87
92
|
const subIndex: u8 = <u8>(index % 8);
|
|
88
93
|
|
|
@@ -100,7 +105,7 @@ export class StoredU32Array {
|
|
|
100
105
|
* @param {u32} value - The u32 value to append.
|
|
101
106
|
*/
|
|
102
107
|
public push(value: u32): void {
|
|
103
|
-
if (this._length
|
|
108
|
+
if (this._length > this.MAX_LENGTH) {
|
|
104
109
|
throw new Revert(
|
|
105
110
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
106
111
|
);
|
|
@@ -258,7 +263,9 @@ export class StoredU32Array {
|
|
|
258
263
|
*/
|
|
259
264
|
@inline
|
|
260
265
|
public getAll(startIndex: u64, count: u64): u32[] {
|
|
261
|
-
|
|
266
|
+
if ((startIndex + count) > this._length) {
|
|
267
|
+
throw new Revert('Requested range exceeds array length');
|
|
268
|
+
}
|
|
262
269
|
|
|
263
270
|
if (u32.MAX_VALUE < count) {
|
|
264
271
|
throw new Revert('Requested range exceeds maximum allowed value.');
|
|
@@ -344,25 +351,6 @@ export class StoredU32Array {
|
|
|
344
351
|
return this._startIndex;
|
|
345
352
|
}
|
|
346
353
|
|
|
347
|
-
/**
|
|
348
|
-
* @method setLength
|
|
349
|
-
* @description Adjusts the length of the array (may truncate if newLength < currentLength).
|
|
350
|
-
* @param {u64} newLength - The new length to set.
|
|
351
|
-
*/
|
|
352
|
-
public setLength(newLength: u64): void {
|
|
353
|
-
if (newLength > this.MAX_LENGTH) {
|
|
354
|
-
throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (newLength > this._startIndex) {
|
|
358
|
-
this._startIndex = newLength;
|
|
359
|
-
this._isChangedStartIndex = true;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
this._length = newLength;
|
|
363
|
-
this._isChangedLength = true;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
354
|
/**
|
|
367
355
|
* @method deleteLast
|
|
368
356
|
* @description Deletes the last element of the array by setting it to zero and decrementing the length.
|
|
@@ -63,7 +63,9 @@ export class StoredU8Array {
|
|
|
63
63
|
*/
|
|
64
64
|
@inline
|
|
65
65
|
public get(index: u64): u8 {
|
|
66
|
-
|
|
66
|
+
if (index >= this._length) {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
67
69
|
|
|
68
70
|
const slotIndex: u64 = index / 32; // Each slot holds thirty-two u8s
|
|
69
71
|
const subIndex: u8 = <u8>(index % 32);
|
|
@@ -80,7 +82,9 @@ export class StoredU8Array {
|
|
|
80
82
|
*/
|
|
81
83
|
@inline
|
|
82
84
|
public set(index: u64, value: u8): void {
|
|
83
|
-
|
|
85
|
+
if (index > this.MAX_LENGTH) {
|
|
86
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
87
|
+
}
|
|
84
88
|
|
|
85
89
|
const slotIndex: u64 = index / 32;
|
|
86
90
|
const subIndex: u8 = <u8>(index % 32);
|
|
@@ -99,7 +103,7 @@ export class StoredU8Array {
|
|
|
99
103
|
* @param {u8} value - The u8 value to append.
|
|
100
104
|
*/
|
|
101
105
|
public push(value: u8): void {
|
|
102
|
-
if (this._length
|
|
106
|
+
if (this._length > this.MAX_LENGTH) {
|
|
103
107
|
throw new Revert(
|
|
104
108
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
105
109
|
);
|
|
@@ -145,38 +149,6 @@ export class StoredU8Array {
|
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
/**
|
|
149
|
-
* @method shift
|
|
150
|
-
* @description Removes the first element of the array by setting it to zero, decrementing the length,
|
|
151
|
-
* and incrementing the startIndex (with wrap-around if needed).
|
|
152
|
-
*/
|
|
153
|
-
public shift(): void {
|
|
154
|
-
if (this._length === 0) {
|
|
155
|
-
throw new Revert('Shift operation failed: Array is empty.');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const currentStartIndex: u64 = this._startIndex;
|
|
159
|
-
const slotIndex: u64 = currentStartIndex / 32;
|
|
160
|
-
const subIndex: u8 = <u8>(currentStartIndex % 32);
|
|
161
|
-
this.ensureValues(slotIndex);
|
|
162
|
-
|
|
163
|
-
const slotValues = this._values.get(slotIndex);
|
|
164
|
-
if (slotValues && slotValues[subIndex] !== 0) {
|
|
165
|
-
slotValues[subIndex] = 0;
|
|
166
|
-
this._isChanged.add(slotIndex);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
this._length -= 1;
|
|
170
|
-
this._isChangedLength = true;
|
|
171
|
-
|
|
172
|
-
if (this._startIndex < this.MAX_LENGTH - 1) {
|
|
173
|
-
this._startIndex += 1;
|
|
174
|
-
} else {
|
|
175
|
-
this._startIndex = 0;
|
|
176
|
-
}
|
|
177
|
-
this._isChangedStartIndex = true;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
152
|
/**
|
|
181
153
|
* @method save
|
|
182
154
|
* @description Persists all cached u8 values, the length, and the startIndex to their respective storage slots if any have been modified.
|
|
@@ -251,7 +223,10 @@ export class StoredU8Array {
|
|
|
251
223
|
*/
|
|
252
224
|
@inline
|
|
253
225
|
public getAll(startIndex: u64, count: u64): u8[] {
|
|
254
|
-
|
|
226
|
+
if ((startIndex + count) > this._length) {
|
|
227
|
+
throw new Revert('Requested range exceeds array length');
|
|
228
|
+
}
|
|
229
|
+
|
|
255
230
|
if (u32.MAX_VALUE < count) {
|
|
256
231
|
throw new Revert('Requested range exceeds maximum allowed value.');
|
|
257
232
|
}
|
|
@@ -335,26 +310,6 @@ export class StoredU8Array {
|
|
|
335
310
|
return this._startIndex;
|
|
336
311
|
}
|
|
337
312
|
|
|
338
|
-
/**
|
|
339
|
-
* @method setLength
|
|
340
|
-
* @description Sets the length of the array.
|
|
341
|
-
* @param {u64} newLength - The new length to set.
|
|
342
|
-
*/
|
|
343
|
-
public setLength(newLength: u64): void {
|
|
344
|
-
if (newLength > this.MAX_LENGTH) {
|
|
345
|
-
throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// If newLength is bigger than _startIndex, adjust startIndex
|
|
349
|
-
if (newLength > this._startIndex) {
|
|
350
|
-
this._startIndex = newLength;
|
|
351
|
-
this._isChangedStartIndex = true;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
this._length = newLength;
|
|
355
|
-
this._isChangedLength = true;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
313
|
/**
|
|
359
314
|
* @method deleteLast
|
|
360
315
|
* @description Removes the last element of the array by setting it to zero and decrementing the length.
|
package/runtime/types/Address.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Potential } from '../lang/Definitions';
|
|
2
|
-
import { decodeHexArray, encodeHexFromBuffer } from '../utils';
|
|
2
|
+
import { ADDRESS_BYTE_LENGTH, decodeHexArray, encodeHexFromBuffer } from '../utils';
|
|
3
3
|
import { bech32m as _bech32m, toWords } from '../utils/b32';
|
|
4
|
-
import { ADDRESS_BYTE_LENGTH } from '../utils/lengths';
|
|
5
4
|
|
|
6
5
|
@final
|
|
7
6
|
export class Address extends Uint8Array {
|
|
@@ -80,15 +80,30 @@ export class SafeMath {
|
|
|
80
80
|
|
|
81
81
|
while (!r.isZero()) {
|
|
82
82
|
const quotient = SafeMath.div(old_r, r);
|
|
83
|
-
const r_copy = r;
|
|
84
|
-
r = SafeMath.sub(old_r, SafeMath.mul(quotient, r));
|
|
85
|
-
old_r = r_copy;
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
// --- Update r ---
|
|
85
|
+
{
|
|
86
|
+
// old_r - (quotient * r)
|
|
87
|
+
const tmp = r;
|
|
88
|
+
r = u256.sub(old_r, u256.mul(quotient, r)); // unchecked subtract
|
|
89
|
+
old_r = tmp;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --- Update s ---
|
|
93
|
+
{
|
|
94
|
+
// old_s - (quotient * s)
|
|
95
|
+
const tmp = s;
|
|
96
|
+
s = u256.sub(old_s, u256.mul(quotient, s)); // unchecked subtract
|
|
97
|
+
old_s = tmp;
|
|
98
|
+
}
|
|
90
99
|
}
|
|
91
100
|
|
|
101
|
+
// At this point, `old_r` is the gcd(k, p). If gcd != 1 => no inverse
|
|
102
|
+
// (in a prime field p, gcd=1 if k != 0).
|
|
103
|
+
// We could enforce this by checking `old_r == 1` but we'll leave it to the caller.
|
|
104
|
+
|
|
105
|
+
// The extended Euclidean algorithm says `old_s` is the inverse (possibly negative),
|
|
106
|
+
// so we reduce mod p
|
|
92
107
|
return SafeMath.mod(old_s, p);
|
|
93
108
|
}
|
|
94
109
|
|
|
@@ -248,52 +263,48 @@ export class SafeMath {
|
|
|
248
263
|
|
|
249
264
|
@unsafe
|
|
250
265
|
public static shl(value: u256, shift: i32): u256 {
|
|
251
|
-
|
|
252
|
-
|
|
266
|
+
// If shift <= 0, no left shift needed (shift=0 => return clone, shift<0 => treat as 0).
|
|
267
|
+
if (shift <= 0) {
|
|
268
|
+
return shift == 0 ? value.clone() : new u256(); // or just return value if shift<0 is invalid
|
|
253
269
|
}
|
|
254
270
|
|
|
255
|
-
|
|
256
|
-
|
|
271
|
+
// If shift >= 256, the result is zero
|
|
272
|
+
if (shift >= 256) {
|
|
273
|
+
return new u256();
|
|
274
|
+
}
|
|
257
275
|
|
|
258
|
-
//
|
|
276
|
+
// Now shift is in [1..255]. Masking is optional for clarity:
|
|
259
277
|
shift &= 255;
|
|
260
278
|
|
|
261
|
-
|
|
262
|
-
return new u256(); // Shift size larger than width results in zero
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Determine how many full 64-bit segments we are shifting
|
|
279
|
+
const bitsPerSegment = 64;
|
|
266
280
|
const segmentShift = (shift / bitsPerSegment) | 0;
|
|
267
281
|
const bitShift = shift % bitsPerSegment;
|
|
268
282
|
|
|
269
283
|
const segments = [value.lo1, value.lo2, value.hi1, value.hi2];
|
|
270
284
|
const result = SafeMath.shlSegment(segments, segmentShift, bitShift, bitsPerSegment, 4);
|
|
271
|
-
|
|
272
285
|
return new u256(result[0], result[1], result[2], result[3]);
|
|
273
286
|
}
|
|
274
287
|
|
|
275
288
|
public static shl128(value: u128, shift: i32): u128 {
|
|
276
|
-
if (shift
|
|
277
|
-
return value.clone();
|
|
289
|
+
if (shift <= 0) {
|
|
290
|
+
return shift == 0 ? value.clone() : new u128();
|
|
278
291
|
}
|
|
279
292
|
|
|
280
|
-
|
|
281
|
-
|
|
293
|
+
// Here the total bit width is 128, so shifting >= 128 bits => zero
|
|
294
|
+
if (shift >= 128) {
|
|
295
|
+
return new u128();
|
|
296
|
+
}
|
|
282
297
|
|
|
283
|
-
//
|
|
284
|
-
shift &=
|
|
298
|
+
// Mask to 0..127
|
|
299
|
+
shift &= 127;
|
|
285
300
|
|
|
286
|
-
|
|
287
|
-
return new u128(); // Shift size larger than width results in zero
|
|
288
|
-
}
|
|
301
|
+
const bitsPerSegment = 64;
|
|
289
302
|
|
|
290
|
-
// Determine how many full 64-bit segments we are shifting
|
|
291
303
|
const segmentShift = (shift / bitsPerSegment) | 0;
|
|
292
304
|
const bitShift = shift % bitsPerSegment;
|
|
293
305
|
|
|
294
306
|
const segments = [value.lo, value.hi];
|
|
295
307
|
const result = SafeMath.shlSegment(segments, segmentShift, bitShift, bitsPerSegment, 2);
|
|
296
|
-
|
|
297
308
|
return new u128(result[0], result[1]);
|
|
298
309
|
}
|
|
299
310
|
|
|
@@ -369,9 +380,26 @@ export class SafeMath {
|
|
|
369
380
|
* @returns The incremented value
|
|
370
381
|
*/
|
|
371
382
|
static inc(value: u256): u256 {
|
|
383
|
+
if (u256.eq(value, u256.Max)) {
|
|
384
|
+
throw new Error('SafeMath: increment overflow');
|
|
385
|
+
}
|
|
386
|
+
|
|
372
387
|
return value.preInc();
|
|
373
388
|
}
|
|
374
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Decrement a u256 value by 1
|
|
392
|
+
* @param value The value to decrement
|
|
393
|
+
* @returns The decremented value
|
|
394
|
+
*/
|
|
395
|
+
public static dec(value: u256): u256 {
|
|
396
|
+
if (u256.eq(value, u256.Zero)) {
|
|
397
|
+
throw new Error('SafeMath: decrement overflow');
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return value.preDec();
|
|
401
|
+
}
|
|
402
|
+
|
|
375
403
|
/**
|
|
376
404
|
* Approximates the binary logarithm (log2) of a u256 integer.
|
|
377
405
|
* @param x - The input value for which to calculate log2(x).
|
|
@@ -96,6 +96,10 @@ export class SafeMathI128 {
|
|
|
96
96
|
* Increment an i128 by 1 with overflow check.
|
|
97
97
|
*/
|
|
98
98
|
public static inc(value: i128): i128 {
|
|
99
|
+
if (value == SafeMathI128.MAX) {
|
|
100
|
+
throw new Error('SafeMathI128: inc overflow');
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
return SafeMathI128.add(value, SafeMathI128.ONE);
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -103,6 +107,10 @@ export class SafeMathI128 {
|
|
|
103
107
|
* Decrement an i128 by 1 with underflow check.
|
|
104
108
|
*/
|
|
105
109
|
public static dec(value: i128): i128 {
|
|
110
|
+
if (value == SafeMathI128.MIN) {
|
|
111
|
+
throw new Error('SafeMathI128: dec underflow');
|
|
112
|
+
}
|
|
113
|
+
|
|
106
114
|
return SafeMathI128.sub(value, SafeMathI128.ONE);
|
|
107
115
|
}
|
|
108
116
|
|
package/runtime/math/rnd.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
let random_state0_64: u64;
|
|
2
|
-
let random_state1_64: u64;
|
|
3
|
-
let random_state0_32: u32;
|
|
4
|
-
let random_state1_32: u32;
|
|
5
|
-
let random_seeded = false;
|
|
6
|
-
|
|
7
|
-
function murmurHash3(h: u64): u64 {
|
|
8
|
-
// Force all bits of a hash block to avalanche
|
|
9
|
-
h ^= h >> 33; // see: https://github.com/aappleby/smhasher
|
|
10
|
-
// eslint-disable-next-line no-loss-of-precision
|
|
11
|
-
h *= 0xff51afd7ed558ccd;
|
|
12
|
-
h ^= h >> 33;
|
|
13
|
-
// eslint-disable-next-line no-loss-of-precision
|
|
14
|
-
h *= 0xc4ceb9fe1a85ec53;
|
|
15
|
-
h ^= h >> 33;
|
|
16
|
-
return h;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function splitMix32(h: u32): u32 {
|
|
20
|
-
h += 0x6d2b79f5;
|
|
21
|
-
h = (h ^ (h >> 15)) * (h | 1);
|
|
22
|
-
h ^= h + (h ^ (h >> 7)) * (h | 61);
|
|
23
|
-
return h ^ (h >> 14);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function seedRandom(value: i64): void {
|
|
27
|
-
// Instead zero seed use golden ratio:
|
|
28
|
-
// phi = (1 + sqrt(5)) / 2
|
|
29
|
-
// trunc(2^64 / phi) = 0x9e3779b97f4a7c15
|
|
30
|
-
|
|
31
|
-
// eslint-disable-next-line no-loss-of-precision
|
|
32
|
-
if (value == 0) value = 0x9e3779b97f4a7c15;
|
|
33
|
-
random_state0_64 = murmurHash3(value);
|
|
34
|
-
random_state1_64 = murmurHash3(~random_state0_64);
|
|
35
|
-
random_state0_32 = splitMix32(<u32>value);
|
|
36
|
-
random_state1_32 = splitMix32(random_state0_32);
|
|
37
|
-
random_seeded = true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Safe deterministic random number generator
|
|
42
|
-
* @param {u64} seed - The seed to use
|
|
43
|
-
*/
|
|
44
|
-
export function randomU64(seed: i64): u64 {
|
|
45
|
-
if (!random_seeded) seedRandom(seed);
|
|
46
|
-
let s1 = random_state0_64;
|
|
47
|
-
const s0 = random_state1_64;
|
|
48
|
-
random_state0_64 = s0;
|
|
49
|
-
s1 ^= s1 << 23;
|
|
50
|
-
s1 ^= s1 >> 17;
|
|
51
|
-
s1 ^= s0;
|
|
52
|
-
s1 ^= s0 >> 26;
|
|
53
|
-
random_state1_64 = s1;
|
|
54
|
-
return s0;
|
|
55
|
-
}
|