use anyhow::Result; use rand::{thread_rng, RngCore}; use serde::{Serialize, Deserialize}; 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) } } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub struct Proof { signature: Signature, message: AnkMessageHash, key: XOnlyPublicKey } impl Proof { pub fn new(message: &[u8], signing_key: SecretKey) -> Self { 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); Self { signature: sig, message: message_hash, key: keypair.x_only_public_key().0 } } pub fn get_key(&self) -> XOnlyPublicKey { self.key } pub fn verify(&self) -> Result<()> { let secp = Secp256k1::verification_only(); secp.verify_schnorr(&self.signature, &Message::from_digest(self.message.to_byte_array()), &self.key)?; Ok(()) } pub fn to_string(&self) -> String { serde_json::to_string(self).unwrap() } }