@btc-vision/btc-runtime 1.4.6 → 1.5.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 (59) hide show
  1. package/package.json +44 -53
  2. package/runtime/abort/abort.ts +25 -0
  3. package/runtime/buffer/BytesReader.ts +171 -140
  4. package/runtime/buffer/BytesWriter.ts +120 -152
  5. package/runtime/contracts/DeployableOP_20.ts +29 -15
  6. package/runtime/contracts/OP_NET.ts +1 -1
  7. package/runtime/env/BlockchainEnvironment.ts +79 -137
  8. package/runtime/env/classes/Block.ts +4 -8
  9. package/runtime/env/classes/Transaction.ts +14 -7
  10. package/runtime/env/classes/UTXO.ts +4 -2
  11. package/runtime/env/global.ts +49 -20
  12. package/runtime/events/predefined/MintEvent.ts +1 -1
  13. package/runtime/exports/index.ts +29 -8
  14. package/runtime/generic/AddressMap.ts +7 -5
  15. package/runtime/generic/Map.ts +32 -2
  16. package/runtime/generic/MapU256.ts +7 -5
  17. package/runtime/generic/MapUint8Array.ts +93 -0
  18. package/runtime/index.ts +4 -12
  19. package/runtime/math/abi.ts +71 -11
  20. package/runtime/math/bytes.ts +177 -41
  21. package/runtime/memory/AddressMemoryMap.ts +22 -19
  22. package/runtime/memory/FastUint8Array.ts +122 -0
  23. package/runtime/memory/KeyMerger.ts +25 -23
  24. package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
  25. package/runtime/memory/MultiStringMemoryMap.ts +8 -5
  26. package/runtime/memory/StringMemoryMap.ts +15 -15
  27. package/runtime/memory/Uint8ArrayMerger.ts +22 -15
  28. package/runtime/storage/Serializable.ts +19 -20
  29. package/runtime/storage/StoredAddress.ts +16 -15
  30. package/runtime/storage/StoredBoolean.ts +26 -21
  31. package/runtime/storage/StoredString.ts +158 -102
  32. package/runtime/storage/StoredU256.ts +25 -28
  33. package/runtime/storage/StoredU64.ts +23 -35
  34. package/runtime/storage/arrays/StoredAddressArray.ts +88 -179
  35. package/runtime/storage/arrays/StoredBooleanArray.ts +150 -272
  36. package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
  37. package/runtime/storage/arrays/StoredU128Array.ts +38 -373
  38. package/runtime/storage/arrays/StoredU16Array.ts +34 -418
  39. package/runtime/storage/arrays/StoredU256Array.ts +21 -346
  40. package/runtime/storage/arrays/StoredU32Array.ts +37 -438
  41. package/runtime/storage/arrays/StoredU64Array.ts +66 -0
  42. package/runtime/storage/arrays/StoredU8Array.ts +29 -451
  43. package/runtime/types/Address.ts +72 -5
  44. package/runtime/types/index.ts +1 -4
  45. package/runtime/utils/encodings.ts +5 -6
  46. package/runtime/utils/hex.ts +1 -1
  47. package/runtime/interfaces/DeployContractResponse.ts +0 -12
  48. package/runtime/math/cyrb53.ts +0 -48
  49. package/runtime/math/sha256.ts +0 -12
  50. package/runtime/memory/MemorySlot.ts +0 -1
  51. package/runtime/memory/MemorySlotPointer.ts +0 -3
  52. package/runtime/storage/utils/StorageBacked.ts +0 -5
  53. package/runtime/storage/utils/StorageLayout.ts +0 -7
  54. package/runtime/storage/utils/StorageSlot.ts +0 -106
  55. package/runtime/storage/utils/StorageStruct.ts +0 -23
  56. package/runtime/storage/utils/StorageValue.ts +0 -36
  57. package/runtime/tests/assert.ts +0 -11
  58. package/runtime/tests/env.ts +0 -7
  59. package/runtime/tests/tests.ts +0 -28
@@ -1,6 +1,24 @@
1
1
  import { Revert } from '../types/Revert';
2
2
 
3
- export class Map<K, V> {
3
+ export interface IMap<K, V> {
4
+ readonly size: i32;
5
+
6
+ has(key: K): bool;
7
+
8
+ set(key: K, value: V): this;
9
+
10
+ get(key: K): V;
11
+
12
+ delete(key: K): bool;
13
+
14
+ clear(): void;
15
+
16
+ keys(): K[]; // preliminary
17
+ values(): V[]; // preliminary
18
+ toString(): string;
19
+ }
20
+
21
+ export class Map<K, V> implements IMap<K, V> {
4
22
  protected _keys: K[] = [];
5
23
  protected _values: V[] = [];
6
24
 
@@ -16,7 +34,7 @@ export class Map<K, V> {
16
34
  return this._values;
17
35
  }
18
36
 
19
- public set(key: K, value: V): void {
37
+ public set(key: K, value: V): this {
20
38
  const index: i32 = this.indexOf(key);
21
39
  if (index == -1) {
22
40
  this._keys.push(key);
@@ -24,6 +42,8 @@ export class Map<K, V> {
24
42
  } else {
25
43
  this._values[index] = value;
26
44
  }
45
+
46
+ return this;
27
47
  }
28
48
 
29
49
  public indexOf(key: K): i32 {
@@ -63,4 +83,14 @@ export class Map<K, V> {
63
83
  this._keys = [];
64
84
  this._values = [];
65
85
  }
86
+
87
+ public toString(): string {
88
+ const str: string = ``;
89
+
90
+ for (let i: i32 = 0; i < this._keys.length; i++) {
91
+ str.concat(`[${this._keys[i]}] => [${this._values[i]}]`);
92
+ }
93
+
94
+ return str;
95
+ }
66
96
  }
@@ -3,14 +3,16 @@ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { Map } from './Map';
4
4
 
5
5
  export class MapU256 extends Map<u256, u256> {
6
- public set(key: u256, value: u256): void {
7
- const index: i32 = this._keys.indexOf(key);
8
- if (index == -1) {
6
+ public set(key: u256, value: u256): this {
7
+ const index: i32 = this.indexOf(key);
8
+ if (index === -1) {
9
9
  this._keys.push(key);
10
10
  this._values.push(value);
11
11
  } else {
12
12
  this._values[index] = value;
13
13
  }
14
+
15
+ return this;
14
16
  }
15
17
 
16
18
  public indexOf(pointerHash: u256): i32 {
@@ -37,7 +39,7 @@ export class MapU256 extends Map<u256, u256> {
37
39
 
38
40
  public get(key: u256): u256 {
39
41
  const index: i32 = this.indexOf(key);
40
- if (index == -1) {
42
+ if (index === -1) {
41
43
  throw new Revert('Key not found in map (u256)');
42
44
  }
43
45
  return this._values[index];
@@ -45,7 +47,7 @@ export class MapU256 extends Map<u256, u256> {
45
47
 
46
48
  public delete(key: u256): bool {
47
49
  const index: i32 = this.indexOf(key);
48
- if (index == -1) {
50
+ if (index === -1) {
49
51
  return false;
50
52
  }
51
53
 
@@ -0,0 +1,93 @@
1
+ import { Revert } from '../types/Revert';
2
+ import { IMap } from './Map';
3
+
4
+ export function eqUint(data: Uint8Array, data2: Uint8Array): bool {
5
+ if (data.length !== data2.length) return false;
6
+
7
+ for (let i = 0; i < data.length; i++) {
8
+ if (data[i] !== data2[i]) return false;
9
+ }
10
+
11
+ return true;
12
+ }
13
+
14
+ @final
15
+ export class MapUint8Array implements IMap<Uint8Array, Uint8Array> {
16
+ protected _keys: Uint8Array[] = [];
17
+ protected _values: Uint8Array[] = [];
18
+
19
+ public get size(): i32 {
20
+ return this._keys.length;
21
+ }
22
+
23
+ public keys(): Uint8Array[] {
24
+ return this._keys;
25
+ }
26
+
27
+ public values(): Uint8Array[] {
28
+ return this._values;
29
+ }
30
+
31
+ public set(key: Uint8Array, value: Uint8Array): this {
32
+ const index: i32 = this.indexOf(key);
33
+ if (index === -1) {
34
+ this._keys.push(key);
35
+ this._values.push(value);
36
+ } else {
37
+ this._values[index] = value;
38
+ }
39
+
40
+ return this;
41
+ }
42
+
43
+ public indexOf(pointerHash: Uint8Array): i32 {
44
+ for (let i: i32 = 0; i < this._keys.length; i++) {
45
+ const key = this._keys[i];
46
+
47
+ if (eqUint(key, pointerHash)) {
48
+ return i;
49
+ }
50
+ }
51
+
52
+ return -1;
53
+ }
54
+
55
+ public has(key: Uint8Array): bool {
56
+ return this.indexOf(key) !== -1;
57
+ }
58
+
59
+ public get(key: Uint8Array): Uint8Array {
60
+ const index: i32 = this.indexOf(key);
61
+ if (index === -1) {
62
+ throw new Revert('Key not found in map (uint8array)');
63
+ }
64
+ return this._values[index];
65
+ }
66
+
67
+ public delete(key: Uint8Array): bool {
68
+ const index: i32 = this.indexOf(key);
69
+ if (index === -1) {
70
+ return false;
71
+ }
72
+
73
+ this._keys.splice(index, 1);
74
+ this._values.splice(index, 1);
75
+
76
+ return true;
77
+ }
78
+
79
+ public clear(): void {
80
+ this._keys = [];
81
+ this._values = [];
82
+ }
83
+
84
+ public toString(): string {
85
+ const str: string = ``;
86
+
87
+ for (let i: i32 = 0; i < this._keys.length; i++) {
88
+ str.concat(`[${this._keys[i].toString()}] => [${this._values[i].toString()}]`);
89
+ }
90
+
91
+ return str;
92
+ }
93
+ }
package/runtime/index.ts CHANGED
@@ -14,7 +14,6 @@ export * from './buffer/BytesWriter';
14
14
 
15
15
  /** Interfaces */
16
16
  export * from './interfaces/IBTC';
17
- export * from './interfaces/DeployContractResponse';
18
17
 
19
18
  /** Events */
20
19
  export * from './events/NetEvent';
@@ -43,16 +42,12 @@ export * from './types/SafeMathI128';
43
42
  /** Math */
44
43
  export * from './math/abi';
45
44
  export * from './math/bytes';
46
- export * from './math/cyrb53';
47
- export * from './math/sha256';
48
45
  export * from './secp256k1/ECPoint';
49
46
 
50
47
  /** Memory */
51
48
  export * from './memory/AddressMemoryMap';
52
49
  export * from './memory/StringMemoryMap';
53
50
  export * from './memory/MultiStringMemoryMap';
54
- export * from './memory/MemorySlot';
55
- export * from './memory/MemorySlotPointer';
56
51
  export * from './memory/KeyMerger';
57
52
  export * from './memory/MultiAddressMemoryMap';
58
53
  export * from './memory/Uint8ArrayMerger';
@@ -67,19 +62,16 @@ export * from './storage/Serializable';
67
62
 
68
63
  /** Arrays */
69
64
  export * from './storage/arrays/StoredAddressArray';
65
+ export * from './storage/arrays/StoredBooleanArray';
66
+
70
67
  export * from './storage/arrays/StoredU8Array';
71
68
  export * from './storage/arrays/StoredU16Array';
72
69
  export * from './storage/arrays/StoredU32Array';
73
- export * from './storage/arrays/StoredBooleanArray';
70
+ export * from './storage/arrays/StoredU64Array';
74
71
  export * from './storage/arrays/StoredU128Array';
75
72
  export * from './storage/arrays/StoredU256Array';
76
73
 
77
- /** Storage Utils */
78
- export * from './storage/utils/StorageBacked';
79
- export * from './storage/utils/StorageSlot';
80
- export * from './storage/utils/StorageStruct';
81
- export * from './storage/utils/StorageLayout';
82
- export * from './storage/utils/StorageValue';
74
+ export * from './memory/FastUint8Array';
83
75
 
84
76
  /** Shared libraries */
85
77
  export * from './shared-libraries/TransferHelper';
@@ -1,28 +1,88 @@
1
- // SO IN TYPESCRIPT, WE CAN NOT USE TWO METHOD WITH THE SAME NAME. SO NOT ADDING THE TYPE TO THE HASH IS A DESIGN CHOICE.
2
- import { bytes32, bytes4 } from './bytes';
3
- import { MemorySlotPointer } from '../memory/MemorySlotPointer';
4
- import { Sha256 } from './sha256';
1
+ import { bytesToU32 } from './bytes';
2
+ import { sha256 } from '../env/global';
3
+ import { u256 } from '@btc-vision/as-bignum/assembly';
5
4
 
6
5
  export type Selector = u32;
7
6
 
8
7
  export function encodeSelector(name: string): Selector {
9
8
  const typed = Uint8Array.wrap(String.UTF8.encode(name));
10
- const hash = Sha256.hash(typed);
9
+ const hash = sha256(typed);
11
10
 
12
- return bytes4(hash);
11
+ return bytesToU32(hash);
13
12
  }
14
13
 
15
- export function encodePointer(uniqueIdentifier: u16, typed: Uint8Array): MemorySlotPointer {
16
- const hash: Uint8Array = typed.length !== 32 ? Sha256.hash(typed) : typed;
14
+ /**
15
+ * Use more gas.
16
+ * @param uniqueIdentifier
17
+ * @param typed
18
+ */
19
+ export function encodePointerUnknownLength(uniqueIdentifier: u16, typed: Uint8Array): Uint8Array {
20
+ const hash = sha256(typed);
21
+
22
+ return encodePointer(uniqueIdentifier, hash, false);
23
+ }
24
+
25
+ export function ensureAtLeast30Bytes(typed: Uint8Array): Uint8Array {
26
+ if (typed.length >= 30) {
27
+ return typed;
28
+ }
29
+
30
+ const result = new Uint8Array(30);
31
+ for (let i = 0; i < typed.length; i++) {
32
+ result[i] = typed[i];
33
+ }
34
+
35
+ return result;
36
+ }
37
+
38
+ @inline
39
+ function toArrayBufferBE(buffer: usize, val: u256): void {
40
+ // Write the upper 3 chunks (each 64 bits) in one shot:
41
+ store<u64>(buffer, bswap(val.hi2), 0); // 0..7
42
+ store<u64>(buffer, bswap(val.hi1), 8); // 8..15
43
+ store<u64>(buffer, bswap(val.lo2), 16); // 16..23
44
+
45
+ // Now handle the final 64 bits (val.lo1) in [32 + 16 + 16] form.
46
+ // - lo1High32 = top 32 bits [bits 63..32]
47
+ // - lo1Mid16 = middle 16 bits [bits 31..16]
48
+ // - lo1Low16 = bottom 16 bits [bits 15..0]
49
+ const lo1High32 = u32(val.lo1 >>> 32);
50
+ const lo1Mid16 = u16((val.lo1 >>> 16) & 0xffff);
51
+
52
+ // Store them in ascending offsets. Because each store is little-endian,
53
+ // we bswap the values so that the final bytes in memory are big-endian.
54
+
55
+ // Offsets 24..27 (4 bytes): top 32 bits of lo1
56
+ store<u32>(buffer, bswap(lo1High32), 24);
57
+
58
+ // Offsets 28..29 (2 bytes): mid 16 bits of lo1
59
+ store<u16>(buffer, bswap(lo1Mid16), 28);
60
+ }
61
+
62
+ export function u256To30Bytes(value: u256): Uint8Array {
63
+ const result = new Uint8Array(30);
64
+ toArrayBufferBE(changetype<usize>(result.dataStart), value);
65
+ return result;
66
+ }
67
+
68
+ /**
69
+ * Optimized pointer encoding, see encodePointerUnknownLength for a more generic version.
70
+ * @param uniqueIdentifier
71
+ * @param typed
72
+ * @param safe
73
+ */
74
+ export function encodePointer(uniqueIdentifier: u16, typed: Uint8Array, safe: boolean = true): Uint8Array {
75
+ const array = ensureAtLeast30Bytes(typed);
76
+
77
+ if (safe) assert(array.length === 30, `Pointers must be 30 bytes. Got ${array.length}.`);
17
78
 
18
79
  const finalPointer = new Uint8Array(32);
19
80
  finalPointer[0] = uniqueIdentifier & 0xff;
20
81
  finalPointer[1] = (uniqueIdentifier >> 8) & 0xff;
21
82
 
22
83
  for (let i = 0; i < 30; i++) {
23
- // drop the last two bytes
24
- finalPointer[i + 2] = hash[i];
84
+ finalPointer[i + 2] = array[i];
25
85
  }
26
86
 
27
- return bytes32(finalPointer);
87
+ return finalPointer;
28
88
  }
@@ -1,57 +1,193 @@
1
- import { u128, u256 } from '@btc-vision/as-bignum/assembly';
2
-
3
- export function bytes(numbers: u256[]): Uint8Array {
4
- const len = numbers.length;
5
- const result = new Uint8Array(32 * len);
6
-
7
- // Loop through the array in reverse order, so that the last element (index = len-1)
8
- // becomes the first chunk in the output, and so on.
9
- for (let i = 0; i < len; i++) {
10
- // Reverse index to pick elements from the end
11
- const rev = len - 1 - i;
12
- const chunk: Uint8Array = numbers[rev].toUint8Array();
13
-
14
- // Copy this 32-byte chunk into the output at offset i * 32.
15
- const offset = i * 32;
16
- for (let b: u32 = 0; b < 32; b++) {
17
- result[offset + b] = chunk[b];
18
- }
1
+ import { Revert } from '../types/Revert';
2
+ import { BytesWriter } from '../buffer/BytesWriter';
3
+ import { BytesReader } from '../buffer/BytesReader';
4
+
5
+ /**
6
+ * Convert a 4-byte big-endian array into a u32.
7
+ * Index 0 is most significant, index 3 is least significant.
8
+ */
9
+ @inline
10
+ export function bytesToU32(number: Uint8Array): u32 {
11
+ if (number.length < 4) {
12
+ throw new Error('bytesToU32: input must be at least 4 bytes');
13
+ }
14
+ return (u32(number[0]) << 24) |
15
+ (u32(number[1]) << 16) |
16
+ (u32(number[2]) << 8) |
17
+ u32(number[3]);
18
+ }
19
+
20
+ // 32-byte buffer of all zeros
21
+ export const EMPTY_BUFFER: Uint8Array = new Uint8Array(32);
22
+
23
+ // 30-byte buffer of all zeros
24
+ export const EMPTY_POINTER: Uint8Array = new Uint8Array(30);
25
+
26
+ // 32-byte buffer representing 1 in big-endian form:
27
+ // index 31 is the least significant byte.
28
+ export const ONE_BUFFER: Uint8Array = new Uint8Array(32);
29
+ ONE_BUFFER[31] = 1;
30
+
31
+ /**
32
+ * Return a new 32-byte zero buffer.
33
+ */
34
+ @inline
35
+ export function GET_EMPTY_BUFFER(): Uint8Array {
36
+ return new Uint8Array(32);
37
+ }
38
+
39
+ /**
40
+ * A helper to add two 32-byte big-endian Uint8Arrays.
41
+ * Returns a new 32-byte Uint8Array with (a + b) mod 2^256.
42
+ *
43
+ * In big-endian, the LSB is at index 31, so we iterate from i = 31 down to 0.
44
+ */
45
+ @inline
46
+ export function addUint8ArraysBE(a: Uint8Array, b: Uint8Array): Uint8Array {
47
+ if (a.length !== 32 || b.length !== 32) {
48
+ throw new Error('addUint8ArraysBE expects 32-byte inputs');
49
+ }
50
+
51
+ const result = new Uint8Array(32);
52
+ let carry = 0;
53
+
54
+ // index 31 is least significant byte
55
+ for (let i = 31; i >= 0; i--) {
56
+ const sum = (a[i] as u32) + (b[i] as u32) + carry;
57
+ result[i] = sum & 0xff;
58
+ carry = sum >> 8;
19
59
  }
20
60
 
21
61
  return result;
22
62
  }
23
63
 
24
- export function bytes4(number: Uint8Array): u32 {
25
- return (u32(number[0]) << 24) | (u32(number[1]) << 16) | (u32(number[2]) << 8) | u32(number[3]);
64
+ /**
65
+ * Convert a u64 value to a 32-byte big-endian Uint8Array,
66
+ * placing the u64 in the *last* 8 bytes (indices 24..31).
67
+ * The most significant 24 bytes (indices 0..23) remain 0.
68
+ */
69
+ @inline
70
+ export function u64ToBE32Bytes(value: u64): Uint8Array {
71
+ const arr = new Uint8Array(32);
72
+
73
+ // Write big-endian into the final 8 bytes:
74
+ for (let i = 0; i < 8; i++) {
75
+ arr[31 - i] = <u8>(value & 0xff);
76
+ value >>= 8;
77
+ }
78
+
79
+ return arr;
26
80
  }
27
81
 
28
- export function bytes8(number: Uint8Array): u64 {
29
- return (
30
- (u64(number[0]) << u64(56)) |
31
- (u64(number[1]) << u64(48)) |
32
- (u64(number[2]) << u64(40)) |
33
- (u64(number[3]) << u64(32)) |
34
- (u64(number[4]) << 24) |
35
- (u64(number[5]) << 16) |
36
- (u64(number[6]) << 8) |
37
- u64(number[7])
38
- );
82
+ /**
83
+ * Get the bit at `bitIndex` (0..255) in a 32-byte buffer **in big-endian bit numbering**.
84
+ * - bitIndex = 0 => the MSB of buffer[0].
85
+ * - bitIndex = 7 => the LSB of buffer[0].
86
+ * - bitIndex = 255 => the LSB of buffer[31].
87
+ */
88
+ @inline
89
+ export function getBit(buffer: Uint8Array, bitIndex: u16): bool {
90
+ if (bitIndex >= 256) {
91
+ throw new Revert('Bit index out of range');
92
+ }
93
+
94
+ // Which byte?
95
+ const byteIndex: u8 = <u8>(bitIndex >>> 3);
96
+
97
+ // Which bit within that byte? (MSB = bit offset 7)
98
+ const offset: u8 = <u8>(7 - (bitIndex & 7));
99
+
100
+ const b: u8 = buffer[byteIndex];
101
+ return ((b >>> offset) & 1) == 1;
39
102
  }
40
103
 
41
- export function bytes16(buffer: Uint8Array): u128 {
42
- // Validate that the buffer is at least 16 bytes:
43
- if (buffer.length < 16) {
44
- throw new Error('bytes16: Buffer must be at least 16 bytes long');
104
+ /**
105
+ * Set or clear the bit at `bitIndex` (0..255) in a 32-byte buffer (**big-endian** bit numbering).
106
+ * - bitIndex = 0 => sets the MSB of buffer[0].
107
+ * - bitIndex = 255 => sets the LSB of buffer[31].
108
+ */
109
+ @inline
110
+ export function setBit(buffer: Uint8Array, bitIndex: u16, bitValue: bool): void {
111
+ if (bitIndex >= 256) {
112
+ throw new Revert('Bit index out of range');
113
+ }
114
+
115
+ // Which byte?
116
+ const byteIndex: u8 = <u8>(bitIndex >>> 3);
117
+
118
+ // Which bit within that byte? (MSB = bit offset 7)
119
+ const offset: u8 = <u8>(7 - (bitIndex & 7));
120
+
121
+ let b: u8 = buffer[byteIndex];
122
+ if (bitValue) {
123
+ b |= 1 << offset;
124
+ } else {
125
+ b &= ~(1 << offset);
45
126
  }
46
127
 
47
- // If it's larger than 16, slice it down:
48
- if (buffer.length > 16) {
49
- buffer = buffer.slice(0, 16);
128
+ buffer[byteIndex] = b;
129
+ }
130
+
131
+
132
+ /**
133
+ * Assume the data is at least 16 bytes, read two u64s from it in big-endian order.
134
+ */
135
+ @inline
136
+ export function readLengthAndStartIndex(data: Uint8Array): u64[] {
137
+ if (data.length < 16) {
138
+ return [0, 0];
50
139
  }
51
140
 
52
- return u128.fromBytes(buffer);
141
+ const reader = new BytesReader(data);
142
+ const length = reader.readU64();
143
+ const startIndex = reader.readU64();
144
+
145
+ return [length, startIndex];
53
146
  }
54
147
 
55
- export function bytes32(number: Uint8Array): u256 {
56
- return u256.fromBytes(number);
148
+ /**
149
+ * Write two u64s into a 32-byte buffer in big-endian order
150
+ */
151
+ @inline
152
+ export function writeLengthAndStartIndex(length: u64, startIndex: u64): Uint8Array {
153
+ const writer = new BytesWriter(32);
154
+ writer.writeU64(length);
155
+ writer.writeU64(startIndex);
156
+
157
+ return writer.getBuffer();
57
158
  }
159
+
160
+ /**
161
+ * Encode a 2-byte pointer + subPointer into a 32-byte buffer in big-endian order.
162
+ */
163
+ @inline
164
+ export function encodeBasePointer(pointer: u16, subPointer: Uint8Array): Uint8Array {
165
+ const writer = new BytesWriter(32);
166
+ writer.writeU16(pointer);
167
+ writer.writeBytes(subPointer);
168
+
169
+ return writer.getBuffer();
170
+ }
171
+
172
+ @inline
173
+ export function bigEndianAdd(base: Uint8Array, increment: u64): Uint8Array {
174
+ const out = new Uint8Array(32);
175
+
176
+ // Copy the base pointer
177
+ for (let i = 0; i < 32; i++) {
178
+ out[i] = base[i];
179
+ }
180
+
181
+ // If this is truly big-endian, out[0] is the MSB, out[31] is the LSB.
182
+ // So to add `increment`, we start from out[31] backward.
183
+ let carry: u64 = increment;
184
+ for (let i = 31; i >= 0; i--) {
185
+ const sum = <u64>out[i] + (carry & 0xFF);
186
+ out[i] = <u8>(sum & 0xFF);
187
+ carry = sum >> 8;
188
+ if (carry == 0 || i == 0) {
189
+ break;
190
+ }
191
+ }
192
+ return out;
193
+ }
@@ -1,44 +1,50 @@
1
- import { MemorySlotPointer } from './MemorySlotPointer';
2
1
  import { Blockchain } from '../env';
3
2
  import { encodePointer } from '../math/abi';
4
- import { MemorySlotData } from './MemorySlot';
5
- import { u256 } from '@btc-vision/as-bignum/assembly';
6
- import { BytesWriter } from '../buffer/BytesWriter';
7
3
  import { Address } from '../types/Address';
4
+ import { u256 } from '@btc-vision/as-bignum/assembly';
5
+ import { EMPTY_BUFFER } from '../math/bytes';
8
6
 
9
7
  @final
10
- export class AddressMemoryMap<V extends MemorySlotData<u256>> {
8
+ export class AddressMemoryMap {
11
9
  public pointer: u16;
12
10
 
13
11
  constructor(
14
12
  pointer: u16,
15
- private readonly defaultValue: V,
16
13
  ) {
17
14
  this.pointer = pointer;
18
15
  }
19
16
 
20
- public set(key: Address, value: V): this {
21
- const keyHash: MemorySlotPointer = this.encodePointer(key);
17
+ public setAsUint8Array(key: Address, value: Uint8Array): this {
18
+ const keyHash: Uint8Array = this.encodePointer(key);
22
19
  Blockchain.setStorageAt(keyHash, value);
23
20
 
24
21
  return this;
25
22
  }
26
23
 
27
- public get(key: Address): MemorySlotData<u256> {
28
- const keyHash: MemorySlotPointer = this.encodePointer(key);
24
+ public set(key: Address, value: u256): this {
25
+ return this.setAsUint8Array(key, value.toUint8Array(true));
26
+ }
29
27
 
30
- return Blockchain.getStorageAt(keyHash, this.defaultValue);
28
+ public getAsUint8Array(key: Address): Uint8Array {
29
+ const keyHash: Uint8Array = this.encodePointer(key);
30
+
31
+ return Blockchain.getStorageAt(keyHash);
32
+ }
33
+
34
+ public get(address: Address): u256 {
35
+ const resp = this.getAsUint8Array(address);
36
+
37
+ return u256.fromUint8ArrayBE(resp);
31
38
  }
32
39
 
33
40
  public has(key: Address): bool {
34
- const keyHash: MemorySlotPointer = this.encodePointer(key);
41
+ const keyHash: Uint8Array = this.encodePointer(key);
35
42
 
36
43
  return Blockchain.hasStorageAt(keyHash);
37
44
  }
38
45
 
39
- @unsafe
40
46
  public delete(key: Address): bool {
41
- this.set(key, this.defaultValue);
47
+ this.setAsUint8Array(key, EMPTY_BUFFER);
42
48
 
43
49
  return true;
44
50
  }
@@ -48,10 +54,7 @@ export class AddressMemoryMap<V extends MemorySlotData<u256>> {
48
54
  throw new Error('Method not implemented.');
49
55
  }
50
56
 
51
- private encodePointer(key: Address): MemorySlotPointer {
52
- const writer = new BytesWriter(key.length);
53
- writer.writeBytes(key);
54
-
55
- return encodePointer(this.pointer, writer.getBuffer());
57
+ private encodePointer(key: Address): Uint8Array {
58
+ return encodePointer(this.pointer, key.slice(0, 30), true);
56
59
  }
57
60
  }