#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
#[cfg(feature = "ed25519")]
mod ed25519;
mod error;
#[cfg(feature = "schnorr")]
mod schnorr;
#[cfg(feature = "secp256k1")]
mod secp256k1;
#[cfg(feature = "testing")]
pub mod testing;
#[cfg(feature = "ed25519")]
pub use ed25519::Ed25519Signer;
pub use error::SignError;
#[cfg(feature = "schnorr")]
pub use schnorr::SchnorrSigner;
#[cfg(feature = "secp256k1")]
pub use secp256k1::Secp256k1Signer;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SignOutput {
Ecdsa {
signature: [u8; 64],
v: u8,
},
EcdsaDer(Vec<u8>),
Ed25519([u8; 64]),
Ed25519WithPubkey {
signature: [u8; 64],
public_key: [u8; 32],
},
Schnorr {
signature: [u8; 64],
xonly_public_key: [u8; 32],
},
}
impl SignOutput {
#[must_use]
pub fn to_bytes(&self) -> Vec<u8> {
match *self {
Self::Ecdsa { signature, v } => {
let mut out = Vec::with_capacity(65);
out.extend_from_slice(&signature);
out.push(v);
out
}
Self::EcdsaDer(ref der) => der.clone(),
Self::Ed25519(sig) | Self::Ed25519WithPubkey { signature: sig, .. } => sig.to_vec(),
Self::Schnorr { signature, .. } => signature.to_vec(),
}
}
#[must_use]
pub fn to_hex(&self) -> String {
hex::encode(self.to_bytes())
}
#[must_use]
pub const fn public_key(&self) -> Option<&[u8]> {
match self {
Self::Ed25519WithPubkey { public_key, .. } => Some(public_key.as_slice()),
Self::Schnorr {
xonly_public_key, ..
} => Some(xonly_public_key.as_slice()),
_ => None,
}
}
#[must_use]
pub const fn v(&self) -> Option<u8> {
match self {
Self::Ecdsa { v, .. } => Some(*v),
_ => None,
}
}
}
pub trait Sign: Send + Sync {
type Error: core::fmt::Debug + core::fmt::Display + From<SignError> + Send + Sync;
fn sign_hash(&self, hash: &[u8; 32]) -> Result<SignOutput, Self::Error>;
fn sign_message(&self, message: &[u8]) -> Result<SignOutput, Self::Error>;
fn sign_transaction(&self, tx_bytes: &[u8]) -> Result<SignOutput, Self::Error>;
fn extract_signable_bytes<'a>(&self, tx_bytes: &'a [u8]) -> Result<&'a [u8], Self::Error> {
Ok(tx_bytes)
}
fn encode_signed_transaction(
&self,
_tx_bytes: &[u8],
_signature: &SignOutput,
) -> Result<Vec<u8>, Self::Error> {
Err(
SignError::InvalidTransaction("encode_signed_transaction not implemented".into())
.into(),
)
}
}
pub trait SignExt: Sign {
fn sign_hash_bytes(&self, hash: &[u8; 32]) -> Result<Vec<u8>, Self::Error> {
self.sign_hash(hash).map(|out| out.to_bytes())
}
fn sign_message_bytes(&self, message: &[u8]) -> Result<Vec<u8>, Self::Error> {
self.sign_message(message).map(|out| out.to_bytes())
}
fn sign_transaction_bytes(&self, tx_bytes: &[u8]) -> Result<Vec<u8>, Self::Error> {
self.sign_transaction(tx_bytes).map(|out| out.to_bytes())
}
}
impl<T: Sign> SignExt for T {}