threshold_bls/sig/
tbls.rs1use crate::poly::{Eval, Idx, Poly, PolyError};
4use crate::sig::{Partial, SignatureScheme, ThresholdScheme};
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub struct Share<S> {
11 pub index: Idx,
13 pub private: S,
15}
16
17#[derive(Debug, Error)]
19pub enum ThresholdError<I: SignatureScheme> {
20 #[error("could not recover public key: {0}")]
22 PolyError(PolyError),
23
24 #[error(transparent)]
26 BincodeError(#[from] bincode::Error),
27
28 #[error("signing error {0}")]
30 SignatureError(I::Error),
31
32 #[error("not enough partial signatures: {0}/{1}")]
35 NotEnoughPartialSignatures(usize, usize),
36}
37
38impl<I: SignatureScheme> ThresholdScheme for I {
39 type Error = ThresholdError<I>;
40
41 fn partial_sign(
42 private: &Share<Self::Private>,
43 msg: &[u8],
44 ) -> Result<Vec<u8>, <Self as ThresholdScheme>::Error> {
45 let sig = Self::sign(&private.private, msg).map_err(ThresholdError::SignatureError)?;
46 let partial = Eval {
47 value: sig,
48 index: private.index,
49 };
50 let ret = bincode::serialize(&partial)?;
51 Ok(ret)
52 }
53
54 fn partial_verify(
55 public: &Poly<Self::Public>,
56 msg: &[u8],
57 partial: &[u8],
58 ) -> Result<(), <Self as ThresholdScheme>::Error> {
59 let partial: Eval<Vec<u8>> = bincode::deserialize(partial)?;
60
61 let public_i = public.eval(partial.index);
62
63 Self::verify(&public_i.value, msg, &partial.value).map_err(ThresholdError::SignatureError)
64 }
65
66 fn aggregate(
67 threshold: usize,
68 partials: &[Partial],
69 ) -> Result<Vec<u8>, <Self as ThresholdScheme>::Error> {
70 if threshold > partials.len() {
71 return Err(ThresholdError::NotEnoughPartialSignatures(
72 partials.len(),
73 threshold,
74 ));
75 }
76
77 let valid_partials: Vec<Eval<Self::Signature>> = partials
78 .iter()
79 .map(|partial| {
80 let eval: Eval<Vec<u8>> = bincode::deserialize(partial)?;
81 let sig = bincode::deserialize(&eval.value)?;
82 Ok(Eval {
83 index: eval.index,
84 value: sig,
85 })
86 })
87 .collect::<Result<_, <Self as ThresholdScheme>::Error>>()?;
88
89 let recovered_sig = Poly::<Self::Signature>::recover(threshold, valid_partials)
90 .map_err(ThresholdError::PolyError)?;
91 Ok(bincode::serialize(&recovered_sig).expect("could not serialize"))
92 }
93}
94
95#[cfg(feature = "bls12_381")]
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use crate::{
100 curve::bls12381::PairingCurve as PCurve,
101 sig::{
102 bls::{G1Scheme, G2Scheme},
103 Scheme,
104 },
105 };
106
107 type ShareCreator<T> = fn(
108 usize,
109 usize,
110 ) -> (
111 Vec<Share<<T as Scheme>::Private>>,
112 Poly<<T as Scheme>::Public>,
113 );
114
115 fn shares<T: ThresholdScheme>(n: usize, t: usize) -> (Vec<Share<T::Private>>, Poly<T::Public>) {
116 let private = Poly::<T::Private>::new(t - 1);
117 let shares = (0..n)
118 .map(|i| private.eval(i as Idx))
119 .map(|e| Share {
120 index: e.index,
121 private: e.value,
122 })
123 .collect();
124 (shares, private.commit())
125 }
126
127 fn test_threshold_scheme<T: ThresholdScheme + SignatureScheme>(creator: ShareCreator<T>) {
128 let threshold = 4;
129 let (shares, public) = creator(5, threshold);
130 let msg = vec![1, 9, 6, 9];
131
132 let partials: Vec<_> = shares
133 .iter()
134 .map(|s| T::partial_sign(s, &msg).unwrap())
135 .collect();
136
137 assert_eq!(
138 false,
139 partials
140 .iter()
141 .any(|p| T::partial_verify(&public, &msg, &p).is_err())
142 );
143 let final_sig = T::aggregate(threshold, &partials).unwrap();
144
145 T::verify(public.public_key(), &msg, &final_sig).unwrap();
146 }
147
148 #[test]
149 fn threshold_g1() {
150 type S = G1Scheme<PCurve>;
151 test_threshold_scheme::<S>(shares::<S>);
152 }
153
154 #[test]
155 fn threshold_g2() {
156 type S = G2Scheme<PCurve>;
157 test_threshold_scheme::<S>(shares::<S>);
158 }
159}