@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.
- 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 +88 -179
- package/runtime/storage/arrays/StoredBooleanArray.ts +150 -272
- package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
- package/runtime/storage/arrays/StoredU128Array.ts +38 -373
- package/runtime/storage/arrays/StoredU16Array.ts +34 -418
- package/runtime/storage/arrays/StoredU256Array.ts +21 -346
- package/runtime/storage/arrays/StoredU32Array.ts +37 -438
- package/runtime/storage/arrays/StoredU64Array.ts +66 -0
- package/runtime/storage/arrays/StoredU8Array.ts +29 -451
- 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
|
@@ -3,27 +3,26 @@ import { BytesReader } from '../buffer/BytesReader';
|
|
|
3
3
|
import { BytesWriter } from '../buffer/BytesWriter';
|
|
4
4
|
import { OP_NET } from '../contracts/OP_NET';
|
|
5
5
|
import { NetEvent } from '../events/NetEvent';
|
|
6
|
-
import { MapU256 } from '../generic/MapU256';
|
|
7
|
-
import { DeployContractResponse } from '../interfaces/DeployContractResponse';
|
|
8
6
|
import { Potential } from '../lang/Definitions';
|
|
9
|
-
import { MemorySlotData } from '../memory/MemorySlot';
|
|
10
|
-
import { MemorySlotPointer } from '../memory/MemorySlotPointer';
|
|
11
|
-
import { PointerStorage } from '../types';
|
|
12
7
|
import { Address } from '../types/Address';
|
|
13
|
-
import { ADDRESS_BYTE_LENGTH
|
|
8
|
+
import { ADDRESS_BYTE_LENGTH } from '../utils';
|
|
14
9
|
import { Block } from './classes/Block';
|
|
15
10
|
import { Transaction } from './classes/Transaction';
|
|
16
11
|
import {
|
|
17
12
|
callContract,
|
|
18
13
|
deployFromAddress,
|
|
19
14
|
emit,
|
|
20
|
-
|
|
15
|
+
env_exit,
|
|
16
|
+
getCallResult,
|
|
21
17
|
loadPointer,
|
|
22
18
|
log,
|
|
19
|
+
sha256,
|
|
23
20
|
storePointer,
|
|
24
21
|
validateBitcoinAddress,
|
|
25
22
|
verifySchnorrSignature,
|
|
26
23
|
} from './global';
|
|
24
|
+
import { eqUint, MapUint8Array } from '../generic/MapUint8Array';
|
|
25
|
+
import { EMPTY_BUFFER } from '../math/bytes';
|
|
27
26
|
|
|
28
27
|
export * from '../env/global';
|
|
29
28
|
|
|
@@ -37,7 +36,7 @@ export class BlockchainEnvironment {
|
|
|
37
36
|
|
|
38
37
|
public readonly DEAD_ADDRESS: Address = Address.dead();
|
|
39
38
|
|
|
40
|
-
private storage:
|
|
39
|
+
private storage: MapUint8Array = new MapUint8Array();
|
|
41
40
|
private _selfContract: Potential<OP_NET> = null;
|
|
42
41
|
|
|
43
42
|
private _block: Potential<Block> = null;
|
|
@@ -65,13 +64,13 @@ export class BlockchainEnvironment {
|
|
|
65
64
|
private _contract: Potential<() => OP_NET> = null;
|
|
66
65
|
|
|
67
66
|
public get contract(): OP_NET {
|
|
68
|
-
this.createContractIfNotExists();
|
|
69
|
-
|
|
70
67
|
return this._selfContract as OP_NET;
|
|
71
68
|
}
|
|
72
69
|
|
|
73
70
|
public set contract(contract: () => OP_NET) {
|
|
74
71
|
this._contract = contract;
|
|
72
|
+
|
|
73
|
+
this.createContractIfNotExists();
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
private _nextPointer: u16 = 0;
|
|
@@ -106,24 +105,28 @@ export class BlockchainEnvironment {
|
|
|
106
105
|
return this._contractAddress as Address;
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
public
|
|
108
|
+
public setEnvironmentVariables(data: Uint8Array): void {
|
|
110
109
|
const reader: BytesReader = new BytesReader(data);
|
|
111
110
|
|
|
111
|
+
const blockHash = reader.readBytes(32);
|
|
112
|
+
const blockNumber = reader.readU64();
|
|
113
|
+
const blockMedianTime = reader.readU64();
|
|
114
|
+
const txHash = reader.readBytes(32);
|
|
115
|
+
const contractAddress = reader.readAddress();
|
|
116
|
+
const contractDeployer = reader.readAddress();
|
|
117
|
+
const caller = reader.readAddress();
|
|
118
|
+
const origin = reader.readAddress();
|
|
119
|
+
|
|
112
120
|
this._tx = new Transaction(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
caller,
|
|
122
|
+
origin,
|
|
123
|
+
txHash,
|
|
116
124
|
);
|
|
117
125
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this._contractDeployer = reader.readAddress();
|
|
121
|
-
this._contractAddress = reader.readAddress();
|
|
126
|
+
this._contractDeployer = contractDeployer;
|
|
127
|
+
this._contractAddress = contractAddress;
|
|
122
128
|
|
|
123
|
-
|
|
124
|
-
const safeRnd64 = reader.readU64();
|
|
125
|
-
|
|
126
|
-
this._block = new Block(currentBlock, medianTimestamp, safeRnd64);
|
|
129
|
+
this._block = new Block(blockHash, blockNumber, blockMedianTime);
|
|
127
130
|
|
|
128
131
|
this.createContractIfNotExists();
|
|
129
132
|
}
|
|
@@ -137,143 +140,105 @@ export class BlockchainEnvironment {
|
|
|
137
140
|
throw this.error('Destination contract is required');
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
const resultLengthBuffer = new ArrayBuffer(32);
|
|
144
|
+
const status = callContract(destinationContract.buffer, calldata.getBuffer().buffer, calldata.bufferLength(), resultLengthBuffer);
|
|
145
|
+
|
|
146
|
+
const reader = new BytesReader(Uint8Array.wrap(resultLengthBuffer));
|
|
147
|
+
const resultLength = reader.readU32(true);
|
|
148
|
+
const resultBuffer = new ArrayBuffer(resultLength);
|
|
149
|
+
getCallResult(0, resultLength, resultBuffer);
|
|
143
150
|
|
|
144
|
-
|
|
151
|
+
if (status !== 0) {
|
|
152
|
+
env_exit(status, resultBuffer, resultLength);
|
|
153
|
+
}
|
|
145
154
|
|
|
146
|
-
return new BytesReader(
|
|
155
|
+
return new BytesReader(Uint8Array.wrap(resultBuffer));
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
public log(data: string): void {
|
|
150
159
|
const writer = new BytesWriter(data.length + 2);
|
|
151
|
-
writer.
|
|
160
|
+
writer.writeString(data);
|
|
152
161
|
|
|
153
162
|
const buffer = writer.getBuffer();
|
|
154
|
-
log(buffer);
|
|
163
|
+
log(buffer.buffer, buffer.length);
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
public emit(event: NetEvent): void {
|
|
158
167
|
const data = event.getEventData();
|
|
159
|
-
const
|
|
168
|
+
const writer = new BytesWriter(event.eventType.length + 6 + data.byteLength);
|
|
160
169
|
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
writer.writeStringWithLength(event.eventType);
|
|
171
|
+
writer.writeBytesWithLength(data);
|
|
163
172
|
|
|
164
|
-
emit(
|
|
173
|
+
emit(writer.getBuffer().buffer, writer.bufferLength());
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
public validateBitcoinAddress(address: string): bool {
|
|
168
177
|
const writer = new BytesWriter(address.length);
|
|
169
178
|
writer.writeString(address);
|
|
170
179
|
|
|
171
|
-
const
|
|
172
|
-
return reader.readBoolean();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
public encodeVirtualAddress(virtualAddress: u8[]): Address {
|
|
176
|
-
const writer: BytesWriter = new BytesWriter(virtualAddress.length + 4);
|
|
177
|
-
writer.writeU32(virtualAddress.length);
|
|
178
|
-
writer.writeBytesU8Array(virtualAddress);
|
|
179
|
-
|
|
180
|
-
const buffer: Uint8Array = writer.getBuffer();
|
|
181
|
-
const cb: Potential<Uint8Array> = encodeAddress(buffer);
|
|
182
|
-
if (!cb) throw this.error('Failed to encode virtual address');
|
|
180
|
+
const result = validateBitcoinAddress(writer.getBuffer().buffer, address.length);
|
|
183
181
|
|
|
184
|
-
|
|
185
|
-
return reader.readAddress();
|
|
182
|
+
return result === 1;
|
|
186
183
|
}
|
|
187
184
|
|
|
188
|
-
/*public deployContract(hash: u256, bytecode: Uint8Array): DeployContractResponse {
|
|
189
|
-
const writer = new BytesWriter(U256_BYTE_LENGTH + bytecode.length);
|
|
190
|
-
writer.writeU256(hash);
|
|
191
|
-
writer.writeBytes(bytecode);
|
|
192
|
-
|
|
193
|
-
const cb: Potential<Uint8Array> = deploy(writer.getBuffer());
|
|
194
|
-
if (!cb) throw this.error('Failed to deploy contract');
|
|
195
|
-
|
|
196
|
-
const reader: BytesReader = new BytesReader(cb as Uint8Array);
|
|
197
|
-
const virtualAddress: u256 = reader.readU256();
|
|
198
|
-
const contractAddress: Address = reader.readAddress();
|
|
199
|
-
|
|
200
|
-
return new DeployContractResponse(virtualAddress, contractAddress);
|
|
201
|
-
}*/
|
|
202
|
-
|
|
203
185
|
public deployContractFromExisting(
|
|
204
186
|
existingAddress: Address,
|
|
205
187
|
salt: u256,
|
|
206
|
-
):
|
|
207
|
-
const
|
|
208
|
-
writer.writeAddress(existingAddress);
|
|
209
|
-
writer.writeU256(salt);
|
|
188
|
+
): Address {
|
|
189
|
+
const resultAddressBuffer = new ArrayBuffer(ADDRESS_BYTE_LENGTH);
|
|
210
190
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
191
|
+
const status = deployFromAddress(
|
|
192
|
+
existingAddress.buffer,
|
|
193
|
+
salt.toUint8Array(true).buffer,
|
|
194
|
+
resultAddressBuffer,
|
|
195
|
+
);
|
|
214
196
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
197
|
+
if (status !== 0) {
|
|
198
|
+
throw this.error('Failed to deploy contract');
|
|
199
|
+
}
|
|
218
200
|
|
|
219
|
-
|
|
201
|
+
const contractAddressReader = new BytesReader(Uint8Array.wrap(resultAddressBuffer));
|
|
202
|
+
return contractAddressReader.readAddress();
|
|
220
203
|
}
|
|
221
204
|
|
|
222
|
-
// TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
|
|
223
205
|
public getStorageAt(
|
|
224
|
-
pointerHash:
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.ensureStorageAtPointer(pointerHash, defaultValue);
|
|
228
|
-
|
|
206
|
+
pointerHash: Uint8Array,
|
|
207
|
+
): Uint8Array {
|
|
208
|
+
this.hasPointerStorageHash(pointerHash);
|
|
229
209
|
if (this.storage.has(pointerHash)) {
|
|
230
210
|
return this.storage.get(pointerHash);
|
|
231
211
|
}
|
|
232
212
|
|
|
233
|
-
return
|
|
213
|
+
return new Uint8Array(32);
|
|
234
214
|
}
|
|
235
215
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
lte: boolean = true,
|
|
240
|
-
): MemorySlotData<u256> {
|
|
241
|
-
const writer = new BytesWriter(U256_BYTE_LENGTH * 2 + BOOLEAN_BYTE_LENGTH);
|
|
242
|
-
writer.writeU256(targetPointer);
|
|
243
|
-
writer.writeU256(valueAtLeast);
|
|
244
|
-
writer.writeBoolean(lte);
|
|
245
|
-
|
|
246
|
-
const result: Uint8Array = nextPointerGreaterThan(writer.getBuffer());
|
|
247
|
-
const reader: BytesReader = new BytesReader(result);
|
|
216
|
+
public sha256(buffer: Uint8Array): Uint8Array {
|
|
217
|
+
return sha256(buffer);
|
|
218
|
+
}
|
|
248
219
|
|
|
249
|
-
|
|
250
|
-
|
|
220
|
+
public hash256(buffer: Uint8Array): Uint8Array {
|
|
221
|
+
return sha256(sha256(buffer));
|
|
222
|
+
}
|
|
251
223
|
|
|
252
224
|
public verifySchnorrSignature(
|
|
253
225
|
publicKey: Address,
|
|
254
226
|
signature: Uint8Array,
|
|
255
227
|
hash: Uint8Array,
|
|
256
228
|
): boolean {
|
|
257
|
-
const
|
|
258
|
-
writer.writeBytes(publicKey);
|
|
259
|
-
writer.writeBytes(signature);
|
|
260
|
-
writer.writeBytes(hash);
|
|
229
|
+
const result: u32 = verifySchnorrSignature(publicKey.buffer, signature.buffer, hash.buffer);
|
|
261
230
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const reader = new BytesReader(result);
|
|
265
|
-
return reader.readBoolean();
|
|
231
|
+
return result === 1;
|
|
266
232
|
}
|
|
267
233
|
|
|
268
|
-
|
|
269
|
-
public hasStorageAt(pointerHash: MemorySlotPointer): bool {
|
|
234
|
+
public hasStorageAt(pointerHash: Uint8Array): bool {
|
|
270
235
|
// We mark zero as the default value for the storage, if something is 0, the storage slot get deleted or is non-existent
|
|
271
|
-
const val:
|
|
236
|
+
const val: Uint8Array = this.getStorageAt(pointerHash);
|
|
272
237
|
|
|
273
|
-
return
|
|
238
|
+
return !eqUint(val, EMPTY_BUFFER);
|
|
274
239
|
}
|
|
275
240
|
|
|
276
|
-
public setStorageAt(pointerHash:
|
|
241
|
+
public setStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
|
|
277
242
|
this._internalSetStorageAt(pointerHash, value);
|
|
278
243
|
}
|
|
279
244
|
|
|
@@ -291,47 +256,24 @@ export class BlockchainEnvironment {
|
|
|
291
256
|
return runtimeError(msg);
|
|
292
257
|
}
|
|
293
258
|
|
|
294
|
-
private _internalSetStorageAt(pointerHash:
|
|
259
|
+
private _internalSetStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
|
|
295
260
|
this.storage.set(pointerHash, value);
|
|
296
261
|
|
|
297
|
-
|
|
298
|
-
writer.writeU256(pointerHash);
|
|
299
|
-
writer.writeU256(value);
|
|
300
|
-
|
|
301
|
-
const buffer: Uint8Array = writer.getBuffer();
|
|
302
|
-
storePointer(buffer);
|
|
262
|
+
storePointer(pointerHash.buffer, value.buffer);
|
|
303
263
|
}
|
|
304
264
|
|
|
305
|
-
private hasPointerStorageHash(pointer:
|
|
265
|
+
private hasPointerStorageHash(pointer: Uint8Array): bool {
|
|
306
266
|
if (this.storage.has(pointer)) {
|
|
307
267
|
return true;
|
|
308
268
|
}
|
|
309
269
|
|
|
310
270
|
// we attempt to load the requested pointer.
|
|
311
|
-
const
|
|
312
|
-
|
|
271
|
+
const resultBuffer = new ArrayBuffer(32);
|
|
272
|
+
loadPointer(pointer.buffer, resultBuffer);
|
|
313
273
|
|
|
314
|
-
const
|
|
315
|
-
const reader: BytesReader = new BytesReader(result);
|
|
316
|
-
|
|
317
|
-
const value: u256 = reader.readU256();
|
|
274
|
+
const value: Uint8Array = Uint8Array.wrap(resultBuffer);
|
|
318
275
|
this.storage.set(pointer, value); // cache the value
|
|
319
276
|
|
|
320
|
-
return !
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
private ensureStorageAtPointer(
|
|
324
|
-
pointerHash: MemorySlotPointer,
|
|
325
|
-
defaultValue: MemorySlotData<u256>,
|
|
326
|
-
): void {
|
|
327
|
-
if (this.hasPointerStorageHash(pointerHash)) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (u256.eq(defaultValue, u256.Zero)) {
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
this._internalSetStorageAt(pointerHash, defaultValue);
|
|
277
|
+
return !eqUint(value, EMPTY_BUFFER);
|
|
336
278
|
}
|
|
337
279
|
}
|
|
@@ -2,17 +2,13 @@ import { u256 } from '@btc-vision/as-bignum/assembly';
|
|
|
2
2
|
|
|
3
3
|
@final
|
|
4
4
|
export class Block {
|
|
5
|
-
|
|
5
|
+
public readonly numberU256: u256;
|
|
6
6
|
|
|
7
7
|
public constructor(
|
|
8
|
-
public readonly
|
|
8
|
+
public readonly hash: Uint8Array,
|
|
9
|
+
public readonly number: u64,
|
|
9
10
|
public readonly medianTimestamp: u64,
|
|
10
|
-
public readonly safeRnd64: u64,
|
|
11
11
|
) {
|
|
12
|
-
this.
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public get numberU64(): u64 {
|
|
16
|
-
return this.u64BlockNumber;
|
|
12
|
+
this.numberU256 = u256.fromU64(number);
|
|
17
13
|
}
|
|
18
14
|
}
|
|
@@ -2,15 +2,16 @@ import { Address } from '../../types/Address';
|
|
|
2
2
|
import { TransactionInput, TransactionOutput } from './UTXO';
|
|
3
3
|
import { Potential } from '../../lang/Definitions';
|
|
4
4
|
import { BytesReader } from '../../buffer/BytesReader';
|
|
5
|
-
import { inputs, outputs } from '../global';
|
|
5
|
+
import { getInputsSize, getOutputsSize, inputs, outputs } from '../global';
|
|
6
6
|
|
|
7
7
|
@final
|
|
8
8
|
export class Transaction {
|
|
9
9
|
public constructor(
|
|
10
10
|
public readonly sender: Address, // "immediate caller"
|
|
11
11
|
public readonly origin: Address, // "leftmost thing in the call chain"
|
|
12
|
-
public readonly
|
|
13
|
-
) {
|
|
12
|
+
public readonly hash: Uint8Array,
|
|
13
|
+
) {
|
|
14
|
+
}
|
|
14
15
|
|
|
15
16
|
private _inputs: Potential<TransactionInput[]> = null;
|
|
16
17
|
|
|
@@ -39,14 +40,20 @@ export class Transaction {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
private loadInputs(): TransactionInput[] {
|
|
42
|
-
const
|
|
43
|
+
const inputsSize = getInputsSize();
|
|
44
|
+
let resultBuffer = new ArrayBuffer(inputsSize);
|
|
45
|
+
inputs(resultBuffer);
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
const reader = new BytesReader(Uint8Array.wrap(resultBuffer));
|
|
48
|
+
return reader.readTransactionInputs();
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
private loadOutputs(): TransactionOutput[] {
|
|
48
|
-
const
|
|
52
|
+
const outputsSize = getOutputsSize();
|
|
53
|
+
let resultBuffer = new ArrayBuffer(outputsSize);
|
|
54
|
+
outputs(resultBuffer);
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
const reader = new BytesReader(Uint8Array.wrap(resultBuffer));
|
|
57
|
+
return reader.readTransactionOutputs();
|
|
51
58
|
}
|
|
52
59
|
}
|
|
@@ -4,7 +4,8 @@ export class TransactionInput {
|
|
|
4
4
|
public readonly txId: Uint8Array,
|
|
5
5
|
public readonly outputIndex: u8,
|
|
6
6
|
public readonly scriptSig: Uint8Array,
|
|
7
|
-
) {
|
|
7
|
+
) {
|
|
8
|
+
}
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
@final
|
|
@@ -13,5 +14,6 @@ export class TransactionOutput {
|
|
|
13
14
|
public readonly index: u8,
|
|
14
15
|
public readonly to: string,
|
|
15
16
|
public readonly value: u64,
|
|
16
|
-
) {
|
|
17
|
+
) {
|
|
18
|
+
}
|
|
17
19
|
}
|
package/runtime/env/global.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
@external('env', 'environment')
|
|
3
|
+
export declare function getEnvironmentVariables(offset: u32, length: u32, result: ArrayBuffer): void;
|
|
4
|
+
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
@external('env', 'calldata')
|
|
7
|
+
export declare function getCalldata(offset: u32, length: u32, result: ArrayBuffer): void;
|
|
8
|
+
|
|
1
9
|
// @ts-ignore
|
|
2
10
|
@external('env', 'load')
|
|
3
|
-
export declare function loadPointer(
|
|
11
|
+
export declare function loadPointer(key: ArrayBuffer, result: ArrayBuffer): void;
|
|
4
12
|
|
|
5
13
|
// @ts-ignore
|
|
6
14
|
@external('env', 'nextPointerGreaterThan')
|
|
@@ -8,52 +16,73 @@ export declare function nextPointerGreaterThan(data: Uint8Array): Uint8Array;
|
|
|
8
16
|
|
|
9
17
|
// @ts-ignore
|
|
10
18
|
@external('env', 'store')
|
|
11
|
-
export declare function storePointer(
|
|
12
|
-
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
@external('env', 'deploy')
|
|
15
|
-
export declare function deploy(data: Uint8Array): Uint8Array;
|
|
19
|
+
export declare function storePointer(key: ArrayBuffer, value: ArrayBuffer): void;
|
|
16
20
|
|
|
17
21
|
// @ts-ignore
|
|
18
22
|
@external('env', 'deployFromAddress')
|
|
19
|
-
export declare function deployFromAddress(
|
|
23
|
+
export declare function deployFromAddress(originAddress: ArrayBuffer, salt: ArrayBuffer, resultAddress: ArrayBuffer): u32;
|
|
20
24
|
|
|
21
25
|
// @ts-ignore
|
|
22
26
|
@external('env', 'call')
|
|
23
|
-
export declare function callContract(
|
|
27
|
+
export declare function callContract(address: ArrayBuffer, calldata: ArrayBuffer, calldataLength: u32, resultLength: ArrayBuffer): u32;
|
|
24
28
|
|
|
25
29
|
// @ts-ignore
|
|
26
|
-
@external('env', '
|
|
27
|
-
export declare function
|
|
30
|
+
@external('env', 'callResult')
|
|
31
|
+
export declare function getCallResult(offset: u32, length: u32, result: ArrayBuffer): void;
|
|
28
32
|
|
|
29
33
|
// @ts-ignore
|
|
30
|
-
@external('
|
|
31
|
-
export declare function
|
|
34
|
+
@external('debug', 'log')
|
|
35
|
+
export declare function log(data: ArrayBuffer, dataLength: u32): void;
|
|
32
36
|
|
|
33
37
|
// @ts-ignore
|
|
34
|
-
@external('env', '
|
|
35
|
-
export declare function
|
|
38
|
+
@external('env', 'emit')
|
|
39
|
+
export declare function emit(data: ArrayBuffer, dataLength: u32): void;
|
|
36
40
|
|
|
37
41
|
// @ts-ignore
|
|
38
42
|
@external('env', 'sha256')
|
|
39
|
-
export declare function
|
|
43
|
+
export declare function _sha256(data: ArrayBuffer, dataLength: u32, result: ArrayBuffer): void;
|
|
44
|
+
|
|
45
|
+
export function sha256(data: Uint8Array): Uint8Array {
|
|
46
|
+
const resultBuffer = new ArrayBuffer(32);
|
|
47
|
+
_sha256(data.buffer, data.length, resultBuffer);
|
|
48
|
+
return Uint8Array.wrap(resultBuffer);
|
|
49
|
+
}
|
|
40
50
|
|
|
41
51
|
// @ts-ignore
|
|
42
52
|
@external('env', 'ripemd160')
|
|
43
|
-
export declare function
|
|
53
|
+
export declare function _ripemd160(data: ArrayBuffer, dataLength: u32, result: ArrayBuffer): void;
|
|
54
|
+
|
|
55
|
+
export function ripemd160(data: Uint8Array): Uint8Array {
|
|
56
|
+
const resultBuffer = new ArrayBuffer(20);
|
|
57
|
+
_ripemd160(data.buffer, data.length, resultBuffer);
|
|
58
|
+
|
|
59
|
+
return Uint8Array.wrap(resultBuffer);
|
|
60
|
+
}
|
|
44
61
|
|
|
45
62
|
// @ts-ignore
|
|
46
63
|
@external('env', 'validateBitcoinAddress')
|
|
47
|
-
export declare function validateBitcoinAddress(
|
|
64
|
+
export declare function validateBitcoinAddress(address: ArrayBuffer, addressLength: u32): u32;
|
|
48
65
|
|
|
49
66
|
// @ts-ignore
|
|
50
67
|
@external('env', 'inputs')
|
|
51
|
-
export declare function inputs():
|
|
68
|
+
export declare function inputs(result: ArrayBuffer): void;
|
|
69
|
+
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
@external('env', 'inputsSize')
|
|
72
|
+
export declare function getInputsSize(): u32;
|
|
52
73
|
|
|
53
74
|
// @ts-ignore
|
|
54
75
|
@external('env', 'outputs')
|
|
55
|
-
export declare function outputs():
|
|
76
|
+
export declare function outputs(result: ArrayBuffer): void;
|
|
77
|
+
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
@external('env', 'outputsSize')
|
|
80
|
+
export declare function getOutputsSize(): u32;
|
|
56
81
|
|
|
57
82
|
// @ts-ignore
|
|
58
83
|
@external('env', 'verifySchnorrSignature')
|
|
59
|
-
export declare function verifySchnorrSignature(
|
|
84
|
+
export declare function verifySchnorrSignature(publicKey: ArrayBuffer, signature: ArrayBuffer, message: ArrayBuffer): u32;
|
|
85
|
+
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
@external('env', 'exit')
|
|
88
|
+
export declare function env_exit(status: u32, data: ArrayBuffer, dataLength: u32): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { u256 } from '@btc-vision/as-bignum/assembly';
|
|
2
2
|
import { BytesWriter } from '../../buffer/BytesWriter';
|
|
3
3
|
import { Address } from '../../types/Address';
|
|
4
|
-
import { ADDRESS_BYTE_LENGTH, U256_BYTE_LENGTH } from '../../utils
|
|
4
|
+
import { ADDRESS_BYTE_LENGTH, U256_BYTE_LENGTH } from '../../utils';
|
|
5
5
|
import { NetEvent } from '../NetEvent';
|
|
6
6
|
|
|
7
7
|
@final
|
package/runtime/exports/index.ts
CHANGED
|
@@ -3,24 +3,45 @@ import { BytesWriter } from '../buffer/BytesWriter';
|
|
|
3
3
|
import { BytesReader } from '../buffer/BytesReader';
|
|
4
4
|
import { Selector } from '../math/abi';
|
|
5
5
|
import { Calldata } from '../types';
|
|
6
|
+
import { env_exit, getCalldata, getEnvironmentVariables } from '../env/global';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const ENVIRONMENT_VARIABLES_BYTE_LENGTH: u32 = 208;
|
|
9
|
+
|
|
10
|
+
export function execute(calldataLength: u32): u32 {
|
|
11
|
+
const environmentVariablesBuffer = new ArrayBuffer(ENVIRONMENT_VARIABLES_BYTE_LENGTH);
|
|
12
|
+
getEnvironmentVariables(0, ENVIRONMENT_VARIABLES_BYTE_LENGTH, environmentVariablesBuffer);
|
|
13
|
+
Blockchain.setEnvironmentVariables(Uint8Array.wrap(environmentVariablesBuffer));
|
|
14
|
+
|
|
15
|
+
const calldataBuffer = new ArrayBuffer(calldataLength);
|
|
16
|
+
getCalldata(0, calldataLength, calldataBuffer);
|
|
17
|
+
|
|
18
|
+
const calldata: Calldata = new BytesReader(Uint8Array.wrap(calldataBuffer));
|
|
9
19
|
const selector: Selector = calldata.readSelector();
|
|
10
20
|
const result: BytesWriter = Blockchain.contract.execute(selector, calldata);
|
|
11
21
|
|
|
12
22
|
Blockchain.contract.onExecutionCompleted();
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
const resultBuffer = result.getBuffer().buffer;
|
|
25
|
+
const resultLength = resultBuffer.byteLength;
|
|
26
|
+
if (resultLength > 0) {
|
|
27
|
+
env_exit(0, resultBuffer, resultLength);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return 0;
|
|
15
31
|
}
|
|
16
32
|
|
|
17
|
-
export function onDeploy(
|
|
18
|
-
const
|
|
33
|
+
export function onDeploy(calldataLength: u32): u32 {
|
|
34
|
+
const environmentVariablesBuffer = new ArrayBuffer(ENVIRONMENT_VARIABLES_BYTE_LENGTH);
|
|
35
|
+
getEnvironmentVariables(0, ENVIRONMENT_VARIABLES_BYTE_LENGTH, environmentVariablesBuffer);
|
|
36
|
+
Blockchain.setEnvironmentVariables(Uint8Array.wrap(environmentVariablesBuffer));
|
|
37
|
+
|
|
38
|
+
const calldataBuffer = new ArrayBuffer(calldataLength);
|
|
39
|
+
getCalldata(0, calldataLength, calldataBuffer);
|
|
40
|
+
|
|
41
|
+
const calldata: Calldata = new BytesReader(Uint8Array.wrap(calldataBuffer));
|
|
19
42
|
|
|
20
43
|
Blockchain.contract.onDeployment(calldata);
|
|
21
44
|
Blockchain.contract.onExecutionCompleted();
|
|
22
|
-
}
|
|
23
45
|
|
|
24
|
-
|
|
25
|
-
Blockchain.setEnvironment(data);
|
|
46
|
+
return 0;
|
|
26
47
|
}
|
|
@@ -4,14 +4,16 @@ import { Address } from '../types/Address';
|
|
|
4
4
|
|
|
5
5
|
@final
|
|
6
6
|
export class AddressMap<V> extends Map<Address, V> {
|
|
7
|
-
public set(key: Address, value: V):
|
|
8
|
-
const index: i32 = this.
|
|
9
|
-
if (index
|
|
7
|
+
public set(key: Address, value: V): this {
|
|
8
|
+
const index: i32 = this.indexOf(key);
|
|
9
|
+
if (index === -1) {
|
|
10
10
|
this._keys.push(key);
|
|
11
11
|
this._values.push(value);
|
|
12
12
|
} else {
|
|
13
13
|
this._values[index] = value;
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
return this;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
public indexOf(address: Address): i32 {
|
|
@@ -38,7 +40,7 @@ export class AddressMap<V> extends Map<Address, V> {
|
|
|
38
40
|
|
|
39
41
|
public get(key: Address): V {
|
|
40
42
|
const index: i32 = this.indexOf(key);
|
|
41
|
-
if (index
|
|
43
|
+
if (index === -1) {
|
|
42
44
|
throw new Revert('Key not found in map (AddressMap)');
|
|
43
45
|
}
|
|
44
46
|
return this._values[index];
|
|
@@ -46,7 +48,7 @@ export class AddressMap<V> extends Map<Address, V> {
|
|
|
46
48
|
|
|
47
49
|
public delete(key: Address): bool {
|
|
48
50
|
const index: i32 = this.indexOf(key);
|
|
49
|
-
if (index
|
|
51
|
+
if (index === -1) {
|
|
50
52
|
return false;
|
|
51
53
|
}
|
|
52
54
|
|