use core::{marker::PhantomData, fmt::Debug};
use std::io::Read;
use rand_core::{RngCore, CryptoRng};
use transcript::Transcript;
use crate::{Curve, FrostError, FrostView, schnorr};
pub use schnorr::SchnorrSignature;
pub trait Algorithm<C: Curve>: Clone {
type Transcript: Transcript + Clone + Debug;
type Signature: Clone + PartialEq + Debug;
fn transcript(&mut self) -> &mut Self::Transcript;
fn nonces(&self) -> Vec<Vec<C::G>>;
fn preprocess_addendum<R: RngCore + CryptoRng>(
&mut self,
rng: &mut R,
params: &FrostView<C>,
) -> Vec<u8>;
fn process_addendum<Re: Read>(
&mut self,
params: &FrostView<C>,
l: u16,
reader: &mut Re,
) -> Result<(), FrostError>;
fn sign_share(
&mut self,
params: &FrostView<C>,
nonce_sums: &[Vec<C::G>],
nonces: &[C::F],
msg: &[u8],
) -> C::F;
#[must_use]
fn verify(&self, group_key: C::G, nonces: &[Vec<C::G>], sum: C::F) -> Option<Self::Signature>;
#[must_use]
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool;
}
#[derive(Clone, Debug)]
pub struct IetfTranscript(Vec<u8>);
impl Transcript for IetfTranscript {
type Challenge = Vec<u8>;
fn new(_: &'static [u8]) -> IetfTranscript {
IetfTranscript(vec![])
}
fn domain_separate(&mut self, _: &[u8]) {}
fn append_message(&mut self, _: &'static [u8], message: &[u8]) {
self.0.extend(message);
}
fn challenge(&mut self, _: &'static [u8]) -> Vec<u8> {
self.0.clone()
}
fn rng_seed(&mut self, _: &'static [u8]) -> [u8; 32] {
unimplemented!()
}
}
pub trait Hram<C: Curve>: Clone {
#[allow(non_snake_case)]
fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F;
}
#[derive(Clone)]
pub struct Schnorr<C: Curve, H: Hram<C>> {
transcript: IetfTranscript,
c: Option<C::F>,
_hram: PhantomData<H>,
}
impl<C: Curve, H: Hram<C>> Default for Schnorr<C, H> {
fn default() -> Self {
Self::new()
}
}
impl<C: Curve, H: Hram<C>> Schnorr<C, H> {
pub fn new() -> Schnorr<C, H> {
Schnorr { transcript: IetfTranscript(vec![]), c: None, _hram: PhantomData }
}
}
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
type Transcript = IetfTranscript;
type Signature = SchnorrSignature<C>;
fn transcript(&mut self) -> &mut Self::Transcript {
&mut self.transcript
}
fn nonces(&self) -> Vec<Vec<C::G>> {
vec![vec![C::generator()]]
}
fn preprocess_addendum<R: RngCore + CryptoRng>(
&mut self,
_: &mut R,
_: &FrostView<C>,
) -> Vec<u8> {
vec![]
}
fn process_addendum<Re: Read>(
&mut self,
_: &FrostView<C>,
_: u16,
_: &mut Re,
) -> Result<(), FrostError> {
Ok(())
}
fn sign_share(
&mut self,
params: &FrostView<C>,
nonce_sums: &[Vec<C::G>],
nonces: &[C::F],
msg: &[u8],
) -> C::F {
let c = H::hram(&nonce_sums[0][0], ¶ms.group_key(), msg);
self.c = Some(c);
schnorr::sign::<C>(params.secret_share(), nonces[0], c).s
}
#[must_use]
fn verify(&self, group_key: C::G, nonces: &[Vec<C::G>], sum: C::F) -> Option<Self::Signature> {
let sig = SchnorrSignature { R: nonces[0][0], s: sum };
if schnorr::verify::<C>(group_key, self.c.unwrap(), &sig) {
Some(sig)
} else {
None
}
}
#[must_use]
fn verify_share(&self, verification_share: C::G, nonces: &[Vec<C::G>], share: C::F) -> bool {
schnorr::verify::<C>(
verification_share,
self.c.unwrap(),
&SchnorrSignature { R: nonces[0][0], s: share },
)
}
}