@btc-vision/btc-runtime 1.3.7 → 1.3.9
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 +1 -1
- package/runtime/buffer/BytesReader.ts +16 -6
- package/runtime/buffer/BytesWriter.ts +17 -2
- package/runtime/contracts/DeployableOP_20.ts +0 -2
- package/runtime/contracts/OP_NET.ts +2 -0
- package/runtime/env/classes/Transaction.ts +16 -11
- package/runtime/env/classes/UTXO.ts +1 -1
- package/runtime/exports/index.ts +2 -0
- package/runtime/index.ts +5 -0
- package/runtime/math/abi.ts +1 -1
- package/runtime/math/bytes.ts +10 -1
- package/runtime/math/u160.ts +779 -0
- package/runtime/storage/Serializable.ts +32 -12
- package/runtime/storage/StoredBoolean.ts +1 -1
- package/runtime/storage/StoredU128Array.ts +271 -0
- package/runtime/storage/StoredU16Array.ts +281 -0
- package/runtime/storage/StoredU256Array.ts +300 -0
- package/runtime/storage/StoredU64.ts +179 -0
- package/runtime/types/SafeMath.ts +139 -6
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
import { i128, u128 } from 'as-bignum/assembly';
|
|
2
|
+
import { __carry, __uadd64, __umulh64 } from 'as-bignum/assembly/globals';
|
|
3
|
+
|
|
4
|
+
@lazy const HEX_CHARS = '0123456789abcdef';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Multiplies two 160-bit unsigned integers and returns the lower 160 bits.
|
|
9
|
+
* @param a_lo1 Lower 64 bits of the first operand.
|
|
10
|
+
* @param a_lo2 Middle 64 bits of the first operand.
|
|
11
|
+
* @param a_hi Upper 32 bits of the first operand.
|
|
12
|
+
* @param b_lo1 Lower 64 bits of the second operand.
|
|
13
|
+
* @param b_lo2 Middle 64 bits of the second operand.
|
|
14
|
+
* @param b_hi Upper 32 bits of the second operand.
|
|
15
|
+
* @returns The lower 160 bits of the product as a u160 instance.
|
|
16
|
+
*/
|
|
17
|
+
@global
|
|
18
|
+
export function __mul160(
|
|
19
|
+
a_lo1: u64,
|
|
20
|
+
a_lo2: u64,
|
|
21
|
+
a_hi: u32,
|
|
22
|
+
b_lo1: u64,
|
|
23
|
+
b_lo2: u64,
|
|
24
|
+
b_hi: u32
|
|
25
|
+
): u160 {
|
|
26
|
+
// Step 1: Multiply lower parts
|
|
27
|
+
let c0 = a_lo1 * b_lo1;
|
|
28
|
+
let c0_hi = __umulh64(a_lo1, b_lo1);
|
|
29
|
+
|
|
30
|
+
// Step 2: Multiply cross terms
|
|
31
|
+
let c1 = a_lo1 * b_lo2;
|
|
32
|
+
let c2 = a_lo2 * b_lo1;
|
|
33
|
+
|
|
34
|
+
// Step 3: Add cross terms and carry
|
|
35
|
+
let lo2 = __uadd64(c1, c2);
|
|
36
|
+
let carry1 = __carry;
|
|
37
|
+
|
|
38
|
+
lo2 = __uadd64(lo2, c0_hi);
|
|
39
|
+
let carry2 = __carry;
|
|
40
|
+
|
|
41
|
+
// Step 4: Multiply high parts
|
|
42
|
+
let c3 = a_lo1 * <u64>b_hi;
|
|
43
|
+
let c4 = <u64>a_hi * b_lo1;
|
|
44
|
+
|
|
45
|
+
// Step 5: Add high parts and carry
|
|
46
|
+
let hi = <u32>(c3 + c4 + carry1 + carry2);
|
|
47
|
+
|
|
48
|
+
return new u160(c0, lo2, hi);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Performs division and modulus on two 160-bit unsigned integers.
|
|
53
|
+
* @param dividend The dividend as a u160 instance.
|
|
54
|
+
* @param divisor The divisor as a u160 instance.
|
|
55
|
+
* @returns An object containing the quotient and remainder as u160 instances.
|
|
56
|
+
*/
|
|
57
|
+
@global
|
|
58
|
+
export function __udivmod160(dividend: u160, divisor: u160): { quotient: u160, remainder: u160 } {
|
|
59
|
+
if (divisor.isZero()) {
|
|
60
|
+
throw new RangeError("Division by zero");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (dividend.lt(divisor)) {
|
|
64
|
+
return { quotient: u160.Zero, remainder: dividend };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (divisor.isZero()) {
|
|
68
|
+
throw new RangeError("Division by zero");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let quotient = u160.Zero;
|
|
72
|
+
let remainder = u160.Zero;
|
|
73
|
+
let temp = dividend.clone();
|
|
74
|
+
|
|
75
|
+
// Determine the number of bits in dividend and divisor
|
|
76
|
+
let dividend_bits = 160 - __clz160(temp.lo1, temp.lo2, temp.hi);
|
|
77
|
+
let divisor_bits = 160 - __clz160(divisor.lo1, divisor.lo2, divisor.hi);
|
|
78
|
+
|
|
79
|
+
let shift = dividend_bits - divisor_bits;
|
|
80
|
+
|
|
81
|
+
// Align divisor with dividend
|
|
82
|
+
let shifted_divisor = divisor << shift;
|
|
83
|
+
|
|
84
|
+
for (let i = shift; i >= 0; i--) {
|
|
85
|
+
if (temp >= shifted_divisor) {
|
|
86
|
+
temp = temp - shifted_divisor;
|
|
87
|
+
quotient = quotient | (u160.One << i);
|
|
88
|
+
}
|
|
89
|
+
shifted_divisor = shifted_divisor >> 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
remainder = temp;
|
|
93
|
+
|
|
94
|
+
return { quotient, remainder };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Counts the leading zeros in a 160-bit unsigned integer.
|
|
99
|
+
* @param lo1 Lower 64 bits.
|
|
100
|
+
* @param lo2 Middle 64 bits.
|
|
101
|
+
* @param hi Upper 32 bits.
|
|
102
|
+
* @returns The number of leading zeros.
|
|
103
|
+
*/
|
|
104
|
+
@inline
|
|
105
|
+
export function __clz160(lo1: u64, lo2: u64, hi: u32): i32 {
|
|
106
|
+
if (hi != 0) {
|
|
107
|
+
return clz(<u64>hi) - 32;
|
|
108
|
+
} else if (lo2 != 0) {
|
|
109
|
+
return 32 + clz(lo2);
|
|
110
|
+
} else {
|
|
111
|
+
return 96 + clz(lo1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Counts the trailing zeros in a 160-bit unsigned integer.
|
|
117
|
+
* @param lo1 Lower 64 bits.
|
|
118
|
+
* @param lo2 Middle 64 bits.
|
|
119
|
+
* @param hi Upper 32 bits.
|
|
120
|
+
* @returns The number of trailing zeros.
|
|
121
|
+
*/
|
|
122
|
+
@inline
|
|
123
|
+
export function __ctz160(lo1: u64, lo2: u64, hi: u32): i32 {
|
|
124
|
+
if (lo1 != 0) {
|
|
125
|
+
return ctz(lo1);
|
|
126
|
+
} else if (lo2 != 0) {
|
|
127
|
+
return 64 + ctz(lo2);
|
|
128
|
+
} else {
|
|
129
|
+
return 128 + ctz(<u32>hi);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Converts a 160-bit unsigned integer to its decimal string representation.
|
|
135
|
+
* @param value The u160 instance to convert.
|
|
136
|
+
* @returns The decimal string representation of the u160 instance.
|
|
137
|
+
*/
|
|
138
|
+
@inline
|
|
139
|
+
export function u160toDecimalString(value: u160): string {
|
|
140
|
+
if (value.isZero()) return "0";
|
|
141
|
+
|
|
142
|
+
let result = "";
|
|
143
|
+
let temp = value.clone();
|
|
144
|
+
|
|
145
|
+
while (!temp.isZero()) {
|
|
146
|
+
let { quotient, remainder } = __udivmod160(temp, u160.fromU64(10));
|
|
147
|
+
let digit = <u8>remainder.lo1; // Assuming remainder < 10
|
|
148
|
+
result = digit.toString() + result;
|
|
149
|
+
temp = quotient;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export class u160 {
|
|
156
|
+
|
|
157
|
+
@inline static get Zero(): u160 { return new u160(); }
|
|
158
|
+
@inline static get One(): u160 { return new u160(1, 0, 0); }
|
|
159
|
+
@inline static get Min(): u160 { return new u160(); }
|
|
160
|
+
@inline static get Max(): u160 { return new u160(<u64>0xFFFFFFFFFFFFFFFF, <u64>0xFFFFFFFFFFFFFFFF, <u32>0xFFFFFFFF); }
|
|
161
|
+
|
|
162
|
+
// TODO: fromString
|
|
163
|
+
|
|
164
|
+
@inline
|
|
165
|
+
static fromU160(value: u160): u160 {
|
|
166
|
+
return new u160(value.lo1, value.lo2, value.hi);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@inline
|
|
170
|
+
static fromU128(value: u128): u160 {
|
|
171
|
+
return new u160(value.lo, value.hi, 0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@inline
|
|
175
|
+
static fromU64(value: u64): u160 {
|
|
176
|
+
return new u160(value, 0, 0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@inline
|
|
180
|
+
static fromI64(value: i64): u160 {
|
|
181
|
+
let mask = <u64>(value >> 63);
|
|
182
|
+
return new u160(<u64>value, mask, <u32>mask);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@inline
|
|
186
|
+
static fromU32(value: u32): u160 {
|
|
187
|
+
return new u160(<u64>value, 0, 0);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@inline
|
|
191
|
+
static fromI32(value: i32): u160 {
|
|
192
|
+
let mask = <u64>(value >> 31);
|
|
193
|
+
return new u160(<u64>value, mask, <u32>mask);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@inline
|
|
197
|
+
static fromBits(
|
|
198
|
+
lo1: u64, lo2: u64, hi: u32
|
|
199
|
+
): u160 {
|
|
200
|
+
return new u160(lo1, lo2, hi);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@inline
|
|
204
|
+
static fromBytes<T>(array: T, bigEndian: bool = false): u160 {
|
|
205
|
+
if (array instanceof u8[]) {
|
|
206
|
+
return bigEndian
|
|
207
|
+
? u160.fromBytesBE(<u8[]>array)
|
|
208
|
+
: u160.fromBytesLE(<u8[]>array);
|
|
209
|
+
} else if (array instanceof Uint8Array) {
|
|
210
|
+
return bigEndian
|
|
211
|
+
? u160.fromUint8ArrayBE(<Uint8Array>array)
|
|
212
|
+
: u160.fromUint8ArrayLE(<Uint8Array>array);
|
|
213
|
+
} else {
|
|
214
|
+
throw new TypeError("Unsupported generic type");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@inline
|
|
219
|
+
static fromBytesLE(array: u8[]): u160 {
|
|
220
|
+
assert(array.length == 20, "Invalid byte array length for u160");
|
|
221
|
+
let lo1 = load<u64>(changetype<usize>(array) + 0);
|
|
222
|
+
let lo2 = load<u64>(changetype<usize>(array) + 8);
|
|
223
|
+
let hi = load<u32>(changetype<usize>(array) + 16);
|
|
224
|
+
return new u160(lo1, lo2, hi);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@inline
|
|
228
|
+
static fromBytesBE(array: u8[]): u160 {
|
|
229
|
+
assert(array.length == 20, "Invalid byte array length for u160");
|
|
230
|
+
let lo1 = bswap(load<u64>(changetype<usize>(array) + 12));
|
|
231
|
+
let lo2 = bswap(load<u64>(changetype<usize>(array) + 4));
|
|
232
|
+
let hi = bswap(load<u32>(changetype<usize>(array) + 0));
|
|
233
|
+
return new u160(lo1, lo2, hi);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@inline
|
|
237
|
+
static fromUint8ArrayLE(array: Uint8Array): u160 {
|
|
238
|
+
assert(array.length == 20, "Invalid Uint8Array length for u160");
|
|
239
|
+
let lo1 = load<u64>(array.dataStart + 0);
|
|
240
|
+
let lo2 = load<u64>(array.dataStart + 8);
|
|
241
|
+
let hi = load<u32>(array.dataStart + 16);
|
|
242
|
+
return new u160(lo1, lo2, hi);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@inline
|
|
246
|
+
static fromUint8ArrayBE(array: Uint8Array): u160 {
|
|
247
|
+
assert(array.length == 20, "Invalid Uint8Array length for u160");
|
|
248
|
+
let lo1 = bswap(load<u64>(array.dataStart + 12));
|
|
249
|
+
let lo2 = bswap(load<u64>(array.dataStart + 4));
|
|
250
|
+
let hi = bswap(load<u32>(array.dataStart + 0));
|
|
251
|
+
return new u160(lo1, lo2, hi);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@operator('<<')
|
|
255
|
+
static shl(a: u160, shift: u32): u160 {
|
|
256
|
+
shift &= 159;
|
|
257
|
+
if (shift == 0) return a;
|
|
258
|
+
|
|
259
|
+
let lo1 = a.lo1;
|
|
260
|
+
let lo2 = a.lo2;
|
|
261
|
+
let hi = a.hi;
|
|
262
|
+
|
|
263
|
+
if (shift < 64) {
|
|
264
|
+
lo2 = (lo2 << shift) | (lo1 >> (64 - shift));
|
|
265
|
+
hi = (hi << shift) | (<u32>(lo2 >> (64 - shift)));
|
|
266
|
+
lo1 = lo1 << shift;
|
|
267
|
+
} else if (shift < 128) {
|
|
268
|
+
lo1 = 0;
|
|
269
|
+
lo2 = a.lo1 << (shift - 64);
|
|
270
|
+
hi = (a.lo2 << (shift - 64)) | (<u32>(a.hi << (shift - 64)));
|
|
271
|
+
} else {
|
|
272
|
+
lo1 = 0;
|
|
273
|
+
lo2 = 0;
|
|
274
|
+
hi = a.lo1 << (shift - 128);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return new u160(lo1, lo2, hi);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// TODO: Improve conversion from floating points
|
|
281
|
+
@inline
|
|
282
|
+
static fromF64(value: f64): u160 {
|
|
283
|
+
let mask = <u64>(reinterpret<i64>(value) >> 63);
|
|
284
|
+
return new u160(<u64>value, mask, <u32>mask);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@inline
|
|
288
|
+
static fromF32(value: f32): u160 {
|
|
289
|
+
let mask = <u64>(reinterpret<i32>(value) >> 31);
|
|
290
|
+
return new u160(<u64>value, mask, <u32>mask);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Create 160-bit unsigned integer from generic type T
|
|
295
|
+
* @param value
|
|
296
|
+
* @returns 160-bit unsigned integer
|
|
297
|
+
*/
|
|
298
|
+
@inline
|
|
299
|
+
static from<T>(value: T): u160 {
|
|
300
|
+
if (value instanceof bool) return u160.fromU64(<u64>value);
|
|
301
|
+
else if (value instanceof i8) return u160.fromI64(<i64>value);
|
|
302
|
+
else if (value instanceof u8) return u160.fromU64(<u64>value);
|
|
303
|
+
else if (value instanceof i16) return u160.fromI64(<i64>value);
|
|
304
|
+
else if (value instanceof u16) return u160.fromU64(<u64>value);
|
|
305
|
+
else if (value instanceof i32) return u160.fromI32(<i32>value);
|
|
306
|
+
else if (value instanceof u32) return u160.fromU32(<u32>value);
|
|
307
|
+
else if (value instanceof i64) return u160.fromI64(<i64>value);
|
|
308
|
+
else if (value instanceof u64) return u160.fromU64(<u64>value);
|
|
309
|
+
else if (value instanceof f32) return u160.fromF32(<f32>value);
|
|
310
|
+
else if (value instanceof f64) return u160.fromF64(<f64>value);
|
|
311
|
+
else if (value instanceof u128) return u160.fromU128(<u128>value);
|
|
312
|
+
else if (value instanceof u160) return u160.fromU160(<u160>value);
|
|
313
|
+
else if (value instanceof u8[]) return u160.fromBytes(<u8[]>value);
|
|
314
|
+
else if (value instanceof Uint8Array) return u160.fromBytes(<Uint8Array>value);
|
|
315
|
+
else throw new TypeError("Unsupported generic type");
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// TODO
|
|
319
|
+
// static fromString(str: string): u160
|
|
320
|
+
|
|
321
|
+
constructor(
|
|
322
|
+
public lo1: u64 = 0,
|
|
323
|
+
public lo2: u64 = 0,
|
|
324
|
+
public hi: u32 = 0,
|
|
325
|
+
) {}
|
|
326
|
+
|
|
327
|
+
@inline
|
|
328
|
+
set(value: u160): this {
|
|
329
|
+
this.lo1 = value.lo1;
|
|
330
|
+
this.lo2 = value.lo2;
|
|
331
|
+
this.hi = value.hi;
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@inline
|
|
336
|
+
setU128(value: u128): this {
|
|
337
|
+
this.lo1 = value.lo;
|
|
338
|
+
this.lo2 = value.hi;
|
|
339
|
+
this.hi = 0;
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
@inline
|
|
344
|
+
setI64(value: i64): this {
|
|
345
|
+
let mask: u64 = <u64>(value >> 63);
|
|
346
|
+
this.lo1 = <u64>value;
|
|
347
|
+
this.lo2 = mask;
|
|
348
|
+
this.hi = <u32>mask;
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@inline
|
|
353
|
+
setU64(value: u64): this {
|
|
354
|
+
this.lo1 = value;
|
|
355
|
+
this.lo2 = 0;
|
|
356
|
+
this.hi = 0;
|
|
357
|
+
return this;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@inline
|
|
361
|
+
setI32(value: i32): this {
|
|
362
|
+
let mask: u64 = <u64>(value >> 31);
|
|
363
|
+
this.lo1 = <u64>value;
|
|
364
|
+
this.lo2 = mask;
|
|
365
|
+
this.hi = <u32>mask;
|
|
366
|
+
return this;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
@inline
|
|
370
|
+
setU32(value: u32): this {
|
|
371
|
+
this.lo1 = <u64>value;
|
|
372
|
+
this.lo2 = 0;
|
|
373
|
+
this.hi = 0;
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@inline
|
|
378
|
+
isZero(): bool {
|
|
379
|
+
return !(this.lo1 | this.lo2 | this.hi);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@inline @operator.prefix('!')
|
|
383
|
+
static isEmpty(value: u160): bool {
|
|
384
|
+
return value.isZero();
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@inline @operator.prefix('~')
|
|
388
|
+
not(): u160 {
|
|
389
|
+
return new u160(~this.lo1, ~this.lo2, ~this.hi);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@inline @operator.prefix('+')
|
|
393
|
+
pos(): u160 {
|
|
394
|
+
return this;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
@operator.prefix('-')
|
|
398
|
+
neg(): u160 {
|
|
399
|
+
let lo1 = ~this.lo1;
|
|
400
|
+
let lo2 = ~this.lo2;
|
|
401
|
+
let hi = ~this.hi;
|
|
402
|
+
|
|
403
|
+
let lo1p = lo1 + 1;
|
|
404
|
+
let carry1 = lo1p < lo1 ? 1 : 0;
|
|
405
|
+
|
|
406
|
+
let lo2p = this.lo2 == 0xFFFFFFFFFFFFFFFF ? 0 : this.lo2 + carry1;
|
|
407
|
+
let carry2 = (lo2p < this.lo2) ? 1 : 0;
|
|
408
|
+
|
|
409
|
+
let hi_p = this.hi + carry2;
|
|
410
|
+
|
|
411
|
+
return new u160(lo1p, lo2p, hi_p);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@operator.prefix('++')
|
|
415
|
+
preInc(): this {
|
|
416
|
+
let lo1p = this.lo1 + 1;
|
|
417
|
+
let carry1 = lo1p < this.lo1 ? 1 : 0;
|
|
418
|
+
|
|
419
|
+
let lo2p = this.lo2 + carry1;
|
|
420
|
+
let carry2 = lo2p < this.lo2 ? 1 : 0;
|
|
421
|
+
|
|
422
|
+
let hi_p = this.hi + <u32>carry2;
|
|
423
|
+
|
|
424
|
+
this.lo1 = lo1p;
|
|
425
|
+
this.lo2 = lo2p;
|
|
426
|
+
this.hi = hi_p;
|
|
427
|
+
|
|
428
|
+
return this;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
@operator.prefix('--')
|
|
432
|
+
preDec(): this {
|
|
433
|
+
let lo1p = this.lo1 - 1;
|
|
434
|
+
let borrow1 = this.lo1 == 0 ? 1 : 0;
|
|
435
|
+
|
|
436
|
+
let lo2p = this.lo2 - <u64>borrow1;
|
|
437
|
+
let borrow2 = this.lo2 < <u64>borrow1 ? 1 : 0;
|
|
438
|
+
|
|
439
|
+
let hi_p = this.hi - <u32>borrow2;
|
|
440
|
+
|
|
441
|
+
this.lo1 = lo1p;
|
|
442
|
+
this.lo2 = lo2p;
|
|
443
|
+
this.hi = hi_p;
|
|
444
|
+
|
|
445
|
+
return this;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
@inline @operator.postfix('++')
|
|
449
|
+
postInc(): u160 {
|
|
450
|
+
let original = this.clone();
|
|
451
|
+
this.preInc();
|
|
452
|
+
return original;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
@inline @operator.postfix('--')
|
|
456
|
+
postDec(): u160 {
|
|
457
|
+
let original = this.clone();
|
|
458
|
+
this.preDec();
|
|
459
|
+
return original;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
@operator('+')
|
|
463
|
+
static add(a: u160, b: u160): u160 {
|
|
464
|
+
let lo1 = a.lo1 + b.lo1;
|
|
465
|
+
let carry1 = lo1 < a.lo1 ? 1 : 0;
|
|
466
|
+
|
|
467
|
+
let lo2 = a.lo2 + b.lo2 + <u64>carry1;
|
|
468
|
+
let carry2 = lo2 < a.lo2 || (carry1 == 1 && lo2 == a.lo2) ? 1 : 0;
|
|
469
|
+
|
|
470
|
+
let hi = a.hi + b.hi + <u32>carry2;
|
|
471
|
+
return new u160(lo1, lo2, hi);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
@operator('-')
|
|
475
|
+
static sub(a: u160, b: u160): u160 {
|
|
476
|
+
let lo1 = a.lo1 - b.lo1;
|
|
477
|
+
let borrow1 = a.lo1 < b.lo1 ? 1 : 0;
|
|
478
|
+
|
|
479
|
+
let lo2 = a.lo2 - b.lo2 - <u64>borrow1;
|
|
480
|
+
let borrow2 = a.lo2 < b.lo2 + <u64>borrow1 ? 1 : 0;
|
|
481
|
+
|
|
482
|
+
let hi = a.hi - b.hi - <u32>borrow2;
|
|
483
|
+
return new u160(lo1, lo2, hi);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
@inline @operator('|')
|
|
487
|
+
static or(a: u160, b: u160): u160 {
|
|
488
|
+
return new u160(a.lo1 | b.lo1, a.lo2 | b.lo2, a.hi | b.hi);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
@inline @operator('^')
|
|
492
|
+
static xor(a: u160, b: u160): u160 {
|
|
493
|
+
return new u160(a.lo1 ^ b.lo1, a.lo2 ^ b.lo2, a.hi ^ b.hi);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
@inline @operator('&')
|
|
497
|
+
static and(a: u160, b: u160): u160 {
|
|
498
|
+
return new u160(a.lo1 & b.lo1, a.lo2 & b.lo2, a.hi & b.hi);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
@operator('>>')
|
|
502
|
+
static shr(value: u160, shift: i32): u160 {
|
|
503
|
+
shift &= 159;
|
|
504
|
+
if (shift == 0) return value;
|
|
505
|
+
|
|
506
|
+
let off = <u64>shift;
|
|
507
|
+
if (shift < 64) {
|
|
508
|
+
let lo1 = value.lo1 >> off;
|
|
509
|
+
let lo2 = (value.lo2 >> off) | (value.lo1 << (64 - off));
|
|
510
|
+
let hi = (value.hi >> off) | (<u32>((value.lo2 << (32 - off)) & 0xFFFFFFFF)) as u32;
|
|
511
|
+
return new u160(lo1, lo2, hi);
|
|
512
|
+
} else if (shift < 128) {
|
|
513
|
+
let lo1 = 0;
|
|
514
|
+
let lo2 = value.lo1 >> (shift - 64);
|
|
515
|
+
let hi = (value.lo2 >> (shift - 64)) | (<u32>(value.hi << (64 - (shift - 64))) & 0xFFFFFFFF);
|
|
516
|
+
return new u160(lo1, lo2, hi);
|
|
517
|
+
} else {
|
|
518
|
+
let lo1 = 0;
|
|
519
|
+
let lo2 = 0;
|
|
520
|
+
let hi = value.lo1 >> (shift - 128);
|
|
521
|
+
return new u160(lo1, lo2, hi as u32);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
@inline @operator('>>>')
|
|
526
|
+
static shr_u(value: u160, shift: i32): u160 {
|
|
527
|
+
return u160.shr(value, shift);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
@inline @operator('==')
|
|
531
|
+
static eq(a: u160, b: u160): bool {
|
|
532
|
+
return (
|
|
533
|
+
a.lo1 == b.lo1 &&
|
|
534
|
+
a.lo2 == b.lo2 &&
|
|
535
|
+
a.hi == b.hi
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
@inline @operator('!=')
|
|
540
|
+
static ne(a: u160, b: u160): bool {
|
|
541
|
+
return !u160.eq(a, b);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
@operator('<')
|
|
545
|
+
static lt(a: u160, b: u160): bool {
|
|
546
|
+
if (a.hi == b.hi) {
|
|
547
|
+
if (a.lo2 == b.lo2) {
|
|
548
|
+
return a.lo1 < b.lo1;
|
|
549
|
+
}
|
|
550
|
+
return a.lo2 < b.lo2;
|
|
551
|
+
}
|
|
552
|
+
return a.hi < b.hi;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
@inline @operator('>')
|
|
556
|
+
static gt(a: u160, b: u160): bool {
|
|
557
|
+
return u160.lt(b, a);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
@inline @operator('<=')
|
|
561
|
+
static le(a: u160, b: u160): bool {
|
|
562
|
+
return !u160.gt(a, b);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
@inline @operator('>=')
|
|
566
|
+
static ge(a: u160, b: u160): bool {
|
|
567
|
+
return !u160.lt(a, b);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// mul: u160 x u160 = u160
|
|
571
|
+
@inline @operator('*')
|
|
572
|
+
static mul(a: u160, b: u160): u160 {
|
|
573
|
+
return __mul160(a.lo1, a.lo2, a.hi, b.lo1, b.lo2, b.hi);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
@inline
|
|
577
|
+
static popcnt(value: u160): i32 {
|
|
578
|
+
let count = popcnt(value.lo1) + popcnt(value.lo2) + popcnt(value.hi);
|
|
579
|
+
return <i32>count;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
@inline
|
|
583
|
+
static clz(value: u160): i32 {
|
|
584
|
+
if (value.hi) return <i32>(clz(value.hi) + 0);
|
|
585
|
+
if (value.lo2) return <i32>(clz(value.lo2) + 32);
|
|
586
|
+
if (value.lo1) return <i32>(clz(value.lo1) + 96);
|
|
587
|
+
return <i32>(clz(0) + 160); // All bits are zero
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
@inline
|
|
591
|
+
static ctz(value: u160): i32 {
|
|
592
|
+
if (value.lo1) return <i32>(ctz(value.lo1) + 0);
|
|
593
|
+
if (value.lo2) return <i32>(ctz(value.lo2) + 64);
|
|
594
|
+
if (value.hi) return <i32>(ctz(value.hi) + 128);
|
|
595
|
+
return <i32>(ctz(0) + 160); // All bits are zero
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Convert to 128-bit signed integer
|
|
600
|
+
* @return 160-bit signed integer
|
|
601
|
+
*/
|
|
602
|
+
@inline
|
|
603
|
+
toI128(): i128 {
|
|
604
|
+
return new i128(
|
|
605
|
+
this.lo1,
|
|
606
|
+
this.lo2,
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Convert to 128-bit unsigned integer
|
|
612
|
+
* @return 128-bit unsigned integer
|
|
613
|
+
*/
|
|
614
|
+
@inline
|
|
615
|
+
toU128(): u128 {
|
|
616
|
+
return new u128(this.lo1, this.lo2);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Convert to 160-bit unsigned integer
|
|
621
|
+
* @returns 160-bit unsigned integer
|
|
622
|
+
*/
|
|
623
|
+
@inline
|
|
624
|
+
toU160(): this {
|
|
625
|
+
return this;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Convert to 64-bit signed integer
|
|
630
|
+
* @return 64-bit signed integer
|
|
631
|
+
*/
|
|
632
|
+
@inline
|
|
633
|
+
toI64(): i64 {
|
|
634
|
+
return <i64>(this.lo1 | (<u64>this.hi << 64));
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Convert to 64-bit unsigned integer
|
|
639
|
+
* @return 64-bit unsigned integer
|
|
640
|
+
*/
|
|
641
|
+
@inline
|
|
642
|
+
toU64(): u64 {
|
|
643
|
+
return this.lo1;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Convert to 32-bit signed integer
|
|
648
|
+
* @return 32-bit signed integer
|
|
649
|
+
*/
|
|
650
|
+
@inline
|
|
651
|
+
toI32(): i32 {
|
|
652
|
+
return <i32>this.lo1;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Convert to 32-bit unsigned integer
|
|
657
|
+
* @return 32-bit unsigned integer
|
|
658
|
+
*/
|
|
659
|
+
@inline
|
|
660
|
+
toU32(): u32 {
|
|
661
|
+
return this.hi;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Convert to 1-bit boolean
|
|
666
|
+
* @return 1-bit boolean
|
|
667
|
+
*/
|
|
668
|
+
@inline
|
|
669
|
+
toBool(): bool {
|
|
670
|
+
return <bool>(this.lo1 | this.lo2 | this.hi);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
@inline
|
|
674
|
+
private toArrayBufferLE(buffer: usize): void {
|
|
675
|
+
store<u64>(buffer, this.lo1, 0 * sizeof<u64>());
|
|
676
|
+
store<u64>(buffer, this.lo2, 1 * sizeof<u64>());
|
|
677
|
+
store<u32>(buffer, this.hi, 2 * sizeof<u64>());
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
@inline
|
|
681
|
+
private toArrayBufferBE(buffer: usize): void {
|
|
682
|
+
store<u32>(buffer, bswap(this.hi), 0 * sizeof<u64>());
|
|
683
|
+
store<u64>(buffer, bswap(this.lo2), 1 * sizeof<u64>());
|
|
684
|
+
store<u64>(buffer, bswap(this.lo1), 3 * sizeof<u64>());
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
@inline
|
|
688
|
+
private toArrayBuffer(buffer: usize, bigEndian: bool = false): void {
|
|
689
|
+
if (bigEndian) {
|
|
690
|
+
this.toArrayBufferBE(buffer);
|
|
691
|
+
} else {
|
|
692
|
+
this.toArrayBufferLE(buffer);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Convert to generic type `T`. Useful inside other generics methods
|
|
698
|
+
* @param T is <bool | i8 | u8 | i16 | u16 | i32 | u32 | i64 | u64 | f32 | f64 | i128 | u128 | u160 | u8[] | Uint8Array | `StaticArray<u8>` | string>
|
|
699
|
+
* @returns type of `T`
|
|
700
|
+
*/
|
|
701
|
+
@inline
|
|
702
|
+
as<T>(): T {
|
|
703
|
+
let dummy!: T;
|
|
704
|
+
if (dummy instanceof bool) return <T>this.toBool();
|
|
705
|
+
else if (dummy instanceof i8) return <T>this.toI64();
|
|
706
|
+
else if (dummy instanceof u8) return <T>this.toU64();
|
|
707
|
+
else if (dummy instanceof i16) return <T>this.toI64();
|
|
708
|
+
else if (dummy instanceof u16) return <T>this.toU64();
|
|
709
|
+
else if (dummy instanceof i32) return <T>this.toI32();
|
|
710
|
+
else if (dummy instanceof u32) return <T>this.toU32();
|
|
711
|
+
else if (dummy instanceof i64) return <T>this.toI64();
|
|
712
|
+
else if (dummy instanceof u64) return <T>this.toU64();
|
|
713
|
+
else if (dummy instanceof i128) return <T>this.toI128();
|
|
714
|
+
else if (dummy instanceof u128) return <T>this.toU128();
|
|
715
|
+
else if (dummy instanceof u160) return <T>this.toU160();
|
|
716
|
+
else if (dummy instanceof u8[]) return <T>this.toBytes();
|
|
717
|
+
else if (dummy instanceof Uint8Array) return <T>this.toUint8Array();
|
|
718
|
+
else if (dummy instanceof StaticArray<u8>) return <T>this.toStaticBytes();
|
|
719
|
+
else if (dummy instanceof String) return <T>this.toString();
|
|
720
|
+
else throw new TypeError('Unsupported generic type');
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Convert to byte array
|
|
725
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
726
|
+
* @returns Array of bytes
|
|
727
|
+
*/
|
|
728
|
+
@inline
|
|
729
|
+
toBytes(bigEndian: bool = false): u8[] {
|
|
730
|
+
let result = new Array<u8>(20);
|
|
731
|
+
this.toArrayBuffer(result.dataStart, bigEndian);
|
|
732
|
+
return result;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Convert to byte static array
|
|
737
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
738
|
+
* @returns StaticArray of bytes
|
|
739
|
+
*/
|
|
740
|
+
@inline
|
|
741
|
+
toStaticBytes(bigEndian: bool = false): StaticArray<u8> {
|
|
742
|
+
let result = new StaticArray<u8>(20);
|
|
743
|
+
this.toArrayBuffer(changetype<usize>(result), bigEndian);
|
|
744
|
+
return result;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Convert to Uint8Array
|
|
749
|
+
* @param bigEndian Little or Big Endian? Default: false
|
|
750
|
+
* @returns Uint8Array
|
|
751
|
+
*/
|
|
752
|
+
@inline
|
|
753
|
+
toUint8Array(bigEndian: bool = false): Uint8Array {
|
|
754
|
+
let result = new Uint8Array(20);
|
|
755
|
+
this.toArrayBuffer(result.dataStart, bigEndian);
|
|
756
|
+
return result;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
clone(): u160 {
|
|
760
|
+
return new u160(this.lo1, this.lo2, this.hi);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
toString(radix: i32 = 10): string {
|
|
764
|
+
assert(radix == 10 || radix == 16, 'radix argument must be either 10 or 16');
|
|
765
|
+
if (this.isZero()) return '0';
|
|
766
|
+
|
|
767
|
+
let result = '';
|
|
768
|
+
if (radix == 16) {
|
|
769
|
+
let shift: i32 = 156 - (u160.clz(this) & ~3);
|
|
770
|
+
while (shift >= 0) {
|
|
771
|
+
let nibble = (<u32>((this >> shift).lo1) & 0xF);
|
|
772
|
+
result += HEX_CHARS.charAt(nibble);
|
|
773
|
+
shift -= 4;
|
|
774
|
+
}
|
|
775
|
+
return result;
|
|
776
|
+
}
|
|
777
|
+
return u160toDecimalString(this);
|
|
778
|
+
}
|
|
779
|
+
}
|