@btc-vision/btc-runtime 1.8.1 → 1.9.0

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.
Files changed (69) hide show
  1. package/README.md +57 -79
  2. package/package.json +8 -8
  3. package/runtime/buffer/BytesReader.ts +36 -45
  4. package/runtime/buffer/BytesWriter.ts +60 -20
  5. package/runtime/contracts/OP20.ts +636 -0
  6. package/runtime/contracts/OP_NET.ts +3 -3
  7. package/runtime/contracts/interfaces/IOP20.ts +15 -0
  8. package/runtime/contracts/interfaces/OP20InitParameters.ts +3 -1
  9. package/runtime/env/BlockchainEnvironment.ts +28 -7
  10. package/runtime/env/classes/Transaction.ts +1 -2
  11. package/runtime/env/global.ts +171 -23
  12. package/runtime/events/NetEvent.ts +1 -1
  13. package/runtime/events/predefined/{ApproveEvent.ts → ApprovedEvent.ts} +3 -3
  14. package/runtime/events/predefined/{MintEvent.ts → BurnedEvent.ts} +5 -6
  15. package/runtime/events/predefined/{TransferEvent.ts → MintedEvent.ts} +5 -6
  16. package/runtime/events/predefined/TransferredEvent.ts +18 -0
  17. package/runtime/events/predefined/index.ts +4 -4
  18. package/runtime/exports/index.ts +4 -4
  19. package/runtime/index.ts +13 -3
  20. package/runtime/math/abi.ts +10 -6
  21. package/runtime/math/bytes.ts +5 -17
  22. package/runtime/memory/AddressMemoryMap.ts +4 -5
  23. package/runtime/memory/KeyMerger.ts +7 -7
  24. package/runtime/memory/MapOfMap.ts +2 -7
  25. package/runtime/memory/Nested.ts +6 -8
  26. package/runtime/nested/PointerManager.ts +1 -1
  27. package/runtime/nested/codecs/AddressCodec.ts +1 -1
  28. package/runtime/nested/codecs/BooleanCodec.ts +1 -1
  29. package/runtime/nested/codecs/Ids.ts +1 -1
  30. package/runtime/nested/codecs/NumericCodec.ts +1 -1
  31. package/runtime/nested/codecs/StringCodec.ts +1 -1
  32. package/runtime/nested/codecs/VariableBytesCodec.ts +3 -3
  33. package/runtime/nested/storage/StorageMap.ts +3 -3
  34. package/runtime/nested/storage/StorageSet.ts +2 -2
  35. package/runtime/plugins/Plugin.ts +5 -7
  36. package/runtime/script/Bech32.ts +369 -0
  37. package/runtime/script/BitcoinAddresses.ts +208 -0
  38. package/runtime/script/BitcoinCodec.ts +395 -0
  39. package/runtime/script/Networks.ts +94 -0
  40. package/runtime/script/Opcodes.ts +155 -0
  41. package/runtime/script/Script.ts +463 -0
  42. package/runtime/script/ScriptUtils.ts +101 -0
  43. package/runtime/script/Segwit.ts +185 -0
  44. package/runtime/script/reader/ScriptReader.ts +247 -0
  45. package/runtime/secp256k1/ECPoint.ts +6 -12
  46. package/runtime/shared-libraries/TransferHelper.ts +72 -31
  47. package/runtime/storage/AdvancedStoredString.ts +1 -1
  48. package/runtime/storage/StoredAddress.ts +1 -1
  49. package/runtime/storage/StoredBoolean.ts +2 -4
  50. package/runtime/storage/StoredString.ts +6 -3
  51. package/runtime/storage/StoredU256.ts +1 -3
  52. package/runtime/storage/StoredU32.ts +1 -6
  53. package/runtime/storage/StoredU64.ts +1 -4
  54. package/runtime/storage/arrays/StoredBooleanArray.ts +7 -12
  55. package/runtime/storage/arrays/StoredPackedArray.ts +3 -13
  56. package/runtime/storage/maps/StoredMapU256.ts +5 -5
  57. package/runtime/types/Address.ts +49 -39
  58. package/runtime/types/SafeMath.ts +19 -18
  59. package/runtime/types/SafeMathI128.ts +14 -13
  60. package/runtime/utils/hex.ts +41 -19
  61. package/runtime/utils/index.ts +0 -2
  62. package/runtime/contracts/DeployableOP_20.ts +0 -415
  63. package/runtime/contracts/OP_20.ts +0 -9
  64. package/runtime/contracts/interfaces/IOP_20.ts +0 -19
  65. package/runtime/events/predefined/BurnEvent.ts +0 -14
  66. package/runtime/utils/b32.ts +0 -243
  67. package/runtime/utils/box.ts +0 -134
  68. package/runtime/utils/encodings.ts +0 -45
  69. /package/{LICENSE → LICENSE.md} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { BytesWriter } from '../buffer/BytesWriter';
2
2
  import { Blockchain } from '../env';
3
3
  import { encodePointerUnknownLength } from '../math/abi';
4
-
4
+ import { Revert } from '../types/Revert';
5
5
 
6
6
  @final
7
7
  export class KeyMerger<K extends string, K2 extends string, V extends Uint8Array> {
@@ -22,24 +22,24 @@ export class KeyMerger<K extends string, K2 extends string, V extends Uint8Array
22
22
  return this;
23
23
  }
24
24
 
25
- public get(key: K): Uint8Array {
25
+ public get(key: K2): Uint8Array {
26
26
  const mergedKey: string = this.mergeKey(key);
27
27
  return Blockchain.getStorageAt(this.encodePointer(mergedKey));
28
28
  }
29
29
 
30
- public has(key: K): bool {
30
+ public has(key: K2): bool {
31
31
  const mergedKey: string = this.mergeKey(key);
32
32
  return Blockchain.hasStorageAt(this.encodePointer(mergedKey));
33
33
  }
34
34
 
35
35
  @unsafe
36
- public delete(_key: K): bool {
37
- throw new Error('Method not implemented.');
36
+ public delete(_key: K2): bool {
37
+ throw new Revert('Method not implemented.');
38
38
  }
39
39
 
40
40
  @unsafe
41
41
  public clear(): void {
42
- throw new Error('Clear method not implemented.');
42
+ throw new Revert('Clear method not implemented.');
43
43
  }
44
44
 
45
45
  /**
@@ -49,7 +49,7 @@ export class KeyMerger<K extends string, K2 extends string, V extends Uint8Array
49
49
  * parentKey = "ab", key = "cdef" => "2:ab4:cdef"
50
50
  */
51
51
  @inline
52
- private mergeKey(key: string): string {
52
+ private mergeKey(key: K2): string {
53
53
  return `${this.parentKey.length}:${this.parentKey}${key.length}:${key}`;
54
54
  }
55
55
 
@@ -2,15 +2,10 @@ import { Address } from '../types/Address';
2
2
  import { Nested } from './Nested';
3
3
 
4
4
  @final
5
- export class MapOfMap<T> extends Map<
6
- Address,
7
- Nested<T>
8
- > {
5
+ export class MapOfMap<T> extends Map<Address, Nested<T>> {
9
6
  public pointer: u16;
10
7
 
11
- constructor(
12
- pointer: u16,
13
- ) {
8
+ constructor(pointer: u16) {
14
9
  super();
15
10
 
16
11
  this.pointer = pointer;
@@ -3,6 +3,7 @@ import { encodePointerUnknownLength } from '../math/abi';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { u256 } from '@btc-vision/as-bignum/assembly';
5
5
  import { Address } from '../types/Address';
6
+ import { Revert } from '../types/Revert';
6
7
 
7
8
  @final
8
9
  export class Nested<T> {
@@ -10,10 +11,7 @@ export class Nested<T> {
10
11
 
11
12
  public pointer: u16;
12
13
 
13
- constructor(
14
- parent: Uint8Array,
15
- pointer: u16,
16
- ) {
14
+ constructor(parent: Uint8Array, pointer: u16) {
17
15
  this.pointer = pointer;
18
16
 
19
17
  this.parentKey = parent;
@@ -40,12 +38,12 @@ export class Nested<T> {
40
38
 
41
39
  @unsafe
42
40
  public delete(_key: Uint8Array): bool {
43
- throw new Error('Method not implemented.');
41
+ throw new Revert('Method not implemented.');
44
42
  }
45
43
 
46
44
  @unsafe
47
45
  public clear(): void {
48
- throw new Error('Clear method not implemented.');
46
+ throw new Revert('Clear method not implemented.');
49
47
  }
50
48
 
51
49
  /**
@@ -70,7 +68,7 @@ export class Nested<T> {
70
68
  return changetype<T>(String.UTF8.decode(value.buffer));
71
69
  }
72
70
 
73
- throw new Error('Unsupported type');
71
+ throw new Revert('Unsupported type');
74
72
  }
75
73
 
76
74
  /**
@@ -95,7 +93,7 @@ export class Nested<T> {
95
93
  return Uint8Array.wrap(String.UTF8.encode(str));
96
94
  }
97
95
 
98
- throw new Error('Unsupported type');
96
+ throw new Revert('Unsupported type');
99
97
  }
100
98
 
101
99
  private getKeyHash(key: Uint8Array): Uint8Array {
@@ -52,4 +52,4 @@ class _PointerManager extends Plugin {
52
52
  }
53
53
 
54
54
  export const PointerManager = new _PointerManager();
55
- Blockchain.registerPlugin(PointerManager);
55
+ Blockchain.registerPlugin(PointerManager);
@@ -16,4 +16,4 @@ class _AddressCodec implements ICodec<Address> {
16
16
  }
17
17
 
18
18
  export const idOfAddressCodec = idof<_AddressCodec>();
19
- export const AddressCodec = new _AddressCodec();
19
+ export const AddressCodec = new _AddressCodec();
@@ -14,4 +14,4 @@ class _BooleanCodec implements ICodec<bool> {
14
14
  }
15
15
 
16
16
  export const idOfBoolCodec = idof<_BooleanCodec>();
17
- export const BooleanCodec = new _BooleanCodec();
17
+ export const BooleanCodec = new _BooleanCodec();
@@ -7,4 +7,4 @@ export const idOfU128 = idof<u128>();
7
7
  export const idOfI128 = idof<i128>();
8
8
  export const idOfUint8Array = idof<Uint8Array>();
9
9
  export const idOfString = idof<string>();
10
- export const idOfAddress = idof<Address>();
10
+ export const idOfAddress = idof<Address>();
@@ -55,4 +55,4 @@ export class NumericCodec<T> implements ICodec<T> {
55
55
  }
56
56
  }
57
57
  }
58
- }
58
+ }
@@ -21,4 +21,4 @@ class IStringCodec implements ICodec<string> {
21
21
  }
22
22
 
23
23
  export const idOfStringCodec = idof<IStringCodec>();
24
- export const StringCodec = new IStringCodec();
24
+ export const StringCodec = new IStringCodec();
@@ -21,7 +21,7 @@ export class IVariableBytesCodec implements ICodec<Uint8Array> {
21
21
 
22
22
  // If remaining > 0, each chunk is 32 bytes.
23
23
  // So total chunks needed = 1 (for first chunk) + ceil(remaining / 32).
24
- const additionalChunks: u32 = remaining == 0 ? 0 : ((remaining + 32 - 1) / 32);
24
+ const additionalChunks: u32 = remaining == 0 ? 0 : (remaining + 32 - 1) / 32;
25
25
  const totalChunks: u32 = 1 + additionalChunks;
26
26
 
27
27
  // 1) Allocate `totalChunks` from PointerManager
@@ -52,7 +52,7 @@ export class IVariableBytesCodec implements ICodec<Uint8Array> {
52
52
  for (let j: u32 = 0; j < chunkSize; j++) {
53
53
  chunk[j] = value[offset + j];
54
54
  }
55
-
55
+
56
56
  offset += chunkSize;
57
57
  remaining -= chunkSize;
58
58
 
@@ -131,4 +131,4 @@ function isAllZero(arr: Uint8Array): bool {
131
131
  }
132
132
 
133
133
  export const idOfVariableBytes = idof<IVariableBytesCodec>();
134
- export const VariableBytesCodec = new IVariableBytesCodec();
134
+ export const VariableBytesCodec = new IVariableBytesCodec();
@@ -4,7 +4,7 @@ import { BytesReader } from '../../buffer/BytesReader';
4
4
  import { encodePointerUnknownLength } from '../../math/abi';
5
5
 
6
6
  import { i128, u128, u256 } from '@btc-vision/as-bignum/assembly';
7
- import { idOfAddress, idOfI128, idOfString, idOfU128, idOfU256, idOfUint8Array } from '../codecs/Ids';
7
+ import { idOfAddress, idOfI128, idOfString, idOfU128, idOfU256, idOfUint8Array, } from '../codecs/Ids';
8
8
 
9
9
  import { AddressCodec } from '../codecs/AddressCodec';
10
10
  import { BooleanCodec } from '../codecs/BooleanCodec';
@@ -66,7 +66,7 @@ export class StorageMap<K, V> {
66
66
  @unsafe
67
67
  public clear(): void {
68
68
  // Not implemented: we'd need key-tracking to remove them all
69
- throw new Error('clear() not implemented; no key-tracking logic here.');
69
+ throw new Revert('clear() not implemented; no key-tracking logic here.');
70
70
  }
71
71
 
72
72
  // ----------------------------------------------------------
@@ -224,4 +224,4 @@ export class StorageMap<K, V> {
224
224
 
225
225
  throw new Revert('encodeValue: Unsupported type');
226
226
  }
227
- }
227
+ }
@@ -2,7 +2,7 @@ import { ICodec } from '../interfaces/ICodec';
2
2
  import { BytesWriter } from '../../buffer/BytesWriter';
3
3
  import { encodePointerUnknownLength } from '../../math/abi';
4
4
  import { Blockchain } from '../../env';
5
-
5
+ import { Revert } from '../../types/Revert';
6
6
 
7
7
  export class StorageSet<T> {
8
8
  private readonly pointer: u16;
@@ -43,7 +43,7 @@ export class StorageSet<T> {
43
43
 
44
44
  @unsafe
45
45
  public clear(): void {
46
- throw new Error('clear() not implemented.');
46
+ throw new Revert('clear() not implemented.');
47
47
  }
48
48
 
49
49
  private getStorageKey(value: T): Uint8Array {
@@ -1,12 +1,10 @@
1
1
  import { Calldata } from '../types';
2
+ import { Selector } from '../math/abi';
2
3
 
3
4
  export class Plugin {
4
- public onDeployment(_calldata: Calldata): void {
5
- }
5
+ public onDeployment(_calldata: Calldata): void {}
6
6
 
7
- public onExecutionStarted(): void {
8
- }
7
+ public onExecutionStarted(_selector: Selector, _calldata: Calldata): void {}
9
8
 
10
- public onExecutionCompleted(): void {
11
- }
12
- }
9
+ public onExecutionCompleted(_selector: Selector, _calldata: Calldata): void {}
10
+ }
@@ -0,0 +1,369 @@
1
+ import { BytesWriter } from '../buffer/BytesWriter';
2
+ import { SegwitDecoded } from './ScriptUtils';
3
+ import { Revert } from '../types/Revert';
4
+
5
+ /**
6
+ * Result type for Bech32 operations that can fail
7
+ */
8
+ @final
9
+ export class Bech32Result<T> {
10
+ public readonly success: bool;
11
+ public readonly value: T | null;
12
+ public readonly error: string | null;
13
+
14
+ public constructor(success: bool, value: T | null, error: string | null) {
15
+ this.success = success;
16
+ this.value = value;
17
+ this.error = error;
18
+ }
19
+
20
+ public static ok<T>(value: T): Bech32Result<T> {
21
+ return new Bech32Result<T>(true, value, null);
22
+ }
23
+
24
+ public static err<T>(error: string): Bech32Result<T> {
25
+ return new Bech32Result<T>(false, null, error);
26
+ }
27
+ }
28
+
29
+ @final
30
+ export class Bech32 {
31
+ private static readonly CHARSET: string = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
32
+ private static decodeTbl: Int8Array | null = null;
33
+
34
+ /**
35
+ * Consider using encodeOrNull instead, this method will throw on error
36
+ * @param hrp
37
+ * @param witver
38
+ * @param program
39
+ */
40
+ public static encode(hrp: string, witver: i32, program: Uint8Array): string {
41
+ const result = Bech32.encodeOrNull(hrp, witver, program);
42
+ if (!result) {
43
+ throw new Revert('Bech32 encoding failed');
44
+ }
45
+
46
+ return result as string;
47
+ }
48
+
49
+ /**
50
+ * Safe encode that returns null on error instead of throwing
51
+ */
52
+ public static encodeOrNull(hrp: string, witver: i32, program: Uint8Array): string | null {
53
+ // Validate inputs
54
+ if (witver < 0 || witver > 16) return null;
55
+ if (witver == 0 && program.length != 20 && program.length != 32) return null;
56
+ if (witver != 0 && (program.length < 2 || program.length > 40)) return null;
57
+
58
+ // Build the 5-bit words array
59
+ const wordsWB = new BytesWriter(1 + (program.length * 8 + 4) / 5);
60
+ wordsWB.writeU8(<u8>witver);
61
+
62
+ const convertResult = Bech32.convertBitsSafe(program, 8, 5, true);
63
+ if (!convertResult.success) return null;
64
+
65
+ if (convertResult.value === null) {
66
+ throw new Revert('Bech32 convertBits failed with unknown error');
67
+ }
68
+
69
+ wordsWB.writeBytes(convertResult.value as Uint8Array);
70
+
71
+ const data = wordsWB.getBuffer().subarray(0, <i32>wordsWB.getOffset());
72
+ const chk = Bech32.createChecksum(hrp, data, /*bech32m*/ witver != 0);
73
+
74
+ // Build final output
75
+ const totalLen = hrp.length + 1 + data.length + chk.length;
76
+ const outWB = new BytesWriter(totalLen);
77
+
78
+ for (let i = 0; i < hrp.length; i++) {
79
+ outWB.writeU8(<u8>hrp.charCodeAt(i));
80
+ }
81
+ outWB.writeU8(49); // '1' separator
82
+
83
+ for (let i = 0; i < data.length; i++) {
84
+ outWB.writeU8(<u8>Bech32.CHARSET.charCodeAt(data[i]));
85
+ }
86
+
87
+ for (let i = 0; i < chk.length; i++) {
88
+ outWB.writeU8(<u8>Bech32.CHARSET.charCodeAt(chk[i]));
89
+ }
90
+
91
+ return String.UTF8.decode(outWB.getBuffer().buffer);
92
+ }
93
+
94
+ /**
95
+ * Consider using decodeOrNull instead, this method will throw on error
96
+ * @param addr
97
+ */
98
+ public static decode(addr: string): SegwitDecoded {
99
+ const result = Bech32.decodeOrNull(addr);
100
+ if (!result) {
101
+ throw new Revert('Bech32 decode failed');
102
+ }
103
+
104
+ return result as SegwitDecoded;
105
+ }
106
+
107
+ /**
108
+ * Safe decode that returns null on error
109
+ */
110
+ public static decodeOrNull(addr: string): SegwitDecoded | null {
111
+ const L = addr.length;
112
+
113
+ // Validate basic length constraints
114
+ if (L < 8 || L > 90) return null;
115
+
116
+ let lower = false;
117
+ let upper = false;
118
+ let pos = -1;
119
+
120
+ // Scan for separator and validate characters
121
+ for (let i = 0; i < L; i++) {
122
+ const c = addr.charCodeAt(i);
123
+ if (c < 33 || c > 126) return null;
124
+
125
+ if (c >= 97 && c <= 122) lower = true;
126
+ else if (c >= 65 && c <= 90) upper = true;
127
+
128
+ if (c == 49) pos = i; // '1' separator
129
+ }
130
+
131
+ // Check case consistency
132
+ if (lower && upper) return null;
133
+
134
+ // Validate separator position
135
+ if (pos < 1 || pos + 7 > L) return null;
136
+
137
+ // Extract HRP and normalize to lowercase
138
+ const hrp = lower ? addr.substring(0, pos) : addr.substring(0, pos).toLowerCase();
139
+
140
+ // Decode the data part
141
+ const dpLen = L - pos - 1;
142
+ const data = new Uint8Array(dpLen);
143
+
144
+ Bech32.ensureTable();
145
+ const tbl = changetype<Int8Array>(Bech32.decodeTbl);
146
+
147
+ for (let i = 0; i < dpLen; i++) {
148
+ let c = addr.charCodeAt(pos + 1 + i);
149
+ // Normalize to lowercase if needed
150
+ if (!lower && c >= 65 && c <= 90) c += 32;
151
+
152
+ const v = c < 128 ? unchecked(tbl[c]) : -1;
153
+ if (v < 0) return null;
154
+
155
+ data[i] = <u8>v;
156
+ }
157
+
158
+ // Verify checksum
159
+ const w = new BytesWriter(hrp.length * 2 + 1 + dpLen);
160
+ w.writeBytes(Bech32.hrpExpand(hrp));
161
+ w.writeBytes(data);
162
+
163
+ const pm = Bech32.polymod(w.getBuffer().subarray(0, <i32>w.getOffset()));
164
+ const witver = <i32>data[0];
165
+
166
+ if (witver < 0 || witver > 16) return null;
167
+
168
+ // Check if checksum matches for either bech32 or bech32m
169
+ let constOK = false;
170
+ if ((pm ^ 1) == 0) constOK = witver == 0; // bech32 for v0
171
+ if ((pm ^ 0x2bc830a3) == 0) constOK = witver != 0; // bech32m for v1+
172
+
173
+ if (!constOK) return null;
174
+
175
+ // Extract witness program
176
+ const words = data.subarray(0, dpLen - 6);
177
+ const progWords = words.subarray(1);
178
+
179
+ const convertResult = Bech32.convertBitsSafe(progWords, 5, 8, false);
180
+ if (!convertResult.success) return null;
181
+
182
+ const program = convertResult.value!;
183
+
184
+ // Validate program length based on witness version
185
+ if (witver == 0) {
186
+ const Lp = program.length;
187
+ if (Lp != 20 && Lp != 32) return null;
188
+ } else {
189
+ const Lp = program.length;
190
+ if (Lp < 2 || Lp > 40) return null;
191
+ }
192
+
193
+ return new SegwitDecoded(hrp, witver, program);
194
+ }
195
+
196
+ /**
197
+ * Ensure the decode table is initialized
198
+ * This is safe to call multiple times
199
+ */
200
+ private static ensureTable(): void {
201
+ if (Bech32.decodeTbl) return;
202
+
203
+ const t = new Int8Array(128);
204
+ for (let i = 0; i < 128; i++) {
205
+ unchecked((t[i] = -1));
206
+ }
207
+
208
+ for (let i = 0; i < 32; i++) {
209
+ const c = Bech32.CHARSET.charCodeAt(i);
210
+ if (c < 128) {
211
+ unchecked((t[c] = <i8>i));
212
+ }
213
+ }
214
+
215
+ Bech32.decodeTbl = t;
216
+ }
217
+
218
+ /**
219
+ * Expand human-readable part for checksum computation
220
+ */
221
+ private static hrpExpand(hrp: string): Uint8Array {
222
+ const L = hrp.length;
223
+ const w = new BytesWriter(L * 2 + 1);
224
+
225
+ // High bits of each character
226
+ for (let i = 0; i < L; i++) {
227
+ w.writeU8(<u8>(hrp.charCodeAt(i) >>> 5));
228
+ }
229
+
230
+ w.writeU8(0); // Separator
231
+
232
+ // Low bits of each character
233
+ for (let i = 0; i < L; i++) {
234
+ w.writeU8(<u8>(hrp.charCodeAt(i) & 31));
235
+ }
236
+
237
+ return w.getBuffer();
238
+ }
239
+
240
+ /**
241
+ * Compute Bech32 checksum polymod
242
+ */
243
+ private static polymod(values: Uint8Array): u32 {
244
+ let chk: u32 = 1;
245
+
246
+ // Generator polynomial coefficients
247
+ const G0: u32 = 0x3b6a57b2;
248
+ const G1: u32 = 0x26508e6d;
249
+ const G2: u32 = 0x1ea119fa;
250
+ const G3: u32 = 0x3d4233dd;
251
+ const G4: u32 = 0x2a1462b3;
252
+
253
+ const L = values.length;
254
+ for (let i = 0; i < L; i++) {
255
+ const top = chk >>> 25;
256
+ chk = ((chk & 0x1ffffff) << 5) ^ (<u32>unchecked(values[i]));
257
+
258
+ if ((top & 1) != 0) chk ^= G0;
259
+ if ((top & 2) != 0) chk ^= G1;
260
+ if ((top & 4) != 0) chk ^= G2;
261
+ if ((top & 8) != 0) chk ^= G3;
262
+ if ((top & 16) != 0) chk ^= G4;
263
+ }
264
+
265
+ return chk;
266
+ }
267
+
268
+ /**
269
+ * Consider using convertBitsSafe instead, this method will throw on error
270
+ */
271
+ private static convertBits(
272
+ data: Uint8Array,
273
+ fromBits: i32,
274
+ toBits: i32,
275
+ pad: bool,
276
+ ): Uint8Array {
277
+ const result = Bech32.convertBitsSafe(data, fromBits, toBits, pad);
278
+ if (!result.success) {
279
+ if (!result.error) {
280
+ throw new Revert('Bech32 convertBits failed with unknown error');
281
+ }
282
+
283
+ throw new Revert(result.error);
284
+ }
285
+ return result.value!;
286
+ }
287
+
288
+ /**
289
+ * Safe version of convertBits that returns a result object
290
+ */
291
+ private static convertBitsSafe(
292
+ data: Uint8Array,
293
+ fromBits: i32,
294
+ toBits: i32,
295
+ pad: bool,
296
+ ): Bech32Result<Uint8Array> {
297
+ let acc: i32 = 0;
298
+ let bits: i32 = 0;
299
+ const maxv = (1 << toBits) - 1;
300
+
301
+ // Calculate output length
302
+ const outLen64: i64 = pad
303
+ ? (<i64>data.length * fromBits + (toBits - 1)) / toBits
304
+ : (<i64>data.length * fromBits) / toBits;
305
+
306
+ if (outLen64 > <i64>0x7fffffff) {
307
+ return Bech32Result.err<Uint8Array>('convertBits outLen overflow');
308
+ }
309
+
310
+ const wb = new BytesWriter(<i32>outLen64);
311
+ const L = data.length;
312
+
313
+ for (let i = 0; i < L; i++) {
314
+ const v = <i32>unchecked(data[i]);
315
+
316
+ // Validate input value
317
+ if (v < 0 || v >> fromBits != 0) {
318
+ return Bech32Result.err<Uint8Array>('invalid value');
319
+ }
320
+
321
+ acc = (acc << fromBits) | v;
322
+ bits += fromBits;
323
+
324
+ while (bits >= toBits) {
325
+ bits -= toBits;
326
+ wb.writeU8(<u8>((acc >> bits) & maxv));
327
+ }
328
+ }
329
+
330
+ if (pad) {
331
+ if (bits > 0) {
332
+ wb.writeU8(<u8>((acc << (toBits - bits)) & maxv));
333
+ }
334
+ } else {
335
+ if (bits >= fromBits) {
336
+ return Bech32Result.err<Uint8Array>('excess padding');
337
+ }
338
+ if (((acc << (toBits - bits)) & maxv) != 0) {
339
+ return Bech32Result.err<Uint8Array>('non-zero padding');
340
+ }
341
+ }
342
+
343
+ return Bech32Result.ok<Uint8Array>(wb.getBuffer().subarray(0, <i32>wb.getOffset()));
344
+ }
345
+
346
+ private static createChecksum(hrp: string, data: Uint8Array, bech32m: bool): Uint8Array {
347
+ const hrpEx = Bech32.hrpExpand(hrp);
348
+ const w = new BytesWriter(hrpEx.length + data.length + 6);
349
+
350
+ w.writeBytes(hrpEx);
351
+ w.writeBytes(data);
352
+
353
+ // Add 6 zero bytes for checksum calculation
354
+ for (let i = 0; i < 6; i++) {
355
+ w.writeU8(0);
356
+ }
357
+
358
+ const pm =
359
+ Bech32.polymod(w.getBuffer().subarray(0, <i32>w.getOffset())) ^
360
+ (bech32m ? 0x2bc830a3 : 1);
361
+
362
+ const out = new Uint8Array(6);
363
+ for (let p = 0; p < 6; p++) {
364
+ out[p] = <u8>((pm >>> (5 * (5 - p))) & 31);
365
+ }
366
+
367
+ return out;
368
+ }
369
+ }