hotshot_types/
signature_key.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7//! Types and structs for the hotshot signature keys
8
9use alloy::primitives::U256;
10use ark_serialize::SerializationError;
11use bitvec::{slice::BitSlice, vec::BitVec};
12use digest::generic_array::GenericArray;
13use jf_signature::{
14    bls_over_bn254::{BLSOverBN254CurveSignatureScheme, KeyPair, SignKey, VerKey},
15    SignatureError, SignatureScheme,
16};
17use rand::SeedableRng;
18use rand_chacha::ChaCha20Rng;
19use tracing::instrument;
20
21use crate::{
22    light_client::{LightClientState, StakeTableState},
23    qc::{BitVectorQc, QcParams},
24    stake_table::StakeTableEntry,
25    traits::{
26        qc::QuorumCertificateScheme,
27        signature_key::{
28            BuilderSignatureKey, PrivateSignatureKey, SignatureKey, StateSignatureKey,
29        },
30    },
31};
32
33/// BLS private key used to sign a consensus message
34pub type BLSPrivKey = SignKey;
35/// BLS public key used to verify a consensus signature
36pub type BLSPubKey = VerKey;
37/// BLS key pair used to sign and verify a consensus message
38pub type BLSKeyPair = KeyPair;
39/// Public parameters for BLS signature scheme
40pub type BLSPublicParam = ();
41/// BLS signature type for consensus votes
42pub type BLSSignature = jf_signature::bls_over_bn254::Signature;
43
44impl PrivateSignatureKey for BLSPrivKey {
45    fn to_bytes(&self) -> Vec<u8> {
46        self.to_bytes()
47    }
48
49    fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
50        Ok(Self::from_bytes(bytes))
51    }
52
53    fn to_tagged_base64(&self) -> Result<tagged_base64::TaggedBase64, tagged_base64::Tb64Error> {
54        self.to_tagged_base64()
55    }
56}
57
58impl SignatureKey for BLSPubKey {
59    type PrivateKey = BLSPrivKey;
60    type StakeTableEntry = StakeTableEntry<VerKey>;
61    type QcParams<'a> = QcParams<
62        'a,
63        BLSPubKey,
64        <BLSOverBN254CurveSignatureScheme as SignatureScheme>::PublicParameter,
65    >;
66    type PureAssembledSignatureType =
67        <BLSOverBN254CurveSignatureScheme as SignatureScheme>::Signature;
68    type QcType = (Self::PureAssembledSignatureType, BitVec);
69    type SignError = SignatureError;
70
71    #[instrument(skip(self))]
72    fn validate(&self, signature: &Self::PureAssembledSignatureType, data: &[u8]) -> bool {
73        // This is the validation for QC partial signature before append().
74        BLSOverBN254CurveSignatureScheme::verify(&(), self, data, signature).is_ok()
75    }
76
77    fn sign(
78        sk: &Self::PrivateKey,
79        data: &[u8],
80    ) -> Result<Self::PureAssembledSignatureType, Self::SignError> {
81        BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
82            &(),
83            sk,
84            data,
85            &mut rand::thread_rng(),
86        )
87    }
88
89    fn from_private(private_key: &Self::PrivateKey) -> Self {
90        BLSPubKey::from(private_key)
91    }
92
93    fn to_bytes(&self) -> Vec<u8> {
94        let mut buf = vec![];
95        ark_serialize::CanonicalSerialize::serialize_compressed(self, &mut buf)
96            .expect("Serialization should not fail.");
97        buf
98    }
99
100    fn from_bytes(bytes: &[u8]) -> Result<Self, SerializationError> {
101        ark_serialize::CanonicalDeserialize::deserialize_compressed(bytes)
102    }
103
104    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::PrivateKey) {
105        let mut hasher = blake3::Hasher::new();
106        hasher.update(&seed);
107        hasher.update(&index.to_le_bytes());
108        let new_seed = *hasher.finalize().as_bytes();
109        let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
110        (kp.ver_key(), kp.sign_key_ref().clone())
111    }
112
113    fn stake_table_entry(&self, stake: U256) -> Self::StakeTableEntry {
114        StakeTableEntry {
115            stake_key: *self,
116            stake_amount: stake,
117        }
118    }
119
120    fn public_key(entry: &Self::StakeTableEntry) -> Self {
121        entry.stake_key
122    }
123
124    fn public_parameter(
125        stake_entries: &'_ [Self::StakeTableEntry],
126        threshold: U256,
127    ) -> Self::QcParams<'_> {
128        QcParams {
129            stake_entries,
130            threshold,
131            agg_sig_pp: (),
132        }
133    }
134
135    fn check(
136        real_qc_pp: &Self::QcParams<'_>,
137        data: &[u8],
138        qc: &Self::QcType,
139    ) -> Result<(), SignatureError> {
140        let msg = GenericArray::from_slice(data);
141        BitVectorQc::<BLSOverBN254CurveSignatureScheme>::check(real_qc_pp, msg, qc).map(|_| ())
142    }
143
144    fn sig_proof(signature: &Self::QcType) -> (Self::PureAssembledSignatureType, BitVec) {
145        signature.clone()
146    }
147
148    fn assemble(
149        real_qc_pp: &Self::QcParams<'_>,
150        signers: &BitSlice,
151        sigs: &[Self::PureAssembledSignatureType],
152    ) -> Self::QcType {
153        BitVectorQc::<BLSOverBN254CurveSignatureScheme>::assemble(real_qc_pp, signers, sigs)
154            .expect("this assembling shouldn't fail")
155    }
156
157    fn genesis_proposer_pk() -> Self {
158        let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed([0u8; 32]));
159        kp.ver_key()
160    }
161}
162
163// Currently implement builder signature key for BLS
164// So copy pasta here, but actually Sequencer will implement the same trait for ethereum types
165/// Builder signature key
166pub type BuilderKey = BLSPubKey;
167
168impl BuilderSignatureKey for BuilderKey {
169    type BuilderPrivateKey = BLSPrivKey;
170    type BuilderSignature = <BLSOverBN254CurveSignatureScheme as SignatureScheme>::Signature;
171    type SignError = SignatureError;
172
173    fn sign_builder_message(
174        private_key: &Self::BuilderPrivateKey,
175        data: &[u8],
176    ) -> Result<Self::BuilderSignature, Self::SignError> {
177        BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
178            &(),
179            private_key,
180            data,
181            &mut rand::thread_rng(),
182        )
183    }
184
185    fn validate_builder_signature(&self, signature: &Self::BuilderSignature, data: &[u8]) -> bool {
186        BLSOverBN254CurveSignatureScheme::verify(&(), self, data, signature).is_ok()
187    }
188
189    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::BuilderPrivateKey) {
190        let mut hasher = blake3::Hasher::new();
191        hasher.update(&seed);
192        hasher.update(&index.to_le_bytes());
193        let new_seed = *hasher.finalize().as_bytes();
194        let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
195        (kp.ver_key(), kp.sign_key_ref().clone())
196    }
197}
198
199pub type SchnorrPubKey = jf_signature::schnorr::VerKey<ark_ed_on_bn254::EdwardsConfig>;
200pub type SchnorrPrivKey = jf_signature::schnorr::SignKey<ark_ed_on_bn254::Fr>;
201pub type SchnorrSignatureScheme =
202    jf_signature::schnorr::SchnorrSignatureScheme<ark_ed_on_bn254::EdwardsConfig>;
203
204impl PrivateSignatureKey for SchnorrPrivKey {
205    fn to_bytes(&self) -> Vec<u8> {
206        self.to_bytes()
207    }
208
209    fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
210        Ok(Self::from_bytes(bytes))
211    }
212
213    fn to_tagged_base64(&self) -> Result<tagged_base64::TaggedBase64, tagged_base64::Tb64Error> {
214        self.to_tagged_base64()
215    }
216}
217
218impl StateSignatureKey for SchnorrPubKey {
219    type StatePrivateKey = SchnorrPrivKey;
220
221    type StateSignature = jf_signature::schnorr::Signature<ark_ed_on_bn254::EdwardsConfig>;
222
223    type SignError = SignatureError;
224
225    fn sign_state(
226        sk: &Self::StatePrivateKey,
227        light_client_state: &LightClientState,
228        next_stake_table_state: &StakeTableState,
229    ) -> Result<Self::StateSignature, Self::SignError> {
230        let mut msg = Vec::with_capacity(7);
231        let state_msg: [_; 3] = light_client_state.into();
232        msg.extend_from_slice(&state_msg);
233        let adv_st_state_msg: [_; 4] = (*next_stake_table_state).into();
234        msg.extend_from_slice(&adv_st_state_msg);
235        SchnorrSignatureScheme::sign(&(), sk, msg, &mut rand::thread_rng())
236    }
237
238    fn verify_state_sig(
239        &self,
240        signature: &Self::StateSignature,
241        light_client_state: &LightClientState,
242        next_stake_table_state: &StakeTableState,
243    ) -> bool {
244        let mut msg = Vec::with_capacity(7);
245        let state_msg: [_; 3] = light_client_state.into();
246        msg.extend_from_slice(&state_msg);
247        let adv_st_state_msg: [_; 4] = (*next_stake_table_state).into();
248        msg.extend_from_slice(&adv_st_state_msg);
249        SchnorrSignatureScheme::verify(&(), self, msg, signature).is_ok()
250    }
251
252    fn legacy_sign_state(
253        sk: &Self::StatePrivateKey,
254        light_client_state: &LightClientState,
255    ) -> Result<Self::StateSignature, Self::SignError> {
256        let state_msg: [_; 3] = light_client_state.into();
257        SchnorrSignatureScheme::sign(&(), sk, state_msg, &mut rand::thread_rng())
258    }
259
260    fn legacy_verify_state_sig(
261        &self,
262        signature: &Self::StateSignature,
263        light_client_state: &LightClientState,
264    ) -> bool {
265        let state_msg: [_; 3] = light_client_state.into();
266        SchnorrSignatureScheme::verify(&(), self, state_msg, signature).is_ok()
267    }
268
269    fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::StatePrivateKey) {
270        let mut hasher = blake3::Hasher::new();
271        hasher.update(&seed);
272        hasher.update(&index.to_le_bytes());
273        let new_seed = *hasher.finalize().as_bytes();
274        let kp = jf_signature::schnorr::KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
275        (kp.ver_key(), kp.sign_key())
276    }
277}