Przeglądaj źródła

feat: nut11 p2pk

thesimplekid 1 rok temu
rodzic
commit
1892a9a4b7

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

@@ -168,15 +168,19 @@ impl Client for HttpClient {
     async fn post_swap(
         &self,
         mint_url: Url,
-        split_request: SwapRequest,
+        swap_request: SwapRequest,
     ) -> Result<SwapResponse, Error> {
         let url = join_url(mint_url, &["v1", "swap"])?;
 
-        let res = minreq::post(url).with_json(&split_request)?.send()?;
+        println!("{}", serde_json::to_string(&swap_request).unwrap());
+
+        let res = minreq::post(url).with_json(&swap_request)?.send()?;
 
         let value = res.json::<Value>()?;
+        println!("{}", value);
         let response: Result<SwapResponse, serde_json::Error> =
             serde_json::from_value(value.clone());
+        println!("{:?}", response);
 
         match response {
             Ok(res) => Ok(res),

+ 1 - 0
crates/cashu-sdk/src/mint/mod.rs

@@ -311,6 +311,7 @@ impl Mint {
             amount,
             b,
             keyset_id,
+            ..
         } = blinded_message;
 
         let keyset = self

+ 141 - 47
crates/cashu-sdk/src/wallet/mod.rs

@@ -9,7 +9,7 @@ use cashu::nuts::nut07::ProofState;
 use cashu::nuts::nut11::SigningKey;
 use cashu::nuts::{
     BlindedSignature, CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, P2PKConditions, PreMintSecrets,
-    PreSwap, Proof, Proofs, SwapRequest, Token,
+    PreSwap, Proof, Proofs, SigFlag, SwapRequest, Token,
 };
 #[cfg(feature = "nut07")]
 use cashu::secret::Secret;
@@ -234,6 +234,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
         }
 
         let keysets = self.client.get_mint_keysets(mint_url.try_into()?).await?;
+        println!("{:?}", keysets);
 
         self.localstore
             .add_mint_keysets(
@@ -353,7 +354,17 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
 
             // TODO: if none fetch keyset for mint
 
-            let keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
+            let keys =
+                if let Some(keys) = self.localstore.get_keys(&active_keyset_id.unwrap()).await? {
+                    keys
+                } else {
+                    self.get_mint_keys(&token.mint, active_keyset_id.unwrap())
+                        .await?;
+                    self.localstore
+                        .get_keys(&active_keyset_id.unwrap())
+                        .await?
+                        .unwrap()
+                };
 
             // Sum amount of all proofs
             let amount: Amount = token.proofs.iter().map(|p| p.amount).sum();
@@ -372,15 +383,20 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
                 swap_response.signatures,
                 pre_swap.pre_mint_secrets.rs(),
                 pre_swap.pre_mint_secrets.secrets(),
-                &keys.unwrap(),
+                &keys,
             )?;
+            //  println!("{:?}", p);
             let mint_proofs = proofs.entry(token.mint).or_default();
 
             mint_proofs.extend(p);
         }
+        //println!("{:?}", proofs);
 
-        for (mint, proofs) in proofs {
-            self.localstore.add_proofs(mint, proofs).await?;
+        for (mint, p) in proofs {
+            println!("{:?}", serde_json::to_string(&p));
+            println!("{:?}", mint);
+            self.add_mint(mint.clone()).await?;
+            self.localstore.add_proofs(mint, p).await?;
         }
 
         Ok(())
@@ -408,9 +424,9 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
             desired_messages.sort_secrets();
             desired_messages
         } else {
-            let value = proofs.iter().map(|p| p.amount).sum();
+            let amount = proofs.iter().map(|p| p.amount).sum();
 
-            PreMintSecrets::random(active_keyset_id, value)?
+            PreMintSecrets::random(active_keyset_id, amount)?
         };
 
         let swap_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
@@ -420,7 +436,51 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
             swap_request,
         })
     }
+    /*
+        /// Create Swap Payload
+        async fn create_swap_signed(
+            &mut self,
+            mint_url: &UncheckedUrl,
+            unit: &CurrencyUnit,
+            amount: Option<Amount>,
+            proofs: Proofs,
+            signing_key: Option<SigningKey>,
+        ) -> Result<PreSwap, Error> {
+            let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?.unwrap();
+
+            let pre_mint_secrets = if let Some(amount) = amount {
+                let mut desired_messages = PreMintSecrets::random(active_keyset_id, amount)?;
+
+                let change_amount = proofs.iter().map(|p| p.amount).sum::<Amount>() - amount;
+
+                let change_messages = if let Some(signing_key) = signing_key {
+                    PreMintSecrets::random_signed(active_keyset_id, change_amount, signing_key)?
+                } else {
+                    PreMintSecrets::random(active_keyset_id, change_amount)?
+                };
+                // Combine the BlindedMessages totoalling the desired amount with change
+                desired_messages.combine(change_messages);
+                // Sort the premint secrets to avoid finger printing
+                desired_messages.sort_secrets();
+                desired_messages
+            } else {
+                let amount = proofs.iter().map(|p| p.amount).sum();
+
+                if let Some(signing_key) = signing_key {
+                    PreMintSecrets::random_signed(active_keyset_id, amount, signing_key)?
+                } else {
+                    PreMintSecrets::random(active_keyset_id, amount)?
+                }
+            };
+
+            let swap_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
 
+            Ok(PreSwap {
+                pre_mint_secrets,
+                swap_request,
+            })
+        }
+    */
     pub async fn process_swap_response(
         &self,
         blinded_messages: PreMintSecrets,
@@ -752,6 +812,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
         encoded_token: &str,
         signing_keys: Vec<SigningKey>,
     ) -> Result<(), Error> {
+        let signing_key = signing_keys[0].clone();
         let pubkey_secret_key: HashMap<String, SigningKey> = signing_keys
             .into_iter()
             .map(|s| (s.public_key().to_string(), s))
@@ -778,6 +839,8 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
 
             let mut proofs = token.proofs;
 
+            let mut sig_flag = None;
+
             for proof in &mut proofs {
                 if let Ok(secret) =
                     <cashu::secret::Secret as TryInto<cashu::nuts::nut10::Secret>>::try_into(
@@ -786,21 +849,36 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
                 {
                     let conditions: Result<P2PKConditions, _> = secret.try_into();
                     if let Ok(conditions) = conditions {
+                        println!("{:?}", conditions);
                         let pubkeys = conditions.pubkeys;
 
                         for pubkey in pubkeys {
                             if let Some(signing) = pubkey_secret_key.get(&pubkey.to_string()) {
-                                proof.sign_p2pk_proof(signing.clone()).ok();
+                                proof.sign_p2pk_proof(signing.clone()).unwrap();
+                                proof.verify_p2pk().unwrap();
+                                println!("v");
                             }
                         }
+
+                        sig_flag = Some(conditions.sig_flag);
                     }
                 }
             }
 
-            let pre_swap = self
+            let mut pre_swap = self
                 .create_swap(&token.mint, &unit, Some(amount), proofs)
                 .await?;
 
+            if let Some(sigflag) = sig_flag {
+                if sigflag.eq(&SigFlag::SigAll) {
+                    for blinded_message in &mut pre_swap.swap_request.outputs {
+                        blinded_message
+                            .sign_p2pk_blinded_message(signing_key.clone())
+                            .unwrap();
+                    }
+                }
+            }
+
             let swap_response = self
                 .client
                 .post_swap(token.mint.clone().try_into()?, pre_swap.swap_request)
@@ -824,54 +902,70 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
 
         Ok(())
     }
+    /*
+        pub async fn claim_p2pk_locked_proofs(
+            &mut self,
+            sigflag: SigFlag,
+            mint_url: &UncheckedUrl,
+            unit: &CurrencyUnit,
+            signing_key: SigningKey,
+            proofs: Proofs,
+        ) -> Result<(), Error> {
+            let active_keyset_id = self.active_mint_keyset(&mint_url, &unit).await?;
 
-    pub async fn claim_p2pk_locked_proofs(
-        &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 keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
 
-        let mut signed_proofs: Proofs = Vec::with_capacity(proofs.len());
+            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();
+            // 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);
-        }
+            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 pre_swap = match sigflag {
+                SigFlag::SigInputs => {
+                    self.create_swap(mint_url, &unit, Some(amount), signed_proofs)
+                        .await?
+                }
+                SigFlag::SigAll => {
+                    self.create_swap_signed(
+                        mint_url,
+                        unit,
+                        Some(amount),
+                        signed_proofs,
+                        Some(signing_key),
+                    )
+                    .await?
+                }
+                _ => todo!(),
+            };
 
-        let swap_response = self
-            .client
-            .post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
-            .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(),
-        )?;
+            // 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
+                .remove_proofs(mint_url.clone(), &proofs)
+                .await?;
 
-        self.localstore.add_proofs(mint_url.clone(), p).await?;
+            self.localstore.add_proofs(mint_url.clone(), p).await?;
 
-        Ok(())
-    }
+            Ok(())
+        }
+    */
 
     pub fn proofs_to_token(
         &self,

+ 9 - 1
crates/cashu/src/error.rs

@@ -64,7 +64,15 @@ pub struct ErrorResponse {
 
 impl ErrorResponse {
     pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
-        serde_json::from_str(json)
+        if let Ok(res) = serde_json::from_str::<ErrorResponse>(json) {
+            Ok(res)
+        } else {
+            Ok(Self {
+                code: 999,
+                error: Some(json.to_string()),
+                detail: None,
+            })
+        }
     }
 }
 

+ 40 - 29
crates/cashu/src/nuts/nut00.rs

@@ -2,13 +2,14 @@
 // https://github.com/cashubtc/nuts/blob/main/00.md
 
 use std::fmt;
-use std::hash::{Hash, Hasher};
+use std::hash::{self, Hasher};
 use std::str::FromStr;
 
 use serde::{Deserialize, Serialize};
 
-use super::{Id, Proofs, PublicKey};
+use super::{Id, Proofs, PublicKey, Signatures, SigningKey};
 use crate::error::Error;
+use crate::nuts::nut11::{witness_deserialize, witness_serialize};
 use crate::secret::Secret;
 use crate::url::UncheckedUrl;
 use crate::Amount;
@@ -24,9 +25,39 @@ pub struct BlindedMessage {
     /// encrypted secret message (B_)
     #[serde(rename = "B_")]
     pub b: PublicKey,
+    /// Witness
+    #[serde(default)]
+    #[serde(skip_serializing_if = "Signatures::is_empty")]
+    #[serde(serialize_with = "witness_serialize")]
+    #[serde(deserialize_with = "witness_deserialize")]
+    pub witness: Signatures,
 }
 
-#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Hash)]
+impl BlindedMessage {
+    pub fn new(amount: Amount, keyset_id: Id, b: PublicKey) -> Self {
+        Self {
+            amount,
+            keyset_id,
+            b,
+            witness: Signatures::default(),
+        }
+    }
+
+    pub fn sign_p2pk_blinded_message(&mut self, secret_key: SigningKey) -> Result<(), Error> {
+        let msg_to_sign = hex::decode(self.b.to_string())?;
+
+        println!("{:?}", msg_to_sign);
+
+        let signature = secret_key.sign(&msg_to_sign);
+
+        self.witness
+            .signatures
+            .push(hex::encode(signature.to_bytes()));
+        Ok(())
+    }
+}
+
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, hash::Hash)]
 #[serde(rename_all = "lowercase")]
 pub enum CurrencyUnit {
     #[default]
@@ -145,11 +176,7 @@ pub mod wallet {
                 let secret = Secret::new();
                 let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
 
-                let blinded_message = BlindedMessage {
-                    amount,
-                    b: blinded,
-                    keyset_id,
-                };
+                let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
 
                 output.push(PreMint {
                     secret,
@@ -172,11 +199,7 @@ pub mod wallet {
             for (secret, amount) in secrets.into_iter().zip(amounts) {
                 let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
 
-                let blinded_message = BlindedMessage {
-                    amount,
-                    b: blinded,
-                    keyset_id,
-                };
+                let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
 
                 output.push(PreMint {
                     secret,
@@ -199,11 +222,7 @@ pub mod wallet {
                 let secret = Secret::new();
                 let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
 
-                let blinded_message = BlindedMessage {
-                    amount: Amount::ZERO,
-                    b: blinded,
-                    keyset_id,
-                };
+                let blinded_message = BlindedMessage::new(Amount::ZERO, keyset_id, blinded);
 
                 output.push(PreMint {
                     secret,
@@ -236,11 +255,7 @@ pub mod wallet {
                 let (blinded, r) =
                     blind_message(&secret.to_bytes()?, Some(blinding_factor.into()))?;
 
-                let blinded_message = BlindedMessage {
-                    keyset_id,
-                    amount,
-                    b: blinded,
-                };
+                let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
 
                 let pre_mint = PreMint {
                     blinded_message,
@@ -270,11 +285,7 @@ pub mod wallet {
                 let secret: Secret = conditions.clone().try_into().unwrap();
                 let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
 
-                let blinded_message = BlindedMessage {
-                    amount,
-                    b: blinded,
-                    keyset_id,
-                };
+                let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
 
                 output.push(PreMint {
                     secret,
@@ -480,7 +491,7 @@ impl Proof {
     }
 }
 
-impl Hash for Proof {
+impl hash::Hash for Proof {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.secret.hash(state);
     }

+ 6 - 0
crates/cashu/src/nuts/nut01.rs

@@ -64,6 +64,12 @@ impl From<VerifyingKey> for PublicKey {
     }
 }
 
+impl From<super::VerifyingKey> for PublicKey {
+    fn from(value: super::VerifyingKey) -> PublicKey {
+        let v: VerifyingKey = value.into();
+        PublicKey(v.into())
+    }
+}
 impl PublicKey {
     pub fn to_bytes(&self) -> Box<[u8]> {
         self.0.to_sec1_bytes()

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

@@ -6,12 +6,11 @@ use std::fmt;
 use std::hash::{self, Hasher};
 use std::str::FromStr;
 
-use bitcoin::hashes::{sha256, Hash};
 use k256::schnorr::signature::{Signer, Verifier};
 use k256::schnorr::Signature;
 use serde::de::Error as DeserializerError;
 use serde::ser::SerializeSeq;
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
 
 use super::nut01::PublicKey;
 use super::nut02::Id;
@@ -25,7 +24,7 @@ use crate::Amount;
 pub struct Signatures {
     #[serde(default)]
     #[serde(skip_serializing_if = "Vec::is_empty")]
-    signatures: Vec<String>,
+    pub signatures: Vec<String>,
 }
 
 impl Signatures {
@@ -50,9 +49,26 @@ pub struct Proof {
     /// Witness
     #[serde(default)]
     #[serde(skip_serializing_if = "Signatures::is_empty")]
+    #[serde(serialize_with = "witness_serialize")]
+    #[serde(deserialize_with = "witness_deserialize")]
     pub witness: Signatures,
 }
 
+pub fn witness_serialize<S>(x: &Signatures, s: S) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+{
+    s.serialize_str(&serde_json::to_string(x).map_err(ser::Error::custom)?)
+}
+
+pub fn witness_deserialize<'de, D>(deserializer: D) -> Result<Signatures, D::Error>
+where
+    D: de::Deserializer<'de>,
+{
+    let s: String = String::deserialize(deserializer)?;
+    serde_json::from_str(&s).map_err(de::Error::custom)
+}
+
 impl Proof {
     pub fn new(amount: Amount, keyset_id: Id, secret: crate::secret::Secret, c: PublicKey) -> Self {
         Proof {
@@ -136,7 +152,9 @@ impl TryFrom<P2PKConditions> for Secret {
             return Err(Error::Amount);
         }
 
-        let data = pubkeys[0].to_string();
+        let data: PublicKey = pubkeys[0].clone().into();
+
+        let data = data.to_string();
 
         let mut tags = vec![];
 
@@ -259,7 +277,13 @@ impl Proof {
 
         let mut valid_sigs = 0;
 
-        let msg = sha256::Hash::hash(&self.secret.to_bytes().unwrap());
+        println!("{:?}", self.secret.to_string());
+        println!(
+            "sec bytes: {:?}",
+            self.secret.to_string().into_bytes().len()
+        );
+
+        let msg = &self.secret.to_bytes().unwrap();
 
         for signature in &self.witness.signatures {
             let mut pubkeys = spending_conditions.pubkeys.clone();
@@ -268,31 +292,30 @@ impl Proof {
             for v in &spending_conditions.pubkeys {
                 let sig = Signature::try_from(hex::decode(signature).unwrap().as_slice()).unwrap();
 
-                if v.verify(&msg.to_byte_array(), &sig).is_ok() {
+                if v.verify(msg, &sig).is_ok() {
                     valid_sigs += 1;
                 } else {
-                    println!("{:?}", v.verify(&msg.to_byte_array(), &sig).unwrap());
+                    println!("{:?}", v.verify(msg, &sig).unwrap());
                 }
             }
         }
 
         if valid_sigs.ge(&spending_conditions.num_sigs.unwrap_or(1)) {
+            println!("valid sigs: {}", valid_sigs);
             return Ok(());
         }
 
         if let Some(locktime) = spending_conditions.locktime {
             // If lock time has passed check if refund witness signature is valid
-            if locktime.lt(&unix_time()) {
-                if !spending_conditions.refund_keys.is_empty() {
-                    for s in &self.witness.signatures {
-                        for v in &spending_conditions.refund_keys {
-                            let sig = Signature::try_from(s.as_bytes())
-                                .map_err(|_| Error::InvalidSignature)?;
-
-                            // As long as there is one valid refund signature it can be spent
-                            if v.verify(&msg.to_byte_array(), &sig).is_ok() {
-                                return Ok(());
-                            }
+            if locktime.lt(&unix_time()) && !spending_conditions.refund_keys.is_empty() {
+                for s in &self.witness.signatures {
+                    for v in &spending_conditions.refund_keys {
+                        let sig = Signature::try_from(s.as_bytes())
+                            .map_err(|_| Error::InvalidSignature)?;
+
+                        // As long as there is one valid refund signature it can be spent
+                        if v.verify(msg, &sig).is_ok() {
+                            return Ok(());
                         }
                     }
                 }
@@ -303,13 +326,14 @@ impl Proof {
     }
 
     pub fn sign_p2pk_proof(&mut self, secret_key: SigningKey) -> Result<(), Error> {
-        let msg_to_sign = sha256::Hash::hash(&self.secret.to_bytes().unwrap());
+        let msg_to_sign = &self.secret.to_bytes().unwrap();
 
-        let signature = secret_key.sign(msg_to_sign.as_byte_array());
+        let signature = secret_key.sign(msg_to_sign);
 
         self.witness
             .signatures
             .push(hex::encode(signature.to_bytes()));
+
         Ok(())
     }
 }
@@ -476,6 +500,7 @@ impl From<Tag> for Vec<String> {
                 let mut tag = vec![TagKind::Pubkeys.to_string()];
 
                 for pubkey in pubkeys {
+                    let pubkey: PublicKey = pubkey.into();
                     tag.push(pubkey.to_string())
                 }
                 tag
@@ -529,7 +554,10 @@ impl VerifyingKey {
     }
 
     pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
-        Ok(self.0.verify(msg, signature).unwrap())
+        self.0
+            .verify(msg, signature)
+            .map_err(|_| Error::InvalidSignature)?;
+        Ok(())
     }
 }
 
@@ -622,7 +650,7 @@ impl From<SecretKey> for SigningKey {
 
 impl SigningKey {
     pub fn public_key(&self) -> VerifyingKey {
-        self.0.verifying_key().clone().into()
+        (*self.0.verifying_key()).into()
     }
 
     pub fn sign(&self, msg: &[u8]) -> Signature {
@@ -630,7 +658,7 @@ impl SigningKey {
     }
 
     pub fn verifying_key(&self) -> VerifyingKey {
-        VerifyingKey(self.0.verifying_key().clone())
+        VerifyingKey(*self.0.verifying_key())
     }
 }
 
@@ -702,15 +730,6 @@ mod tests {
     }
 
     #[test]
-    fn test_verify() {
-        let proof_str = r#"{"amount":0,"secret":"[\"P2PK\",{\"nonce\":\"190badde56afcbf67937e228744ea896bb3e48bcb60efa412799e1518618c287\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id": "009a1f293253e41e","witness":{"signatures":["2b117c29a0e405fcbcac4c632b5862eb3ace0d67c681e8209d3aa2f52d5198471629b1ec6bce75d3879c47725be89d28938e31236307b40bc6c89491fa540e35"]}}"#;
-
-        let proof: Proof = serde_json::from_str(proof_str).unwrap();
-
-        assert!(proof.verify_p2pk().is_ok());
-    }
-
-    #[test]
     fn sign_proof() {
         let secret_key = SigningKey::from_str(
             "04918dfc36c93e7db6cc0d60f37e1522f1c36b64d3f4b424c532d7c595febbc5",
@@ -721,7 +740,7 @@ mod tests {
 
         let conditions = P2PKConditions {
             locktime: None,
-            pubkeys: vec![v_key.into()],
+            pubkeys: vec![v_key],
             refund_keys: vec![],
             num_sigs: None,
             sig_flag: SigFlag::SigInputs,
@@ -732,7 +751,7 @@ mod tests {
         let mut proof = Proof {
             keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
             amount: Amount::ZERO,
-            secret: secret.try_into().unwrap(),
+            secret: secret.clone().try_into().unwrap(),
             c: PublicKey::from_str(
                 "02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
             )
@@ -740,9 +759,7 @@ mod tests {
             witness: Signatures { signatures: vec![] },
         };
 
-        let signing_key: SigningKey = secret_key.try_into().unwrap();
-
-        proof.sign_p2pk_proof(signing_key).unwrap();
+        proof.sign_p2pk_proof(secret_key).unwrap();
 
         assert!(proof.verify_p2pk().is_ok());
     }

+ 1 - 1
crates/cashu/src/secret.rs

@@ -69,7 +69,7 @@ impl Secret {
             serde_json::from_str(&self.0);
 
         match secret {
-            Ok(_) => Ok(self.0.clone().into_bytes()),
+            Ok(_) => Ok(self.0.clone().replace('\\', "").into_bytes()),
             Err(_) => Ok(hex::decode(&self.0)?),
         }
     }