@btc-vision/btc-runtime 1.5.7 → 1.6.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.5.7",
3
+ "version": "1.6.0",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {},
@@ -17,7 +17,7 @@
17
17
  "author": "BlobMaster41",
18
18
  "license": "MIT",
19
19
  "devDependencies": {
20
- "@types/node": "^22.13.10",
20
+ "@types/node": "^22.14.0",
21
21
  "assemblyscript": "^0.27.35"
22
22
  },
23
23
  "repository": {
@@ -37,10 +37,10 @@
37
37
  "dependencies": {
38
38
  "@assemblyscript/loader": "^0.27.35",
39
39
  "@btc-vision/as-bignum": "^0.0.5",
40
- "@eslint/js": "^9.22.0",
40
+ "@eslint/js": "^9.24.0",
41
41
  "gulplog": "^2.2.0",
42
42
  "ts-node": "^10.9.2",
43
- "typescript": "^5.8.2",
44
- "typescript-eslint": "^8.26.1"
43
+ "typescript": "^5.8.3",
44
+ "typescript-eslint": "^8.29.1"
45
45
  }
46
46
  }
@@ -233,6 +233,8 @@ export class BytesReader {
233
233
  * Reads an Address (32 bytes).
234
234
  */
235
235
  public readAddress(): Address {
236
+ this.verifyEnd(this.currentOffset + ADDRESS_BYTE_LENGTH);
237
+
236
238
  const addr = new Address();
237
239
  for (let i: i32 = 0; i < ADDRESS_BYTE_LENGTH; i++) {
238
240
  addr[i] = this.readU8();
@@ -279,13 +279,14 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
279
279
 
280
280
  // Build the hash to match exactly what the user signed, including the nonce
281
281
  const writer = new BytesWriter(
282
- ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH + U256_BYTE_LENGTH,
282
+ ADDRESS_BYTE_LENGTH * 3 + U256_BYTE_LENGTH + U256_BYTE_LENGTH,
283
283
  );
284
284
 
285
285
  writer.writeAddress(owner);
286
286
  writer.writeAddress(spender);
287
287
  writer.writeU256(value);
288
288
  writer.writeU256(nonce);
289
+ writer.writeAddress(this.address);
289
290
 
290
291
  const hash = sha256(writer.getBuffer());
291
292
  if (!Blockchain.verifySchnorrSignature(owner, signature, hash)) {
@@ -15,11 +15,15 @@ import {
15
15
  env_exit,
16
16
  getCallResult,
17
17
  loadPointer,
18
+ tLoadPointer,
18
19
  log,
19
20
  sha256,
20
21
  storePointer,
22
+ tStorePointer,
21
23
  validateBitcoinAddress,
22
24
  verifySchnorrSignature,
25
+ getAccountType,
26
+ getBlockHash,
23
27
  } from './global';
24
28
  import { eqUint, MapUint8Array } from '../generic/MapUint8Array';
25
29
  import { EMPTY_BUFFER } from '../math/bytes';
@@ -36,6 +40,7 @@ export class BlockchainEnvironment {
36
40
  public readonly DEAD_ADDRESS: Address = Address.dead();
37
41
 
38
42
  private storage: MapUint8Array = new MapUint8Array();
43
+ private transientStorage: MapUint8Array = new MapUint8Array();
39
44
  private _selfContract: Potential<OP_NET> = null;
40
45
  private _plugins: Plugin[] = [];
41
46
 
@@ -217,15 +222,20 @@ export class BlockchainEnvironment {
217
222
  public deployContractFromExisting(
218
223
  existingAddress: Address,
219
224
  salt: u256,
225
+ calldata: BytesWriter,
220
226
  ): Address {
221
227
  const resultAddressBuffer = new ArrayBuffer(ADDRESS_BYTE_LENGTH);
228
+ const callDataBuffer = calldata.getBuffer().buffer;
222
229
 
223
230
  const status = deployFromAddress(
224
231
  existingAddress.buffer,
225
232
  salt.toUint8Array(true).buffer,
233
+ callDataBuffer,
234
+ callDataBuffer.byteLength,
226
235
  resultAddressBuffer,
227
236
  );
228
237
 
238
+ // TODO: Decode revert data if status is not 0
229
239
  if (status !== 0) {
230
240
  throw new Revert('Failed to deploy contract');
231
241
  }
@@ -245,6 +255,17 @@ export class BlockchainEnvironment {
245
255
  return new Uint8Array(32);
246
256
  }
247
257
 
258
+ public getTransientStorageAt(
259
+ pointerHash: Uint8Array,
260
+ ): Uint8Array {
261
+ this.hasPointerTransientStorageHash(pointerHash);
262
+ if (this.transientStorage.has(pointerHash)) {
263
+ return this.transientStorage.get(pointerHash);
264
+ }
265
+
266
+ return new Uint8Array(32);
267
+ }
268
+
248
269
  public sha256(buffer: Uint8Array): Uint8Array {
249
270
  return sha256(buffer);
250
271
  }
@@ -270,10 +291,21 @@ export class BlockchainEnvironment {
270
291
  return !eqUint(val, EMPTY_BUFFER);
271
292
  }
272
293
 
294
+ public hasTransientStorageAt(pointerHash: Uint8Array): bool {
295
+ // We mark zero as the default value for the storage, if something is 0, the storage slot get deleted or is non-existent
296
+ const val: Uint8Array = this.getTransientStorageAt(pointerHash);
297
+
298
+ return !eqUint(val, EMPTY_BUFFER);
299
+ }
300
+
273
301
  public setStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
274
302
  this._internalSetStorageAt(pointerHash, value);
275
303
  }
276
304
 
305
+ public setTransientStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
306
+ this._internalSetTransientStorageAt(pointerHash, value);
307
+ }
308
+
277
309
  private createContractIfNotExists(): void {
278
310
  if (!this._contract) {
279
311
  throw new Revert('Contract is required');
@@ -290,6 +322,12 @@ export class BlockchainEnvironment {
290
322
  storePointer(pointerHash.buffer, value.buffer);
291
323
  }
292
324
 
325
+ private _internalSetTransientStorageAt(pointerHash: Uint8Array, value: Uint8Array): void {
326
+ this.transientStorage.set(pointerHash, value);
327
+
328
+ tStorePointer(pointerHash.buffer, value.buffer);
329
+ }
330
+
293
331
  private hasPointerStorageHash(pointer: Uint8Array): bool {
294
332
  if (this.storage.has(pointer)) {
295
333
  return true;
@@ -304,4 +342,29 @@ export class BlockchainEnvironment {
304
342
 
305
343
  return !eqUint(value, EMPTY_BUFFER);
306
344
  }
345
+
346
+ private hasPointerTransientStorageHash(pointer: Uint8Array): bool {
347
+ if (this.storage.has(pointer)) {
348
+ return true;
349
+ }
350
+
351
+ // we attempt to load the requested pointer.
352
+ const resultBuffer = new ArrayBuffer(32);
353
+ tLoadPointer(pointer.buffer, resultBuffer);
354
+
355
+ const value: Uint8Array = Uint8Array.wrap(resultBuffer);
356
+ this.storage.set(pointer, value); // cache the value
357
+
358
+ return !eqUint(value, EMPTY_BUFFER);
359
+ }
360
+
361
+ public getAccountType(address: Address): u32 {
362
+ return getAccountType(address.buffer)
363
+ }
364
+
365
+ public getBlockHash(blockNumber: u64): Uint8Array {
366
+ const hash = new ArrayBuffer(32);
367
+ getBlockHash(blockNumber, hash);
368
+ return Uint8Array.wrap(hash);
369
+ }
307
370
  }
@@ -10,17 +10,21 @@ export declare function getCalldata(offset: u32, length: u32, result: ArrayBuffe
10
10
  @external('env', 'load')
11
11
  export declare function loadPointer(key: ArrayBuffer, result: ArrayBuffer): void;
12
12
 
13
- // @ts-ignore
14
- @external('env', 'nextPointerGreaterThan')
15
- export declare function nextPointerGreaterThan(data: Uint8Array): Uint8Array;
16
-
17
13
  // @ts-ignore
18
14
  @external('env', 'store')
19
15
  export declare function storePointer(key: ArrayBuffer, value: ArrayBuffer): void;
20
16
 
17
+ // @ts-ignore
18
+ @external('env', 'tload')
19
+ export declare function tLoadPointer(key: ArrayBuffer, result: ArrayBuffer): void;
20
+
21
+ // @ts-ignore
22
+ @external('env', 'tstore')
23
+ export declare function tStorePointer(key: ArrayBuffer, value: ArrayBuffer): void;
24
+
21
25
  // @ts-ignore
22
26
  @external('env', 'deployFromAddress')
23
- export declare function deployFromAddress(originAddress: ArrayBuffer, salt: ArrayBuffer, resultAddress: ArrayBuffer): u32;
27
+ export declare function deployFromAddress(originAddress: ArrayBuffer, salt: ArrayBuffer, calldata: ArrayBuffer, calldataLength: u32, resultAddress: ArrayBuffer): u32;
24
28
 
25
29
  // @ts-ignore
26
30
  @external('env', 'call')
@@ -83,6 +87,14 @@ export declare function getOutputsSize(): u32;
83
87
  @external('env', 'verifySchnorrSignature')
84
88
  export declare function verifySchnorrSignature(publicKey: ArrayBuffer, signature: ArrayBuffer, message: ArrayBuffer): u32;
85
89
 
90
+ // @ts-ignore
91
+ @external('env', 'blockHash')
92
+ export declare function getBlockHash(block_number: u64, result: ArrayBuffer): void;
93
+
94
+ // @ts-ignore
95
+ @external('env', 'accountType')
96
+ export declare function getAccountType(address: ArrayBuffer): u32;
97
+
86
98
  // @ts-ignore
87
99
  @external('env', 'exit')
88
100
  export declare function env_exit(status: u32, data: ArrayBuffer, dataLength: u32): void;