acta_maker_sdk/
signing.rs1use std::future::Future;
2use std::pin::Pin;
3
4use ed25519_dalek::{Signature, VerifyingKey};
5use thiserror::Error;
6
7pub type SigningFuture<'a> =
8 Pin<Box<dyn Future<Output = Result<[u8; 64], SigningError>> + Send + 'a>>;
9
10#[derive(Debug, Clone, PartialEq, Eq, Error)]
11#[error("{message}")]
12pub struct SigningError {
13 message: String,
14}
15
16impl SigningError {
17 #[must_use]
18 pub fn new(message: impl Into<String>) -> Self {
19 Self {
20 message: message.into(),
21 }
22 }
23}
24
25pub trait AsyncSignerLike: Send + Sync {
29 fn pubkey_bytes(&self) -> [u8; 32];
30
31 fn sign_message<'a>(&'a self, message: &'a [u8]) -> SigningFuture<'a>;
32}
33
34pub(crate) async fn sign_verified<S: AsyncSignerLike + ?Sized>(
35 signer: &S,
36 message: &[u8],
37) -> Result<[u8; 64], SigningError> {
38 let signature = signer.sign_message(message).await?;
39 let verifying_key = VerifyingKey::from_bytes(&signer.pubkey_bytes())
40 .map_err(|_| SigningError::new("async signer returned an invalid Ed25519 public key"))?;
41 verifying_key
42 .verify_strict(message, &Signature::from_bytes(&signature))
43 .map_err(|_| {
44 SigningError::new("async signer returned a signature for a different key or message")
45 })?;
46 Ok(signature)
47}