@btc-vision/btc-runtime 1.3.15 → 1.3.16
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
CHANGED
|
@@ -10,13 +10,11 @@ import { OP_NET } from '../contracts/OP_NET';
|
|
|
10
10
|
import { PointerStorage } from '../types';
|
|
11
11
|
import {
|
|
12
12
|
callContract,
|
|
13
|
-
deploy,
|
|
14
13
|
deployFromAddress,
|
|
15
14
|
emit,
|
|
16
15
|
encodeAddress,
|
|
17
16
|
loadPointer,
|
|
18
17
|
log,
|
|
19
|
-
nextPointerGreaterThan,
|
|
20
18
|
storePointer,
|
|
21
19
|
validateBitcoinAddress,
|
|
22
20
|
verifySchnorrSignature,
|
|
@@ -186,7 +184,7 @@ export class BlockchainEnvironment {
|
|
|
186
184
|
return reader.readAddress();
|
|
187
185
|
}
|
|
188
186
|
|
|
189
|
-
public deployContract(hash: u256, bytecode: Uint8Array): DeployContractResponse {
|
|
187
|
+
/*public deployContract(hash: u256, bytecode: Uint8Array): DeployContractResponse {
|
|
190
188
|
const writer = new BytesWriter(32 + bytecode.length);
|
|
191
189
|
writer.writeU256(hash);
|
|
192
190
|
writer.writeBytes(bytecode);
|
|
@@ -199,7 +197,7 @@ export class BlockchainEnvironment {
|
|
|
199
197
|
const contractAddress: Address = reader.readAddress();
|
|
200
198
|
|
|
201
199
|
return new DeployContractResponse(virtualAddress, contractAddress);
|
|
202
|
-
}
|
|
200
|
+
}*/
|
|
203
201
|
|
|
204
202
|
public deployContractFromExisting(
|
|
205
203
|
existingAddress: Address,
|
|
@@ -220,6 +218,7 @@ export class BlockchainEnvironment {
|
|
|
220
218
|
return new DeployContractResponse(virtualAddress, contractAddress);
|
|
221
219
|
}
|
|
222
220
|
|
|
221
|
+
// TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
|
|
223
222
|
public getStorageAt(
|
|
224
223
|
pointerHash: MemorySlotPointer,
|
|
225
224
|
defaultValue: MemorySlotData<u256>,
|
|
@@ -233,7 +232,7 @@ export class BlockchainEnvironment {
|
|
|
233
232
|
return defaultValue;
|
|
234
233
|
}
|
|
235
234
|
|
|
236
|
-
public getNextPointerGreaterThan(
|
|
235
|
+
/*public getNextPointerGreaterThan(
|
|
237
236
|
targetPointer: MemorySlotPointer,
|
|
238
237
|
valueAtLeast: u256,
|
|
239
238
|
lte: boolean = true,
|
|
@@ -247,7 +246,7 @@ export class BlockchainEnvironment {
|
|
|
247
246
|
const reader: BytesReader = new BytesReader(result);
|
|
248
247
|
|
|
249
248
|
return reader.readU256();
|
|
250
|
-
}
|
|
249
|
+
}*/
|
|
251
250
|
|
|
252
251
|
public verifySchnorrSignature(
|
|
253
252
|
publicKey: Address,
|
|
@@ -265,6 +264,7 @@ export class BlockchainEnvironment {
|
|
|
265
264
|
return reader.readBoolean();
|
|
266
265
|
}
|
|
267
266
|
|
|
267
|
+
// TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
|
|
268
268
|
public hasStorageAt(pointerHash: MemorySlotPointer): bool {
|
|
269
269
|
// We mark zero as the default value for the storage, if something is 0, the storage slot get deleted or is non-existent
|
|
270
270
|
const val: u256 = this.getStorageAt(pointerHash, u256.Zero);
|
package/runtime/index.ts
CHANGED
|
@@ -70,6 +70,7 @@ export * from './storage/StoredString';
|
|
|
70
70
|
export * from './storage/StoredAddress';
|
|
71
71
|
export * from './storage/StoredBoolean';
|
|
72
72
|
export * from './storage/Serializable';
|
|
73
|
+
export * from './storage/StoredAddressArray';
|
|
73
74
|
|
|
74
75
|
export * from './storage/StorageBacked';
|
|
75
76
|
export * from './storage/StorageSlot';
|
|
@@ -7,7 +7,8 @@ import { Revert } from '../types/Revert';
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @class StoredAddressArray
|
|
10
|
-
* @description Manages an array of
|
|
10
|
+
* @description Manages an array of Address values across multiple storage slots.
|
|
11
|
+
* Each slot holds one Address (stored as u256 in storage).
|
|
11
12
|
*/
|
|
12
13
|
@final
|
|
13
14
|
export class StoredAddressArray {
|
|
@@ -15,7 +16,7 @@ export class StoredAddressArray {
|
|
|
15
16
|
private readonly lengthPointer: u256;
|
|
16
17
|
|
|
17
18
|
// Internal cache for storage slots
|
|
18
|
-
private _values: Map<u64, Address> = new Map(); // Map from slotIndex to
|
|
19
|
+
private _values: Map<u64, Address> = new Map(); // Map from slotIndex to Address value
|
|
19
20
|
private _isLoaded: Set<u64> = new Set(); // Set of slotIndexes that are loaded
|
|
20
21
|
private _isChanged: Set<u64> = new Set(); // Set of slotIndexes that are modified
|
|
21
22
|
|
|
@@ -26,25 +27,24 @@ export class StoredAddressArray {
|
|
|
26
27
|
private _isChangedStartIndex: bool = false; // Indicates if the startIndex has been modified
|
|
27
28
|
|
|
28
29
|
// Define a maximum allowed length to prevent excessive storage usage
|
|
29
|
-
private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
|
|
30
|
+
private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* @constructor
|
|
33
34
|
* @param {u16} pointer - The primary pointer identifier.
|
|
34
35
|
* @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
|
|
35
|
-
* @param {
|
|
36
|
+
* @param {Address} defaultValue - The default Address value if storage is uninitialized.
|
|
36
37
|
*/
|
|
37
38
|
constructor(
|
|
38
39
|
public pointer: u16,
|
|
39
40
|
public subPointer: Uint8Array,
|
|
40
41
|
private defaultValue: Address,
|
|
41
42
|
) {
|
|
42
|
-
// Initialize the base
|
|
43
|
+
// Initialize the base pointer
|
|
43
44
|
const writer = new BytesWriter(32);
|
|
44
45
|
writer.writeU16(pointer);
|
|
45
46
|
writer.writeBytes(subPointer);
|
|
46
47
|
|
|
47
|
-
// Initialize the base and length pointers
|
|
48
48
|
const baseU256Pointer = u256.fromBytes(writer.getBuffer(), true);
|
|
49
49
|
const lengthPointer = baseU256Pointer.clone();
|
|
50
50
|
|
|
@@ -60,7 +60,7 @@ export class StoredAddressArray {
|
|
|
60
60
|
/**
|
|
61
61
|
* @method get
|
|
62
62
|
* @description Retrieves the Address value at the specified global index.
|
|
63
|
-
* @param {u64} index - The global index
|
|
63
|
+
* @param {u64} index - The global index of the Address to retrieve.
|
|
64
64
|
* @returns {Address} - The Address value at the specified index.
|
|
65
65
|
*/
|
|
66
66
|
@inline
|
|
@@ -75,7 +75,7 @@ export class StoredAddressArray {
|
|
|
75
75
|
/**
|
|
76
76
|
* @method set
|
|
77
77
|
* @description Sets the Address value at the specified global index.
|
|
78
|
-
* @param {u64} index - The global index
|
|
78
|
+
* @param {u64} index - The global index of the Address to set.
|
|
79
79
|
* @param {Address} value - The Address value to assign.
|
|
80
80
|
*/
|
|
81
81
|
@inline
|
|
@@ -91,10 +91,38 @@ export class StoredAddressArray {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* @method indexOf
|
|
96
|
+
* @description Searches for the first occurrence of the specified Address value and returns its index.
|
|
97
|
+
* @param {Address} value - The Address to locate.
|
|
98
|
+
* @returns {i64} - The index of the first occurrence, or -1 if not found.
|
|
99
|
+
*/
|
|
100
|
+
@inline
|
|
101
|
+
public indexOf(value: Address): i64 {
|
|
102
|
+
for (let i: u64 = 0; i < this._length; i++) {
|
|
103
|
+
const currentValue = this.get(i);
|
|
104
|
+
if (currentValue == value) {
|
|
105
|
+
return i64(i);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return -1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @method contains
|
|
113
|
+
* @description Determines whether the array contains the specified Address value.
|
|
114
|
+
* @param {Address} value - The Address to locate.
|
|
115
|
+
* @returns {boolean} - True if found; otherwise, false.
|
|
116
|
+
*/
|
|
117
|
+
@inline
|
|
118
|
+
public contains(value: Address): boolean {
|
|
119
|
+
return this.indexOf(value) !== -1;
|
|
120
|
+
}
|
|
121
|
+
|
|
94
122
|
/**
|
|
95
123
|
* @method push
|
|
96
|
-
* @description Appends a new
|
|
97
|
-
* @param {
|
|
124
|
+
* @description Appends a new Address value to the end of the array.
|
|
125
|
+
* @param {Address} value - The Address to append.
|
|
98
126
|
*/
|
|
99
127
|
public push(value: Address): void {
|
|
100
128
|
if (this._length >= this.MAX_LENGTH) {
|
|
@@ -104,23 +132,22 @@ export class StoredAddressArray {
|
|
|
104
132
|
}
|
|
105
133
|
|
|
106
134
|
const newIndex: u64 = this._length;
|
|
107
|
-
const effectiveIndex: u64 = this._startIndex + newIndex;
|
|
108
135
|
const wrappedIndex: u64 =
|
|
109
|
-
|
|
136
|
+
newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
|
|
110
137
|
const slotIndex: u32 = <u32>wrappedIndex;
|
|
111
138
|
|
|
112
|
-
// Ensure the slot is loaded
|
|
113
139
|
this.ensureValues(slotIndex);
|
|
114
|
-
|
|
115
|
-
// Set the new value
|
|
116
140
|
this._values.set(slotIndex, value);
|
|
117
141
|
this._isChanged.add(slotIndex);
|
|
118
142
|
|
|
119
|
-
// Increment the length
|
|
120
143
|
this._length += 1;
|
|
121
144
|
this._isChangedLength = true;
|
|
122
145
|
}
|
|
123
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @method deleteLast
|
|
149
|
+
* @description Deletes the last element from the array.
|
|
150
|
+
*/
|
|
124
151
|
public deleteLast(): void {
|
|
125
152
|
if (this._length === 0) {
|
|
126
153
|
throw new Revert('Delete operation failed: Array is empty.');
|
|
@@ -136,11 +163,15 @@ export class StoredAddressArray {
|
|
|
136
163
|
this._isChanged.add(slotIndex);
|
|
137
164
|
}
|
|
138
165
|
|
|
139
|
-
// Decrement the length
|
|
140
166
|
this._length -= 1;
|
|
141
167
|
this._isChangedLength = true;
|
|
142
168
|
}
|
|
143
169
|
|
|
170
|
+
/**
|
|
171
|
+
* @method setStartingIndex
|
|
172
|
+
* @description Sets the starting index of the array.
|
|
173
|
+
* @param {u64} index - The new starting index.
|
|
174
|
+
*/
|
|
144
175
|
public setStartingIndex(index: u64): void {
|
|
145
176
|
this._startIndex = index;
|
|
146
177
|
this._isChangedStartIndex = true;
|
|
@@ -148,8 +179,8 @@ export class StoredAddressArray {
|
|
|
148
179
|
|
|
149
180
|
/**
|
|
150
181
|
* @method delete
|
|
151
|
-
* @description Deletes the Address value at the specified index by setting it to
|
|
152
|
-
* @param {u64} index - The global index of the
|
|
182
|
+
* @description Deletes the Address value at the specified index by setting it to defaultValue.
|
|
183
|
+
* @param {u64} index - The global index of the Address value to delete.
|
|
153
184
|
*/
|
|
154
185
|
public delete(index: u64): void {
|
|
155
186
|
if (index >= this._length) {
|
|
@@ -168,8 +199,7 @@ export class StoredAddressArray {
|
|
|
168
199
|
|
|
169
200
|
/**
|
|
170
201
|
* @method shift
|
|
171
|
-
* @description Removes the first element of the array
|
|
172
|
-
* If the startIndex reaches the maximum value of u64, it wraps around to 0.
|
|
202
|
+
* @description Removes the first element of the array.
|
|
173
203
|
*/
|
|
174
204
|
public shift(): void {
|
|
175
205
|
if (this._length === 0) {
|
|
@@ -186,7 +216,6 @@ export class StoredAddressArray {
|
|
|
186
216
|
this._isChanged.add(slotIndex);
|
|
187
217
|
}
|
|
188
218
|
|
|
189
|
-
// Decrement the length
|
|
190
219
|
this._length -= 1;
|
|
191
220
|
this._isChangedLength = true;
|
|
192
221
|
|
|
@@ -201,7 +230,7 @@ export class StoredAddressArray {
|
|
|
201
230
|
|
|
202
231
|
/**
|
|
203
232
|
* @method save
|
|
204
|
-
* @description Persists all
|
|
233
|
+
* @description Persists all changes to storage.
|
|
205
234
|
*/
|
|
206
235
|
public save(): void {
|
|
207
236
|
// Save all changed slots
|
|
@@ -227,10 +256,10 @@ export class StoredAddressArray {
|
|
|
227
256
|
|
|
228
257
|
/**
|
|
229
258
|
* @method deleteAll
|
|
230
|
-
* @description Deletes
|
|
259
|
+
* @description Deletes the entire array and resets length and startIndex.
|
|
231
260
|
*/
|
|
232
261
|
public deleteAll(): void {
|
|
233
|
-
//
|
|
262
|
+
// Clear all loaded slots
|
|
234
263
|
const keys = this._values.keys();
|
|
235
264
|
for (let i = 0; i < keys.length; i++) {
|
|
236
265
|
const slotIndex = keys[i];
|
|
@@ -238,7 +267,7 @@ export class StoredAddressArray {
|
|
|
238
267
|
Blockchain.setStorageAt(storagePointer, u256.fromBytes(this.defaultValue));
|
|
239
268
|
}
|
|
240
269
|
|
|
241
|
-
// Reset the length and startIndex
|
|
270
|
+
// Reset the length and startIndex
|
|
242
271
|
const zeroLengthAndStartIndex = u256.Zero;
|
|
243
272
|
Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
|
|
244
273
|
this._length = 0;
|
|
@@ -254,9 +283,9 @@ export class StoredAddressArray {
|
|
|
254
283
|
|
|
255
284
|
/**
|
|
256
285
|
* @method setMultiple
|
|
257
|
-
* @description Sets multiple
|
|
286
|
+
* @description Sets multiple Address values starting from a specific global index.
|
|
258
287
|
* @param {u32} startIndex - The starting global index.
|
|
259
|
-
* @param {
|
|
288
|
+
* @param {Address[]} values - An array of Address values to set.
|
|
260
289
|
*/
|
|
261
290
|
@inline
|
|
262
291
|
public setMultiple(startIndex: u32, values: Address[]): void {
|
|
@@ -267,10 +296,10 @@ export class StoredAddressArray {
|
|
|
267
296
|
|
|
268
297
|
/**
|
|
269
298
|
* @method getAll
|
|
270
|
-
* @description Retrieves a range of values
|
|
271
|
-
* @param {u32} startIndex - The
|
|
272
|
-
* @param {u32} count - The number of
|
|
273
|
-
* @returns {Address[]} -
|
|
299
|
+
* @description Retrieves a range of Address values.
|
|
300
|
+
* @param {u32} startIndex - The start index.
|
|
301
|
+
* @param {u32} count - The number of items to get.
|
|
302
|
+
* @returns {Address[]} - The requested Address values.
|
|
274
303
|
*/
|
|
275
304
|
@inline
|
|
276
305
|
public getAll(startIndex: u32, count: u32): Address[] {
|
|
@@ -284,8 +313,8 @@ export class StoredAddressArray {
|
|
|
284
313
|
|
|
285
314
|
/**
|
|
286
315
|
* @method toString
|
|
287
|
-
* @description Returns a string representation of
|
|
288
|
-
* @returns {string} - A string
|
|
316
|
+
* @description Returns a string representation of the array.
|
|
317
|
+
* @returns {string} - A string of the form "[addr0, addr1, ...]".
|
|
289
318
|
*/
|
|
290
319
|
@inline
|
|
291
320
|
public toString(): string {
|
|
@@ -304,7 +333,7 @@ export class StoredAddressArray {
|
|
|
304
333
|
/**
|
|
305
334
|
* @method toBytes
|
|
306
335
|
* @description Returns the packed Address values as a byte array.
|
|
307
|
-
* @returns {u8[]} - The packed
|
|
336
|
+
* @returns {u8[]} - The packed byte array.
|
|
308
337
|
*/
|
|
309
338
|
@inline
|
|
310
339
|
public toBytes(): u8[] {
|
|
@@ -313,7 +342,7 @@ export class StoredAddressArray {
|
|
|
313
342
|
this.ensureValues(i);
|
|
314
343
|
const value = this._values.get(i);
|
|
315
344
|
if (value) {
|
|
316
|
-
const valueBytes = value;
|
|
345
|
+
const valueBytes = value; // Address is assumed to be or contain a Uint8Array
|
|
317
346
|
for (let j: u32 = 0; j < valueBytes.length; j++) {
|
|
318
347
|
bytes.push(valueBytes[j]);
|
|
319
348
|
}
|
|
@@ -324,16 +353,14 @@ export class StoredAddressArray {
|
|
|
324
353
|
|
|
325
354
|
/**
|
|
326
355
|
* @method reset
|
|
327
|
-
* @description Resets
|
|
356
|
+
* @description Resets the array by clearing all elements and resetting length and startIndex to zero.
|
|
328
357
|
*/
|
|
329
358
|
@inline
|
|
330
359
|
public reset(): void {
|
|
331
|
-
// Reset the length and startIndex to zero
|
|
332
360
|
this._length = 0;
|
|
333
361
|
this._startIndex = 0;
|
|
334
362
|
this._isChangedLength = true;
|
|
335
363
|
this._isChangedStartIndex = true;
|
|
336
|
-
|
|
337
364
|
this.save();
|
|
338
365
|
}
|
|
339
366
|
|
|
@@ -358,8 +385,8 @@ export class StoredAddressArray {
|
|
|
358
385
|
|
|
359
386
|
/**
|
|
360
387
|
* @method setLength
|
|
361
|
-
* @description Sets the length of the array.
|
|
362
|
-
* @param {u64} newLength - The new length
|
|
388
|
+
* @description Sets the length of the array, truncating if necessary.
|
|
389
|
+
* @param {u64} newLength - The new length.
|
|
363
390
|
*/
|
|
364
391
|
public setLength(newLength: u64): void {
|
|
365
392
|
if (newLength > this.MAX_LENGTH) {
|
|
@@ -380,15 +407,15 @@ export class StoredAddressArray {
|
|
|
380
407
|
/**
|
|
381
408
|
* @private
|
|
382
409
|
* @method ensureValues
|
|
383
|
-
* @description Loads and caches the
|
|
410
|
+
* @description Loads and caches the Address from the specified storage slot if not already loaded.
|
|
384
411
|
* @param {u32} slotIndex - The index of the storage slot.
|
|
385
412
|
*/
|
|
386
413
|
private ensureValues(slotIndex: u32): void {
|
|
387
414
|
if (!this._isLoaded.has(slotIndex)) {
|
|
388
415
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
389
|
-
const storedU256 = Blockchain.getStorageAt(storagePointer, u256.Zero);
|
|
416
|
+
const storedU256: u256 = Blockchain.getStorageAt(storagePointer, u256.Zero);
|
|
390
417
|
const storedAddress: Address =
|
|
391
|
-
storedU256
|
|
418
|
+
storedU256 == u256.Zero ? this.defaultValue : new Address(storedU256.toBytes());
|
|
392
419
|
this._values.set(slotIndex, storedAddress);
|
|
393
420
|
this._isLoaded.add(slotIndex);
|
|
394
421
|
}
|
|
@@ -397,13 +424,13 @@ export class StoredAddressArray {
|
|
|
397
424
|
/**
|
|
398
425
|
* @private
|
|
399
426
|
* @method calculateStoragePointer
|
|
400
|
-
* @description Calculates the storage pointer for a given slot index
|
|
401
|
-
* @param {
|
|
427
|
+
* @description Calculates the storage pointer for a given slot index.
|
|
428
|
+
* @param {u64} slotIndex - The index of the storage slot.
|
|
402
429
|
* @returns {u256} - The calculated storage pointer.
|
|
403
430
|
*/
|
|
404
431
|
private calculateStoragePointer(slotIndex: u64): u256 {
|
|
405
432
|
// Each slot is identified by baseU256Pointer + slotIndex + 1
|
|
406
|
-
// Slot 0: baseU256Pointer + 1
|
|
433
|
+
// Slot 0: baseU256Pointer + 1
|
|
407
434
|
// Slot 1: baseU256Pointer + 2, etc.
|
|
408
435
|
return SafeMath.add(this.baseU256Pointer, u256.fromU64(slotIndex + 1));
|
|
409
436
|
}
|