@btc-vision/btc-runtime 1.9.16 → 1.10.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.
- package/package.json +2 -2
- package/runtime/buffer/BytesReader.ts +1 -1
- package/runtime/constants/Exports.ts +11 -11
- package/runtime/contracts/OP20.ts +312 -12
- package/runtime/contracts/OP721.ts +15 -9
- package/runtime/env/BlockchainEnvironment.ts +202 -5
- package/runtime/env/classes/Transaction.ts +36 -3
- package/runtime/env/consensus/ConsensusRules.ts +228 -0
- package/runtime/env/consensus/MLDSAMetadata.ts +181 -0
- package/runtime/env/consensus/Signatures.ts +7 -0
- package/runtime/env/global.ts +111 -7
- package/runtime/exports/index.ts +2 -1
- package/runtime/index.ts +7 -11
- package/runtime/interfaces/as.ts +5 -0
- package/runtime/shared-libraries/TransferHelper.ts +4 -17
- package/runtime/types/Address.ts +230 -46
- package/runtime/types/ExtendedAddress.ts +426 -0
- package/runtime/nested/PointerManager.ts +0 -55
- package/runtime/nested/codecs/AddressCodec.ts +0 -19
- package/runtime/nested/codecs/BooleanCodec.ts +0 -17
- package/runtime/nested/codecs/Ids.ts +0 -10
- package/runtime/nested/codecs/NumericCodec.ts +0 -58
- package/runtime/nested/codecs/StringCodec.ts +0 -24
- package/runtime/nested/codecs/U256Codec.ts +0 -20
- package/runtime/nested/codecs/VariableBytesCodec.ts +0 -134
- package/runtime/nested/interfaces/ICodec.ts +0 -12
- package/runtime/nested/storage/StorageMap.ts +0 -207
- package/runtime/nested/storage/StorageSet.ts +0 -60
package/runtime/types/Address.ts
CHANGED
|
@@ -1,14 +1,57 @@
|
|
|
1
1
|
import { Potential } from '../lang/Definitions';
|
|
2
2
|
import { ADDRESS_BYTE_LENGTH, decodeHexArray, encodeHexFromBuffer } from '../utils';
|
|
3
3
|
import { Revert } from './Revert';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { loadMLDSAPublicKey } from '../env/global';
|
|
5
|
+
import { MLDSASecurityLevel } from '../env/consensus/MLDSAMetadata';
|
|
6
|
+
import { ArrayLike } from '../interfaces/as';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a 32-byte address in the OPNet system.
|
|
10
|
+
*
|
|
11
|
+
* This class extends Uint8Array to provide a fixed-size 32-byte address with additional
|
|
12
|
+
* functionality for quantum-resistant cryptography. The address stores the SHA256 hash
|
|
13
|
+
* of an ML-DSA public key and provides lazy loading of the full ML-DSA public key when
|
|
14
|
+
* needed for signature verification.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Addresses are immutable once set - attempting to modify an address after construction
|
|
18
|
+
* will throw an error. This ensures address integrity throughout the contract lifecycle.
|
|
19
|
+
*
|
|
20
|
+
* The class provides operator overloading for comparison operations, treating addresses
|
|
21
|
+
* as big-endian 256-bit integers for ordering purposes.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Create from hex string
|
|
26
|
+
* const addr1 = Address.fromString('0x1234...abcd');
|
|
27
|
+
*
|
|
28
|
+
* // Create zero address
|
|
29
|
+
* const zero = Address.zero();
|
|
30
|
+
*
|
|
31
|
+
* // Compare addresses
|
|
32
|
+
* if (addr1 > zero) {
|
|
33
|
+
* // addr1 is greater than zero
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // Get ML-DSA public key for verification
|
|
37
|
+
* const mldsaKey = addr1.mldsaPublicKey;
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
9
40
|
export class Address extends Uint8Array {
|
|
10
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Indicates whether the address has been initialized with data.
|
|
43
|
+
* Once true, the address becomes immutable.
|
|
44
|
+
*/
|
|
45
|
+
protected isDefined: boolean = false;
|
|
11
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new Address instance.
|
|
49
|
+
*
|
|
50
|
+
* @param bytes - Optional 32-byte array representing the address.
|
|
51
|
+
* If empty or not provided, creates a zero address.
|
|
52
|
+
*
|
|
53
|
+
* @throws {Revert} If bytes length is not exactly 32
|
|
54
|
+
*/
|
|
12
55
|
public constructor(bytes: u8[] = []) {
|
|
13
56
|
super(ADDRESS_BYTE_LENGTH);
|
|
14
57
|
|
|
@@ -18,17 +61,64 @@ export class Address extends Uint8Array {
|
|
|
18
61
|
}
|
|
19
62
|
|
|
20
63
|
/**
|
|
21
|
-
*
|
|
22
|
-
|
|
64
|
+
* Cached ML-DSA public key, loaded lazily when first accessed.
|
|
65
|
+
*/
|
|
66
|
+
protected _mldsaPublicKey: Potential<Uint8Array> = null;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Gets the ML-DSA public key associated with this address.
|
|
70
|
+
*
|
|
71
|
+
* The full ML-DSA public key is loaded from storage on first access and cached
|
|
72
|
+
* for subsequent uses. This key is used for quantum-resistant signature verification
|
|
73
|
+
* when the consensus transitions away from Schnorr signatures.
|
|
74
|
+
*
|
|
75
|
+
* @returns The ML-DSA Level 2 (ML-DSA-44) public key for this address
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* The address itself stores only the SHA256 hash of the ML-DSA public key.
|
|
79
|
+
* The full key (which is much larger, typically ~1312 bytes for Level 2)
|
|
80
|
+
* is stored separately and loaded on demand for efficiency.
|
|
23
81
|
*/
|
|
24
|
-
public
|
|
25
|
-
|
|
82
|
+
public get mldsaPublicKey(): Uint8Array {
|
|
83
|
+
if (!this._mldsaPublicKey) {
|
|
84
|
+
this._mldsaPublicKey = loadMLDSAPublicKey(this, MLDSASecurityLevel.Level2);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this._mldsaPublicKey as Uint8Array;
|
|
26
88
|
}
|
|
27
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Creates a zero address (all 32 bytes are 0x00).
|
|
92
|
+
*
|
|
93
|
+
* @returns A new Address instance with all bytes set to zero
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const zero = Address.zero();
|
|
98
|
+
* console.log(zero.isZero()); // true
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
28
101
|
public static zero(): Address {
|
|
29
102
|
return ZERO_ADDRESS.clone();
|
|
30
103
|
}
|
|
31
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Creates an Address from a hexadecimal string representation.
|
|
107
|
+
*
|
|
108
|
+
* @param pubKey - The 32-byte address as a hexadecimal string.
|
|
109
|
+
* Can be prefixed with '0x' or unprefixed.
|
|
110
|
+
*
|
|
111
|
+
* @returns A new Address instance
|
|
112
|
+
*
|
|
113
|
+
* @throws {Error} If the decoded hex string is not exactly 32 bytes
|
|
114
|
+
* @throws {Error} If the string contains invalid hexadecimal characters
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const addr1 = Address.fromString('0x' + '00'.repeat(32));
|
|
119
|
+
* const addr2 = Address.fromString('deadbeef'.repeat(8));
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
32
122
|
public static fromString(pubKey: string): Address {
|
|
33
123
|
if (pubKey.startsWith('0x')) {
|
|
34
124
|
pubKey = pubKey.slice(2);
|
|
@@ -37,23 +127,41 @@ export class Address extends Uint8Array {
|
|
|
37
127
|
return new Address(decodeHexArray(pubKey));
|
|
38
128
|
}
|
|
39
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Creates an Address from a Uint8Array using direct memory copy.
|
|
132
|
+
*
|
|
133
|
+
* This method is more efficient than the constructor for creating
|
|
134
|
+
* addresses from existing Uint8Array data as it uses direct memory
|
|
135
|
+
* copying instead of element-by-element copying.
|
|
136
|
+
*
|
|
137
|
+
* @param bytes - The source Uint8Array containing exactly 32 bytes
|
|
138
|
+
*
|
|
139
|
+
* @returns A new Address instance with data copied from the input
|
|
140
|
+
*
|
|
141
|
+
* @remarks
|
|
142
|
+
* The input array must be exactly ADDRESS_BYTE_LENGTH (32) bytes.
|
|
143
|
+
* This method performs a raw memory copy, so ensure the input is valid.
|
|
144
|
+
*/
|
|
40
145
|
public static fromUint8Array(bytes: Uint8Array): Address {
|
|
41
|
-
const cloned = new Address();
|
|
146
|
+
const cloned = new Address([]);
|
|
147
|
+
|
|
42
148
|
// Copy the raw memory directly:
|
|
43
149
|
memory.copy(cloned.dataStart, bytes.dataStart, ADDRESS_BYTE_LENGTH);
|
|
44
150
|
|
|
45
151
|
return cloned;
|
|
46
152
|
}
|
|
47
153
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Checks if this address is the zero address.
|
|
156
|
+
*
|
|
157
|
+
* @returns `true` if all 32 bytes are zero, `false` otherwise
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* const addr = Address.zero();
|
|
162
|
+
* console.log(addr.isZero()); // true
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
57
165
|
public isZero(): bool {
|
|
58
166
|
for (let i = 0; i < this.length; i++) {
|
|
59
167
|
if (this[i] != 0) {
|
|
@@ -64,25 +172,18 @@ export class Address extends Uint8Array {
|
|
|
64
172
|
return true;
|
|
65
173
|
}
|
|
66
174
|
|
|
67
|
-
public isDead(): bool {
|
|
68
|
-
for (let i = 0; i < this.length; i++) {
|
|
69
|
-
if (this[i] != DEAD_ADDRESS[i]) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public p2tr(): string {
|
|
77
|
-
return BitcoinAddresses.p2trKeyPathAddress(this, Network.hrp(Blockchain.network));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
175
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
176
|
+
* Creates a deep copy of this Address.
|
|
177
|
+
*
|
|
178
|
+
* @returns A new Address instance with the same data and isDefined state
|
|
179
|
+
*
|
|
180
|
+
* @remarks
|
|
181
|
+
* Uses direct memory copy for efficiency. The cloned address maintains
|
|
182
|
+
* the same mutability state as the original.
|
|
83
183
|
*/
|
|
84
184
|
public clone(): Address {
|
|
85
|
-
const cloned = new Address();
|
|
185
|
+
const cloned = new Address([]);
|
|
186
|
+
|
|
86
187
|
// Copy the raw memory directly:
|
|
87
188
|
memory.copy(cloned.dataStart, this.dataStart, ADDRESS_BYTE_LENGTH);
|
|
88
189
|
|
|
@@ -92,10 +193,27 @@ export class Address extends Uint8Array {
|
|
|
92
193
|
return cloned;
|
|
93
194
|
}
|
|
94
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Converts the address to a hexadecimal string representation.
|
|
198
|
+
*
|
|
199
|
+
* @returns The address as a lowercase hex string without '0x' prefix
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* const addr = Address.fromString('0xdead' + '00'.repeat(30));
|
|
204
|
+
* console.log(addr.toHex()); // "dead" + "00".repeat(30)
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
95
207
|
public toHex(): string {
|
|
96
208
|
return encodeHexFromBuffer(this.buffer);
|
|
97
209
|
}
|
|
98
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Checks equality with another address (operator ==).
|
|
213
|
+
*
|
|
214
|
+
* @param a - The address to compare with
|
|
215
|
+
* @returns `true` if both addresses have identical bytes, `false` otherwise
|
|
216
|
+
*/
|
|
99
217
|
@operator('==')
|
|
100
218
|
public equals(a: Address): bool {
|
|
101
219
|
if (a.length != this.length) {
|
|
@@ -111,6 +229,14 @@ export class Address extends Uint8Array {
|
|
|
111
229
|
return true;
|
|
112
230
|
}
|
|
113
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Checks if this address is less than another (operator <).
|
|
234
|
+
*
|
|
235
|
+
* Comparison is done byte-by-byte treating addresses as big-endian 256-bit integers.
|
|
236
|
+
*
|
|
237
|
+
* @param a - The address to compare with
|
|
238
|
+
* @returns `true` if this address is numerically less than `a`
|
|
239
|
+
*/
|
|
114
240
|
@operator('<')
|
|
115
241
|
public lessThan(a: Address): bool {
|
|
116
242
|
// Compare the two addresses byte-by-byte, treating them as big-endian uint256
|
|
@@ -128,6 +254,14 @@ export class Address extends Uint8Array {
|
|
|
128
254
|
return false;
|
|
129
255
|
}
|
|
130
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Checks if this address is greater than another (operator >).
|
|
259
|
+
*
|
|
260
|
+
* Comparison is done byte-by-byte treating addresses as big-endian 256-bit integers.
|
|
261
|
+
*
|
|
262
|
+
* @param a - The address to compare with
|
|
263
|
+
* @returns `true` if this address is numerically greater than `a`
|
|
264
|
+
*/
|
|
131
265
|
@operator('>')
|
|
132
266
|
public greaterThan(a: Address): bool {
|
|
133
267
|
// Compare the two addresses byte-by-byte, treating them as big-endian uint256
|
|
@@ -145,31 +279,58 @@ export class Address extends Uint8Array {
|
|
|
145
279
|
return false;
|
|
146
280
|
}
|
|
147
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Checks if this address is less than or equal to another (operator <=).
|
|
284
|
+
*
|
|
285
|
+
* @param a - The address to compare with
|
|
286
|
+
* @returns `true` if this address is numerically less than or equal to `a`
|
|
287
|
+
*/
|
|
148
288
|
@operator('<=')
|
|
149
289
|
public lessThanOrEqual(a: Address): bool {
|
|
150
290
|
return this.lessThan(a) || this.equals(a);
|
|
151
291
|
}
|
|
152
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Checks if this address is greater than or equal to another (operator >=).
|
|
295
|
+
*
|
|
296
|
+
* @param a - The address to compare with
|
|
297
|
+
* @returns `true` if this address is numerically greater than or equal to `a`
|
|
298
|
+
*/
|
|
153
299
|
@operator('>=')
|
|
154
300
|
public greaterThanOrEqual(a: Address): bool {
|
|
155
301
|
return this.greaterThan(a) || this.equals(a);
|
|
156
302
|
}
|
|
157
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Checks inequality with another address (operator !=).
|
|
306
|
+
*
|
|
307
|
+
* @param a - The address to compare with
|
|
308
|
+
* @returns `true` if addresses have different bytes, `false` if identical
|
|
309
|
+
*/
|
|
158
310
|
@operator('!=')
|
|
159
311
|
public notEquals(a: Address): bool {
|
|
160
312
|
return !this.equals(a);
|
|
161
313
|
}
|
|
162
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Returns the hexadecimal string representation of the address.
|
|
317
|
+
*
|
|
318
|
+
* @returns The address as a hex string (delegates to toHex())
|
|
319
|
+
*/
|
|
163
320
|
public toString(): string {
|
|
164
|
-
return this.
|
|
321
|
+
return this.toHex();
|
|
165
322
|
}
|
|
166
323
|
|
|
167
324
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* @
|
|
325
|
+
* Sets the address data and marks it as immutable.
|
|
326
|
+
*
|
|
327
|
+
* @param publicKey - The 32-byte public key data
|
|
328
|
+
*
|
|
329
|
+
* @throws {Revert} If publicKey length is not exactly 32 bytes
|
|
330
|
+
*
|
|
331
|
+
* @private
|
|
171
332
|
*/
|
|
172
|
-
private newSet(publicKey:
|
|
333
|
+
private newSet<U extends ArrayLike<number>>(publicKey: U): void {
|
|
173
334
|
if (publicKey.length !== 32) {
|
|
174
335
|
throw new Revert(`Invalid public key length (${publicKey.length})`);
|
|
175
336
|
}
|
|
@@ -179,6 +340,16 @@ export class Address extends Uint8Array {
|
|
|
179
340
|
this.isDefined = true;
|
|
180
341
|
}
|
|
181
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Array index getter (operator []).
|
|
345
|
+
*
|
|
346
|
+
* @param index - The byte index to access (0-31)
|
|
347
|
+
* @returns The byte value at the specified index
|
|
348
|
+
*
|
|
349
|
+
* @throws {RangeError} If index is out of bounds
|
|
350
|
+
*
|
|
351
|
+
* @private
|
|
352
|
+
*/
|
|
182
353
|
@operator('[]')
|
|
183
354
|
private ___get(index: i32): u8 {
|
|
184
355
|
if (u32(index) >= u32(this.length)) {
|
|
@@ -188,6 +359,17 @@ export class Address extends Uint8Array {
|
|
|
188
359
|
return load<u8>(this.dataStart + <usize>index);
|
|
189
360
|
}
|
|
190
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Array index setter (operator []=).
|
|
364
|
+
*
|
|
365
|
+
* @param index - The byte index to set (0-31)
|
|
366
|
+
* @param value - The byte value to set
|
|
367
|
+
*
|
|
368
|
+
* @throws {Revert} If the address is already defined (immutable)
|
|
369
|
+
* @throws {RangeError} If index is out of bounds
|
|
370
|
+
*
|
|
371
|
+
* @private
|
|
372
|
+
*/
|
|
191
373
|
@operator('[]=')
|
|
192
374
|
private ___set(index: i32, value: u8): void {
|
|
193
375
|
if (this.isDefined) {
|
|
@@ -202,10 +384,12 @@ export class Address extends Uint8Array {
|
|
|
202
384
|
}
|
|
203
385
|
}
|
|
204
386
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
]);
|
|
387
|
+
/**
|
|
388
|
+
* Pre-initialized zero address constant for efficiency.
|
|
389
|
+
*/
|
|
390
|
+
export const ZERO_ADDRESS: Address = new Address([]);
|
|
210
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Type alias for nullable Address references.
|
|
394
|
+
*/
|
|
211
395
|
export declare type PotentialAddress = Potential<Address>;
|