@btc-vision/btc-runtime 1.10.8 → 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 +52 -27
  43. package/runtime/memory/MapOfMap.ts +1 -0
  44. package/LICENSE.md +0 -21
@@ -0,0 +1,660 @@
1
+ # Quantum Resistance
2
+
3
+ OPNet includes built-in quantum-resistant cryptography through ML-DSA (Module-Lattice Digital Signature Algorithm). The `Address` class provides automatic access to ML-DSA public keys without requiring any custom storage.
4
+
5
+ ## Overview
6
+
7
+ Quantum computers pose a threat to traditional cryptographic schemes:
8
+
9
+ | Algorithm | Quantum Threat | OPNet Status |
10
+ |-----------|---------------|--------------|
11
+ | ECDSA | Vulnerable (Shor's algorithm) | Not used |
12
+ | Schnorr | Vulnerable (Shor's algorithm) | Supported, with transition plan |
13
+ | ML-DSA | Quantum-resistant | **Fully supported** |
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { Blockchain, sha256 } from '@btc-vision/btc-runtime/runtime';
19
+
20
+ // Verify a signature with quantum resistance
21
+ const message = new BytesWriter(32);
22
+ message.writeString('Sign this message');
23
+ const messageHash = sha256(message.getBuffer());
24
+
25
+ // forceMLDSA = true ensures quantum-resistant verification
26
+ const isValid = Blockchain.verifySignature(
27
+ Blockchain.tx.origin, // Signer's address
28
+ signature, // Signature bytes
29
+ messageHash, // Message hash
30
+ true // Force ML-DSA (quantum-resistant)
31
+ );
32
+ ```
33
+
34
+ ## Why Quantum Resistance?
35
+
36
+ ### The Threat
37
+
38
+ - **Public keys are exposed** when addresses send transactions
39
+ - Quantum computers with ~4000 qubits could derive private keys
40
+ - Existing signatures remain safe (retroactive attack impossible)
41
+ - Future transactions from exposed addresses are at risk
42
+
43
+ ### OPNet's Approach
44
+
45
+ 1. **Dual signature support** - Both Schnorr and ML-DSA signatures
46
+ 2. **Extended addresses** - Store both Schnorr (taproot) and ML-DSA key references
47
+ 3. **Built-in key access** - `Address.mldsaPublicKey` property loads keys automatically
48
+ 4. **Consensus-managed transition** - Automatic migration from Schnorr to ML-DSA
49
+
50
+ ## ML-DSA Security Levels
51
+
52
+ OPNet supports three ML-DSA security levels, from classical Schnorr to quantum-resistant ML-DSA:
53
+
54
+ ```mermaid
55
+ ---
56
+ config:
57
+ theme: dark
58
+ ---
59
+ flowchart LR
60
+ subgraph OPNet["OPNet Security Architecture"]
61
+ subgraph Classical["Classical Security"]
62
+ C1["Schnorr<br/>256-bit<br/>Classical: Strong<br/>Quantum: Broken"]
63
+ end
64
+
65
+ subgraph PostQuantum["Post-Quantum Security Levels"]
66
+ Q1["ML-DSA-44<br/>Level2<br/>~AES-128<br/>Quantum: Strong"]
67
+ Q2["ML-DSA-65<br/>Level3<br/>~AES-192<br/>Quantum: Stronger"]
68
+ Q3["ML-DSA-87<br/>Level5<br/>~AES-256<br/>Quantum: Strongest"]
69
+ end
70
+
71
+ QC["Quantum Computer<br/>4000+ qubits"]
72
+
73
+ QC -.->|"Breaks in hours"| C1
74
+ QC -.->|"Cannot break"| Q1
75
+ QC -.->|"Cannot break"| Q2
76
+ QC -.->|"Cannot break"| Q3
77
+ end
78
+ ```
79
+
80
+ | Level | Name | Public Key | Signature | Private Key | NIST Category |
81
+ |-------|------|------------|-----------|-------------|---------------|
82
+ | Level2 | ML-DSA-44 | 1,312 bytes | 2,420 bytes | 2,560 bytes | Category 2 (~AES-128) |
83
+ | Level3 | ML-DSA-65 | 1,952 bytes | 3,309 bytes | 4,032 bytes | Category 3 (~AES-192) |
84
+ | Level5 | ML-DSA-87 | 2,592 bytes | 4,627 bytes | 4,896 bytes | Category 5 (~AES-256) |
85
+
86
+ **OPNet uses ML-DSA-44 (Level2) by default**, balancing security and performance.
87
+
88
+ ### Level Constants
89
+
90
+ ```typescript
91
+ import {
92
+ MLDSASecurityLevel,
93
+ MLDSA44_PUBLIC_KEY_LEN, // 1312
94
+ MLDSA44_SIGNATURE_LEN, // 2420
95
+ MLDSA65_PUBLIC_KEY_LEN, // 1952
96
+ MLDSA65_SIGNATURE_LEN, // 3309
97
+ MLDSA87_PUBLIC_KEY_LEN, // 2592
98
+ MLDSA87_SIGNATURE_LEN // 4627
99
+ } from '@btc-vision/btc-runtime/runtime';
100
+ ```
101
+
102
+ ## ML-DSA Signature Structure
103
+
104
+ The ML-DSA signature format follows FIPS 204:
105
+
106
+ ```mermaid
107
+ ---
108
+ config:
109
+ theme: dark
110
+ ---
111
+ flowchart LR
112
+ subgraph OPNet["OPNet Quantum-Resistant Signatures"]
113
+ subgraph MLDSA["ML-DSA-44 - Level2 - Default"]
114
+ PK["Public Key<br/>1,312 bytes"]
115
+ SIG["Signature<br/>2,420 bytes"]
116
+ SK["Private Key<br/>2,560 bytes"]
117
+ end
118
+
119
+ subgraph PKComp["Public Key Components"]
120
+ PK1["rho: seed"]
121
+ PK2["t1: compressed hint"]
122
+ end
123
+
124
+ subgraph SigComp["Signature Components"]
125
+ SIG1["c_tilde: commitment hash"]
126
+ SIG2["z: response vector"]
127
+ SIG3["h: hint"]
128
+ end
129
+ end
130
+ ```
131
+
132
+ ## The Address Class
133
+
134
+ ### Automatic ML-DSA Key Access
135
+
136
+ Every `Address` in OPNet stores the SHA256 hash of an ML-DSA public key. The full public key is automatically loaded on demand:
137
+
138
+ ```typescript
139
+ import { Address, Blockchain } from '@btc-vision/btc-runtime/runtime';
140
+
141
+ // Any address can access its ML-DSA public key
142
+ const sender: Address = Blockchain.tx.sender;
143
+
144
+ // Get the ML-DSA public key (loaded automatically from the blockchain)
145
+ const mldsaKey: Uint8Array = sender.mldsaPublicKey;
146
+
147
+ // The key is cached after first access for efficiency
148
+ const sameKey: Uint8Array = sender.mldsaPublicKey; // Returns cached key
149
+ ```
150
+
151
+ **Key points:**
152
+ - No custom storage needed - the runtime handles key storage
153
+ - Keys are lazily loaded on first access and cached
154
+ - The address itself is the SHA256 hash of the ML-DSA public key
155
+
156
+ ### How It Works Internally
157
+
158
+ ```typescript
159
+ // Address stores 32-byte SHA256 hash of ML-DSA public key
160
+ class Address extends Uint8Array {
161
+ protected _mldsaPublicKey: Uint8Array | null = null;
162
+
163
+ // Getter loads key from blockchain on demand
164
+ public get mldsaPublicKey(): Uint8Array {
165
+ if (!this._mldsaPublicKey) {
166
+ this._mldsaPublicKey = loadMLDSAPublicKey(this, MLDSASecurityLevel.Level2);
167
+ }
168
+ return this._mldsaPublicKey;
169
+ }
170
+ }
171
+ ```
172
+
173
+ ## Extended Address
174
+
175
+ `ExtendedAddress` supports dual-key addresses for the quantum transition:
176
+
177
+ ```typescript
178
+ import { ExtendedAddress } from '@btc-vision/btc-runtime/runtime';
179
+
180
+ // Create from both key components
181
+ const extAddr = ExtendedAddress.fromStringPair(
182
+ '0x' + 'aa'.repeat(32), // Tweaked Schnorr key (taproot)
183
+ '0x' + 'bb'.repeat(32) // ML-DSA key hash
184
+ );
185
+
186
+ // Access the tweaked Schnorr key (for taproot/P2TR)
187
+ const schnorrKey: Uint8Array = extAddr.tweakedPublicKey; // 32 bytes
188
+
189
+ // Access the ML-DSA public key (inherited from Address)
190
+ const mldsaKey: Uint8Array = extAddr.mldsaPublicKey; // 1312 bytes (ML-DSA-44)
191
+
192
+ // Generate Bitcoin addresses
193
+ const p2trAddress: string = extAddr.p2tr(); // "bc1p..." or "tb1p..."
194
+ ```
195
+
196
+ ### Dual Key Structure
197
+
198
+ ```
199
+ ExtendedAddress (64 bytes reference)
200
+ +-- tweakedPublicKey: Uint8Array[32] --> Schnorr (taproot)
201
+ +-- Address bytes: Uint8Array[32] --> SHA256(ML-DSA public key)
202
+ +-> .mldsaPublicKey loads full key
203
+ ```
204
+
205
+ ## ML-DSA Key Generation and Verification Flow
206
+
207
+ The following diagram shows the complete lifecycle from key generation to signature verification:
208
+
209
+ ```mermaid
210
+ ---
211
+ config:
212
+ theme: dark
213
+ ---
214
+ sequenceDiagram
215
+ participant User as 👤 User
216
+ participant Wallet as Wallet
217
+ participant Blockchain as OPNet Runtime
218
+ participant Contract as Contract
219
+
220
+ Note over User,Blockchain: Key Generation (Off-chain)
221
+ User->>Wallet: Generate ML-DSA keypair
222
+ Wallet->>Wallet: Generate random seed
223
+ Wallet->>Wallet: Expand seed to matrix A
224
+ Wallet->>Wallet: Sample secret vectors s1, s2
225
+ Wallet->>Wallet: Compute t = As1 + s2
226
+ Wallet->>Wallet: Public key = (rho, t1)
227
+ Wallet->>Wallet: Private key = (rho, K, tr, s1, s2, t0)
228
+
229
+ Note over User,Blockchain: Address Creation
230
+ Wallet->>Wallet: Hash ML-DSA public key (SHA256)
231
+ Wallet->>Wallet: Store 32-byte hash as Address
232
+ Wallet->>Blockchain: Register address with full public key
233
+
234
+ Note over User,Contract: Signature Verification
235
+ User->>Contract: call method(signature, message)
236
+ Contract->>Contract: Get sender address (32-byte hash)
237
+ Contract->>Blockchain: verifySignature(address, sig, hash, true)
238
+ Blockchain->>Blockchain: Load cached ML-DSA public key
239
+ Note over Blockchain: If not cached, load from storage
240
+ Blockchain->>Blockchain: Verify ML-DSA signature
241
+ Blockchain->>Blockchain: Decode signature (c_tilde, z, h)
242
+ Blockchain->>Blockchain: Reconstruct commitment w'
243
+ Blockchain->>Blockchain: Verify ||z|| < gamma1 - beta
244
+ Blockchain->>Blockchain: Verify high-order bits match
245
+ Blockchain-->>Contract: valid: bool
246
+ ```
247
+
248
+ ## Signature Verification
249
+
250
+ ### The Simple Way (Recommended)
251
+
252
+ Just use `Blockchain.verifySignature()` - it handles everything:
253
+
254
+ ```typescript
255
+ import { Blockchain, sha256 } from '@btc-vision/btc-runtime/runtime';
256
+
257
+ @method(ABIDataTypes.BYTES)
258
+ @returns({ name: 'valid', type: ABIDataTypes.BOOL })
259
+ public verifySignature(calldata: Calldata): BytesWriter {
260
+ const signature = calldata.readBytesWithLength();
261
+
262
+ // Create message hash
263
+ const message = new BytesWriter(55);
264
+ message.writeString('Hello, world! This is a test message for MLDSA signing.');
265
+ const messageHash = sha256(message.getBuffer());
266
+
267
+ // Verify with quantum resistance (forceMLDSA = true)
268
+ const isValid = Blockchain.verifySignature(
269
+ Blockchain.tx.origin,
270
+ signature,
271
+ messageHash,
272
+ true // Force ML-DSA
273
+ );
274
+
275
+ const writer = new BytesWriter(1);
276
+ writer.writeBoolean(isValid);
277
+ return writer;
278
+ }
279
+ ```
280
+
281
+ ### Consensus-Aware Verification
282
+
283
+ Let the consensus decide which algorithm to use:
284
+
285
+ ```typescript
286
+ // During transition: uses Schnorr if allowed, ML-DSA otherwise
287
+ // After transition: always uses ML-DSA
288
+ const isValid = Blockchain.verifySignature(
289
+ signer,
290
+ signature,
291
+ messageHash,
292
+ false // Let consensus decide
293
+ );
294
+ ```
295
+
296
+ ### Direct ML-DSA Verification
297
+
298
+ For cases where you need explicit control:
299
+
300
+ ```typescript
301
+ import { MLDSASecurityLevel } from '@btc-vision/btc-runtime/runtime';
302
+
303
+ const isValid = Blockchain.verifyMLDSASignature(
304
+ MLDSASecurityLevel.Level2, // Security level
305
+ signer.mldsaPublicKey, // Auto-loaded from address
306
+ signature, // 2420-byte signature
307
+ messageHash // 32-byte message hash
308
+ );
309
+ ```
310
+
311
+ ## Migration Path: Schnorr to ML-DSA
312
+
313
+ OPNet manages a phased transition from classical to quantum-resistant signatures:
314
+
315
+ ```mermaid
316
+ ---
317
+ config:
318
+ theme: dark
319
+ ---
320
+ sequenceDiagram
321
+ participant User as User/Wallet
322
+ participant Network as OPNet Network
323
+ participant Consensus as Consensus Rules
324
+
325
+ Note over User,Consensus: Phase 1: Transition Period (Current)
326
+ User->>Network: Submit Schnorr signature
327
+ Network->>Consensus: Check UNSAFE_QUANTUM_SIGNATURES_ALLOWED
328
+ Consensus-->>Network: Flag = true
329
+ Network-->>User: Signature accepted
330
+ User->>Network: Submit ML-DSA signature
331
+ Network-->>User: Signature accepted
332
+ Note over Network: Both signature types valid
333
+
334
+ Note over User,Consensus: Phase 2: Warning Period
335
+ User->>Network: Submit Schnorr signature
336
+ Network->>Consensus: Check signature type
337
+ Consensus-->>Network: Log deprecation warning
338
+ Network-->>User: Signature accepted (with warning)
339
+ Note over User: Encouraged to migrate to ML-DSA
340
+
341
+ Note over User,Consensus: Phase 3: Quantum-Safe Only
342
+ User->>Network: Submit Schnorr signature
343
+ Network->>Consensus: Check UNSAFE_QUANTUM_SIGNATURES_ALLOWED
344
+ Consensus-->>Network: Flag = false
345
+ Network-->>User: Signature REJECTED
346
+ User->>Network: Submit ML-DSA signature
347
+ Network-->>User: Signature accepted
348
+ Note over Network: Only ML-DSA signatures valid
349
+ ```
350
+
351
+ The `UNSAFE_QUANTUM_SIGNATURES_ALLOWED` consensus flag controls whether Schnorr signatures are still permitted. When disabled, only ML-DSA signatures will be valid.
352
+
353
+ ## Complete Contract Example
354
+
355
+ ```typescript
356
+ import {
357
+ OP_NET,
358
+ Blockchain,
359
+ Calldata,
360
+ BytesWriter,
361
+ Revert,
362
+ sha256,
363
+ ABIDataTypes
364
+ } from '@btc-vision/btc-runtime/runtime';
365
+
366
+ @final
367
+ class QuantumSecureContract extends OP_NET {
368
+
369
+ @method(
370
+ { name: 'message', type: ABIDataTypes.BYTES },
371
+ { name: 'signature', type: ABIDataTypes.BYTES },
372
+ )
373
+ @returns({ name: 'valid', type: ABIDataTypes.BOOL })
374
+ public verifyQuantum(calldata: Calldata): BytesWriter {
375
+ const message = calldata.readBytesWithLength();
376
+ const signature = calldata.readBytesWithLength();
377
+
378
+ const messageHash = sha256(message);
379
+
380
+ // Always use quantum-resistant verification
381
+ const isValid = Blockchain.verifySignature(
382
+ Blockchain.tx.origin,
383
+ signature,
384
+ messageHash,
385
+ true // Force ML-DSA
386
+ );
387
+
388
+ const writer = new BytesWriter(1);
389
+ writer.writeBoolean(isValid);
390
+ return writer;
391
+ }
392
+
393
+ @method(
394
+ { name: 'signer', type: ABIDataTypes.ADDRESS },
395
+ { name: 'message', type: ABIDataTypes.BYTES },
396
+ { name: 'signature', type: ABIDataTypes.BYTES },
397
+ )
398
+ @returns({ name: 'valid', type: ABIDataTypes.BOOL })
399
+ public verifyForAddress(calldata: Calldata): BytesWriter {
400
+ const signer = calldata.readAddress();
401
+ const message = calldata.readBytesWithLength();
402
+ const signature = calldata.readBytesWithLength();
403
+
404
+ const messageHash = sha256(message);
405
+
406
+ // Verify for a specific address
407
+ const isValid = Blockchain.verifySignature(
408
+ signer,
409
+ signature,
410
+ messageHash,
411
+ true
412
+ );
413
+
414
+ const writer = new BytesWriter(1);
415
+ writer.writeBoolean(isValid);
416
+ return writer;
417
+ }
418
+
419
+ @method({ name: 'owner', type: ABIDataTypes.ADDRESS })
420
+ @returns({ name: 'keyLength', type: ABIDataTypes.UINT32 })
421
+ public getMLDSAKeyLength(calldata: Calldata): BytesWriter {
422
+ const owner = calldata.readAddress();
423
+
424
+ // Access ML-DSA public key - automatically loaded
425
+ const mldsaKey = owner.mldsaPublicKey;
426
+
427
+ const writer = new BytesWriter(4);
428
+ writer.writeU32(mldsaKey.length); // 1312 for Level2
429
+ return writer;
430
+ }
431
+ }
432
+ ```
433
+
434
+ ## Solidity vs OPNet: Quantum Resistance Comparison
435
+
436
+ OPNet is the first smart contract platform with built-in quantum-resistant cryptography. Solidity and the EVM have no quantum resistance capabilities.
437
+
438
+ ### Feature Comparison Table
439
+
440
+ | Feature | Solidity/EVM | OPNet | OPNet Advantage |
441
+ |---------|--------------|-------|-----------------|
442
+ | **Quantum-Safe Signatures** | Not supported | ML-DSA (FIPS 204) | Future-proof security |
443
+ | **Post-Quantum Algorithm** | None | ML-DSA-44/65/87 | NIST standardized |
444
+ | **Dual-Key Architecture** | Not available | Schnorr + ML-DSA | Smooth transition |
445
+ | **Key Loading** | Manual storage/derivation | Automatic via `Address` | Zero setup required |
446
+ | **Consensus Migration** | Not applicable | Built-in transition plan | Network-coordinated |
447
+ | **Security Levels** | ECDSA only | 3 ML-DSA levels | Flexible security |
448
+ | **Algorithm Selection** | Fixed (ECDSA) | Consensus-aware | Automatic switching |
449
+
450
+ ### Quantum Threat Analysis
451
+
452
+ | Algorithm | Shor's Algorithm Impact | Grover's Algorithm Impact | Status in OPNet |
453
+ |-----------|------------------------|---------------------------|-----------------|
454
+ | ECDSA (Solidity) | **Broken** (polynomial time) | Weakened | Not used |
455
+ | Schnorr (OPNet) | **Broken** (polynomial time) | Weakened | Transition only |
456
+ | ML-DSA (OPNet) | **Secure** | Minimal impact | **Recommended** |
457
+
458
+ ### Security Level Comparison
459
+
460
+ | Security Level | Solidity | OPNet ML-DSA | NIST Category | Quantum Security |
461
+ |----------------|----------|--------------|---------------|------------------|
462
+ | ~AES-128 equivalent | ECDSA (broken by quantum) | ML-DSA-44 (Level2) | Category 2 | **Secure** |
463
+ | ~AES-192 equivalent | Not available | ML-DSA-65 (Level3) | Category 3 | **Secure** |
464
+ | ~AES-256 equivalent | Not available | ML-DSA-87 (Level5) | Category 5 | **Secure** |
465
+
466
+ ### Key and Signature Size Comparison
467
+
468
+ | Metric | Solidity (ECDSA) | OPNet (Schnorr) | OPNet (ML-DSA-44) | OPNet (ML-DSA-87) |
469
+ |--------|------------------|-----------------|-------------------|-------------------|
470
+ | Public Key Size | 33/65 bytes | 32 bytes | 1,312 bytes | 2,592 bytes |
471
+ | Signature Size | 65 bytes | 64 bytes | 2,420 bytes | 4,627 bytes |
472
+ | Private Key Size | 32 bytes | 32 bytes | 2,560 bytes | 4,896 bytes |
473
+ | Quantum Safe | **No** | **No** | **Yes** | **Yes** |
474
+
475
+ ### Capability Matrix
476
+
477
+ | Capability | Solidity | OPNet |
478
+ |------------|:--------:|:-----:|
479
+ | ECDSA verification | Yes | No (deprecated) |
480
+ | Schnorr verification | No | Yes |
481
+ | ML-DSA-44 verification | No | Yes |
482
+ | ML-DSA-65 verification | No | Yes |
483
+ | ML-DSA-87 verification | No | Yes |
484
+ | Automatic public key loading | No | Yes |
485
+ | Quantum-resistant addresses | No | Yes |
486
+ | Dual-key addresses | No | Yes |
487
+ | Consensus-aware algorithm | No | Yes |
488
+ | Phased migration support | No | Yes |
489
+
490
+ ### Timeline: Quantum Threat vs Platform Readiness
491
+
492
+ | Timeframe | Quantum Computer Status | Solidity Status | OPNet Status |
493
+ |-----------|------------------------|-----------------|--------------|
494
+ | **2024-2025** | Early NISQ era (~1000 qubits) | Vulnerable (no plan) | ML-DSA ready |
495
+ | **2026-2030** | Scaling (~4000+ qubits possible) | **Critical risk** | Dual-key transition |
496
+ | **2030+** | Cryptographically relevant | **Funds at risk** | ML-DSA only (secure) |
497
+
498
+ ### Migration Path Comparison
499
+
500
+ ```mermaid
501
+ ---
502
+ config:
503
+ theme: dark
504
+ ---
505
+ flowchart LR
506
+ subgraph Solidity["Solidity/EVM - No Migration Path"]
507
+ S1["ECDSA Only"] --> S2["No quantum option"]
508
+ S2 --> S3["Fork required?"]
509
+ S3 --> S4["Funds at risk"]
510
+ end
511
+
512
+ subgraph OPNet["OPNet - Built-in Migration"]
513
+ O1["Schnorr (current)"] --> O2["Dual-key period"]
514
+ O2 --> O3["ML-DSA only"]
515
+ O3 --> O4["Quantum secure"]
516
+ end
517
+ ```
518
+
519
+ ### Signature Verification Comparison
520
+
521
+ #### Solidity: No Quantum Protection
522
+
523
+ ```solidity
524
+ // Solidity - Vulnerable to quantum attacks
525
+ // There is NO way to add quantum resistance to Solidity/EVM
526
+ function verify(bytes32 hash, uint8 v, bytes32 r, bytes32 s) external view returns (bool) {
527
+ address recovered = ecrecover(hash, v, r, s);
528
+ return recovered == expectedSigner;
529
+
530
+ // CRITICAL VULNERABILITIES:
531
+ // - ECDSA is broken by Shor's algorithm
532
+ // - No upgrade path to quantum-safe algorithms
533
+ // - All funds signed with exposed public keys at risk
534
+ // - No way to add ML-DSA or other PQC algorithms
535
+ }
536
+
537
+ // Even with precompiles, no quantum-safe option exists
538
+ // EIP proposals for PQC have not been implemented
539
+ ```
540
+
541
+ #### OPNet: Built-in Quantum Resistance
542
+
543
+ ```typescript
544
+ // OPNet - Quantum-resistant
545
+ @method(
546
+ { name: 'hash', type: ABIDataTypes.BYTES32 },
547
+ { name: 'signature', type: ABIDataTypes.BYTES },
548
+ )
549
+ @returns({ name: 'valid', type: ABIDataTypes.BOOL })
550
+ public verify(calldata: Calldata): BytesWriter {
551
+ const hash = calldata.readBytes(32);
552
+ const signature = calldata.readBytesWithLength();
553
+
554
+ // ML-DSA provides quantum resistance
555
+ // FIPS 204 standardized algorithm
556
+ // Public key loaded automatically from address
557
+ const valid = Blockchain.verifySignature(
558
+ this.expectedSigner.value,
559
+ signature,
560
+ hash,
561
+ true // Force quantum-resistant ML-DSA
562
+ );
563
+
564
+ const writer = new BytesWriter(1);
565
+ writer.writeBoolean(valid);
566
+ return writer;
567
+ }
568
+
569
+ // Advantages:
570
+ // - ML-DSA is quantum-resistant (lattice-based)
571
+ // - NIST standardized (FIPS 204)
572
+ // - Automatic key loading from address
573
+ // - Consensus-managed transition
574
+ // - No code changes needed for migration
575
+ ```
576
+
577
+ ### Public Key Access Comparison
578
+
579
+ ```solidity
580
+ // Solidity - Must store or derive public key
581
+ contract SolidityContract {
582
+ // Must manually store public keys
583
+ mapping(address => bytes) public publicKeys;
584
+
585
+ function registerKey(bytes calldata pubkey) external {
586
+ // Verify key matches address
587
+ require(address(uint160(uint256(keccak256(pubkey)))) == msg.sender);
588
+ publicKeys[msg.sender] = pubkey;
589
+ }
590
+
591
+ // No way to store/use ML-DSA keys (1,312+ bytes each!)
592
+ // Storage costs would be prohibitive
593
+ }
594
+ ```
595
+
596
+ ```typescript
597
+ // OPNet - Automatic key access
598
+ @final
599
+ class OPNetContract extends OP_NET {
600
+
601
+ public getPublicKey(calldata: Calldata): BytesWriter {
602
+ const user = calldata.readAddress();
603
+
604
+ // ML-DSA public key loaded automatically!
605
+ // No storage needed - runtime handles it
606
+ const mldsaKey = user.mldsaPublicKey; // 1,312 bytes
607
+
608
+ // Key is cached after first access
609
+ const writer = new BytesWriter(4);
610
+ writer.writeU32(mldsaKey.length);
611
+ return writer;
612
+ }
613
+ }
614
+ ```
615
+
616
+ ### Why OPNet for Quantum Security?
617
+
618
+ | Solidity Limitation | OPNet Solution |
619
+ |---------------------|----------------|
620
+ | ECDSA only (quantum vulnerable) | ML-DSA (quantum resistant) |
621
+ | No upgrade path | Built-in consensus migration |
622
+ | Must store large keys manually | Automatic key loading |
623
+ | No NIST PQC algorithms | FIPS 204 ML-DSA |
624
+ | Single key per address | Dual-key architecture |
625
+ | Fixed algorithm forever | Consensus-aware selection |
626
+ | Fork required for PQC | Smooth transition built-in |
627
+ | All funds at risk | Protected from day one |
628
+
629
+ ### Cost Comparison
630
+
631
+ | Operation | Solidity | OPNet Cost | Notes |
632
+ |-----------|----------|------------|-------|
633
+ | Store ML-DSA public key | Not practical (1,312 bytes) | 0 | OPNet loads automatically |
634
+ | Store ML-DSA signature | Not practical (2,420 bytes) | N/A | Not stored, verified |
635
+ | Quantum-safe verification | Not possible | Standard | No additional cost |
636
+ | Key migration | Contract redeploy | Consensus-managed | No user action needed |
637
+
638
+ ## Best Practices
639
+
640
+ 1. **Use `Address.mldsaPublicKey`** - Don't store ML-DSA keys manually; the Address class handles key loading and caching automatically (see [The Address Class](#the-address-class))
641
+
642
+ 2. **Force ML-DSA for high-security operations** - Set `forceMLDSA = true` in `Blockchain.verifySignature()` for critical operations (see [Signature Verification](#signature-verification))
643
+
644
+ 3. **Use consensus-aware verification for general use** - Set `forceMLDSA = false` to let the network decide which algorithm to use during the transition period
645
+
646
+ 4. **Document security level** - When using quantum-resistant signatures, document the ML-DSA level in your contract comments:
647
+
648
+ ```typescript
649
+ /**
650
+ * Security Note: This contract uses ML-DSA-44 for quantum resistance.
651
+ * ML-DSA-44 provides NIST Category 2 security (~AES-128 equivalent).
652
+ * For higher security requirements, ML-DSA-65 or ML-DSA-87 may be used.
653
+ */
654
+ ```
655
+
656
+ ---
657
+
658
+ **Navigation:**
659
+ - Previous: [Signature Verification](./signature-verification.md)
660
+ - Next: [Bitcoin Scripts](./bitcoin-scripts.md)