use anyhow::Result; use rand::{thread_rng, RngCore}; use serde::{Deserialize, Serialize}; use sp_client::bitcoin::hashes::{sha256t_hash_newtype, Hash, HashEngine}; use sp_client::bitcoin::key::Secp256k1; use sp_client::bitcoin::secp256k1::schnorr::Signature; use sp_client::bitcoin::secp256k1::{Keypair, Message, PublicKey, SecretKey}; sha256t_hash_newtype! { pub struct AnkMessageTag = hash_str("4nk/Message"); #[hash_newtype(forward)] pub struct AnkMessageHash(_); pub struct AnkValidationYesTag = hash_str("4nk/yes"); #[hash_newtype(forward)] pub struct AnkValidationYesHash(_); pub struct AnkValidationNoTag = hash_str("4nk/no"); #[hash_newtype(forward)] pub struct AnkValidationNoHash(_); } impl AnkMessageHash { pub fn from_message(message: &[u8]) -> Self { let mut eng = AnkMessageHash::engine(); eng.input(&message); AnkMessageHash::from_engine(eng) } } impl AnkValidationYesHash { pub fn from_merkle_root(merkle_root: [u8; 32]) -> Self { let mut eng = AnkValidationYesHash::engine(); eng.input(&merkle_root); AnkValidationYesHash::from_engine(eng) } } impl AnkValidationNoHash { pub fn from_merkle_root(merkle_root: [u8; 32]) -> Self { let mut eng = AnkValidationNoHash::engine(); eng.input(&merkle_root); AnkValidationNoHash::from_engine(eng) } } #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum AnkHash { Message(AnkMessageHash), ValidationYes(AnkValidationYesHash), ValidationNo(AnkValidationNoHash), } impl AnkHash { pub fn to_byte_array(&self) -> [u8; 32] { match self { AnkHash::Message(hash) => hash.to_byte_array(), AnkHash::ValidationYes(hash) => hash.to_byte_array(), AnkHash::ValidationNo(hash) => hash.to_byte_array(), } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Proof { signature: Signature, message: [u8; 32], key: PublicKey, } impl Proof { pub fn new(message_hash: AnkHash, signing_key: SecretKey) -> Self { 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.to_byte_array(), key: keypair.public_key(), } } pub fn get_key(&self) -> PublicKey { self.key } pub fn get_message(&self) -> [u8; 32] { self.message } pub fn verify(&self) -> Result<()> { let secp = Secp256k1::verification_only(); secp.verify_schnorr( &self.signature, &Message::from_digest(self.message), &self.key.x_only_public_key().0, )?; Ok(()) } pub fn to_string(&self) -> String { serde_json::to_string(self).unwrap() } }