use crate::{frost, signature, verification_key, SpendAuth};
use group::GroupEncoding;
use serde::{Deserialize, Serialize};
use alloc::vec::Vec;
use std::{collections::BTreeMap, convert::TryInto};
#[cfg(test)]
use proptest_derive::Arbitrary;
#[cfg(test)]
mod arbitrary;
mod constants;
mod serialize;
#[cfg(test)]
mod tests;
mod validate;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct Secret([u8; 32]);
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Copy)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct Commitment([u8; 32]);
impl<S: SpendAuth> From<frost::Commitment<S>> for Commitment {
fn from(value: frost::Commitment<S>) -> Commitment {
Commitment(value.0.to_bytes().as_ref().try_into().unwrap())
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct GroupCommitment([u8; 32]);
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct SignatureResponse([u8; 32]);
impl<S: SpendAuth> From<signature::Signature<S>> for SignatureResponse {
fn from(value: signature::Signature<S>) -> SignatureResponse {
SignatureResponse(value.s_bytes)
}
}
impl<S: SpendAuth> From<signature::Signature<S>> for GroupCommitment {
fn from(value: signature::Signature<S>) -> GroupCommitment {
GroupCommitment(value.r_bytes)
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Copy, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct VerificationKey([u8; 32]);
impl<S: SpendAuth> From<verification_key::VerificationKey<S>> for VerificationKey {
fn from(value: verification_key::VerificationKey<S>) -> VerificationKey {
VerificationKey(<[u8; 32]>::from(value))
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct Message {
header: Header,
payload: Payload,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
pub struct Header {
version: MsgVersion,
sender: ParticipantId,
receiver: ParticipantId,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub enum Payload {
SharePackage(SharePackage),
SigningCommitments(SigningCommitments),
SigningPackage(SigningPackage),
SignatureShare(SignatureShare),
AggregateSignature(AggregateSignature),
}
#[repr(u32)]
#[non_exhaustive]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum MsgType {
SharePackage,
SigningCommitments,
SigningPackage,
SignatureShare,
AggregateSignature,
}
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, Copy)]
pub struct MsgVersion(u8);
#[derive(PartialEq, Eq, Hash, PartialOrd, Debug, Copy, Clone, Ord)]
pub enum ParticipantId {
Signer(u64),
Dealer,
Aggregator,
}
impl From<ParticipantId> for u64 {
fn from(value: ParticipantId) -> u64 {
match value {
ParticipantId::Signer(id) => id + 1,
ParticipantId::Dealer => constants::DEALER_PARTICIPANT_ID,
ParticipantId::Aggregator => constants::AGGREGATOR_PARTICIPANT_ID,
}
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct SharePackage {
group_public: VerificationKey,
secret_share: Secret,
share_commitment: BTreeMap<ParticipantId, Commitment>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct SigningCommitments {
hiding: Commitment,
binding: Commitment,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct SigningPackage {
signing_commitments: BTreeMap<ParticipantId, SigningCommitments>,
message: Vec<u8>,
}
impl<S: SpendAuth> From<SigningPackage> for frost::SigningPackage<S> {
fn from(value: SigningPackage) -> frost::SigningPackage<S> {
let mut signing_commitments = Vec::new();
for (participant_id, commitment) in &value.signing_commitments {
let mut hiding_repr = <S::Point as GroupEncoding>::Repr::default();
let mut binding_repr = <S::Point as GroupEncoding>::Repr::default();
hiding_repr.as_mut().copy_from_slice(&commitment.hiding.0);
binding_repr.as_mut().copy_from_slice(&commitment.binding.0);
let s = frost::SigningCommitments {
index: u64::from(*participant_id),
hiding: S::Point::from_bytes(&hiding_repr).unwrap(),
binding: S::Point::from_bytes(&binding_repr).unwrap(),
};
signing_commitments.push(s);
}
frost::SigningPackage {
signing_commitments,
message: value.message,
}
}
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct SignatureShare {
signature: SignatureResponse,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct AggregateSignature {
group_commitment: GroupCommitment,
schnorr_signature: SignatureResponse,
}