@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.
- package/LICENSE +190 -0
- package/README.md +258 -137
- package/SECURITY.md +226 -0
- package/docs/README.md +614 -0
- package/docs/advanced/bitcoin-scripts.md +939 -0
- package/docs/advanced/cross-contract-calls.md +579 -0
- package/docs/advanced/plugins.md +1006 -0
- package/docs/advanced/quantum-resistance.md +660 -0
- package/docs/advanced/signature-verification.md +715 -0
- package/docs/api-reference/blockchain.md +729 -0
- package/docs/api-reference/events.md +642 -0
- package/docs/api-reference/op20.md +902 -0
- package/docs/api-reference/op721.md +819 -0
- package/docs/api-reference/safe-math.md +510 -0
- package/docs/api-reference/storage.md +840 -0
- package/docs/contracts/op-net-base.md +786 -0
- package/docs/contracts/op20-token.md +687 -0
- package/docs/contracts/op20s-signatures.md +614 -0
- package/docs/contracts/op721-nft.md +785 -0
- package/docs/contracts/reentrancy-guard.md +787 -0
- package/docs/core-concepts/blockchain-environment.md +724 -0
- package/docs/core-concepts/decorators.md +466 -0
- package/docs/core-concepts/events.md +652 -0
- package/docs/core-concepts/pointers.md +391 -0
- package/docs/core-concepts/security.md +473 -0
- package/docs/core-concepts/storage-system.md +969 -0
- package/docs/examples/basic-token.md +745 -0
- package/docs/examples/nft-with-reservations.md +1440 -0
- package/docs/examples/oracle-integration.md +1212 -0
- package/docs/examples/stablecoin.md +1180 -0
- package/docs/getting-started/first-contract.md +575 -0
- package/docs/getting-started/installation.md +384 -0
- package/docs/getting-started/project-structure.md +630 -0
- package/docs/storage/memory-maps.md +764 -0
- package/docs/storage/stored-arrays.md +778 -0
- package/docs/storage/stored-maps.md +758 -0
- package/docs/storage/stored-primitives.md +655 -0
- package/docs/types/address.md +773 -0
- package/docs/types/bytes-writer-reader.md +938 -0
- package/docs/types/calldata.md +744 -0
- package/docs/types/safe-math.md +446 -0
- package/package.json +52 -27
- package/runtime/memory/MapOfMap.ts +1 -0
- 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)
|