commonware_cryptography/bls12381/dkg/
types.rs1use crate::{
7 bls12381::primitives::{group, poly::Public, variant::Variant},
8 PublicKey, Signature, Signer,
9};
10use bytes::{Buf, BufMut};
11use commonware_codec::{varint::UInt, EncodeSize, FixedSize, Read, ReadExt, Write};
12use commonware_utils::quorum;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct Share<V: Variant> {
24 pub commitment: Public<V>,
28 pub share: group::Share,
32}
33
34impl<V: Variant> Share<V> {
35 pub fn new(commitment: Public<V>, share: group::Share) -> Self {
37 Self { commitment, share }
38 }
39}
40
41impl<V: Variant> Write for Share<V> {
42 fn write(&self, buf: &mut impl BufMut) {
43 self.commitment.write(buf);
44 self.share.write(buf);
45 }
46}
47
48impl<V: Variant> EncodeSize for Share<V> {
49 fn encode_size(&self) -> usize {
50 self.commitment.encode_size() + self.share.encode_size()
51 }
52}
53
54impl<V: Variant> Read for Share<V> {
55 type Cfg = u32;
56
57 fn read_cfg(buf: &mut impl Buf, t: &u32) -> Result<Self, commonware_codec::Error> {
58 let q = quorum(*t);
59 Ok(Self {
60 commitment: Public::<V>::read_cfg(buf, &(q as usize))?,
61 share: group::Share::read(buf)?,
62 })
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct Ack<S: Signature> {
75 pub player: u32,
79 pub signature: S,
84}
85
86impl<S: Signature> Ack<S> {
87 pub fn new<C, V>(
89 namespace: &[u8],
90 signer: &C,
91 player: u32,
92 round: u64,
93 dealer: &C::PublicKey,
94 commitment: &Public<V>,
95 ) -> Self
96 where
97 C: Signer<Signature = S>,
98 V: Variant,
99 {
100 let payload = Self::signature_payload::<V, C::PublicKey>(round, dealer, commitment);
101 let signature = signer.sign(Some(namespace), &payload);
102 Self { player, signature }
103 }
104
105 pub fn verify<V: Variant, P: PublicKey<Signature = S>>(
107 &self,
108 namespace: &[u8],
109 public_key: &P,
110 round: u64,
111 dealer: &P,
112 commitment: &Public<V>,
113 ) -> bool {
114 let payload = Self::signature_payload::<V, P>(round, dealer, commitment);
115 public_key.verify(Some(namespace), &payload, &self.signature)
116 }
117
118 fn signature_payload<V: Variant, P: PublicKey>(
125 round: u64,
126 dealer: &P,
127 commitment: &Public<V>,
128 ) -> Vec<u8> {
129 let mut payload = Vec::with_capacity(u64::SIZE + P::SIZE + commitment.encode_size());
130 round.write(&mut payload);
131 dealer.write(&mut payload);
132 commitment.write(&mut payload);
133 payload
134 }
135}
136
137impl<S: Signature> Write for Ack<S> {
138 fn write(&self, buf: &mut impl BufMut) {
139 UInt(self.player).write(buf);
140 self.signature.write(buf);
141 }
142}
143
144impl<S: Signature> EncodeSize for Ack<S> {
145 fn encode_size(&self) -> usize {
146 UInt(self.player).encode_size() + self.signature.encode_size()
147 }
148}
149
150impl<S: Signature> Read for Ack<S> {
151 type Cfg = ();
152
153 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, commonware_codec::Error> {
154 Ok(Self {
155 player: UInt::read(buf)?.into(),
156 signature: S::read(buf)?,
157 })
158 }
159}
160
161#[cfg(test)]
162mod test {
163 use super::*;
164 use crate::{
165 bls12381::{
166 dkg::ops,
167 primitives::{group, poly::Public, variant::MinSig},
168 },
169 ed25519::PrivateKey,
170 PrivateKeyExt, Signer,
171 };
172 use commonware_utils::quorum;
173 use rand::SeedableRng;
174 use rand_chacha::ChaCha8Rng;
175
176 const ACK_NAMESPACE: &[u8] = b"DKG_ACK";
177
178 fn generate_identities(num_peers: u32) -> (Public<MinSig>, Vec<(PrivateKey, group::Share)>) {
179 let mut rng = ChaCha8Rng::seed_from_u64(num_peers as u64);
180
181 let threshold = quorum(num_peers);
183 let (polynomial, shares) =
184 ops::generate_shares::<_, MinSig>(&mut rng, None, num_peers, threshold);
185
186 let mut peer_signers = (0..num_peers)
188 .map(|_| PrivateKey::from_rng(&mut rng))
189 .collect::<Vec<_>>();
190 peer_signers.sort_by_key(|signer| signer.public_key());
191
192 let identities = peer_signers.into_iter().zip(shares).collect::<Vec<_>>();
193
194 (polynomial, identities)
195 }
196
197 #[test]
198 fn test_share_roundtrip() {
199 const NUM_PARTICIPANTS: u32 = 4;
200
201 let (commitment, identities) = generate_identities(NUM_PARTICIPANTS);
202 let (_, share) = &identities[0];
203
204 let share = Share::<MinSig>::new(commitment.clone(), share.clone());
205
206 let mut buf = Vec::with_capacity(share.encode_size());
207 share.write(&mut buf);
208
209 let decoded = Share::<MinSig>::read_cfg(&mut buf.as_slice(), &NUM_PARTICIPANTS).unwrap();
210 assert_eq!(decoded, share);
211 }
212
213 #[test]
214 fn test_ack_roundtrip() {
215 const NUM_PARTICIPANTS: u32 = 4;
216
217 let (commitment, identities) = generate_identities(NUM_PARTICIPANTS);
218 let (signer, _) = &identities[0];
219
220 let ack = Ack::new::<PrivateKey, MinSig>(
221 ACK_NAMESPACE,
222 signer,
223 1337,
224 42,
225 &signer.public_key(),
226 &commitment,
227 );
228
229 let mut buf = Vec::with_capacity(ack.encode_size());
230 ack.write(&mut buf);
231
232 let decoded =
233 Ack::<<PrivateKey as Signer>::Signature>::read_cfg(&mut buf.as_slice(), &()).unwrap();
234 assert_eq!(decoded, ack);
235 }
236}