@btc-vision/btc-runtime 1.10.10 → 1.10.11

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 (44) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +258 -137
  3. package/SECURITY.md +226 -0
  4. package/docs/README.md +614 -0
  5. package/docs/advanced/bitcoin-scripts.md +939 -0
  6. package/docs/advanced/cross-contract-calls.md +579 -0
  7. package/docs/advanced/plugins.md +1006 -0
  8. package/docs/advanced/quantum-resistance.md +660 -0
  9. package/docs/advanced/signature-verification.md +715 -0
  10. package/docs/api-reference/blockchain.md +729 -0
  11. package/docs/api-reference/events.md +642 -0
  12. package/docs/api-reference/op20.md +902 -0
  13. package/docs/api-reference/op721.md +819 -0
  14. package/docs/api-reference/safe-math.md +510 -0
  15. package/docs/api-reference/storage.md +840 -0
  16. package/docs/contracts/op-net-base.md +786 -0
  17. package/docs/contracts/op20-token.md +687 -0
  18. package/docs/contracts/op20s-signatures.md +614 -0
  19. package/docs/contracts/op721-nft.md +785 -0
  20. package/docs/contracts/reentrancy-guard.md +787 -0
  21. package/docs/core-concepts/blockchain-environment.md +724 -0
  22. package/docs/core-concepts/decorators.md +466 -0
  23. package/docs/core-concepts/events.md +652 -0
  24. package/docs/core-concepts/pointers.md +391 -0
  25. package/docs/core-concepts/security.md +473 -0
  26. package/docs/core-concepts/storage-system.md +969 -0
  27. package/docs/examples/basic-token.md +745 -0
  28. package/docs/examples/nft-with-reservations.md +1440 -0
  29. package/docs/examples/oracle-integration.md +1212 -0
  30. package/docs/examples/stablecoin.md +1180 -0
  31. package/docs/getting-started/first-contract.md +575 -0
  32. package/docs/getting-started/installation.md +384 -0
  33. package/docs/getting-started/project-structure.md +630 -0
  34. package/docs/storage/memory-maps.md +764 -0
  35. package/docs/storage/stored-arrays.md +778 -0
  36. package/docs/storage/stored-maps.md +758 -0
  37. package/docs/storage/stored-primitives.md +655 -0
  38. package/docs/types/address.md +773 -0
  39. package/docs/types/bytes-writer-reader.md +938 -0
  40. package/docs/types/calldata.md +744 -0
  41. package/docs/types/safe-math.md +446 -0
  42. package/package.json +51 -26
  43. package/runtime/memory/MapOfMap.ts +1 -0
  44. package/LICENSE.md +0 -21
@@ -0,0 +1,729 @@
1
+ # Blockchain API Reference
2
+
3
+ The `Blockchain` singleton provides access to the runtime environment, storage, and blockchain operations.
4
+
5
+ ## Import
6
+
7
+ ```typescript
8
+ import { Blockchain } from '@btc-vision/btc-runtime/runtime';
9
+ ```
10
+
11
+ ## Properties
12
+
13
+ ### Block Context
14
+
15
+ | Property | Type | Description |
16
+ |----------|------|-------------|
17
+ | `Blockchain.block` | `Block` | Current block information |
18
+ | `Blockchain.block.number` | `u64` | Block height |
19
+ | `Blockchain.block.numberU256` | `u256` | Block height as u256 |
20
+ | `Blockchain.block.hash` | `Uint8Array` | 32-byte block hash |
21
+ | `Blockchain.block.medianTimestamp` | `u64` | Median timestamp (seconds) |
22
+
23
+ ```typescript
24
+ const blockNum = Blockchain.block.number;
25
+ const timestamp = Blockchain.block.medianTimestamp;
26
+ ```
27
+
28
+ **Solidity Comparison:**
29
+ | Solidity | OPNet |
30
+ |----------|-------|
31
+ | `block.number` | `Blockchain.block.number` |
32
+ | `block.timestamp` | `Blockchain.block.medianTimestamp` |
33
+
34
+ ### Transaction Context
35
+
36
+ | Property | Type | Description |
37
+ |----------|------|-------------|
38
+ | `Blockchain.tx` | `Transaction` | Current transaction info |
39
+ | `Blockchain.tx.sender` | `Address` | Immediate caller |
40
+ | `Blockchain.tx.origin` | `ExtendedAddress` | Original signer |
41
+ | `Blockchain.tx.txId` | `Uint8Array` | Transaction ID |
42
+ | `Blockchain.tx.hash` | `Uint8Array` | Transaction hash |
43
+ | `Blockchain.tx.inputs` | `TransactionInput[]` | Transaction inputs (UTXOs) |
44
+ | `Blockchain.tx.outputs` | `TransactionOutput[]` | Transaction outputs (UTXOs) |
45
+ | `Blockchain.tx.consensus` | `ConsensusRules` | Consensus rules |
46
+
47
+ ```typescript
48
+ const caller = Blockchain.tx.sender; // Immediate caller
49
+ const signer = Blockchain.tx.origin; // Original signer
50
+ const unsafeAllowed = Blockchain.tx.consensus.unsafeSignaturesAllowed();
51
+ ```
52
+
53
+ **Solidity Comparison:**
54
+ | Solidity | OPNet |
55
+ |----------|-------|
56
+ | `msg.sender` | `Blockchain.tx.sender` |
57
+ | `tx.origin` | `Blockchain.tx.origin` |
58
+
59
+ ### Contract Context
60
+
61
+ | Property | Type | Description |
62
+ |----------|------|-------------|
63
+ | `Blockchain.contract` | `OP_NET` | Current contract instance |
64
+ | `Blockchain.contractAddress` | `Address` | This contract's address |
65
+ | `Blockchain.contractDeployer` | `Address` | Deployer's address |
66
+
67
+ ```typescript
68
+ const self = Blockchain.contractAddress;
69
+ const deployer = Blockchain.contractDeployer;
70
+ ```
71
+
72
+ **Solidity Comparison:**
73
+ | Solidity | OPNet |
74
+ |----------|-------|
75
+ | `address(this)` | `Blockchain.contractAddress` |
76
+
77
+ ### Network Context
78
+
79
+ | Property | Type | Description |
80
+ |----------|------|-------------|
81
+ | `Blockchain.network` | `Networks` | Network identifier |
82
+ | `Blockchain.chainId` | `Uint8Array` | 32-byte chain ID |
83
+ | `Blockchain.protocolId` | `Uint8Array` | 32-byte protocol ID |
84
+ | `Blockchain.DEAD_ADDRESS` | `ExtendedAddress` | Burn address |
85
+
86
+ ```typescript
87
+ if (Blockchain.network === Networks.Mainnet) {
88
+ // Mainnet-specific logic
89
+ }
90
+ ```
91
+
92
+ **Solidity Comparison:**
93
+ | Solidity | OPNet |
94
+ |----------|-------|
95
+ | `block.chainid` | `Blockchain.chainId` |
96
+
97
+ ## Storage Architecture
98
+
99
+ ### Storage Pointers
100
+
101
+ | Property | Type | Description |
102
+ |----------|------|-------------|
103
+ | `Blockchain.nextPointer` | `u16` | Get next storage pointer |
104
+
105
+ ```typescript
106
+ private myPointer: u16 = Blockchain.nextPointer;
107
+ ```
108
+
109
+ The storage system uses a pointer-based architecture where each storage slot is identified by a unique hash:
110
+
111
+ ```mermaid
112
+ graph LR
113
+ subgraph "Pointer Allocation"
114
+ A[Contract] -->|Allocate| B[Blockchain.nextPointer]
115
+ B -->|Returns u16<br/>0-65535| C[Pointer ID]
116
+ end
117
+
118
+ subgraph "Key Generation"
119
+ C -->|Pointer u16| F[encodePointer]
120
+ D[SubPointer<br/>30 bytes] -->|Address/Key Data| F
121
+ F -->|SHA-256 Hash| G[32-byte Storage Key]
122
+ end
123
+
124
+ subgraph "Storage Operations"
125
+ G -->|Read| H[getStorageAt<br/>Returns 32 bytes]
126
+ G -->|Write| I[setStorageAt<br/>Stores value]
127
+ G -->|Check| J[hasStorageAt<br/>Returns boolean]
128
+ end
129
+
130
+ H --> K[Persistent Storage]
131
+ I --> K
132
+ J --> K
133
+ ```
134
+
135
+ ## Storage Methods
136
+
137
+ ### encodePointer
138
+
139
+ Generates a storage key hash from a pointer and subPointer.
140
+
141
+ ```typescript
142
+ encodePointer(pointer: u16, subPointer: Uint8Array): Uint8Array
143
+ ```
144
+
145
+ | Parameter | Type | Description |
146
+ |-----------|------|-------------|
147
+ | `pointer` | `u16` | Storage slot identifier (0-65535) |
148
+ | `subPointer` | `Uint8Array` | Sub-index bytes (typically 30 bytes) |
149
+ | **Returns** | `Uint8Array` | 32-byte storage key hash |
150
+
151
+ ```typescript
152
+ import { encodePointer } from '@btc-vision/btc-runtime/runtime';
153
+
154
+ const pointer: u16 = Blockchain.nextPointer;
155
+ const subPointer = address.toBytes(); // or u256.toUint8Array(true)
156
+
157
+ // Generate storage key
158
+ const pointerHash = encodePointer(pointer, subPointer);
159
+ ```
160
+
161
+ ### getStorageAt
162
+
163
+ Reads from persistent storage.
164
+
165
+ ```typescript
166
+ getStorageAt(pointerHash: Uint8Array): Uint8Array
167
+ ```
168
+
169
+ | Parameter | Type | Description |
170
+ |-----------|------|-------------|
171
+ | `pointerHash` | `Uint8Array` | 32-byte storage key (from encodePointer) |
172
+ | **Returns** | `Uint8Array` | 32-byte value (zeros if unset) |
173
+
174
+ ```typescript
175
+ import { encodePointer } from '@btc-vision/btc-runtime/runtime';
176
+
177
+ // Create storage key
178
+ const pointerHash = encodePointer(pointer, subPointer);
179
+
180
+ // Read from storage
181
+ const stored = Blockchain.getStorageAt(pointerHash);
182
+ const value = u256.fromUint8ArrayBE(stored);
183
+ ```
184
+
185
+ ### setStorageAt
186
+
187
+ Writes to persistent storage.
188
+
189
+ ```typescript
190
+ setStorageAt(pointerHash: Uint8Array, value: Uint8Array): void
191
+ ```
192
+
193
+ | Parameter | Type | Description |
194
+ |-----------|------|-------------|
195
+ | `pointerHash` | `Uint8Array` | 32-byte storage key (from encodePointer) |
196
+ | `value` | `Uint8Array` | Value to store (auto-padded to 32 bytes) |
197
+
198
+ ```typescript
199
+ import { encodePointer } from '@btc-vision/btc-runtime/runtime';
200
+
201
+ // Create storage key
202
+ const pointerHash = encodePointer(pointer, subPointer);
203
+
204
+ // Write to storage
205
+ Blockchain.setStorageAt(pointerHash, value.toUint8Array(true));
206
+ ```
207
+
208
+ ### hasStorageAt
209
+
210
+ Checks if storage slot has non-zero value.
211
+
212
+ ```typescript
213
+ hasStorageAt(pointerHash: Uint8Array): bool
214
+ ```
215
+
216
+ ```typescript
217
+ const pointerHash = encodePointer(pointer, subPointer);
218
+ if (Blockchain.hasStorageAt(pointerHash)) {
219
+ // Slot has a value
220
+ }
221
+ ```
222
+
223
+ ### Storage Flow
224
+
225
+ The following sequence diagram illustrates the complete flow of storage operations:
226
+
227
+ ```mermaid
228
+ sequenceDiagram
229
+ participant C as Contract
230
+ participant B as Blockchain
231
+ participant S as Storage Layer
232
+
233
+ Note over C,S: Storage Pointer Allocation
234
+ C->>B: Blockchain.nextPointer
235
+ B->>C: Returns u16 (e.g., 5)
236
+
237
+ Note over C,S: Write Operation
238
+ C->>C: address.toBytes() -> subPointer
239
+ C->>B: encodePointer(5, subPointer)
240
+ B->>B: SHA-256(pointer + subPointer)
241
+ B->>C: Returns 32-byte hash
242
+ C->>B: setStorageAt(hash, value)
243
+ B->>S: Persist to storage
244
+
245
+ Note over C,S: Read Operation
246
+ C->>B: encodePointer(5, subPointer)
247
+ B->>C: Returns 32-byte hash
248
+ C->>B: getStorageAt(hash)
249
+ S->>B: Retrieve value
250
+ B->>C: Returns 32-byte value
251
+ ```
252
+
253
+ ### Storage Pattern Example
254
+
255
+ Complete example showing the correct pattern:
256
+
257
+ ```typescript
258
+ import { u256 } from '@btc-vision/as-bignum/assembly';
259
+ import {
260
+ Blockchain,
261
+ encodePointer,
262
+ Address
263
+ } from '@btc-vision/btc-runtime/runtime';
264
+
265
+ // Allocate pointer
266
+ private balancesPointer: u16 = Blockchain.nextPointer;
267
+
268
+ // Write balance
269
+ public setBalance(address: Address, amount: u256): void {
270
+ const pointerHash = encodePointer(this.balancesPointer, address.toBytes());
271
+ Blockchain.setStorageAt(pointerHash, amount.toUint8Array(true));
272
+ }
273
+
274
+ // Read balance
275
+ public getBalance(address: Address): u256 {
276
+ const pointerHash = encodePointer(this.balancesPointer, address.toBytes());
277
+ const stored = Blockchain.getStorageAt(pointerHash);
278
+ return u256.fromUint8ArrayBE(stored);
279
+ }
280
+ ```
281
+
282
+ **Solidity Comparison:**
283
+ | Solidity | OPNet |
284
+ |----------|-------|
285
+ | `mapping(address => uint256) balances` | `AddressMemoryMap` with pointer |
286
+ | `balances[addr] = value` | `Blockchain.setStorageAt(pointerHash, value)` |
287
+ | `balances[addr]` | `Blockchain.getStorageAt(pointerHash)` |
288
+
289
+ ### Transient Storage (Experimental)
290
+
291
+ > **Warning:** Transient storage is NOT enabled in production. Only available in testing.
292
+
293
+ ```typescript
294
+ getTransientStorageAt(pointerHash: Uint8Array): Uint8Array
295
+ setTransientStorageAt(pointerHash: Uint8Array, value: Uint8Array): void
296
+ hasTransientStorageAt(pointerHash: Uint8Array): bool
297
+ ```
298
+
299
+ ## Cross-Contract Calls
300
+
301
+ ### call
302
+
303
+ Calls another contract.
304
+
305
+ ```typescript
306
+ call(
307
+ destinationContract: Address,
308
+ calldata: BytesWriter,
309
+ stopExecutionOnFailure: boolean = true
310
+ ): CallResult
311
+ ```
312
+
313
+ | Parameter | Type | Description |
314
+ |-----------|------|-------------|
315
+ | `destinationContract` | `Address` | Target contract |
316
+ | `calldata` | `BytesWriter` | Encoded call data |
317
+ | `stopExecutionOnFailure` | `boolean` | Revert on failure (default: true) |
318
+ | **Returns** | `CallResult` | Success flag and response data |
319
+
320
+ The following diagram shows the two call patterns - standard calls that revert on failure, and try-catch style calls that handle failures gracefully:
321
+
322
+ ```mermaid
323
+ flowchart LR
324
+ subgraph StdPattern["stopOnFailure = true"]
325
+ A1["Call"] --> B1{"Success?"}
326
+ B1 -->|"Yes"| C1["Continue"]
327
+ B1 -->|"No"| D1["REVERT TX"]
328
+ end
329
+
330
+ subgraph TryPattern["stopOnFailure = false"]
331
+ A2["Call"] --> B2{"Success?"}
332
+ B2 -->|"Yes"| C2["Continue"]
333
+ B2 -->|"No"| D2["Handle error"]
334
+ end
335
+ ```
336
+
337
+ ```typescript
338
+ // Standard call - reverts on failure
339
+ const result = Blockchain.call(tokenAddress, calldata);
340
+ const balance = result.data.readU256();
341
+
342
+ // Try-catch pattern - handles failure gracefully
343
+ const result = Blockchain.call(tokenAddress, calldata, false);
344
+ if (result.success) {
345
+ // Process response
346
+ } else {
347
+ // Handle failure without reverting
348
+ }
349
+ ```
350
+
351
+ The complete call flow with both success and failure scenarios:
352
+
353
+ ```mermaid
354
+ sequenceDiagram
355
+ participant Caller as Calling Contract
356
+ participant BC as Blockchain
357
+ participant Target as Target Contract
358
+
359
+ Note over Caller,Target: Standard Call (stopExecutionOnFailure=true)
360
+ Caller->>Caller: Encode calldata (BytesWriter)
361
+ Caller->>BC: call(targetAddress, calldata, true)
362
+ BC->>Target: Execute method
363
+
364
+ alt Success Case
365
+ Target->>Target: Process request
366
+ Target->>BC: Return BytesWriter response
367
+ BC->>Caller: CallResult{success: true, data}
368
+ Caller->>Caller: Process response.data
369
+ else Failure Case
370
+ Target->>BC: Throw Revert
371
+ BC->>Caller: Transaction reverts
372
+ Note over Caller: Execution stops
373
+ end
374
+
375
+ Note over Caller,Target: Try-Catch Pattern (stopExecutionOnFailure=false)
376
+ Caller->>BC: call(targetAddress, calldata, false)
377
+ BC->>Target: Execute method
378
+
379
+ alt Success Case
380
+ Target->>BC: Return response
381
+ BC->>Caller: CallResult{success: true, data}
382
+ Caller->>Caller: Handle success
383
+ else Failure Case
384
+ Target->>BC: Throw Revert
385
+ BC->>Caller: CallResult{success: false, data}
386
+ Caller->>Caller: Handle failure gracefully
387
+ Note over Caller: Execution continues
388
+ end
389
+ ```
390
+
391
+ **Solidity Comparison:**
392
+ | Solidity | OPNet |
393
+ |----------|-------|
394
+ | `target.call(data)` | `Blockchain.call(target, calldata, false)` |
395
+ | `target.functionCall(args)` | `Blockchain.call(target, calldata, true)` |
396
+ | `try target.call() { } catch { }` | `Blockchain.call(target, calldata, false)` + check `result.success` |
397
+
398
+ ### CallResult
399
+
400
+ ```typescript
401
+ class CallResult {
402
+ readonly success: boolean;
403
+ readonly data: BytesReader;
404
+ }
405
+ ```
406
+
407
+ ### deployContractFromExisting
408
+
409
+ Deploys a new contract from a template.
410
+
411
+ ```typescript
412
+ deployContractFromExisting(
413
+ existingAddress: Address,
414
+ salt: u256,
415
+ calldata: BytesWriter
416
+ ): Address
417
+ ```
418
+
419
+ | Parameter | Type | Description |
420
+ |-----------|------|-------------|
421
+ | `existingAddress` | `Address` | Template contract |
422
+ | `salt` | `u256` | Unique salt for address |
423
+ | `calldata` | `BytesWriter` | Constructor parameters |
424
+ | **Returns** | `Address` | New contract address |
425
+
426
+ ```typescript
427
+ const salt = u256.fromBytes(Blockchain.sha256(uniqueData));
428
+ const newContract = Blockchain.deployContractFromExisting(
429
+ templateAddress,
430
+ salt,
431
+ constructorData
432
+ );
433
+ ```
434
+
435
+ ## Cryptographic Operations
436
+
437
+ ### sha256
438
+
439
+ Computes SHA-256 hash.
440
+
441
+ ```typescript
442
+ sha256(buffer: Uint8Array): Uint8Array
443
+ ```
444
+
445
+ ```typescript
446
+ const hash = Blockchain.sha256(data); // 32 bytes
447
+ ```
448
+
449
+ ### hash256
450
+
451
+ Computes double SHA-256 (Bitcoin standard).
452
+
453
+ ```typescript
454
+ hash256(buffer: Uint8Array): Uint8Array
455
+ ```
456
+
457
+ ```typescript
458
+ const txHash = Blockchain.hash256(txData); // 32 bytes
459
+ ```
460
+
461
+ ## Signature Verification
462
+
463
+ ### verifySignature
464
+
465
+ Verifies signature based on current consensus rules.
466
+
467
+ ```typescript
468
+ verifySignature(
469
+ address: ExtendedAddress,
470
+ signature: Uint8Array,
471
+ hash: Uint8Array,
472
+ forceMLDSA: boolean = false
473
+ ): boolean
474
+ ```
475
+
476
+ | Parameter | Type | Description |
477
+ |-----------|------|-------------|
478
+ | `address` | `ExtendedAddress` | Signer's address |
479
+ | `signature` | `Uint8Array` | Signature bytes (64 for Schnorr, 2420+ for ML-DSA) |
480
+ | `hash` | `Uint8Array` | 32-byte message hash |
481
+ | `forceMLDSA` | `boolean` | Force ML-DSA verification |
482
+ | **Returns** | `boolean` | True if valid |
483
+
484
+ The signature verification selects the appropriate algorithm based on consensus rules:
485
+
486
+ ```mermaid
487
+ flowchart LR
488
+ subgraph "verifySignature Flow"
489
+ Start([Verify Signature]) --> GetInput[Receive address,<br/>signature, hash]
490
+ GetInput --> CheckConsensus{unsafeSignaturesAllowed()<br/>AND !forceMLDSA?}
491
+ CheckConsensus -->|Yes| Schnorr[Schnorr Path]
492
+ CheckConsensus -->|No| MLDSA[ML-DSA Path]
493
+ end
494
+
495
+ subgraph "Schnorr Verification"
496
+ Schnorr --> ValidateSig{signature.length<br/>== 64?}
497
+ ValidateSig -->|Yes| SchnorrVerify[Verify Schnorr]
498
+ ValidateSig -->|No| SchnorrFail([Revert])
499
+ SchnorrVerify --> SchnorrResult{Valid?}
500
+ end
501
+
502
+ subgraph "ML-DSA Verification"
503
+ MLDSA --> MLDSAVerify[Verify ML-DSA-44<br/>Level2]
504
+ MLDSAVerify --> MLDSAResult{Valid?}
505
+ end
506
+
507
+ MLDSAResult -->|Yes| Success([Return true])
508
+ MLDSAResult -->|No| Fail([Return false])
509
+ SchnorrResult -->|Yes| Success
510
+ SchnorrResult -->|No| Fail
511
+ ```
512
+
513
+ ```typescript
514
+ const isValid = Blockchain.verifySignature(
515
+ signerAddress,
516
+ signatureBytes,
517
+ messageHash
518
+ );
519
+ if (!isValid) {
520
+ throw new Revert('Invalid signature');
521
+ }
522
+ ```
523
+
524
+ The complete EIP-712 style signature verification flow:
525
+
526
+ ```mermaid
527
+ sequenceDiagram
528
+ participant C as Contract
529
+ participant BC as Blockchain
530
+ participant Cons as Consensus Layer
531
+ participant Crypto as Crypto Module
532
+
533
+ Note over C,Crypto: EIP-712 Style Signature Verification
534
+ C->>C: Build domain separator
535
+ C->>C: Hash struct data
536
+ C->>C: Combine: 0x1901 + domain + structHash
537
+ C->>C: messageHash = SHA-256(combined)
538
+
539
+ C->>BC: verifySignature(address, signature, messageHash, forceMLDSA?)
540
+
541
+ BC->>Cons: Check consensus flags
542
+ Cons->>BC: unsafeSignaturesAllowed()
543
+
544
+ alt unsafeSignaturesAllowed() AND !forceMLDSA
545
+ BC->>BC: Validate signature.length == 64
546
+ BC->>Crypto: verifySchnorr(tweakedPublicKey, sig, hash)
547
+ Crypto->>BC: Valid/Invalid
548
+ else ML-DSA required (consensus or forced)
549
+ BC->>BC: Use ML-DSA Level2 (ML-DSA-44)
550
+ BC->>Crypto: verifyMLDSA(Level2, mldsaPublicKey, sig, hash)
551
+ Crypto->>BC: Valid/Invalid
552
+ end
553
+
554
+ BC->>C: Return boolean
555
+ ```
556
+
557
+ ### verifyMLDSASignature
558
+
559
+ Verifies ML-DSA (quantum-resistant) signature.
560
+
561
+ ```typescript
562
+ verifyMLDSASignature(
563
+ level: MLDSASecurityLevel,
564
+ publicKey: Uint8Array,
565
+ signature: Uint8Array,
566
+ hash: Uint8Array
567
+ ): boolean
568
+ ```
569
+
570
+ | Parameter | Type | Description |
571
+ |-----------|------|-------------|
572
+ | `level` | `MLDSASecurityLevel` | Security level (Level2, Level3, Level5) |
573
+ | `publicKey` | `Uint8Array` | ML-DSA public key |
574
+ | `signature` | `Uint8Array` | ML-DSA signature |
575
+ | `hash` | `Uint8Array` | 32-byte message hash |
576
+ | **Returns** | `boolean` | True if valid |
577
+
578
+ ```typescript
579
+ import { MLDSASecurityLevel } from '@btc-vision/btc-runtime/runtime';
580
+
581
+ const isValid = Blockchain.verifyMLDSASignature(
582
+ MLDSASecurityLevel.Level2, // ML-DSA-44
583
+ address.mldsaPublicKey, // 1312 bytes
584
+ signature, // 2420 bytes
585
+ messageHash // 32 bytes
586
+ );
587
+ ```
588
+
589
+ ### verifySchnorrSignature (Deprecated)
590
+
591
+ ```typescript
592
+ verifySchnorrSignature(
593
+ publicKey: ExtendedAddress,
594
+ signature: Uint8Array,
595
+ hash: Uint8Array
596
+ ): boolean
597
+ ```
598
+
599
+ > **Note:** Use `verifySignature()` instead for automatic consensus migration.
600
+
601
+ ## Utility Methods
602
+
603
+ ### validateBitcoinAddress
604
+
605
+ Validates a Bitcoin address string.
606
+
607
+ ```typescript
608
+ validateBitcoinAddress(address: string): bool
609
+ ```
610
+
611
+ ```typescript
612
+ if (!Blockchain.validateBitcoinAddress(userAddress)) {
613
+ throw new Revert('Invalid Bitcoin address');
614
+ }
615
+ ```
616
+
617
+ ### isContract
618
+
619
+ Checks if an address is a contract.
620
+
621
+ ```typescript
622
+ isContract(address: Address): boolean
623
+ ```
624
+
625
+ ```typescript
626
+ if (Blockchain.isContract(targetAddress)) {
627
+ // Is a contract, not EOA
628
+ }
629
+ ```
630
+
631
+ **Solidity Comparison:**
632
+ | Solidity | OPNet |
633
+ |----------|-------|
634
+ | `address.code.length > 0` | `Blockchain.isContract(address)` |
635
+
636
+ ### getAccountType
637
+
638
+ Gets account type code.
639
+
640
+ ```typescript
641
+ getAccountType(address: Address): u32
642
+ ```
643
+
644
+ | Return Value | Meaning |
645
+ |--------------|---------|
646
+ | `0` | EOA or uninitialized |
647
+ | `>0` | Contract (type code) |
648
+
649
+ ### getBlockHash
650
+
651
+ Retrieves historical block hash.
652
+
653
+ ```typescript
654
+ getBlockHash(blockNumber: u64): Uint8Array
655
+ ```
656
+
657
+ ```typescript
658
+ const hash = Blockchain.getBlockHash(Blockchain.block.number - 10);
659
+ ```
660
+
661
+ > **Warning:** Only ~256 recent blocks available. Older blocks return zeros.
662
+
663
+ **Solidity Comparison:**
664
+ | Solidity | OPNet |
665
+ |----------|-------|
666
+ | `blockhash(blockNumber)` | `Blockchain.getBlockHash(blockNumber)` |
667
+
668
+ ## Event Methods
669
+
670
+ ### emit
671
+
672
+ Emits an event.
673
+
674
+ ```typescript
675
+ emit(event: NetEvent): void
676
+ ```
677
+
678
+ ```typescript
679
+ Blockchain.emit(new TransferEvent(from, to, amount));
680
+ ```
681
+
682
+ **Solidity Comparison:**
683
+ | Solidity | OPNet |
684
+ |----------|-------|
685
+ | `emit Transfer(from, to, amount)` | `Blockchain.emit(new TransferEvent(from, to, amount))` |
686
+
687
+ ### log
688
+
689
+ Logs debug message (testing only).
690
+
691
+ ```typescript
692
+ log(data: string): void
693
+ ```
694
+
695
+ > **Warning:** Only available in unit testing framework.
696
+
697
+ ```typescript
698
+ Blockchain.log('Debug: operation started');
699
+ ```
700
+
701
+ ## Plugin Methods
702
+
703
+ ### registerPlugin
704
+
705
+ Registers a plugin.
706
+
707
+ ```typescript
708
+ registerPlugin(plugin: Plugin): void
709
+ ```
710
+
711
+ ```typescript
712
+ Blockchain.registerPlugin(new MyPlugin());
713
+ ```
714
+
715
+ ## Lifecycle Hooks
716
+
717
+ These are called by the runtime:
718
+
719
+ | Method | When Called |
720
+ |--------|-------------|
721
+ | `onDeployment(calldata)` | Contract deployment |
722
+ | `onExecutionStarted(selector, calldata)` | Before method execution |
723
+ | `onExecutionCompleted(selector, calldata)` | After successful execution |
724
+
725
+ ---
726
+
727
+ **Navigation:**
728
+ - Previous: [Oracle Integration](../examples/oracle-integration.md)
729
+ - Next: [OP20 API](./op20.md)