#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::{string::String, vec::Vec};
#[cfg(feature = "ed25519")]
mod ed25519;
mod error;
mod macros;
#[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;
#[doc(hidden)]
pub mod __private {
pub use alloc::string::String;
pub use hex::FromHexError;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SignOutput {
pub signature: Vec<u8>,
pub recovery_id: Option<u8>,
pub public_key: Option<Vec<u8>>,
}
impl SignOutput {
#[must_use]
pub const fn secp256k1(signature: Vec<u8>, recovery_id: u8) -> Self {
Self {
signature,
recovery_id: Some(recovery_id),
public_key: None,
}
}
#[must_use]
pub const fn ed25519(signature: Vec<u8>) -> Self {
Self {
signature,
recovery_id: None,
public_key: None,
}
}
#[must_use]
pub const fn ed25519_with_pubkey(signature: Vec<u8>, public_key: Vec<u8>) -> Self {
Self {
signature,
recovery_id: None,
public_key: Some(public_key),
}
}
#[must_use]
pub const fn schnorr(signature: Vec<u8>, xonly_public_key: Vec<u8>) -> Self {
Self {
signature,
recovery_id: None,
public_key: Some(xonly_public_key),
}
}
#[must_use]
pub fn signature_hex(&self) -> String {
hex::encode(&self.signature)
}
#[must_use]
pub fn public_key_hex(&self) -> Option<String> {
self.public_key.as_ref().map(hex::encode)
}
}
pub trait Sign: Send + Sync {
type Error: core::fmt::Debug + core::fmt::Display + From<SignError> + Send + Sync;
fn sign_hash(&self, hash: &[u8]) -> 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]) -> Result<Vec<u8>, Self::Error> {
self.sign_hash(hash).map(|out| out.signature)
}
fn sign_transaction_bytes(&self, tx_bytes: &[u8]) -> Result<Vec<u8>, Self::Error> {
self.sign_transaction(tx_bytes).map(|out| out.signature)
}
}
impl<T: Sign> SignExt for T {}