Преглед изворни кода

feat: wallet create and unlock p2pk

nut11 verifying and signingkeys
thesimplekid пре 1 година
родитељ
комит
9f842d2c3c

+ 6 - 7
crates/cashu-sdk/src/client/minreq_client.rs

@@ -14,7 +14,7 @@ use cashu::nuts::{CheckStateRequest, CheckStateResponse};
 use cashu::secret::Secret;
 use cashu::{Amount, Bolt11Invoice};
 use serde_json::Value;
-use tracing::{error, warn};
+use tracing::warn;
 use url::Url;
 
 use super::join_url;
@@ -170,19 +170,18 @@ impl Client for HttpClient {
         mint_url: Url,
         split_request: SwapRequest,
     ) -> Result<SwapResponse, Error> {
-        // TODO: Add to endpoint
         let url = join_url(mint_url, &["v1", "swap"])?;
 
         let res = minreq::post(url).with_json(&split_request)?.send()?;
 
+        let value = res.json::<Value>()?;
         let response: Result<SwapResponse, serde_json::Error> =
-            serde_json::from_value(res.json::<Value>()?.clone());
+            serde_json::from_value(value.clone());
 
-        if let Err(err) = &response {
-            error!("{}", err)
+        match response {
+            Ok(res) => Ok(res),
+            Err(_) => Err(ErrorResponse::from_json(&value.to_string())?.into()),
         }
-
-        Ok(response?)
     }
 
     /// Spendable check [NUT-07]

+ 2 - 2
crates/cashu-sdk/src/mint/mod.rs

@@ -64,10 +64,10 @@ pub enum Error {
 }
 
 impl From<Error> for ErrorResponse {
-    fn from(_err: Error) -> ErrorResponse {
+    fn from(err: Error) -> ErrorResponse {
         ErrorResponse {
             code: 9999,
-            error: None,
+            error: Some(err.to_string()),
             detail: None,
         }
     }

+ 120 - 10
crates/cashu-sdk/src/wallet/mod.rs

@@ -6,9 +6,10 @@ use bip39::Mnemonic;
 use cashu::dhke::{construct_proofs, unblind_message};
 #[cfg(feature = "nut07")]
 use cashu::nuts::nut07::ProofState;
+use cashu::nuts::nut11::SigningKey;
 use cashu::nuts::{
-    BlindedSignature, CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PreMintSecrets, PreSwap, Proof,
-    Proofs, SwapRequest, Token,
+    BlindedSignature, CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, P2PKConditions, PreMintSecrets,
+    PreSwap, Proof, Proofs, SwapRequest, Token,
 };
 #[cfg(feature = "nut07")]
 use cashu::secret::Secret;
@@ -363,7 +364,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
 
             let swap_response = self
                 .client
-                .post_swap(token.mint.clone().try_into()?, pre_swap.split_request)
+                .post_swap(token.mint.clone().try_into()?, pre_swap.swap_request)
                 .await?;
 
             // Proof to keep
@@ -393,9 +394,6 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
         amount: Option<Amount>,
         proofs: Proofs,
     ) -> Result<PreSwap, Error> {
-        // Since swap is used to get the needed combination of tokens for a specific
-        // amount first blinded messages are created for the amount
-
         let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?.unwrap();
 
         let pre_mint_secrets = if let Some(amount) = amount {
@@ -415,11 +413,11 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
             PreMintSecrets::random(active_keyset_id, value)?
         };
 
-        let split_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
+        let swap_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
 
         Ok(PreSwap {
             pre_mint_secrets,
-            split_request,
+            swap_request,
         })
     }
 
@@ -471,7 +469,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
 
         let swap_response = self
             .client
-            .post_swap(mint_url.clone().try_into()?, pre_swap.split_request)
+            .post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
             .await?;
 
         let mut keep_proofs = Proofs::new();
@@ -553,7 +551,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
     }
 
     // Select proofs
-    async fn select_proofs(
+    pub async fn select_proofs(
         &self,
         mint_url: UncheckedUrl,
         unit: &CurrencyUnit,
@@ -676,6 +674,118 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
         Ok(melted)
     }
 
+    /// Create P2PK locked proofs
+    /// Uses a swap to swap proofs for locked p2pk conditions
+    pub async fn create_p2pk_proofs(
+        &mut self,
+        mint_url: &UncheckedUrl,
+        unit: &CurrencyUnit,
+        input_proofs: Proofs,
+        conditions: P2PKConditions,
+    ) -> Result<Proofs, Error> {
+        let amount = input_proofs.iter().map(|p| p.amount).sum();
+        let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?.unwrap();
+
+        let pre_mint_secrets =
+            PreMintSecrets::with_p2pk_conditions(active_keyset_id, amount, conditions)?;
+        let swap_request =
+            SwapRequest::new(input_proofs.clone(), pre_mint_secrets.blinded_messages());
+
+        let pre_swap = PreSwap {
+            pre_mint_secrets,
+            swap_request,
+        };
+
+        let swap_response = self
+            .client
+            .post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
+            .await?;
+
+        let post_swap_proofs = construct_proofs(
+            swap_response.signatures,
+            pre_swap.pre_mint_secrets.rs(),
+            pre_swap.pre_mint_secrets.secrets(),
+            &self.active_keys(mint_url, unit).await?.unwrap(),
+        )?;
+
+        let mut send_proofs = vec![];
+        let mut change_proofs = vec![];
+
+        for proof in post_swap_proofs {
+            let conditions: Result<cashu::nuts::nut10::Secret, _> = (&proof.secret).try_into();
+            println!("{:?}", conditions);
+            if conditions.is_ok() {
+                send_proofs.push(proof);
+            } else {
+                change_proofs.push(proof);
+            }
+        }
+
+        self.localstore
+            .remove_proofs(mint_url.clone(), &input_proofs)
+            .await?;
+
+        self.localstore
+            .add_pending_proofs(mint_url.clone(), input_proofs)
+            .await?;
+        self.localstore
+            .add_pending_proofs(mint_url.clone(), send_proofs.clone())
+            .await?;
+        self.localstore
+            .add_proofs(mint_url.clone(), change_proofs.clone())
+            .await?;
+
+        Ok(send_proofs)
+    }
+
+    pub async fn claim_p2pk_locked_proof(
+        &mut self,
+        mint_url: &UncheckedUrl,
+        unit: &CurrencyUnit,
+        signing_key: SigningKey,
+        proofs: Proofs,
+    ) -> Result<(), Error> {
+        let active_keyset_id = self.active_mint_keyset(&mint_url, &unit).await?;
+
+        let keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
+
+        let mut signed_proofs: Proofs = Vec::with_capacity(proofs.len());
+
+        // Sum amount of all proofs
+        let amount: Amount = proofs.iter().map(|p| p.amount).sum();
+
+        for p in proofs.clone() {
+            let mut p = p;
+            p.sign_p2pk_proof(signing_key.clone()).unwrap();
+            signed_proofs.push(p);
+        }
+
+        let pre_swap = self
+            .create_swap(mint_url, &unit, Some(amount), signed_proofs)
+            .await?;
+
+        let swap_response = self
+            .client
+            .post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
+            .await?;
+
+        // Proof to keep
+        let p = construct_proofs(
+            swap_response.signatures,
+            pre_swap.pre_mint_secrets.rs(),
+            pre_swap.pre_mint_secrets.secrets(),
+            &keys.unwrap(),
+        )?;
+
+        self.localstore
+            .remove_proofs(mint_url.clone(), &proofs)
+            .await?;
+
+        self.localstore.add_proofs(mint_url.clone(), p).await?;
+
+        Ok(())
+    }
+
     pub fn proofs_to_token(
         &self,
         mint_url: UncheckedUrl,

+ 4 - 4
crates/cashu/src/dhke.rs

@@ -229,7 +229,7 @@ mod tests {
             assert_eq!(sec, r.into());
 
             assert_eq!(
-                b.to_hex(),
+                b.to_string(),
                 PublicKey::from(
                     k256::PublicKey::from_sec1_bytes(
                         &hex::decode(
@@ -239,7 +239,7 @@ mod tests {
                     )
                     .unwrap()
                 )
-                .to_hex()
+                .to_string()
             );
 
             let message = "f1aaf16c2239746f369572c0784d9dd3d032d952c2d992175873fb58fae31a60";
@@ -254,7 +254,7 @@ mod tests {
             assert_eq!(sec, r.into());
 
             assert_eq!(
-                b.to_hex(),
+                b.to_string(),
                 PublicKey::from(
                     k256::PublicKey::from_sec1_bytes(
                         &hex::decode(
@@ -264,7 +264,7 @@ mod tests {
                     )
                     .unwrap()
                 )
-                .to_hex()
+                .to_string()
             );
         }
 

+ 1 - 1
crates/cashu/src/nuts/mod.rs

@@ -40,6 +40,6 @@ pub use nut08::{MeltBolt11Request, MeltBolt11Response};
 #[cfg(feature = "nut10")]
 pub use nut10::{Kind, Secret as Nut10Secret, SecretData};
 #[cfg(feature = "nut11")]
-pub use nut11::{P2PKConditions, Proof, SigFlag, Signatures};
+pub use nut11::{P2PKConditions, Proof, SigFlag, Signatures, SigningKey, VerifyingKey};
 
 pub type Proofs = Vec<Proof>;

+ 7 - 13
crates/cashu/src/nuts/nut01.rs

@@ -65,16 +65,6 @@ impl From<VerifyingKey> for PublicKey {
 }
 
 impl PublicKey {
-    pub fn from_hex(hex: String) -> Result<Self, Error> {
-        let hex = hex::decode(hex)?;
-        Ok(PublicKey(k256::PublicKey::from_sec1_bytes(&hex)?))
-    }
-
-    pub fn to_hex(&self) -> String {
-        let bytes = self.0.to_sec1_bytes();
-        hex::encode(bytes)
-    }
-
     pub fn to_bytes(&self) -> Box<[u8]> {
         self.0.to_sec1_bytes()
     }
@@ -91,7 +81,8 @@ impl FromStr for PublicKey {
 
 impl std::fmt::Display for PublicKey {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.write_str(&self.to_hex())
+        let bytes = self.0.to_sec1_bytes();
+        f.write_str(&hex::encode(bytes))
     }
 }
 
@@ -280,9 +271,12 @@ mod tests {
     #[test]
     fn pubkey() {
         let pubkey_str = "02c020067db727d586bc3183aecf97fcb800c3f4cc4759f69c626c9db5d8f5b5d4";
+        let pubkey = PublicKey::from_str(pubkey_str).unwrap();
+        assert_eq!(pubkey_str, pubkey.to_string());
+        /*
+        let pubkey_str = "04918dfc36c93e7db6cc0d60f37e1522f1c36b64d3f4b424c532d7c595febbc5";
         let pubkey = PublicKey::from_hex(pubkey_str.to_string()).unwrap();
-
-        assert_eq!(pubkey_str, pubkey.to_hex())
+        assert_eq!(pubkey_str, pubkey.to_hex())*/
     }
 
     #[test]

+ 1 - 1
crates/cashu/src/nuts/nut03.rs

@@ -14,7 +14,7 @@ pub use crate::Bolt11Invoice;
 #[derive(Debug, Clone, PartialEq, Eq, Serialize)]
 pub struct PreSwap {
     pub pre_mint_secrets: PreMintSecrets,
-    pub split_request: SwapRequest,
+    pub swap_request: SwapRequest,
 }
 
 /// Split Request [NUT-06]

+ 176 - 37
crates/cashu/src/nuts/nut11.rs

@@ -8,7 +8,7 @@ use std::str::FromStr;
 
 use bitcoin::hashes::{sha256, Hash};
 use k256::schnorr::signature::{Signer, Verifier};
-use k256::schnorr::{Signature, SigningKey, VerifyingKey};
+use k256::schnorr::Signature;
 use serde::de::Error as DeserializerError;
 use serde::ser::SerializeSeq;
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -16,17 +16,22 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
 use super::nut01::PublicKey;
 use super::nut02::Id;
 use super::nut10::{Secret, SecretData};
+use super::SecretKey;
 use crate::error::Error;
 use crate::utils::unix_time;
 use crate::Amount;
 
 #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
 pub struct Signatures {
+    #[serde(default)]
+    #[serde(skip_serializing_if = "Vec::is_empty")]
     signatures: Vec<String>,
 }
 
-fn no_signatures(signatures: &Signatures) -> bool {
-    signatures.signatures.is_empty()
+impl Signatures {
+    pub fn is_empty(&self) -> bool {
+        self.signatures.is_empty()
+    }
 }
 
 /// Proofs [NUT-11]
@@ -44,7 +49,7 @@ pub struct Proof {
     pub keyset_id: Id,
     /// Witness
     #[serde(default)]
-    #[serde(skip_serializing_if = "no_signatures")]
+    #[serde(skip_serializing_if = "Signatures::is_empty")]
     pub witness: Signatures,
 }
 
@@ -82,10 +87,10 @@ impl PartialOrd for Proof {
 pub struct P2PKConditions {
     #[serde(skip_serializing_if = "Option::is_none")]
     pub locktime: Option<u64>,
-    pub pubkeys: Vec<PublicKey>,
+    pub pubkeys: Vec<VerifyingKey>,
     #[serde(default)]
     #[serde(skip_serializing_if = "Vec::is_empty")]
-    pub refund_keys: Vec<PublicKey>,
+    pub refund_keys: Vec<VerifyingKey>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub num_sigs: Option<u64>,
     pub sig_flag: SigFlag,
@@ -94,8 +99,8 @@ pub struct P2PKConditions {
 impl P2PKConditions {
     pub fn new(
         locktime: Option<u64>,
-        pubkeys: Vec<PublicKey>,
-        refund_keys: Vec<PublicKey>,
+        pubkeys: Vec<VerifyingKey>,
+        refund_keys: Vec<VerifyingKey>,
         num_sigs: Option<u64>,
         sig_flag: Option<SigFlag>,
     ) -> Result<Self, Error> {
@@ -131,7 +136,7 @@ impl TryFrom<P2PKConditions> for Secret {
             return Err(Error::Amount);
         }
 
-        let data = pubkeys[0].to_hex();
+        let data = pubkeys[0].to_string();
 
         let mut tags = vec![];
 
@@ -187,14 +192,14 @@ impl TryFrom<Secret> for P2PKConditions {
             })
             .collect();
 
-        let mut pubkeys: Vec<PublicKey> = vec![];
+        let mut pubkeys: Vec<VerifyingKey> = vec![];
 
         if let Some(Tag::PubKeys(keys)) = tags.get(&TagKind::Pubkeys) {
             let mut keys = keys.clone();
             pubkeys.append(&mut keys);
         }
 
-        let data_pubkey = PublicKey::from_hex(secret.secret_data.data)?;
+        let data_pubkey = VerifyingKey::from_str(&secret.secret_data.data)?;
         pubkeys.push(data_pubkey);
 
         let locktime = if let Some(tag) = tags.get(&TagKind::Locktime) {
@@ -258,20 +263,15 @@ impl Proof {
 
         for signature in &self.witness.signatures {
             let mut pubkeys = spending_conditions.pubkeys.clone();
-            let data_key = PublicKey::from_str(&secret.secret_data.data).unwrap();
+            let data_key = VerifyingKey::from_str(&secret.secret_data.data).unwrap();
             pubkeys.push(data_key);
             for v in &spending_conditions.pubkeys {
                 let sig = Signature::try_from(hex::decode(signature).unwrap().as_slice()).unwrap();
 
-                let verifying_key: VerifyingKey = v.try_into()?;
-
-                if verifying_key.verify(&msg.to_byte_array(), &sig).is_ok() {
+                if v.verify(&msg.to_byte_array(), &sig).is_ok() {
                     valid_sigs += 1;
                 } else {
-                    println!(
-                        "{:?}",
-                        verifying_key.verify(&msg.to_byte_array(), &sig).unwrap()
-                    );
+                    println!("{:?}", v.verify(&msg.to_byte_array(), &sig).unwrap());
                 }
             }
         }
@@ -288,7 +288,6 @@ impl Proof {
                         for v in &spending_conditions.refund_keys {
                             let sig = Signature::try_from(s.as_bytes())
                                 .map_err(|_| Error::InvalidSignature)?;
-                            let v: VerifyingKey = v.clone().try_into()?;
 
                             // As long as there is one valid refund signature it can be spent
                             if v.verify(&msg.to_byte_array(), &sig).is_ok() {
@@ -398,8 +397,8 @@ pub enum Tag {
     SigFlag(SigFlag),
     NSigs(u64),
     LockTime(u64),
-    Refund(Vec<PublicKey>),
-    PubKeys(Vec<PublicKey>),
+    Refund(Vec<VerifyingKey>),
+    PubKeys(Vec<VerifyingKey>),
 }
 
 impl Tag {
@@ -445,7 +444,7 @@ where
                     let pubkeys = tag
                         .iter()
                         .skip(1)
-                        .flat_map(|p| PublicKey::from_hex(p.as_ref().to_string()))
+                        .flat_map(|p| VerifyingKey::from_str(p.as_ref()))
                         .collect();
 
                     Ok(Self::Refund(pubkeys))
@@ -454,7 +453,7 @@ where
                     let pubkeys = tag
                         .iter()
                         .skip(1)
-                        .flat_map(|p| PublicKey::from_hex(p.as_ref().to_string()))
+                        .flat_map(|p| VerifyingKey::from_str(p.as_ref()))
                         .collect();
 
                     Ok(Self::PubKeys(pubkeys))
@@ -477,7 +476,7 @@ impl From<Tag> for Vec<String> {
                 let mut tag = vec![TagKind::Pubkeys.to_string()];
 
                 for pubkey in pubkeys {
-                    tag.push(pubkey.to_hex())
+                    tag.push(pubkey.to_string())
                 }
                 tag
             }
@@ -485,7 +484,7 @@ impl From<Tag> for Vec<String> {
                 let mut tag = vec![TagKind::Refund.to_string()];
 
                 for pubkey in pubkeys {
-                    tag.push(pubkey.to_hex())
+                    tag.push(pubkey.to_string())
                 }
                 tag
             }
@@ -518,33 +517,174 @@ impl<'de> Deserialize<'de> for Tag {
     }
 }
 
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct VerifyingKey(k256::schnorr::VerifyingKey);
+
+impl VerifyingKey {
+    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
+        Ok(VerifyingKey(
+            k256::schnorr::VerifyingKey::from_bytes(bytes).unwrap(),
+        ))
+    }
+
+    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
+        Ok(self.0.verify(msg, signature).unwrap())
+    }
+}
+
+impl FromStr for VerifyingKey {
+    type Err = Error;
+
+    fn from_str(hex: &str) -> Result<Self, Self::Err> {
+        let bytes = hex::decode(hex)?;
+
+        let bytes = if bytes.len().eq(&33) {
+            bytes.iter().skip(1).cloned().collect()
+        } else {
+            bytes.to_vec()
+        };
+
+        Ok(VerifyingKey(
+            k256::schnorr::VerifyingKey::from_bytes(&bytes).map_err(|_| Error::Key)?,
+        ))
+    }
+}
+
+impl std::fmt::Display for VerifyingKey {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let bytes = self.0.to_bytes();
+        f.write_str(&hex::encode(bytes))
+    }
+}
+
+impl From<VerifyingKey> for k256::schnorr::VerifyingKey {
+    fn from(value: VerifyingKey) -> k256::schnorr::VerifyingKey {
+        value.0
+    }
+}
+
+impl From<&VerifyingKey> for k256::schnorr::VerifyingKey {
+    fn from(value: &VerifyingKey) -> k256::schnorr::VerifyingKey {
+        value.0
+    }
+}
+
+impl From<k256::schnorr::VerifyingKey> for VerifyingKey {
+    fn from(value: k256::schnorr::VerifyingKey) -> VerifyingKey {
+        VerifyingKey(value)
+    }
+}
+
+impl TryFrom<PublicKey> for VerifyingKey {
+    type Error = Error;
+    fn try_from(value: PublicKey) -> Result<VerifyingKey, Self::Error> {
+        (&value).try_into()
+    }
+}
+
+impl TryFrom<&PublicKey> for VerifyingKey {
+    type Error = Error;
+    fn try_from(value: &PublicKey) -> Result<VerifyingKey, Self::Error> {
+        let bytes = value.to_bytes();
+
+        let bytes = if bytes.len().eq(&33) {
+            bytes.iter().skip(1).cloned().collect()
+        } else {
+            bytes.to_vec()
+        };
+
+        VerifyingKey::from_bytes(&bytes).map_err(|_| Error::Key)
+    }
+}
+
+#[derive(Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct SigningKey(k256::schnorr::SigningKey);
+
+impl From<SigningKey> for k256::schnorr::SigningKey {
+    fn from(value: SigningKey) -> k256::schnorr::SigningKey {
+        value.0
+    }
+}
+
+impl From<k256::schnorr::SigningKey> for SigningKey {
+    fn from(value: k256::schnorr::SigningKey) -> Self {
+        Self(value)
+    }
+}
+
+impl From<SecretKey> for SigningKey {
+    fn from(value: SecretKey) -> SigningKey {
+        value.into()
+    }
+}
+
+impl SigningKey {
+    pub fn public_key(&self) -> VerifyingKey {
+        self.0.verifying_key().clone().into()
+    }
+
+    pub fn sign(&self, msg: &[u8]) -> Signature {
+        self.0.sign(msg)
+    }
+
+    pub fn verifying_key(&self) -> VerifyingKey {
+        VerifyingKey(self.0.verifying_key().clone())
+    }
+}
+
+impl FromStr for SigningKey {
+    type Err = Error;
+
+    fn from_str(hex: &str) -> Result<Self, Self::Err> {
+        let bytes = hex::decode(hex)?;
+
+        let bytes = if bytes.len().eq(&33) {
+            bytes.iter().skip(1).cloned().collect()
+        } else {
+            bytes.to_vec()
+        };
+
+        Ok(SigningKey(
+            k256::schnorr::SigningKey::from_bytes(&bytes).map_err(|_| Error::Key)?,
+        ))
+    }
+}
+
+impl std::fmt::Display for SigningKey {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let bytes = self.0.to_bytes();
+
+        f.write_str(&hex::encode(bytes))
+    }
+}
 #[cfg(test)]
 mod tests {
 
     use std::str::FromStr;
 
     use super::*;
-    use crate::nuts::SecretKey;
 
     #[test]
     fn test_secret_ser() {
         let conditions = P2PKConditions {
             locktime: Some(99999),
             pubkeys: vec![
-                PublicKey::from_str(
+                VerifyingKey::from_str(
                     "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
                 )
                 .unwrap(),
-                PublicKey::from_str(
+                VerifyingKey::from_str(
                     "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
                 )
                 .unwrap(),
-                PublicKey::from_str(
+                VerifyingKey::from_str(
                     "023192200a0cfd3867e48eb63b03ff599c7e46c8f4e41146b2d281173ca6c50c54",
                 )
                 .unwrap(),
             ],
-            refund_keys: vec![PublicKey::from_str(
+            refund_keys: vec![VerifyingKey::from_str(
                 "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
             )
             .unwrap()],
@@ -572,13 +712,12 @@ mod tests {
 
     #[test]
     fn sign_proof() {
-        let secret_key =
-            SecretKey::from_hex("04918dfc36c93e7db6cc0d60f37e1522f1c36b64d3f4b424c532d7c595febbc5")
-                .unwrap();
-
-        let pubkey: PublicKey = secret_key.public_key();
+        let secret_key = SigningKey::from_str(
+            "04918dfc36c93e7db6cc0d60f37e1522f1c36b64d3f4b424c532d7c595febbc5",
+        )
+        .unwrap();
 
-        let v_key: VerifyingKey = pubkey.clone().try_into().unwrap();
+        let v_key: VerifyingKey = secret_key.verifying_key();
 
         let conditions = P2PKConditions {
             locktime: None,