1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! Key schemes: the typed layer that defines how raw secret bytes become
//! usable keys, public keys, and signatures.
//!
//! # Concept
//!
//! A *scheme* answers three questions for any key family:
//!
//! 1. **What is stored?** — Typically a 32-byte seed; sometimes a full keypair
//! or curve scalar.
//! 2. **How is a public key derived?** — Pure function of the stored bytes.
//! 3. **How is a signature produced?** — Pure function of the stored bytes and
//! a message.
//!
//! Each [`KeyScheme`] implementation also pins two on-disk identifiers:
//!
//! - A 6-byte **magic prefix** (e.g., `b"DIGVK1"`) — the first bytes of every
//! file of this scheme. Human-readable for support ("what is this file?"),
//! machine-enforceable for type safety.
//! - A 2-byte **scheme id** (e.g., `0x0001`) — included in the header to
//! guard against MAGIC-collisions if we ever need to distinguish minor
//! variants without bumping the magic.
//!
//! # Supplied schemes
//!
//! | Scheme | Magic | ID | Curve | Role |
//! |---|---|---|---|---|
//! | [`BlsSigning`] | `DIGVK1` | 0x0001 | BLS12-381 G1/G2 | DIG L2 validator signing key |
//! | [`L1WalletBls`] | `DIGLW1` | 0x0003 | BLS12-381 G1/G2 | Chia L1 wallet master seed |
//!
//! Additional schemes (e.g., `L1WalletSecp256k1` for hypothetical Ethereum L1
//! wallets, or hardware-signer wrappers) can be added by implementing the
//! trait in a fresh module.
//!
//! # Why separate types and not a runtime enum
//!
//! A runtime enum (`enum KeyType { Bls, L1Wallet, ... }`) would force every
//! caller into a `match` at every sign call. The trait-based approach:
//!
//! - Makes `Keystore<BlsSigning>` and `Keystore<L1WalletBls>` distinct types;
//! you cannot accidentally feed a validator key where a wallet key was
//! expected at compile time.
//! - Lets each scheme choose its own `PublicKey` and `Signature` associated
//! types. `BlsSigning` produces `chia_bls::Signature`; a future secp256k1
//! scheme would produce `k256::ecdsa::Signature`.
//! - Keeps the cryptographic code of each scheme localised for auditing.
//!
//! # References
//!
//! - [`chia-bls` crate](https://crates.io/crates/chia-bls) 0.26 — BLS12-381
//! primitives used by all shipped schemes.
//! - [IETF draft-irtf-cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05)
//! — the augmented BLS scheme (`BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_`)
//! `chia-bls::sign` implements.
//! - [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) — master-key
//! derivation from a seed (what `SecretKey::from_seed` follows).
use ;
use Zeroizing;
use crateResult;
pub use BlsSigning;
pub use L1WalletBls;
/// Trait implemented by every supported key scheme.
///
/// Implementors define:
/// - how to generate fresh secret bytes (typically a 32-byte seed);
/// - how to derive a public key from the secret bytes;
/// - how to sign a byte message with the secret bytes;
/// - the 6-byte on-disk magic prefix and 2-byte scheme id.
///
/// # Contract
///
/// - `public_key` and `sign` must be **pure functions** of the secret bytes
/// and message — no external state, no RNG calls. Determinism is required so
/// signatures are reproducible across runs given identical inputs.
/// - `generate` must use the provided `CryptoRng` — no `OsRng::default()`
/// shortcuts, so tests can inject a deterministic RNG.
/// - Implementors must not panic on malformed input. Return an
/// [`Err`](crate::error::KeystoreError) instead.
///
/// # Safety
///
/// Implementations are expected to handle secret bytes through zeroizing
/// wrappers and never log / Debug-print them. The [`crate::Keystore`]
/// orchestration and [`crate::SignerHandle`] guarantee that secret bytes
/// passed to `public_key` / `sign` live inside a [`Zeroizing`] buffer for the
/// duration of the call.