@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.
|
|
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.
|
|
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.
|
|
40
|
+
"@eslint/js": "^9.24.0",
|
|
41
41
|
"gulplog": "^2.2.0",
|
|
42
42
|
"ts-node": "^10.9.2",
|
|
43
|
-
"typescript": "^5.8.
|
|
44
|
-
"typescript-eslint": "^8.
|
|
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 *
|
|
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
|
}
|
package/runtime/env/global.ts
CHANGED
|
@@ -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;
|