use alloc::borrow::Cow;
use frost_core::Scalar;
use crate::curve::NestedSuite;
use crate::error::Error;
use crate::nested::{
inner_sign, InnerNonces, InnerSignatureShare, NestedSigningRequest, SpentSessions,
};
use crate::SecretShare;
pub struct SignRequest<'a, C: NestedSuite> {
pub nonces: InnerNonces<Scalar<C>>,
pub nested: &'a NestedSigningRequest<'a, C>,
message: Cow<'a, [u8]>,
}
impl<'a, C: NestedSuite> SignRequest<'a, C> {
pub fn raw(
nonces: InnerNonces<Scalar<C>>,
approved_message: &'a [u8],
nested: &'a NestedSigningRequest<'a, C>,
) -> Self {
Self {
nonces,
nested,
message: Cow::Borrowed(approved_message),
}
}
pub fn bound(
nonces: InnerNonces<Scalar<C>>,
ctx: &crate::SigningContext<'_>,
nested: &'a NestedSigningRequest<'a, C>,
) -> Self {
Self {
nonces,
nested,
message: Cow::Owned(ctx.encode()),
}
}
pub fn approved_message(&self) -> &[u8] {
&self.message
}
}
pub trait Signer<C: NestedSuite> {
fn sign(&mut self, req: SignRequest<'_, C>) -> Result<InnerSignatureShare<Scalar<C>>, Error>;
}
pub trait Layer<S> {
type Signer;
fn layer(self, inner: S) -> Self::Signer;
}
pub struct Stack<S>(S);
impl<S> Stack<S> {
pub fn new(inner: S) -> Self {
Self(inner)
}
pub fn layer<L: Layer<S>>(self, layer: L) -> Stack<L::Signer> {
Stack(layer.layer(self.0))
}
pub fn into_inner(self) -> S {
self.0
}
}
pub struct Holder<'k, C: NestedSuite> {
share: &'k SecretShare<Scalar<C>>,
verifying_key: &'k frost_core::VerifyingKey<C>,
}
impl<'k, C: NestedSuite> Holder<'k, C> {
pub fn new(
share: &'k SecretShare<Scalar<C>>,
verifying_key: &'k frost_core::VerifyingKey<C>,
) -> Self {
Self {
share,
verifying_key,
}
}
}
impl<C: NestedSuite> Signer<C> for Holder<'_, C> {
fn sign(&mut self, req: SignRequest<'_, C>) -> Result<InnerSignatureShare<Scalar<C>>, Error> {
inner_sign::<C>(
req.nonces,
self.share,
self.verifying_key,
&req.message,
req.nested,
)
}
}
pub struct Spend<T> {
store: T,
}
impl<T: SpentSessions> Spend<T> {
pub fn new(store: T) -> Self {
Self { store }
}
}
pub struct Spending<T, S> {
store: T,
inner: S,
}
impl<T: SpentSessions, S> Spending<T, S> {
pub fn into_store(self) -> T {
self.store
}
pub fn store(&self) -> &T {
&self.store
}
}
impl<T: SpentSessions, S> Layer<S> for Spend<T> {
type Signer = Spending<T, S>;
fn layer(self, inner: S) -> Self::Signer {
Spending {
store: self.store,
inner,
}
}
}
impl<C, T, S> Signer<C> for Spending<T, S>
where
C: NestedSuite,
T: SpentSessions,
S: Signer<C>,
{
fn sign(&mut self, req: SignRequest<'_, C>) -> Result<InnerSignatureShare<Scalar<C>>, Error> {
self.store
.spend(&req.nonces.session_id, req.nonces.holder_index)?;
self.inner.sign(req)
}
}