1use alloy::primitives::U256;
10use ark_serialize::SerializationError;
11use bitvec::{slice::BitSlice, vec::BitVec};
12use generic_array::GenericArray;
13use jf_signature::{
14 SignatureError, SignatureScheme,
15 bls_over_bn254::{BLSOverBN254CurveSignatureScheme, KeyPair, SignKey, VerKey},
16};
17use rand::SeedableRng;
18use rand_chacha::ChaCha20Rng;
19use tracing::instrument;
20
21use crate::{
22 light_client::{CircuitField, LightClientState, StakeTableState},
23 qc::{BitVectorQc, QcParams},
24 stake_table::StakeTableEntry,
25 traits::{
26 qc::QuorumCertificateScheme,
27 signature_key::{
28 BuilderSignatureKey, LCV1StateSignatureKey, LCV2StateSignatureKey,
29 LCV3StateSignatureKey, PrivateSignatureKey, SignatureKey, StateSignatureKey,
30 },
31 },
32};
33
34pub type BLSPrivKey = SignKey;
36pub type BLSPubKey = VerKey;
38pub type BLSKeyPair = KeyPair;
40pub type BLSPublicParam = ();
42pub type BLSSignature = jf_signature::bls_over_bn254::Signature;
44
45impl PrivateSignatureKey for BLSPrivKey {
46 fn to_bytes(&self) -> Vec<u8> {
47 self.to_bytes()
48 }
49
50 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
51 Ok(Self::from_bytes(bytes))
52 }
53
54 fn to_tagged_base64(&self) -> Result<tagged_base64::TaggedBase64, tagged_base64::Tb64Error> {
55 self.to_tagged_base64()
56 }
57}
58
59impl SignatureKey for BLSPubKey {
60 type PrivateKey = BLSPrivKey;
61 type StakeTableEntry = StakeTableEntry<VerKey>;
62 type QcParams<'a> = QcParams<
63 'a,
64 BLSPubKey,
65 <BLSOverBN254CurveSignatureScheme as SignatureScheme>::PublicParameter,
66 >;
67 type PureAssembledSignatureType =
68 <BLSOverBN254CurveSignatureScheme as SignatureScheme>::Signature;
69 type VerificationKeyType = Self;
70 type QcType = (Self::PureAssembledSignatureType, BitVec);
71 type SignError = SignatureError;
72
73 #[instrument(skip(self))]
74 fn validate(&self, signature: &Self::PureAssembledSignatureType, data: &[u8]) -> bool {
75 BLSOverBN254CurveSignatureScheme::verify(&(), self, data, signature).is_ok()
77 }
78
79 fn sign(
80 sk: &Self::PrivateKey,
81 data: &[u8],
82 ) -> Result<Self::PureAssembledSignatureType, Self::SignError> {
83 BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
84 &(),
85 sk,
86 data,
87 &mut rand::thread_rng(),
88 )
89 }
90
91 fn from_private(private_key: &Self::PrivateKey) -> Self {
92 BLSPubKey::from(private_key)
93 }
94
95 fn to_bytes(&self) -> Vec<u8> {
96 let mut buf = vec![];
97 ark_serialize::CanonicalSerialize::serialize_compressed(self, &mut buf)
98 .expect("Serialization should not fail.");
99 buf
100 }
101
102 fn from_bytes(bytes: &[u8]) -> Result<Self, SerializationError> {
103 ark_serialize::CanonicalDeserialize::deserialize_compressed(bytes)
104 }
105
106 fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::PrivateKey) {
107 let mut hasher = blake3::Hasher::new();
108 hasher.update(&seed);
109 hasher.update(&index.to_le_bytes());
110 let new_seed = *hasher.finalize().as_bytes();
111 let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
112 (kp.ver_key(), kp.sign_key_ref().clone())
113 }
114
115 fn stake_table_entry(&self, stake: U256) -> Self::StakeTableEntry {
116 StakeTableEntry {
117 stake_key: *self,
118 stake_amount: stake,
119 }
120 }
121
122 fn public_key(entry: &Self::StakeTableEntry) -> Self {
123 entry.stake_key
124 }
125
126 fn public_parameter(
127 stake_entries: &'_ [Self::StakeTableEntry],
128 threshold: U256,
129 ) -> Self::QcParams<'_> {
130 QcParams {
131 stake_entries,
132 threshold,
133 agg_sig_pp: (),
134 }
135 }
136
137 fn check(
138 real_qc_pp: &Self::QcParams<'_>,
139 data: &[u8],
140 qc: &Self::QcType,
141 ) -> Result<(), SignatureError> {
142 let msg = GenericArray::from_slice(data);
143 BitVectorQc::<BLSOverBN254CurveSignatureScheme>::check(real_qc_pp, msg, qc).map(|_| ())
144 }
145
146 fn signers(
147 real_qc_pp: &Self::QcParams<'_>,
148 qc: &Self::QcType,
149 ) -> Result<Vec<Self>, SignatureError> {
150 BitVectorQc::<BLSOverBN254CurveSignatureScheme>::signers(real_qc_pp, qc)
151 }
152
153 fn sig_proof(signature: &Self::QcType) -> (Self::PureAssembledSignatureType, BitVec) {
154 signature.clone()
155 }
156
157 fn assemble(
158 real_qc_pp: &Self::QcParams<'_>,
159 signers: &BitSlice,
160 sigs: &[Self::PureAssembledSignatureType],
161 ) -> Self::QcType {
162 BitVectorQc::<BLSOverBN254CurveSignatureScheme>::assemble(real_qc_pp, signers, sigs)
163 .expect("this assembling shouldn't fail")
164 }
165
166 fn genesis_proposer_pk() -> Self {
167 let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed([0u8; 32]));
168 kp.ver_key()
169 }
170
171 fn to_verification_key(&self) -> Self::VerificationKeyType {
172 *self
173 }
174}
175
176pub type BuilderKey = BLSPubKey;
180
181impl BuilderSignatureKey for BuilderKey {
182 type BuilderPrivateKey = BLSPrivKey;
183 type BuilderSignature = <BLSOverBN254CurveSignatureScheme as SignatureScheme>::Signature;
184 type SignError = SignatureError;
185
186 fn sign_builder_message(
187 private_key: &Self::BuilderPrivateKey,
188 data: &[u8],
189 ) -> Result<Self::BuilderSignature, Self::SignError> {
190 BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
191 &(),
192 private_key,
193 data,
194 &mut rand::thread_rng(),
195 )
196 }
197
198 fn validate_builder_signature(&self, signature: &Self::BuilderSignature, data: &[u8]) -> bool {
199 BLSOverBN254CurveSignatureScheme::verify(&(), self, data, signature).is_ok()
200 }
201
202 fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::BuilderPrivateKey) {
203 let mut hasher = blake3::Hasher::new();
204 hasher.update(&seed);
205 hasher.update(&index.to_le_bytes());
206 let new_seed = *hasher.finalize().as_bytes();
207 let kp = KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
208 (kp.ver_key(), kp.sign_key_ref().clone())
209 }
210}
211
212pub type SchnorrPubKey = jf_signature::schnorr::VerKey<ark_ed_on_bn254::EdwardsConfig>;
213pub type SchnorrPrivKey = jf_signature::schnorr::SignKey<ark_ed_on_bn254::Fr>;
214pub type SchnorrSignatureScheme =
215 jf_signature::schnorr::SchnorrSignatureScheme<ark_ed_on_bn254::EdwardsConfig>;
216
217impl PrivateSignatureKey for SchnorrPrivKey {
218 fn to_bytes(&self) -> Vec<u8> {
219 self.to_bytes()
220 }
221
222 fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
223 Ok(Self::from_bytes(bytes))
224 }
225
226 fn to_tagged_base64(&self) -> Result<tagged_base64::TaggedBase64, tagged_base64::Tb64Error> {
227 self.to_tagged_base64()
228 }
229}
230
231impl StateSignatureKey for SchnorrPubKey {
232 type StatePrivateKey = SchnorrPrivKey;
233
234 type StateSignature = jf_signature::schnorr::Signature<ark_ed_on_bn254::EdwardsConfig>;
235
236 type SignError = SignatureError;
237
238 fn generated_from_seed_indexed(seed: [u8; 32], index: u64) -> (Self, Self::StatePrivateKey) {
239 let mut hasher = blake3::Hasher::new();
240 hasher.update(&seed);
241 hasher.update(&index.to_le_bytes());
242 let new_seed = *hasher.finalize().as_bytes();
243 let kp = jf_signature::schnorr::KeyPair::generate(&mut ChaCha20Rng::from_seed(new_seed));
244 (kp.ver_key(), kp.sign_key())
245 }
246}
247
248impl LCV1StateSignatureKey for SchnorrPubKey {
249 fn sign_state(
250 sk: &Self::StatePrivateKey,
251 light_client_state: &LightClientState,
252 ) -> Result<Self::StateSignature, Self::SignError> {
253 let state_msg: [_; 3] = light_client_state.into();
254 SchnorrSignatureScheme::sign(&(), sk, state_msg, &mut rand::thread_rng())
255 }
256
257 fn verify_state_sig(
258 &self,
259 signature: &Self::StateSignature,
260 light_client_state: &LightClientState,
261 ) -> bool {
262 let state_msg: [_; 3] = light_client_state.into();
263 SchnorrSignatureScheme::verify(&(), self, state_msg, signature).is_ok()
264 }
265}
266
267impl LCV2StateSignatureKey for SchnorrPubKey {
268 fn sign_state(
269 sk: &Self::StatePrivateKey,
270 light_client_state: &LightClientState,
271 next_stake_table_state: &StakeTableState,
272 ) -> Result<Self::StateSignature, Self::SignError> {
273 let mut msg = Vec::with_capacity(7);
274 let state_msg: [_; 3] = light_client_state.into();
275 msg.extend_from_slice(&state_msg);
276 let adv_st_state_msg: [_; 4] = (*next_stake_table_state).into();
277 msg.extend_from_slice(&adv_st_state_msg);
278 SchnorrSignatureScheme::sign(&(), sk, msg, &mut rand::thread_rng())
279 }
280
281 fn verify_state_sig(
282 &self,
283 signature: &Self::StateSignature,
284 light_client_state: &LightClientState,
285 next_stake_table_state: &StakeTableState,
286 ) -> bool {
287 let mut msg = Vec::with_capacity(7);
288 let state_msg: [_; 3] = light_client_state.into();
289 msg.extend_from_slice(&state_msg);
290 let adv_st_state_msg: [_; 4] = (*next_stake_table_state).into();
291 msg.extend_from_slice(&adv_st_state_msg);
292 SchnorrSignatureScheme::verify(&(), self, msg, signature).is_ok()
293 }
294}
295
296impl LCV3StateSignatureKey for SchnorrPubKey {
297 fn sign_state(
301 private_key: &Self::StatePrivateKey,
302 msg: CircuitField,
303 ) -> Result<Self::StateSignature, Self::SignError> {
304 SchnorrSignatureScheme::sign(&(), private_key, [msg], &mut rand::thread_rng())
305 }
306
307 fn verify_state_sig(&self, signature: &Self::StateSignature, msg: CircuitField) -> bool {
311 SchnorrSignatureScheme::verify(&(), self, [msg], signature).is_ok()
312 }
313}
314
315#[cfg(test)]
316mod tests {
317 use alloy::primitives::U256;
318 use bitvec::prelude::*;
319 use jf_signature::bls_over_bn254::{BLSOverBN254CurveSignatureScheme, KeyPair};
320
321 use super::BLSPubKey;
322 use crate::{
323 qc::BitVectorQc,
324 stake_table::StakeTableEntry,
325 traits::{qc::QuorumCertificateScheme, signature_key::SignatureKey},
326 };
327
328 #[test]
329 fn test_to_verification_key_is_identity() {
330 let mut rng = jf_utils::test_rng();
331 let kp = KeyPair::generate(&mut rng);
332 let pub_key: BLSPubKey = kp.ver_key();
333 assert_eq!(pub_key.to_verification_key(), pub_key);
335 }
336
337 #[test]
338 fn test_bls_signers_correct_keys() {
339 let mut rng = jf_utils::test_rng();
340 let kp1 = KeyPair::generate(&mut rng);
341 let kp2 = KeyPair::generate(&mut rng);
342 let kp3 = KeyPair::generate(&mut rng);
343 let entries: Vec<StakeTableEntry<BLSPubKey>> = vec![
344 StakeTableEntry {
345 stake_key: kp1.ver_key(),
346 stake_amount: U256::from(1u8),
347 },
348 StakeTableEntry {
349 stake_key: kp2.ver_key(),
350 stake_amount: U256::from(1u8),
351 },
352 StakeTableEntry {
353 stake_key: kp3.ver_key(),
354 stake_amount: U256::from(1u8),
355 },
356 ];
357 let qc_pp = BLSPubKey::public_parameter(&entries, U256::from(2u8));
359 let msg = [55u8; 32];
360 let sig1 = BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
361 &(),
362 kp1.sign_key_ref(),
363 msg,
364 &mut rng,
365 )
366 .unwrap();
367 let sig2 = BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
368 &(),
369 kp2.sign_key_ref(),
370 msg,
371 &mut rng,
372 )
373 .unwrap();
374 let signers_bv = bitvec![1, 1, 0];
376 let qc = BitVectorQc::<BLSOverBN254CurveSignatureScheme>::assemble(
377 &qc_pp,
378 signers_bv.as_bitslice(),
379 &[sig1, sig2],
380 )
381 .unwrap();
382 let result = BLSPubKey::signers(&qc_pp, &qc).unwrap();
383 assert_eq!(result, vec![kp1.ver_key(), kp2.ver_key()]);
384 }
385
386 #[test]
387 fn test_bls_signers_bitvec_mismatch() {
388 let mut rng = jf_utils::test_rng();
389 let kp1 = KeyPair::generate(&mut rng);
390 let kp2 = KeyPair::generate(&mut rng);
391 let kp3 = KeyPair::generate(&mut rng);
392 let entries: Vec<StakeTableEntry<BLSPubKey>> = vec![
393 StakeTableEntry {
394 stake_key: kp1.ver_key(),
395 stake_amount: U256::from(1u8),
396 },
397 StakeTableEntry {
398 stake_key: kp2.ver_key(),
399 stake_amount: U256::from(1u8),
400 },
401 StakeTableEntry {
402 stake_key: kp3.ver_key(),
403 stake_amount: U256::from(1u8),
404 },
405 ];
406 let qc_pp = BLSPubKey::public_parameter(&entries, U256::from(2u8));
407
408 let wrong_bv = bitvec![1, 1];
410 let sig = BitVectorQc::<BLSOverBN254CurveSignatureScheme>::sign(
411 &(),
412 kp1.sign_key_ref(),
413 [0u8; 32],
414 &mut rng,
415 )
416 .unwrap();
417 let qc_bad = (sig, wrong_bv);
418 let result = BLSPubKey::signers(&qc_pp, &qc_bad);
419 assert!(result.is_err());
420 }
421}