@btc-vision/btc-runtime 1.4.5 → 1.4.7
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 +16 -58
- package/runtime/storage/arrays/StoredBooleanArray.ts +22 -66
- package/runtime/storage/arrays/StoredU128Array.ts +17 -63
- package/runtime/storage/arrays/StoredU16Array.ts +15 -59
- package/runtime/storage/arrays/StoredU256Array.ts +26 -65
- package/runtime/storage/arrays/StoredU32Array.ts +15 -25
- package/runtime/storage/arrays/StoredU8Array.ts +15 -58
- 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
|
@@ -19,13 +19,13 @@ export class StoredU256Array {
|
|
|
19
19
|
private _isChanged: Set<u64> = new Set(); // Set of slotIndexes that are modified
|
|
20
20
|
|
|
21
21
|
// Internal variables for length and startIndex management
|
|
22
|
-
private _length: u64 = 0;
|
|
22
|
+
private _length: u64 = 0; // Current length of the array
|
|
23
23
|
private _startIndex: u64 = 0; // Starting index of the array
|
|
24
|
-
private _isChangedLength: bool = false;
|
|
25
|
-
private _isChangedStartIndex: bool = false;
|
|
24
|
+
private _isChangedLength: bool = false; // Indicates if the length has been modified
|
|
25
|
+
private _isChangedStartIndex: bool = false; // Indicates if the startIndex has been modified
|
|
26
26
|
|
|
27
27
|
// Define a maximum allowed length to prevent excessive storage usage
|
|
28
|
-
private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
|
|
28
|
+
private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* @constructor
|
|
@@ -52,21 +52,26 @@ export class StoredU256Array {
|
|
|
52
52
|
this.lengthPointer = lengthPointer;
|
|
53
53
|
this.baseU256Pointer = baseU256Pointer;
|
|
54
54
|
|
|
55
|
-
this._length = storedLengthAndStartIndex.lo1;
|
|
55
|
+
this._length = storedLengthAndStartIndex.lo1; // Bytes 0-7: length
|
|
56
56
|
this._startIndex = storedLengthAndStartIndex.lo2; // Bytes 8-15: startIndex
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* @method get
|
|
61
61
|
* @description Retrieves the u256 value at the specified global index.
|
|
62
|
+
* Returns zero instead of reverting if the index is out of bounds.
|
|
62
63
|
* @param {u64} index - The global index (0 to ∞) of the u256 value to retrieve.
|
|
63
|
-
* @returns {u256} - The u256 value at the specified index.
|
|
64
|
+
* @returns {u256} - The u256 value at the specified index or zero if out of bounds.
|
|
64
65
|
*/
|
|
65
66
|
@inline
|
|
66
67
|
public get(index: u64): u256 {
|
|
67
|
-
|
|
68
|
+
if (index > this.MAX_LENGTH) {
|
|
69
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
const slotIndex: u32 = <u32>index;
|
|
69
73
|
this.ensureValues(slotIndex);
|
|
74
|
+
|
|
70
75
|
const value = this._values.get(slotIndex);
|
|
71
76
|
return value ? value : u256.Zero;
|
|
72
77
|
}
|
|
@@ -79,7 +84,10 @@ export class StoredU256Array {
|
|
|
79
84
|
*/
|
|
80
85
|
@inline
|
|
81
86
|
public set(index: u64, value: u256): void {
|
|
82
|
-
|
|
87
|
+
if (index > this.MAX_LENGTH) {
|
|
88
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
89
|
+
}
|
|
90
|
+
|
|
83
91
|
const slotIndex: u32 = <u32>index;
|
|
84
92
|
this.ensureValues(slotIndex);
|
|
85
93
|
|
|
@@ -96,7 +104,7 @@ export class StoredU256Array {
|
|
|
96
104
|
* @param {u256} value - The u256 value to append.
|
|
97
105
|
*/
|
|
98
106
|
public push(value: u256): void {
|
|
99
|
-
if (this._length
|
|
107
|
+
if (this._length > this.MAX_LENGTH) {
|
|
100
108
|
throw new Revert(
|
|
101
109
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
102
110
|
);
|
|
@@ -150,8 +158,8 @@ export class StoredU256Array {
|
|
|
150
158
|
* @param {u64} index - The global index of the u256 value to delete.
|
|
151
159
|
*/
|
|
152
160
|
public delete(index: u64): void {
|
|
153
|
-
if (index
|
|
154
|
-
throw new Revert('
|
|
161
|
+
if (index > this.MAX_LENGTH) {
|
|
162
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
155
163
|
}
|
|
156
164
|
|
|
157
165
|
const slotIndex: u32 = <u32>index;
|
|
@@ -164,42 +172,10 @@ export class StoredU256Array {
|
|
|
164
172
|
}
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
/**
|
|
168
|
-
* @method shift
|
|
169
|
-
* @description Removes the first element of the array by setting it to zero, decrementing the length, and incrementing the startIndex.
|
|
170
|
-
* If the startIndex reaches the maximum value of u64, it wraps around to 0.
|
|
171
|
-
*/
|
|
172
|
-
public shift(): void {
|
|
173
|
-
if (this._length === 0) {
|
|
174
|
-
throw new Revert('Shift operation failed: Array is empty.');
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const currentStartIndex: u64 = this._startIndex;
|
|
178
|
-
const slotIndex: u32 = <u32>currentStartIndex;
|
|
179
|
-
this.ensureValues(slotIndex);
|
|
180
|
-
|
|
181
|
-
const currentValue = this._values.get(slotIndex);
|
|
182
|
-
if (!u256.eq(currentValue, u256.Zero)) {
|
|
183
|
-
this._values.set(slotIndex, u256.Zero);
|
|
184
|
-
this._isChanged.add(slotIndex);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Decrement the length
|
|
188
|
-
this._length -= 1;
|
|
189
|
-
this._isChangedLength = true;
|
|
190
|
-
|
|
191
|
-
// Increment the startIndex with wrap-around
|
|
192
|
-
if (this._startIndex < this.MAX_LENGTH - 1) {
|
|
193
|
-
this._startIndex += 1;
|
|
194
|
-
} else {
|
|
195
|
-
this._startIndex = 0;
|
|
196
|
-
}
|
|
197
|
-
this._isChangedStartIndex = true;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
175
|
/**
|
|
201
176
|
* @method save
|
|
202
|
-
* @description Persists all cached u256 values, the length, and the startIndex to their respective storage slots
|
|
177
|
+
* @description Persists all cached u256 values, the length, and the startIndex to their respective storage slots
|
|
178
|
+
* if any have been modified.
|
|
203
179
|
*/
|
|
204
180
|
public save(): void {
|
|
205
181
|
// Save all changed slots
|
|
@@ -210,6 +186,7 @@ export class StoredU256Array {
|
|
|
210
186
|
const value = this._values.get(slotIndex);
|
|
211
187
|
Blockchain.setStorageAt(storagePointer, value);
|
|
212
188
|
}
|
|
189
|
+
|
|
213
190
|
this._isChanged.clear();
|
|
214
191
|
|
|
215
192
|
// Save length and startIndex if changed
|
|
@@ -239,6 +216,7 @@ export class StoredU256Array {
|
|
|
239
216
|
// Reset the length and startIndex to zero
|
|
240
217
|
const zeroLengthAndStartIndex = u256.Zero;
|
|
241
218
|
Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
|
|
219
|
+
|
|
242
220
|
this._length = 0;
|
|
243
221
|
this._startIndex = 0;
|
|
244
222
|
this._isChangedLength = false;
|
|
@@ -272,7 +250,9 @@ export class StoredU256Array {
|
|
|
272
250
|
*/
|
|
273
251
|
@inline
|
|
274
252
|
public getAll(startIndex: u32, count: u32): u256[] {
|
|
275
|
-
|
|
253
|
+
if ((startIndex + count) > this._length) {
|
|
254
|
+
throw new Revert('Requested range exceeds array length');
|
|
255
|
+
}
|
|
276
256
|
const result: u256[] = new Array<u256>(count);
|
|
277
257
|
for (let i: u32 = 0; i < count; i++) {
|
|
278
258
|
result[i] = this.get(<u64>(startIndex + i));
|
|
@@ -354,25 +334,6 @@ export class StoredU256Array {
|
|
|
354
334
|
return this._startIndex;
|
|
355
335
|
}
|
|
356
336
|
|
|
357
|
-
/**
|
|
358
|
-
* @method setLength
|
|
359
|
-
* @description Sets the length of the array.
|
|
360
|
-
* @param {u64} newLength - The new length to set.
|
|
361
|
-
*/
|
|
362
|
-
public setLength(newLength: u64): void {
|
|
363
|
-
if (newLength > this.MAX_LENGTH) {
|
|
364
|
-
throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
if (newLength > this._startIndex) {
|
|
368
|
-
this._startIndex = newLength;
|
|
369
|
-
this._isChangedStartIndex = true;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
this._length = newLength;
|
|
373
|
-
this._isChangedLength = true;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
337
|
/**
|
|
377
338
|
* @private
|
|
378
339
|
* @method ensureValues
|
|
@@ -65,11 +65,15 @@ export class StoredU32Array {
|
|
|
65
65
|
*/
|
|
66
66
|
@inline
|
|
67
67
|
public get(index: u64): u32 {
|
|
68
|
-
|
|
68
|
+
if (index > this.MAX_LENGTH) {
|
|
69
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
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
|
|
74
|
+
|
|
72
75
|
this.ensureValues(slotIndex);
|
|
76
|
+
|
|
73
77
|
const slotValues = this._values.get(slotIndex);
|
|
74
78
|
return slotValues ? slotValues[subIndex] : 0;
|
|
75
79
|
}
|
|
@@ -82,7 +86,10 @@ export class StoredU32Array {
|
|
|
82
86
|
*/
|
|
83
87
|
@inline
|
|
84
88
|
public set(index: u64, value: u32): void {
|
|
85
|
-
|
|
89
|
+
if (index > this.MAX_LENGTH) {
|
|
90
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
91
|
+
}
|
|
92
|
+
|
|
86
93
|
const slotIndex: u64 = index / 8;
|
|
87
94
|
const subIndex: u8 = <u8>(index % 8);
|
|
88
95
|
|
|
@@ -100,7 +107,7 @@ export class StoredU32Array {
|
|
|
100
107
|
* @param {u32} value - The u32 value to append.
|
|
101
108
|
*/
|
|
102
109
|
public push(value: u32): void {
|
|
103
|
-
if (this._length
|
|
110
|
+
if (this._length > this.MAX_LENGTH) {
|
|
104
111
|
throw new Revert(
|
|
105
112
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
106
113
|
);
|
|
@@ -134,8 +141,8 @@ export class StoredU32Array {
|
|
|
134
141
|
* @param {u64} index - The global index of the u32 value to delete.
|
|
135
142
|
*/
|
|
136
143
|
public delete(index: u64): void {
|
|
137
|
-
if (index
|
|
138
|
-
throw new Revert('
|
|
144
|
+
if (index > this.MAX_LENGTH) {
|
|
145
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
139
146
|
}
|
|
140
147
|
|
|
141
148
|
const slotIndex: u64 = index / 8;
|
|
@@ -258,7 +265,9 @@ export class StoredU32Array {
|
|
|
258
265
|
*/
|
|
259
266
|
@inline
|
|
260
267
|
public getAll(startIndex: u64, count: u64): u32[] {
|
|
261
|
-
|
|
268
|
+
if ((startIndex + count) > this._length) {
|
|
269
|
+
throw new Revert('Requested range exceeds array length');
|
|
270
|
+
}
|
|
262
271
|
|
|
263
272
|
if (u32.MAX_VALUE < count) {
|
|
264
273
|
throw new Revert('Requested range exceeds maximum allowed value.');
|
|
@@ -344,25 +353,6 @@ export class StoredU32Array {
|
|
|
344
353
|
return this._startIndex;
|
|
345
354
|
}
|
|
346
355
|
|
|
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
356
|
/**
|
|
367
357
|
* @method deleteLast
|
|
368
358
|
* @description Deletes the last element of the array by setting it to zero and decrementing the length.
|
|
@@ -63,11 +63,15 @@ export class StoredU8Array {
|
|
|
63
63
|
*/
|
|
64
64
|
@inline
|
|
65
65
|
public get(index: u64): u8 {
|
|
66
|
-
|
|
66
|
+
if (index > this.MAX_LENGTH) {
|
|
67
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
68
|
+
}
|
|
67
69
|
|
|
68
70
|
const slotIndex: u64 = index / 32; // Each slot holds thirty-two u8s
|
|
69
71
|
const subIndex: u8 = <u8>(index % 32);
|
|
72
|
+
|
|
70
73
|
this.ensureValues(slotIndex);
|
|
74
|
+
|
|
71
75
|
const slotValues = this._values.get(slotIndex);
|
|
72
76
|
return slotValues ? slotValues[subIndex] : 0;
|
|
73
77
|
}
|
|
@@ -80,7 +84,9 @@ export class StoredU8Array {
|
|
|
80
84
|
*/
|
|
81
85
|
@inline
|
|
82
86
|
public set(index: u64, value: u8): void {
|
|
83
|
-
|
|
87
|
+
if (index > this.MAX_LENGTH) {
|
|
88
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
89
|
+
}
|
|
84
90
|
|
|
85
91
|
const slotIndex: u64 = index / 32;
|
|
86
92
|
const subIndex: u8 = <u8>(index % 32);
|
|
@@ -99,7 +105,7 @@ export class StoredU8Array {
|
|
|
99
105
|
* @param {u8} value - The u8 value to append.
|
|
100
106
|
*/
|
|
101
107
|
public push(value: u8): void {
|
|
102
|
-
if (this._length
|
|
108
|
+
if (this._length > this.MAX_LENGTH) {
|
|
103
109
|
throw new Revert(
|
|
104
110
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
105
111
|
);
|
|
@@ -130,8 +136,8 @@ export class StoredU8Array {
|
|
|
130
136
|
* @param {u64} index - The global index of the u8 value to delete.
|
|
131
137
|
*/
|
|
132
138
|
public delete(index: u64): void {
|
|
133
|
-
if (index
|
|
134
|
-
throw new Revert('
|
|
139
|
+
if (index > this.MAX_LENGTH) {
|
|
140
|
+
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
const slotIndex: u64 = index / 32;
|
|
@@ -145,38 +151,6 @@ export class StoredU8Array {
|
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
|
|
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
154
|
/**
|
|
181
155
|
* @method save
|
|
182
156
|
* @description Persists all cached u8 values, the length, and the startIndex to their respective storage slots if any have been modified.
|
|
@@ -251,7 +225,10 @@ export class StoredU8Array {
|
|
|
251
225
|
*/
|
|
252
226
|
@inline
|
|
253
227
|
public getAll(startIndex: u64, count: u64): u8[] {
|
|
254
|
-
|
|
228
|
+
if ((startIndex + count) > this._length) {
|
|
229
|
+
throw new Revert('Requested range exceeds array length');
|
|
230
|
+
}
|
|
231
|
+
|
|
255
232
|
if (u32.MAX_VALUE < count) {
|
|
256
233
|
throw new Revert('Requested range exceeds maximum allowed value.');
|
|
257
234
|
}
|
|
@@ -335,26 +312,6 @@ export class StoredU8Array {
|
|
|
335
312
|
return this._startIndex;
|
|
336
313
|
}
|
|
337
314
|
|
|
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
315
|
/**
|
|
359
316
|
* @method deleteLast
|
|
360
317
|
* @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
|
-
}
|