use crate::{
bls12381::primitives::{group, poly::Public, variant::Variant},
PublicKey, Signature, Signer,
};
use bytes::{Buf, BufMut};
use commonware_codec::{varint::UInt, EncodeSize, FixedSize, Read, ReadExt, Write};
use commonware_utils::quorum;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Share<V: Variant> {
pub commitment: Public<V>,
pub share: group::Share,
}
impl<V: Variant> Share<V> {
pub fn new(commitment: Public<V>, share: group::Share) -> Self {
Self { commitment, share }
}
}
impl<V: Variant> Write for Share<V> {
fn write(&self, buf: &mut impl BufMut) {
self.commitment.write(buf);
self.share.write(buf);
}
}
impl<V: Variant> EncodeSize for Share<V> {
fn encode_size(&self) -> usize {
self.commitment.encode_size() + self.share.encode_size()
}
}
impl<V: Variant> Read for Share<V> {
type Cfg = u32;
fn read_cfg(buf: &mut impl Buf, t: &u32) -> Result<Self, commonware_codec::Error> {
let q = quorum(*t);
Ok(Self {
commitment: Public::<V>::read_cfg(buf, &(q as usize))?,
share: group::Share::read(buf)?,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ack<S: Signature> {
pub player: u32,
pub signature: S,
}
impl<S: Signature> Ack<S> {
pub fn new<C, V>(
namespace: &[u8],
signer: &C,
player: u32,
round: u64,
dealer: &C::PublicKey,
commitment: &Public<V>,
) -> Self
where
C: Signer<Signature = S>,
V: Variant,
{
let payload = Self::signature_payload::<V, C::PublicKey>(round, dealer, commitment);
let signature = signer.sign(Some(namespace), &payload);
Self { player, signature }
}
pub fn verify<V: Variant, P: PublicKey<Signature = S>>(
&self,
namespace: &[u8],
public_key: &P,
round: u64,
dealer: &P,
commitment: &Public<V>,
) -> bool {
let payload = Self::signature_payload::<V, P>(round, dealer, commitment);
public_key.verify(Some(namespace), &payload, &self.signature)
}
fn signature_payload<V: Variant, P: PublicKey>(
round: u64,
dealer: &P,
commitment: &Public<V>,
) -> Vec<u8> {
let mut payload = Vec::with_capacity(u64::SIZE + P::SIZE + commitment.encode_size());
round.write(&mut payload);
dealer.write(&mut payload);
commitment.write(&mut payload);
payload
}
}
impl<S: Signature> Write for Ack<S> {
fn write(&self, buf: &mut impl BufMut) {
UInt(self.player).write(buf);
self.signature.write(buf);
}
}
impl<S: Signature> EncodeSize for Ack<S> {
fn encode_size(&self) -> usize {
UInt(self.player).encode_size() + self.signature.encode_size()
}
}
impl<S: Signature> Read for Ack<S> {
type Cfg = ();
fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, commonware_codec::Error> {
Ok(Self {
player: UInt::read(buf)?.into(),
signature: S::read(buf)?,
})
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{
bls12381::{
dkg::ops,
primitives::{group, poly::Public, variant::MinSig},
},
ed25519::PrivateKey,
PrivateKeyExt, Signer,
};
use commonware_utils::quorum;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
const ACK_NAMESPACE: &[u8] = b"DKG_ACK";
fn generate_identities(num_peers: u32) -> (Public<MinSig>, Vec<(PrivateKey, group::Share)>) {
let mut rng = ChaCha8Rng::seed_from_u64(num_peers as u64);
let threshold = quorum(num_peers);
let (polynomial, shares) =
ops::generate_shares::<_, MinSig>(&mut rng, None, num_peers, threshold);
let mut peer_signers = (0..num_peers)
.map(|_| PrivateKey::from_rng(&mut rng))
.collect::<Vec<_>>();
peer_signers.sort_by_key(|signer| signer.public_key());
let identities = peer_signers.into_iter().zip(shares).collect::<Vec<_>>();
(polynomial, identities)
}
#[test]
fn test_share_roundtrip() {
const NUM_PARTICIPANTS: u32 = 4;
let (commitment, identities) = generate_identities(NUM_PARTICIPANTS);
let (_, share) = &identities[0];
let share = Share::<MinSig>::new(commitment.clone(), share.clone());
let mut buf = Vec::with_capacity(share.encode_size());
share.write(&mut buf);
let decoded = Share::<MinSig>::read_cfg(&mut buf.as_slice(), &NUM_PARTICIPANTS).unwrap();
assert_eq!(decoded, share);
}
#[test]
fn test_ack_roundtrip() {
const NUM_PARTICIPANTS: u32 = 4;
let (commitment, identities) = generate_identities(NUM_PARTICIPANTS);
let (signer, _) = &identities[0];
let ack = Ack::new::<PrivateKey, MinSig>(
ACK_NAMESPACE,
signer,
1337,
42,
&signer.public_key(),
&commitment,
);
let mut buf = Vec::with_capacity(ack.encode_size());
ack.write(&mut buf);
let decoded =
Ack::<<PrivateKey as Signer>::Signature>::read_cfg(&mut buf.as_slice(), &()).unwrap();
assert_eq!(decoded, ack);
}
}