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