use anyhow::Result; use rand::{thread_rng, RngCore}; use sp_client::bitcoin::key::Secp256k1; use sp_client::bitcoin::secp256k1::schnorr::Signature; use sp_client::bitcoin::secp256k1::{Keypair, Message, SecretKey, XOnlyPublicKey}; use sp_client::bitcoin::hashes::{sha256t_hash_newtype, Hash, HashEngine}; sha256t_hash_newtype! { pub struct AnkMessageTag = hash_str("4nk/Message"); #[hash_newtype(forward)] pub struct AnkMessageHash(_); } impl AnkMessageHash { pub fn from_message(message: &[u8]) -> Self { let mut eng = AnkMessageHash::engine(); eng.input(&message); AnkMessageHash::from_engine(eng) } } pub fn sign_message(message: &[u8], signing_key: SecretKey) -> Result { let message_hash = AnkMessageHash::from_message(message); let secp = Secp256k1::signing_only(); let keypair = Keypair::from_secret_key(&secp, &signing_key); let mut aux_rand = [0u8; 32]; thread_rng().fill_bytes(&mut aux_rand); let sig = secp.sign_schnorr_with_aux_rand(&Message::from_digest(message_hash.to_byte_array()), &keypair, &aux_rand); Ok(sig) } pub fn verify(sig: Signature, message: &[u8], x_only_key: XOnlyPublicKey) -> Result<()> { let secp = Secp256k1::verification_only(); let message_hash = AnkMessageHash::from_message(message); secp.verify_schnorr(&sig, &Message::from_digest(message_hash.to_byte_array()), &x_only_key)?; Ok(()) }