use core::fmt;
use rand::{CryptoRng, RngCore};
use crate::{
keys::SpendAuthorizingKey,
primitives::redpallas::{self, SpendAuth},
};
impl super::Action {
pub fn sign<R: RngCore + CryptoRng>(
&mut self,
sighash: [u8; 32],
ask: &SpendAuthorizingKey,
rng: R,
) -> Result<(), SignerError> {
let alpha = self
.spend
.alpha
.ok_or(SignerError::MissingSpendAuthRandomizer)?;
let rsk = ask.randomize(&alpha);
let rk = redpallas::VerificationKey::from(&rsk);
if self.spend.rk == rk {
self.spend.spend_auth_sig = Some(rsk.sign(rng, &sighash));
Ok(())
} else {
Err(SignerError::WrongSpendAuthorizingKey)
}
}
pub fn apply_signature(
&mut self,
sighash: [u8; 32],
signature: redpallas::Signature<SpendAuth>,
) -> Result<(), SignerError> {
if self.spend.rk.verify(&sighash, &signature).is_ok() {
self.spend.spend_auth_sig = Some(signature);
Ok(())
} else {
Err(SignerError::InvalidExternalSignature)
}
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum SignerError {
InvalidExternalSignature,
MissingSpendAuthRandomizer,
WrongSpendAuthorizingKey,
}
impl fmt::Display for SignerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SignerError::InvalidExternalSignature => {
write!(f, "External signature is invalid for the action's spend")
}
SignerError::MissingSpendAuthRandomizer => {
write!(f, "`alpha` must be set for the Signer role")
}
SignerError::WrongSpendAuthorizingKey => {
write!(f, "provided `ask` does not own the action's spent note")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for SignerError {}