@btc-vision/btc-runtime 1.4.7 → 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.
- package/package.json +44 -53
- package/runtime/abort/abort.ts +25 -0
- package/runtime/buffer/BytesReader.ts +171 -140
- package/runtime/buffer/BytesWriter.ts +120 -152
- package/runtime/contracts/DeployableOP_20.ts +29 -15
- package/runtime/contracts/OP_NET.ts +1 -1
- package/runtime/env/BlockchainEnvironment.ts +79 -137
- package/runtime/env/classes/Block.ts +4 -8
- package/runtime/env/classes/Transaction.ts +14 -7
- package/runtime/env/classes/UTXO.ts +4 -2
- package/runtime/env/global.ts +49 -20
- package/runtime/events/predefined/MintEvent.ts +1 -1
- package/runtime/exports/index.ts +29 -8
- package/runtime/generic/AddressMap.ts +7 -5
- package/runtime/generic/Map.ts +32 -2
- package/runtime/generic/MapU256.ts +7 -5
- package/runtime/generic/MapUint8Array.ts +93 -0
- package/runtime/index.ts +4 -12
- package/runtime/math/abi.ts +71 -11
- package/runtime/math/bytes.ts +177 -41
- package/runtime/memory/AddressMemoryMap.ts +22 -19
- package/runtime/memory/FastUint8Array.ts +122 -0
- package/runtime/memory/KeyMerger.ts +25 -23
- package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
- package/runtime/memory/MultiStringMemoryMap.ts +8 -5
- package/runtime/memory/StringMemoryMap.ts +15 -15
- package/runtime/memory/Uint8ArrayMerger.ts +22 -15
- package/runtime/storage/Serializable.ts +19 -20
- package/runtime/storage/StoredAddress.ts +16 -15
- package/runtime/storage/StoredBoolean.ts +26 -21
- package/runtime/storage/StoredString.ts +158 -102
- package/runtime/storage/StoredU256.ts +25 -28
- package/runtime/storage/StoredU64.ts +23 -35
- package/runtime/storage/arrays/StoredAddressArray.ts +83 -175
- package/runtime/storage/arrays/StoredBooleanArray.ts +146 -271
- package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
- package/runtime/storage/arrays/StoredU128Array.ts +38 -374
- package/runtime/storage/arrays/StoredU16Array.ts +34 -420
- package/runtime/storage/arrays/StoredU256Array.ts +21 -347
- package/runtime/storage/arrays/StoredU32Array.ts +37 -440
- package/runtime/storage/arrays/StoredU64Array.ts +66 -0
- package/runtime/storage/arrays/StoredU8Array.ts +29 -453
- package/runtime/types/Address.ts +72 -5
- package/runtime/types/index.ts +1 -4
- package/runtime/utils/encodings.ts +5 -6
- package/runtime/utils/hex.ts +1 -1
- package/runtime/interfaces/DeployContractResponse.ts +0 -12
- package/runtime/math/cyrb53.ts +0 -48
- package/runtime/math/sha256.ts +0 -12
- package/runtime/memory/MemorySlot.ts +0 -1
- package/runtime/memory/MemorySlotPointer.ts +0 -3
- package/runtime/storage/utils/StorageBacked.ts +0 -5
- package/runtime/storage/utils/StorageLayout.ts +0 -7
- package/runtime/storage/utils/StorageSlot.ts +0 -106
- package/runtime/storage/utils/StorageStruct.ts +0 -23
- package/runtime/storage/utils/StorageValue.ts +0 -36
- package/runtime/tests/assert.ts +0 -11
- package/runtime/tests/env.ts +0 -7
- package/runtime/tests/tests.ts +0 -28
package/package.json
CHANGED
|
@@ -1,55 +1,46 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
"@btc-vision/as-bignum": "^0.0.4",
|
|
47
|
-
"@eslint/js": "^9.10.0",
|
|
48
|
-
"gulplog": "^2.2.0",
|
|
49
|
-
"mocha": "^10.7.3",
|
|
50
|
-
"ts-node": "^10.9.2",
|
|
51
|
-
"typescript": "^5.6.2",
|
|
52
|
-
"typescript-eslint": "^8.6.0",
|
|
53
|
-
"yargs": "^17.7.2"
|
|
54
|
-
}
|
|
2
|
+
"name": "@btc-vision/btc-runtime",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Bitcoin Smart Contract Runtime",
|
|
5
|
+
"main": "btc/index.ts",
|
|
6
|
+
"scripts": {},
|
|
7
|
+
"types": "btc/index.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"bitcoin",
|
|
10
|
+
"smart",
|
|
11
|
+
"contract",
|
|
12
|
+
"runtime",
|
|
13
|
+
"opnet",
|
|
14
|
+
"OP_NET"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://opnet.org",
|
|
17
|
+
"author": "BlobMaster41",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^22.13.10",
|
|
21
|
+
"assemblyscript": "^0.27.35"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/btc-vision/btc-runtime"
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"files": [
|
|
29
|
+
"package.json",
|
|
30
|
+
"runtime",
|
|
31
|
+
"runtime/*.ts",
|
|
32
|
+
"runtime/**/*.ts",
|
|
33
|
+
"!**/*.js.map",
|
|
34
|
+
"!**/*.tsbuildinfo",
|
|
35
|
+
"test/*.ts"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@assemblyscript/loader": "^0.27.35",
|
|
39
|
+
"@btc-vision/as-bignum": "^0.0.5",
|
|
40
|
+
"@eslint/js": "^9.22.0",
|
|
41
|
+
"gulplog": "^2.2.0",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"typescript": "^5.8.2",
|
|
44
|
+
"typescript-eslint": "^8.26.1"
|
|
45
|
+
}
|
|
55
46
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DataView } from 'dataview';
|
|
2
|
+
import { ArrayBuffer } from 'arraybuffer';
|
|
3
|
+
import { env_exit } from '../env/global';
|
|
4
|
+
|
|
5
|
+
export function revertOnError(message: string, fileName: string, line: u32, column: u32): void {
|
|
6
|
+
const selector = 0x63739d5c; // Error(string)
|
|
7
|
+
|
|
8
|
+
const revertMessage = `${message} at ${fileName}:${line}:${column}`;
|
|
9
|
+
|
|
10
|
+
// THIS MIGHT OVERFLOW, IT'S OK.
|
|
11
|
+
const length = u16(revertMessage.length);
|
|
12
|
+
const _length_i32 = i32(length);
|
|
13
|
+
|
|
14
|
+
const arrayBuffer = new ArrayBuffer(4 + _length_i32 + 2);
|
|
15
|
+
const writer = new DataView(arrayBuffer);
|
|
16
|
+
|
|
17
|
+
writer.setUint32(0, selector, false);
|
|
18
|
+
writer.setUint16(4, length, false);
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < _length_i32; i++) {
|
|
21
|
+
writer.setUint8(6 + i, <u8>revertMessage.charCodeAt(i));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
env_exit(1, arrayBuffer, arrayBuffer.byteLength);
|
|
25
|
+
}
|
|
@@ -19,238 +19,270 @@ import {
|
|
|
19
19
|
@final
|
|
20
20
|
export class BytesReader {
|
|
21
21
|
private readonly buffer: DataView;
|
|
22
|
-
|
|
23
22
|
private currentOffset: i32 = 0;
|
|
24
23
|
|
|
25
24
|
constructor(bytes: Uint8Array) {
|
|
26
25
|
this.buffer = new DataView(bytes.buffer);
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
public get byteLength(): i32 {
|
|
29
|
+
return this.buffer.byteLength;
|
|
30
|
+
}
|
|
31
|
+
|
|
29
32
|
public readU8(): u8 {
|
|
30
33
|
this.verifyEnd(this.currentOffset + U8_BYTE_LENGTH);
|
|
31
|
-
|
|
32
34
|
const value = this.buffer.getUint8(this.currentOffset);
|
|
33
35
|
this.currentOffset += U8_BYTE_LENGTH;
|
|
34
|
-
|
|
35
36
|
return value;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
/**
|
|
40
|
+
* By default, big-endian (be = true).
|
|
41
|
+
*/
|
|
42
|
+
public readU16(be: boolean = true): u16 {
|
|
39
43
|
this.verifyEnd(this.currentOffset + U16_BYTE_LENGTH);
|
|
40
|
-
|
|
41
|
-
const value = this.buffer.getUint16(this.currentOffset, true);
|
|
44
|
+
const value = this.buffer.getUint16(this.currentOffset, !be);
|
|
42
45
|
this.currentOffset += U16_BYTE_LENGTH;
|
|
43
|
-
|
|
44
46
|
return value;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
/**
|
|
50
|
+
* By default, big-endian (be = true).
|
|
51
|
+
*/
|
|
52
|
+
public readU32(be: boolean = true): u32 {
|
|
48
53
|
this.verifyEnd(this.currentOffset + U32_BYTE_LENGTH);
|
|
49
|
-
|
|
50
|
-
const value = this.buffer.getUint32(this.currentOffset, le);
|
|
54
|
+
const value = this.buffer.getUint32(this.currentOffset, !be);
|
|
51
55
|
this.currentOffset += U32_BYTE_LENGTH;
|
|
52
56
|
return value;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
/**
|
|
60
|
+
* By default, big-endian (be = true).
|
|
61
|
+
*/
|
|
62
|
+
public readU64(be: boolean = true): u64 {
|
|
56
63
|
this.verifyEnd(this.currentOffset + U64_BYTE_LENGTH);
|
|
57
|
-
|
|
58
|
-
const value = this.buffer.getUint64(this.currentOffset, true);
|
|
64
|
+
const value = this.buffer.getUint64(this.currentOffset, !be);
|
|
59
65
|
this.currentOffset += U64_BYTE_LENGTH;
|
|
60
|
-
|
|
61
66
|
return value;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Reads 256 bits. The writer calls `writeU256(value, be)`.
|
|
71
|
+
* If be=true, we do big-endian; if be=false, little-endian.
|
|
72
|
+
*/
|
|
73
|
+
public readU256(be: boolean = true): u256 {
|
|
65
74
|
this.verifyEnd(this.currentOffset + U256_BYTE_LENGTH);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return u256.fromBytesBE(next32Bytes);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
@inline
|
|
73
|
-
public readBytesBE(count: i32): u8[] {
|
|
74
|
-
const next32Bytes: u8[] = [];
|
|
75
|
-
for (let i = 0; i < count; i++) {
|
|
76
|
-
next32Bytes[i] = this.readU8();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return next32Bytes;
|
|
75
|
+
const raw: u8[] = this.readBytesArray(U256_BYTE_LENGTH);
|
|
76
|
+
return be ? u256.fromBytesBE(raw) : u256.fromBytesLE(raw);
|
|
80
77
|
}
|
|
81
78
|
|
|
82
|
-
public readI64(): i64 {
|
|
79
|
+
public readI64(be: boolean = true): i64 {
|
|
83
80
|
this.verifyEnd(this.currentOffset + I64_BYTE_LENGTH);
|
|
84
|
-
|
|
85
|
-
const value = this.buffer.getInt64(this.currentOffset, true);
|
|
81
|
+
const value = this.buffer.getInt64(this.currentOffset, !be);
|
|
86
82
|
this.currentOffset += I64_BYTE_LENGTH;
|
|
87
|
-
|
|
88
83
|
return value;
|
|
89
84
|
}
|
|
90
85
|
|
|
91
|
-
public readU128(): u128 {
|
|
86
|
+
public readU128(be: boolean = true): u128 {
|
|
92
87
|
this.verifyEnd(this.currentOffset + U128_BYTE_LENGTH);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return u128.fromBytesBE(next16Bytes);
|
|
88
|
+
const raw: u8[] = this.readBytesArray(U128_BYTE_LENGTH);
|
|
89
|
+
return be ? u128.fromBytesBE(raw) : u128.fromBytesLE(raw);
|
|
97
90
|
}
|
|
98
91
|
|
|
99
|
-
public readI128(): i128 {
|
|
92
|
+
public readI128(be: boolean = true): i128 {
|
|
100
93
|
this.verifyEnd(this.currentOffset + I128_BYTE_LENGTH);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return i128.fromBytesBE(next16Bytes);
|
|
94
|
+
const raw: u8[] = this.readBytesArray(I128_BYTE_LENGTH);
|
|
95
|
+
return be ? i128.fromBytesBE(raw) : i128.fromBytesLE(raw);
|
|
105
96
|
}
|
|
106
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Reads `length` bytes, optionally stopping early if a 0x00 is seen.
|
|
100
|
+
*/
|
|
107
101
|
public readBytes(length: u32, zeroStop: boolean = false): Uint8Array {
|
|
108
|
-
let bytes
|
|
102
|
+
let bytes = new Uint8Array(length);
|
|
109
103
|
for (let i: u32 = 0; i < length; i++) {
|
|
110
|
-
const
|
|
111
|
-
if (zeroStop &&
|
|
112
|
-
bytes = bytes.
|
|
104
|
+
const b: u8 = this.readU8();
|
|
105
|
+
if (zeroStop && b === 0) {
|
|
106
|
+
bytes = bytes.subarray(0, i);
|
|
113
107
|
break;
|
|
114
108
|
}
|
|
115
|
-
|
|
116
|
-
bytes[i] = byte;
|
|
109
|
+
bytes[i] = b;
|
|
117
110
|
}
|
|
118
|
-
|
|
119
111
|
return bytes;
|
|
120
112
|
}
|
|
121
113
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
for (let i
|
|
129
|
-
|
|
130
|
-
const responseSize: u8 = this.readU8();
|
|
131
|
-
|
|
132
|
-
if (responseSize > 10) throw new Revert('Too many calls.');
|
|
133
|
-
|
|
134
|
-
const calls: Uint8Array[] = [];
|
|
135
|
-
for (let j: u8 = 0; j < responseSize; j++) {
|
|
136
|
-
const response: Uint8Array = this.readBytesWithLength();
|
|
137
|
-
calls.push(response);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
map.set(address, calls);
|
|
114
|
+
/**
|
|
115
|
+
* Convenience for reading a fixed number of bytes into a plain u8[] array.
|
|
116
|
+
*/
|
|
117
|
+
@inline
|
|
118
|
+
public readBytesArray(count: i32): u8[] {
|
|
119
|
+
const arr = new Array<u8>(count);
|
|
120
|
+
for (let i = 0; i < count; i++) {
|
|
121
|
+
arr[i] = this.readU8();
|
|
141
122
|
}
|
|
142
|
-
|
|
143
|
-
return map;
|
|
123
|
+
return arr;
|
|
144
124
|
}
|
|
145
125
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
126
|
+
/**
|
|
127
|
+
* [u32 length][raw bytes]. By default big-endian for the length,
|
|
128
|
+
* to match AS BytesWriter's `writeBytesWithLength`.
|
|
129
|
+
*/
|
|
130
|
+
public readBytesWithLength(be: boolean = true): Uint8Array {
|
|
131
|
+
const length = this.readU32(be);
|
|
149
132
|
return this.readBytes(length);
|
|
150
133
|
}
|
|
151
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Reads a string of `length` raw bytes, zeroStop = true for convenience.
|
|
137
|
+
* (Or the writer may not have used zeroStop.)
|
|
138
|
+
*/
|
|
152
139
|
public readString(length: u16): string {
|
|
153
140
|
const bytes = this.readBytes(length, true);
|
|
154
|
-
|
|
155
141
|
return String.UTF8.decode(bytes.buffer);
|
|
156
142
|
}
|
|
157
143
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
144
|
+
/**
|
|
145
|
+
* [u16 length][raw bytes].
|
|
146
|
+
* The AS writer calls `writeStringWithLength(value: string)` => writes length big-endian by default.
|
|
147
|
+
*/
|
|
148
|
+
public readStringWithLength(be: boolean = true): string {
|
|
149
|
+
const length = this.readU16(be);
|
|
150
|
+
return this.readString(length);
|
|
151
|
+
}
|
|
161
152
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const scriptSig = this.readBytesWithLength();
|
|
153
|
+
public readBoolean(): boolean {
|
|
154
|
+
return this.readU8() !== 0;
|
|
155
|
+
}
|
|
166
156
|
|
|
167
|
-
|
|
168
|
-
|
|
157
|
+
public readSelector(): Selector {
|
|
158
|
+
return this.readU32(true);
|
|
159
|
+
}
|
|
169
160
|
|
|
170
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Reads an Address (32 bytes).
|
|
163
|
+
*/
|
|
164
|
+
public readAddress(): Address {
|
|
165
|
+
const addr = new Address();
|
|
166
|
+
for (let i: i32 = 0; i < ADDRESS_BYTE_LENGTH; i++) {
|
|
167
|
+
addr[i] = this.readU8();
|
|
168
|
+
}
|
|
169
|
+
return addr;
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
|
|
174
|
-
const length = this.readU8();
|
|
175
|
-
const result = new Array<TransactionOutput>(length);
|
|
172
|
+
// ------------------- Arrays ------------------- //
|
|
176
173
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
174
|
+
/**
|
|
175
|
+
* The AS writer does `writeU32(length)` for U256 arrays, so we read a u32.
|
|
176
|
+
* If you changed it to a `u16`, then do readU16() here.
|
|
177
|
+
*/
|
|
178
|
+
public readU256Array(be: boolean = true): u256[] {
|
|
179
|
+
// The AS writer currently writes a u32 length for U256 arrays
|
|
180
|
+
const length = this.readU32();
|
|
181
|
+
const result = new Array<u256>(length);
|
|
182
|
+
for (let i: u32 = 0; i < length; i++) {
|
|
183
|
+
result[i] = this.readU256(be);
|
|
183
184
|
}
|
|
184
|
-
|
|
185
185
|
return result;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
/**
|
|
189
|
+
* The AS writer uses a [u16 length] for U64 arrays.
|
|
190
|
+
*/
|
|
191
|
+
public readU64Array(be: boolean = true): u64[] {
|
|
192
|
+
const length = this.readU16(be);
|
|
193
|
+
const result = new Array<u64>(length);
|
|
192
194
|
for (let i: u32 = 0; i < length; i++) {
|
|
193
|
-
result[i] = this.
|
|
195
|
+
result[i] = this.readU64(be);
|
|
194
196
|
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
195
199
|
|
|
200
|
+
public readU32Array(be: boolean = true): u32[] {
|
|
201
|
+
const length = this.readU16(be);
|
|
202
|
+
const result = new Array<u32>(length);
|
|
203
|
+
for (let i: u16 = 0; i < length; i++) {
|
|
204
|
+
result[i] = this.readU32(be);
|
|
205
|
+
}
|
|
196
206
|
return result;
|
|
197
207
|
}
|
|
198
208
|
|
|
199
|
-
public
|
|
200
|
-
const length = this.readU16();
|
|
201
|
-
const result
|
|
209
|
+
public readU16Array(be: boolean = true): u16[] {
|
|
210
|
+
const length = this.readU16(be);
|
|
211
|
+
const result = new Array<u16>(length);
|
|
212
|
+
for (let i: u16 = 0; i < length; i++) {
|
|
213
|
+
result[i] = this.readU16(be);
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
202
217
|
|
|
218
|
+
public readU128Array(be: boolean = true): u128[] {
|
|
219
|
+
const length = this.readU16(be);
|
|
220
|
+
const result = new Array<u128>(length);
|
|
203
221
|
for (let i: u16 = 0; i < length; i++) {
|
|
204
|
-
result[i] = this.readU128();
|
|
222
|
+
result[i] = this.readU128(be);
|
|
205
223
|
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
206
226
|
|
|
227
|
+
/**
|
|
228
|
+
* The AS writer uses a [u8 length] for transaction inputs/outputs in the example,
|
|
229
|
+
* but for an "AddressArray" we use [u16 length].
|
|
230
|
+
*/
|
|
231
|
+
public readAddressArray(be: boolean = true): Address[] {
|
|
232
|
+
const length = this.readU16(be);
|
|
233
|
+
const result = new Array<Address>(length);
|
|
234
|
+
for (let i: u16 = 0; i < length; i++) {
|
|
235
|
+
result[i] = this.readAddress();
|
|
236
|
+
}
|
|
207
237
|
return result;
|
|
208
238
|
}
|
|
209
239
|
|
|
210
|
-
|
|
211
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Map of [u16 length] entries, each entry = [Address, U256], consistent with the writer’s `writeAddressMapU256`.
|
|
242
|
+
*/
|
|
243
|
+
public readAddressMapU256(be: boolean = true): AddressMap<u256> {
|
|
244
|
+
const length = this.readU16(be);
|
|
212
245
|
const result = new AddressMap<u256>();
|
|
213
246
|
|
|
214
247
|
for (let i: u16 = 0; i < length; i++) {
|
|
215
248
|
const address = this.readAddress();
|
|
216
|
-
const value = this.readU256();
|
|
217
|
-
|
|
218
|
-
if (result.has(address)) throw new Revert('Duplicate address found in map');
|
|
249
|
+
const value = this.readU256(be);
|
|
219
250
|
|
|
251
|
+
if (result.has(address)) {
|
|
252
|
+
throw new Revert('Duplicate address found in map');
|
|
253
|
+
}
|
|
220
254
|
result.set(address, value);
|
|
221
255
|
}
|
|
222
256
|
|
|
223
257
|
return result;
|
|
224
258
|
}
|
|
225
259
|
|
|
226
|
-
public
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
public readStringWithLength(): string {
|
|
231
|
-
const length = this.readU16();
|
|
260
|
+
public readTransactionInputs(): TransactionInput[] {
|
|
261
|
+
const length = this.readU8();
|
|
262
|
+
const result = new Array<TransactionInput>(length);
|
|
232
263
|
|
|
233
|
-
|
|
234
|
-
|
|
264
|
+
for (let i: u16 = 0; i < length; i++) {
|
|
265
|
+
const txId = this.readBytes(32);
|
|
266
|
+
const outputIndex = this.readU8();
|
|
267
|
+
const scriptSig = this.readBytesWithLength();
|
|
268
|
+
result[i] = new TransactionInput(txId, outputIndex, scriptSig);
|
|
269
|
+
}
|
|
235
270
|
|
|
236
|
-
|
|
237
|
-
return this.readU8() !== 0;
|
|
271
|
+
return result;
|
|
238
272
|
}
|
|
239
273
|
|
|
240
|
-
public
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return value;
|
|
245
|
-
}
|
|
274
|
+
public readTransactionOutputs(): TransactionOutput[] {
|
|
275
|
+
const length = this.readU8();
|
|
276
|
+
const result = new Array<TransactionOutput>(length);
|
|
246
277
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
278
|
+
for (let i: u16 = 0; i < length; i++) {
|
|
279
|
+
const index = this.readU8();
|
|
280
|
+
const scriptPubKey = this.readStringWithLength();
|
|
281
|
+
const value = this.readU64();
|
|
282
|
+
result[i] = new TransactionOutput(index, scriptPubKey, value);
|
|
251
283
|
}
|
|
252
284
|
|
|
253
|
-
return
|
|
285
|
+
return result;
|
|
254
286
|
}
|
|
255
287
|
|
|
256
288
|
public getOffset(): i32 {
|
|
@@ -261,20 +293,19 @@ export class BytesReader {
|
|
|
261
293
|
this.currentOffset = offset;
|
|
262
294
|
}
|
|
263
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Checks if we have enough bytes left in the buffer.
|
|
298
|
+
*/
|
|
264
299
|
public verifyEnd(size: i32): void {
|
|
265
300
|
if (size > this.buffer.byteLength) {
|
|
266
|
-
throw new Error(
|
|
301
|
+
throw new Error(
|
|
302
|
+
`Attempt to read beyond buffer length. Requested up to offset ${size}, ` +
|
|
303
|
+
`but buffer is only ${this.buffer.byteLength} bytes.`,
|
|
304
|
+
);
|
|
267
305
|
}
|
|
268
306
|
}
|
|
269
307
|
|
|
270
|
-
public
|
|
271
|
-
|
|
272
|
-
const result = new Array<Address>(length);
|
|
273
|
-
|
|
274
|
-
for (let i: u16 = 0; i < length; i++) {
|
|
275
|
-
result[i] = this.readAddress();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return result;
|
|
308
|
+
public toString(): string {
|
|
309
|
+
return Uint8Array.wrap(this.buffer.buffer).toString();
|
|
279
310
|
}
|
|
280
311
|
}
|