@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
@@ -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, U256_BYTE_LENGTH } from '../utils/lengths';
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
- encodeAddress,
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: PointerStorage = new MapU256();
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 setEnvironment(data: Uint8Array): void {
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
- reader.readAddress(),
114
- reader.readAddress(),
115
- reader.readBytes(32),
121
+ caller,
122
+ origin,
123
+ txHash,
116
124
  );
117
125
 
118
- const currentBlock = reader.readU256();
119
-
120
- this._contractDeployer = reader.readAddress();
121
- this._contractAddress = reader.readAddress();
126
+ this._contractDeployer = contractDeployer;
127
+ this._contractAddress = contractAddress;
122
128
 
123
- const medianTimestamp = reader.readU64();
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 call = new BytesWriter(ADDRESS_BYTE_LENGTH + calldata.bufferLength() + 4);
141
- call.writeAddress(destinationContract);
142
- call.writeBytesWithLength(calldata.getBuffer());
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
- const response: Uint8Array = callContract(call.getBuffer());
151
+ if (status !== 0) {
152
+ env_exit(status, resultBuffer, resultLength);
153
+ }
145
154
 
146
- return new BytesReader(response);
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.writeStringWithLength(data);
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 buffer = new BytesWriter(event.eventType.length + 6 + data.byteLength);
168
+ const writer = new BytesWriter(event.eventType.length + 6 + data.byteLength);
160
169
 
161
- buffer.writeStringWithLength(event.eventType);
162
- buffer.writeBytesWithLength(data);
170
+ writer.writeStringWithLength(event.eventType);
171
+ writer.writeBytesWithLength(data);
163
172
 
164
- emit(buffer.getBuffer());
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 reader = new BytesReader(validateBitcoinAddress(writer.getBuffer()));
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
- const reader: BytesReader = new BytesReader(cb as Uint8Array);
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
- ): DeployContractResponse {
207
- const writer = new BytesWriter(ADDRESS_BYTE_LENGTH + U256_BYTE_LENGTH);
208
- writer.writeAddress(existingAddress);
209
- writer.writeU256(salt);
188
+ ): Address {
189
+ const resultAddressBuffer = new ArrayBuffer(ADDRESS_BYTE_LENGTH);
210
190
 
211
- const buffer: Uint8Array = writer.getBuffer();
212
- const cb: Potential<Uint8Array> = deployFromAddress(buffer);
213
- if (!cb) throw this.error('Failed to deploy contract');
191
+ const status = deployFromAddress(
192
+ existingAddress.buffer,
193
+ salt.toUint8Array(true).buffer,
194
+ resultAddressBuffer,
195
+ );
214
196
 
215
- const reader: BytesReader = new BytesReader(cb as Uint8Array);
216
- const virtualAddress: u256 = reader.readU256();
217
- const contractAddress: Address = reader.readAddress();
197
+ if (status !== 0) {
198
+ throw this.error('Failed to deploy contract');
199
+ }
218
200
 
219
- return new DeployContractResponse(virtualAddress, contractAddress);
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: MemorySlotPointer,
225
- defaultValue: MemorySlotData<u256>,
226
- ): MemorySlotData<u256> {
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 defaultValue;
213
+ return new Uint8Array(32);
234
214
  }
235
215
 
236
- /*public getNextPointerGreaterThan(
237
- targetPointer: MemorySlotPointer,
238
- valueAtLeast: u256,
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
- return reader.readU256();
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 writer = new BytesWriter(ADDRESS_BYTE_LENGTH + 64 + 32);
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
- const result: Uint8Array = verifySchnorrSignature(writer.getBuffer());
263
-
264
- const reader = new BytesReader(result);
265
- return reader.readBoolean();
231
+ return result === 1;
266
232
  }
267
233
 
268
- // TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
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: u256 = this.getStorageAt(pointerHash, u256.Zero);
236
+ const val: Uint8Array = this.getStorageAt(pointerHash);
272
237
 
273
- return u256.ne(val, u256.Zero);
238
+ return !eqUint(val, EMPTY_BUFFER);
274
239
  }
275
240
 
276
- public setStorageAt(pointerHash: MemorySlotPointer, value: MemorySlotData<u256>): void {
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: u256, value: MemorySlotData<u256>): void {
259
+ private _internalSetStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
295
260
  this.storage.set(pointerHash, value);
296
261
 
297
- const writer: BytesWriter = new BytesWriter(U256_BYTE_LENGTH * 2);
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: MemorySlotPointer): bool {
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 writer = new BytesWriter(U256_BYTE_LENGTH);
312
- writer.writeU256(pointer);
271
+ const resultBuffer = new ArrayBuffer(32);
272
+ loadPointer(pointer.buffer, resultBuffer);
313
273
 
314
- const result: Uint8Array = loadPointer(writer.getBuffer());
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 !u256.eq(value, u256.Zero);
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
- private readonly u64BlockNumber: u64;
5
+ public readonly numberU256: u256;
6
6
 
7
7
  public constructor(
8
- public readonly number: u256,
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.u64BlockNumber = number.toU64();
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 id: Uint8Array,
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 buffer = new BytesReader(inputs());
43
+ const inputsSize = getInputsSize();
44
+ let resultBuffer = new ArrayBuffer(inputsSize);
45
+ inputs(resultBuffer);
43
46
 
44
- return buffer.readTransactionInputs();
47
+ const reader = new BytesReader(Uint8Array.wrap(resultBuffer));
48
+ return reader.readTransactionInputs();
45
49
  }
46
50
 
47
51
  private loadOutputs(): TransactionOutput[] {
48
- const buffer = new BytesReader(outputs());
52
+ const outputsSize = getOutputsSize();
53
+ let resultBuffer = new ArrayBuffer(outputsSize);
54
+ outputs(resultBuffer);
49
55
 
50
- return buffer.readTransactionOutputs();
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
  }
@@ -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(data: Uint8Array): Uint8Array;
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(data: Uint8Array): Uint8Array;
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(data: Uint8Array): Uint8Array;
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(data: Uint8Array): Uint8Array;
27
+ export declare function callContract(address: ArrayBuffer, calldata: ArrayBuffer, calldataLength: u32, resultLength: ArrayBuffer): u32;
24
28
 
25
29
  // @ts-ignore
26
- @external('env', 'log')
27
- export declare function log(data: Uint8Array): void;
30
+ @external('env', 'callResult')
31
+ export declare function getCallResult(offset: u32, length: u32, result: ArrayBuffer): void;
28
32
 
29
33
  // @ts-ignore
30
- @external('env', 'emit')
31
- export declare function emit(data: Uint8Array): void;
34
+ @external('debug', 'log')
35
+ export declare function log(data: ArrayBuffer, dataLength: u32): void;
32
36
 
33
37
  // @ts-ignore
34
- @external('env', 'encodeAddress')
35
- export declare function encodeAddress(data: Uint8Array): Uint8Array;
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 sha256(data: Uint8Array): Uint8Array;
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 ripemd160(data: Uint8Array): Uint8Array;
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(data: Uint8Array): Uint8Array;
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(): Uint8Array;
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(): Uint8Array;
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(data: Uint8Array): Uint8Array;
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/lengths';
4
+ import { ADDRESS_BYTE_LENGTH, U256_BYTE_LENGTH } from '../../utils';
5
5
  import { NetEvent } from '../NetEvent';
6
6
 
7
7
  @final
@@ -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
- export function execute(data: Uint8Array): Uint8Array {
8
- const calldata: Calldata = new BytesReader(data);
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
- return result.getBuffer();
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(data: Uint8Array): void {
18
- const calldata: Calldata = new BytesReader(data);
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
- export function setEnvironment(data: Uint8Array): void {
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): void {
8
- const index: i32 = this._keys.indexOf(key);
9
- if (index == -1) {
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 == -1) {
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 == -1) {
51
+ if (index === -1) {
50
52
  return false;
51
53
  }
52
54