0
# Cryptographic Primitives
1
2
Core blockchain cryptography implementations providing Ed25519 keypairs, signatures, public keys, and SHA-256 hashing. These primitives form the foundation for all Solana operations including account identification, transaction signing, and data integrity verification.
3
4
## Capabilities
5
6
### Public Key Operations
7
8
Solana addresses and program identifiers represented as 32-byte Ed25519 public keys with derivation and validation capabilities.
9
10
```python { .api }
11
class Pubkey:
12
"""
13
Represents a 32-byte Solana public key used for addresses and program IDs.
14
"""
15
def __init__(self, value: bytes):
16
"""
17
Create a Pubkey from 32 bytes.
18
19
Parameters:
20
- value: bytes, exactly 32 bytes representing the public key
21
22
Raises:
23
- ValueError: if value is not exactly 32 bytes
24
"""
25
26
@classmethod
27
def from_string(cls, s: str) -> 'Pubkey':
28
"""
29
Parse a base58-encoded string into a Pubkey.
30
31
Parameters:
32
- s: str, base58-encoded public key string
33
34
Returns:
35
Pubkey object
36
37
Raises:
38
- ValueError: if string is not valid base58 or wrong length
39
"""
40
41
@classmethod
42
def from_bytes(cls, data: bytes) -> 'Pubkey':
43
"""
44
Create Pubkey from byte array.
45
46
Parameters:
47
- data: bytes, public key data
48
49
Returns:
50
Pubkey object
51
"""
52
53
@staticmethod
54
def find_program_address(seeds: List[bytes], program_id: 'Pubkey') -> Tuple['Pubkey', int]:
55
"""
56
Find a program derived address (PDA) with bump seed.
57
58
Parameters:
59
- seeds: List[bytes], seed components for derivation
60
- program_id: Pubkey, program that owns the derived address
61
62
Returns:
63
Tuple of (derived_pubkey, bump_seed)
64
"""
65
66
@staticmethod
67
def create_program_address(seeds: List[bytes], program_id: 'Pubkey') -> 'Pubkey':
68
"""
69
Create program address from seeds (must not be on Ed25519 curve).
70
71
Parameters:
72
- seeds: List[bytes], seed components including bump
73
- program_id: Pubkey, program that owns the derived address
74
75
Returns:
76
Pubkey object
77
78
Raises:
79
- ValueError: if derived address is on Ed25519 curve
80
"""
81
82
def __str__(self) -> str:
83
"""Return base58 string representation."""
84
85
def __bytes__(self) -> bytes:
86
"""Return 32-byte representation."""
87
88
def __eq__(self, other) -> bool:
89
"""Compare equality with another Pubkey."""
90
```
91
92
### Keypair Management
93
94
Ed25519 keypair generation and management for transaction signing and account ownership.
95
96
```python { .api }
97
class Keypair:
98
"""
99
Ed25519 key pair for signing transactions and proving account ownership.
100
"""
101
def __init__(self):
102
"""Generate a new random keypair."""
103
104
@classmethod
105
def from_seed(cls, seed: bytes) -> 'Keypair':
106
"""
107
Create keypair from a 32-byte seed for deterministic generation.
108
109
Parameters:
110
- seed: bytes, exactly 32 bytes for deterministic key generation
111
112
Returns:
113
Keypair object
114
115
Raises:
116
- ValueError: if seed is not exactly 32 bytes
117
"""
118
119
@classmethod
120
def from_secret_key_bytes(cls, secret_key: bytes) -> 'Keypair':
121
"""
122
Create keypair from 64-byte secret key.
123
124
Parameters:
125
- secret_key: bytes, 64-byte Ed25519 secret key
126
127
Returns:
128
Keypair object
129
"""
130
131
@classmethod
132
def from_base58_string(cls, s: str) -> 'Keypair':
133
"""
134
Create keypair from base58-encoded secret key string.
135
136
Parameters:
137
- s: str, base58-encoded secret key
138
139
Returns:
140
Keypair object
141
"""
142
143
def pubkey(self) -> Pubkey:
144
"""
145
Get the public key component.
146
147
Returns:
148
Pubkey object representing the public key
149
"""
150
151
def secret(self) -> bytes:
152
"""
153
Get the secret key bytes.
154
155
Returns:
156
bytes, 64-byte secret key (private key + public key)
157
"""
158
159
def sign_message(self, message: bytes) -> 'Signature':
160
"""
161
Sign a message with this keypair.
162
163
Parameters:
164
- message: bytes, message to sign
165
166
Returns:
167
Signature object
168
"""
169
170
def to_base58_string(self) -> str:
171
"""
172
Export secret key as base58 string.
173
174
Returns:
175
str, base58-encoded secret key
176
"""
177
```
178
179
### Digital Signatures
180
181
Ed25519 signature creation and verification for transaction authentication.
182
183
```python { .api }
184
class Signature:
185
"""
186
Represents a 64-byte Ed25519 signature for transaction authentication.
187
"""
188
def __init__(self, signature_bytes: bytes):
189
"""
190
Create signature from 64 bytes.
191
192
Parameters:
193
- signature_bytes: bytes, exactly 64 bytes representing the signature
194
195
Raises:
196
- ValueError: if signature_bytes is not exactly 64 bytes
197
"""
198
199
@classmethod
200
def from_string(cls, s: str) -> 'Signature':
201
"""
202
Parse a base58-encoded signature string.
203
204
Parameters:
205
- s: str, base58-encoded signature string
206
207
Returns:
208
Signature object
209
210
Raises:
211
- ValueError: if string is not valid base58 or wrong length
212
"""
213
214
@classmethod
215
def default() -> 'Signature':
216
"""
217
Create a default (all zeros) signature.
218
219
Returns:
220
Signature object with all zero bytes
221
"""
222
223
def __str__(self) -> str:
224
"""Return base58 string representation."""
225
226
def __bytes__(self) -> bytes:
227
"""Return 64-byte signature."""
228
229
def __eq__(self, other) -> bool:
230
"""Compare equality with another Signature."""
231
232
def verify(self, pubkey: Pubkey, message: bytes) -> bool:
233
"""
234
Verify signature against public key and message.
235
236
Parameters:
237
- pubkey: Pubkey, public key to verify against
238
- message: bytes, original message that was signed
239
240
Returns:
241
bool, True if signature is valid
242
"""
243
```
244
245
### Hash Operations
246
247
SHA-256 hashing for blockhashes, transaction IDs, and data integrity verification.
248
249
```python { .api }
250
class Hash:
251
"""
252
Represents a 32-byte SHA-256 hash used for blockhashes and transaction IDs.
253
"""
254
def __init__(self, value: bytes):
255
"""
256
Create hash from 32 bytes.
257
258
Parameters:
259
- value: bytes, exactly 32 bytes representing the hash
260
261
Raises:
262
- ValueError: if value is not exactly 32 bytes
263
"""
264
265
@classmethod
266
def from_string(cls, s: str) -> 'Hash':
267
"""
268
Parse a base58-encoded hash string.
269
270
Parameters:
271
- s: str, base58-encoded hash string
272
273
Returns:
274
Hash object
275
276
Raises:
277
- ParseHashError: if string is not valid base58 or wrong length
278
"""
279
280
@classmethod
281
def default() -> 'Hash':
282
"""
283
Create a default (all zeros) hash.
284
285
Returns:
286
Hash object with all zero bytes
287
"""
288
289
@staticmethod
290
def hash(data: bytes) -> 'Hash':
291
"""
292
Compute SHA-256 hash of data.
293
294
Parameters:
295
- data: bytes, data to hash
296
297
Returns:
298
Hash object containing the SHA-256 digest
299
"""
300
301
@staticmethod
302
def hashv(data: List[bytes]) -> 'Hash':
303
"""
304
Compute SHA-256 hash of multiple byte arrays.
305
306
Parameters:
307
- data: List[bytes], list of byte arrays to hash together
308
309
Returns:
310
Hash object containing the SHA-256 digest
311
"""
312
313
def __str__(self) -> str:
314
"""Return base58 string representation."""
315
316
def __bytes__(self) -> bytes:
317
"""Return 32-byte hash."""
318
319
def __eq__(self, other) -> bool:
320
"""Compare equality with another Hash."""
321
```
322
323
### Alternative Signers
324
325
Non-standard signer implementations for specialized use cases.
326
327
```python { .api }
328
class NullSigner:
329
"""
330
No-op signer for read-only operations and simulation.
331
"""
332
def __init__(self, pubkey: Pubkey):
333
"""
334
Create null signer with specified public key.
335
336
Parameters:
337
- pubkey: Pubkey, public key this signer represents
338
"""
339
340
def pubkey(self) -> Pubkey:
341
"""
342
Get the public key.
343
344
Returns:
345
Pubkey object
346
"""
347
348
class Presigner:
349
"""
350
Container for pre-computed signatures.
351
"""
352
def __init__(self, pubkey: Pubkey, signature: Signature):
353
"""
354
Create presigner with public key and signature.
355
356
Parameters:
357
- pubkey: Pubkey, public key that created the signature
358
- signature: Signature, pre-computed signature
359
"""
360
361
def pubkey(self) -> Pubkey:
362
"""
363
Get the public key.
364
365
Returns:
366
Pubkey object
367
"""
368
369
def signature(self) -> Signature:
370
"""
371
Get the pre-computed signature.
372
373
Returns:
374
Signature object
375
"""
376
```
377
378
## Usage Examples
379
380
### Basic Keypair Operations
381
382
```python
383
from solders.keypair import Keypair
384
from solders.pubkey import Pubkey
385
386
# Generate new keypair
387
keypair = Keypair()
388
pubkey = keypair.pubkey()
389
print(f"Public key: {pubkey}")
390
print(f"Secret key: {keypair.to_base58_string()}")
391
392
# Create from seed for deterministic generation
393
seed = b'my_deterministic_seed_32_bytes!'
394
deterministic_keypair = Keypair.from_seed(seed)
395
396
# Sign and verify a message
397
message = b"Hello, Solana!"
398
signature = keypair.sign_message(message)
399
is_valid = signature.verify(keypair.pubkey(), message)
400
print(f"Signature valid: {is_valid}")
401
```
402
403
### Program Derived Addresses
404
405
```python
406
from solders.pubkey import Pubkey
407
408
# Find PDA for token metadata
409
mint_pubkey = Pubkey.from_string("So11111111111111111111111111111111111111112")
410
metadata_program_id = Pubkey.from_string("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
411
412
seeds = [
413
b"metadata",
414
bytes(metadata_program_id),
415
bytes(mint_pubkey)
416
]
417
418
pda, bump = Pubkey.find_program_address(seeds, metadata_program_id)
419
print(f"Metadata PDA: {pda}, bump: {bump}")
420
421
# Create the actual address with bump
422
seeds_with_bump = seeds + [bytes([bump])]
423
actual_pda = Pubkey.create_program_address(seeds_with_bump, metadata_program_id)
424
assert pda == actual_pda
425
```
426
427
### Hash Operations
428
429
```python
430
from solders.hash import Hash
431
432
# Hash single data
433
data = b"transaction_data"
434
hash_result = Hash.hash(data)
435
print(f"SHA-256 hash: {hash_result}")
436
437
# Hash multiple pieces of data
438
hash_multiple = Hash.hashv([b"part1", b"part2", b"part3"])
439
print(f"Multi-part hash: {hash_multiple}")
440
441
# Parse from string
442
hash_from_string = Hash.from_string("11111111111111111111111111111112")
443
```
444
445
## Constants and Identifiers
446
447
### Well-Known Public Keys
448
449
```python { .api }
450
# System Program ID
451
SYSTEM_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string("11111111111111111111111111111112")
452
453
# Native SOL Token Mint
454
NATIVE_MINT: Final[Pubkey] = Pubkey.from_string("So11111111111111111111111111111111111111112")
455
456
# SPL Token Program ID
457
TOKEN_PROGRAM_ID: Final[Pubkey] = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
458
```
459
460
### Default Values
461
462
```python { .api }
463
# Default signature (all zeros)
464
DEFAULT_SIGNATURE: Final[Signature] = Signature.default()
465
466
# Default hash (all zeros)
467
DEFAULT_HASH: Final[Hash] = Hash.default()
468
```
469
470
## Error Handling
471
472
### Parse Errors
473
474
```python { .api }
475
class ParseHashError(Exception):
476
"""
477
Exception raised when hash string parsing fails.
478
479
Raised by:
480
- Hash.from_string() with invalid base58 or wrong length
481
"""
482
```
483
484
Common error scenarios:
485
486
```python
487
from solders.hash import Hash, ParseHashError
488
from solders.pubkey import Pubkey
489
490
try:
491
# Invalid base58 string
492
invalid_hash = Hash.from_string("invalid_base58_string!!!")
493
except ParseHashError as e:
494
print(f"Hash parse error: {e}")
495
496
try:
497
# Wrong length bytes
498
invalid_pubkey = Pubkey(b"too_short")
499
except ValueError as e:
500
print(f"Pubkey creation error: {e}")
501
502
try:
503
# Invalid seed length
504
invalid_keypair = Keypair.from_seed(b"wrong_length")
505
except ValueError as e:
506
print(f"Keypair creation error: {e}")
507
```