balius-runtime 0.5.2

Runtime for run Headless dApps on UTxO-based blockchains
Documentation
use std::collections::HashMap;

use pallas::crypto::key::ed25519;
use rand::rngs::OsRng;

use crate::wit::balius::app::sign as wit;

use super::SignerProvider;

#[derive(Default, Clone)]
pub struct Signer {
    map: HashMap<String, HashMap<String, SignerKey>>,
}

impl Signer {
    pub fn new() -> Self {
        Self::default()
    }
}

impl From<HashMap<String, HashMap<String, SignerKey>>> for Signer {
    fn from(value: HashMap<String, HashMap<String, SignerKey>>) -> Self {
        Self { map: value }
    }
}

#[async_trait::async_trait]
impl SignerProvider for Signer {
    async fn add_key(&mut self, worker_id: &str, key_name: String, algorithm: String) -> Vec<u8> {
        if algorithm != "ed25519" {
            panic!("Unsupported algorithm")
        }
        let keys = self.map.entry(worker_id.to_string()).or_default();
        let secret_key = keys
            .entry(key_name)
            .or_insert(ed25519::SecretKey::new(OsRng).into());
        secret_key.public_key()
    }

    async fn sign_payload(
        &mut self,
        worker_id: &str,
        key_name: String,
        payload: wit::Payload,
    ) -> Result<wit::Signature, wit::SignError> {
        let Some(key) = self
            .map
            .entry(worker_id.to_string())
            .or_default()
            .get(&key_name)
        else {
            return Err(wit::SignError::KeyNotFound(key_name.to_string()));
        };
        key.sign_payload(payload)
    }
}

#[derive(Clone, Debug)]
pub enum SignerKey {
    Ed25519(Ed25519Key),
}

impl From<ed25519::SecretKey> for SignerKey {
    fn from(value: ed25519::SecretKey) -> Self {
        Self::Ed25519(Ed25519Key::SecretKey(value))
    }
}

impl From<ed25519::SecretKeyExtended> for SignerKey {
    fn from(value: ed25519::SecretKeyExtended) -> Self {
        Self::Ed25519(Ed25519Key::SecretKeyExtended(value))
    }
}

impl SignerKey {
    pub fn sign_payload(&self, payload: wit::Payload) -> Result<wit::Signature, wit::SignError> {
        match self {
            Self::Ed25519(key) => Ok(key.sign_payload(payload)),
        }
    }

    pub fn public_key(&self) -> Vec<u8> {
        match self {
            Self::Ed25519(key) => key.public_key(),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Ed25519Key {
    SecretKey(ed25519::SecretKey),
    SecretKeyExtended(ed25519::SecretKeyExtended),
}
impl Ed25519Key {
    fn sign_payload(&self, payload: wit::Payload) -> wit::Signature {
        let signature = match self {
            Self::SecretKey(key) => key.sign(payload),
            Self::SecretKeyExtended(key) => key.sign(payload),
        };
        signature.as_ref().to_vec()
    }
    fn public_key(&self) -> Vec<u8> {
        match self {
            Self::SecretKey(key) => key.public_key().as_ref().to_vec(),
            Self::SecretKeyExtended(key) => key.public_key().as_ref().to_vec(),
        }
    }
}