@btc-vision/btc-runtime 1.4.4 → 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 +2 -12
- package/runtime/buffer/BytesWriter.ts +1 -12
- 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/utils/lengths.ts +0 -1
- package/runtime/math/rnd.ts +0 -55
|
@@ -64,7 +64,9 @@ export class StoredU16Array {
|
|
|
64
64
|
*/
|
|
65
65
|
@inline
|
|
66
66
|
public get(index: u64): u16 {
|
|
67
|
-
|
|
67
|
+
if (index >= this._length) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
68
70
|
|
|
69
71
|
const slotIndex: u64 = index / 16; // Each slot holds sixteen u16s
|
|
70
72
|
const subIndex: u8 = <u8>(index % 16); // 0 to 15
|
|
@@ -81,7 +83,10 @@ export class StoredU16Array {
|
|
|
81
83
|
*/
|
|
82
84
|
@inline
|
|
83
85
|
public set(index: u64, value: u16): void {
|
|
84
|
-
|
|
86
|
+
if (index > this.MAX_LENGTH) {
|
|
87
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
const slotIndex: u64 = index / 16;
|
|
86
91
|
const subIndex: u8 = <u8>(index % 16);
|
|
87
92
|
this.ensureValues(slotIndex);
|
|
@@ -99,7 +104,7 @@ export class StoredU16Array {
|
|
|
99
104
|
* @param {u16} value - The u16 value to append.
|
|
100
105
|
*/
|
|
101
106
|
public push(value: u16): void {
|
|
102
|
-
if (this._length
|
|
107
|
+
if (this._length > this.MAX_LENGTH) {
|
|
103
108
|
throw new Revert(
|
|
104
109
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
105
110
|
);
|
|
@@ -148,40 +153,6 @@ export class StoredU16Array {
|
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
/**
|
|
152
|
-
* @method shift
|
|
153
|
-
* @description Removes the first element of the array by setting it to zero, decrementing the length, and incrementing the startIndex.
|
|
154
|
-
* If the startIndex reaches the maximum value of u64, it wraps around to 0.
|
|
155
|
-
*/
|
|
156
|
-
public shift(): void {
|
|
157
|
-
if (this._length === 0) {
|
|
158
|
-
throw new Revert('Shift operation failed: Array is empty.');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const currentStartIndex: u64 = this._startIndex;
|
|
162
|
-
const slotIndex: u64 = currentStartIndex / 16;
|
|
163
|
-
const subIndex: u8 = <u8>(currentStartIndex % 16);
|
|
164
|
-
this.ensureValues(slotIndex);
|
|
165
|
-
|
|
166
|
-
const slotValues = this._values.get(slotIndex);
|
|
167
|
-
if (slotValues && slotValues[subIndex] !== 0) {
|
|
168
|
-
slotValues[subIndex] = 0;
|
|
169
|
-
this._isChanged.add(slotIndex);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Decrement the length
|
|
173
|
-
this._length -= 1;
|
|
174
|
-
this._isChangedLength = true;
|
|
175
|
-
|
|
176
|
-
// Increment the startIndex with wrap-around
|
|
177
|
-
if (this._startIndex < this.MAX_LENGTH - 1) {
|
|
178
|
-
this._startIndex += 1;
|
|
179
|
-
} else {
|
|
180
|
-
this._startIndex = 0;
|
|
181
|
-
}
|
|
182
|
-
this._isChangedStartIndex = true;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
156
|
/**
|
|
186
157
|
* @method save
|
|
187
158
|
* @description Persists all cached u16 values, the length, and the startIndex to their respective storage slots if any have been modified.
|
|
@@ -257,7 +228,9 @@ export class StoredU16Array {
|
|
|
257
228
|
*/
|
|
258
229
|
@inline
|
|
259
230
|
public getAll(startIndex: u64, count: u64): u16[] {
|
|
260
|
-
|
|
231
|
+
if ((startIndex + count) > this._length) {
|
|
232
|
+
throw new Revert('Requested range exceeds array length');
|
|
233
|
+
}
|
|
261
234
|
|
|
262
235
|
if (u32.MAX_VALUE < count) {
|
|
263
236
|
throw new Revert('Requested range exceeds maximum allowed value.');
|
|
@@ -344,25 +317,6 @@ export class StoredU16Array {
|
|
|
344
317
|
return this._startIndex;
|
|
345
318
|
}
|
|
346
319
|
|
|
347
|
-
/**
|
|
348
|
-
* @method setLength
|
|
349
|
-
* @description Sets the length of the array.
|
|
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
320
|
public deleteLast(): void {
|
|
367
321
|
if (this._length === 0) {
|
|
368
322
|
throw new Revert('DeleteLast operation failed: Array is empty.');
|
|
@@ -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,19 +52,23 @@ 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._length) {
|
|
69
|
+
return u256.Zero;
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
const slotIndex: u32 = <u32>index;
|
|
69
73
|
this.ensureValues(slotIndex);
|
|
70
74
|
const value = this._values.get(slotIndex);
|
|
@@ -79,7 +83,10 @@ export class StoredU256Array {
|
|
|
79
83
|
*/
|
|
80
84
|
@inline
|
|
81
85
|
public set(index: u64, value: u256): void {
|
|
82
|
-
|
|
86
|
+
if (index > this.MAX_LENGTH) {
|
|
87
|
+
throw new Revert('Set operation failed: Index exceeds maximum allowed value.');
|
|
88
|
+
}
|
|
89
|
+
|
|
83
90
|
const slotIndex: u32 = <u32>index;
|
|
84
91
|
this.ensureValues(slotIndex);
|
|
85
92
|
|
|
@@ -96,7 +103,7 @@ export class StoredU256Array {
|
|
|
96
103
|
* @param {u256} value - The u256 value to append.
|
|
97
104
|
*/
|
|
98
105
|
public push(value: u256): void {
|
|
99
|
-
if (this._length
|
|
106
|
+
if (this._length > this.MAX_LENGTH) {
|
|
100
107
|
throw new Revert(
|
|
101
108
|
'Push operation failed: Array has reached its maximum allowed length.',
|
|
102
109
|
);
|
|
@@ -164,42 +171,10 @@ export class StoredU256Array {
|
|
|
164
171
|
}
|
|
165
172
|
}
|
|
166
173
|
|
|
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
174
|
/**
|
|
201
175
|
* @method save
|
|
202
|
-
* @description Persists all cached u256 values, the length, and the startIndex to their respective storage slots
|
|
176
|
+
* @description Persists all cached u256 values, the length, and the startIndex to their respective storage slots
|
|
177
|
+
* if any have been modified.
|
|
203
178
|
*/
|
|
204
179
|
public save(): void {
|
|
205
180
|
// Save all changed slots
|
|
@@ -210,6 +185,7 @@ export class StoredU256Array {
|
|
|
210
185
|
const value = this._values.get(slotIndex);
|
|
211
186
|
Blockchain.setStorageAt(storagePointer, value);
|
|
212
187
|
}
|
|
188
|
+
|
|
213
189
|
this._isChanged.clear();
|
|
214
190
|
|
|
215
191
|
// Save length and startIndex if changed
|
|
@@ -239,6 +215,7 @@ export class StoredU256Array {
|
|
|
239
215
|
// Reset the length and startIndex to zero
|
|
240
216
|
const zeroLengthAndStartIndex = u256.Zero;
|
|
241
217
|
Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
|
|
218
|
+
|
|
242
219
|
this._length = 0;
|
|
243
220
|
this._startIndex = 0;
|
|
244
221
|
this._isChangedLength = false;
|
|
@@ -272,7 +249,9 @@ export class StoredU256Array {
|
|
|
272
249
|
*/
|
|
273
250
|
@inline
|
|
274
251
|
public getAll(startIndex: u32, count: u32): u256[] {
|
|
275
|
-
|
|
252
|
+
if ((startIndex + count) > this._length) {
|
|
253
|
+
throw new Revert('Requested range exceeds array length');
|
|
254
|
+
}
|
|
276
255
|
const result: u256[] = new Array<u256>(count);
|
|
277
256
|
for (let i: u32 = 0; i < count; i++) {
|
|
278
257
|
result[i] = this.get(<u64>(startIndex + i));
|
|
@@ -354,25 +333,6 @@ export class StoredU256Array {
|
|
|
354
333
|
return this._startIndex;
|
|
355
334
|
}
|
|
356
335
|
|
|
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
336
|
/**
|
|
377
337
|
* @private
|
|
378
338
|
* @method ensureValues
|
|
@@ -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/utils/lengths.ts
CHANGED
|
@@ -8,7 +8,6 @@ export const U32_BYTE_LENGTH: i32 = 4;
|
|
|
8
8
|
export const U16_BYTE_LENGTH: i32 = 2;
|
|
9
9
|
export const U8_BYTE_LENGTH: i32 = 1;
|
|
10
10
|
|
|
11
|
-
export const I256_BYTE_LENGTH: i32 = 32;
|
|
12
11
|
export const I128_BYTE_LENGTH: i32 = 16;
|
|
13
12
|
export const I64_BYTE_LENGTH: i32 = 8;
|
|
14
13
|
export const I32_BYTE_LENGTH: i32 = 4;
|
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
|
-
}
|