diff --git a/crates/cashu-sdk/src/mint/mod.rs b/crates/cashu-sdk/src/mint/mod.rs index ebaaab43..75b51da1 100644 --- a/crates/cashu-sdk/src/mint/mod.rs +++ b/crates/cashu-sdk/src/mint/mod.rs @@ -48,13 +48,17 @@ pub enum Error { #[error("`{0}`")] Custom(String), #[error("`{0}`")] - Cashu(#[from] cashu::error::mint::Error), + CashuMint(#[from] cashu::error::mint::Error), + #[error("`{0}`")] + Cashu(#[from] cashu::error::Error), #[error("`{0}`")] Localstore(#[from] localstore::Error), #[error("`{0}`")] Secret(#[from] cashu::secret::Error), #[error("Unknown quote")] UnknownQuote, + #[error("Unknown secret kind")] + UnknownSecretKind, #[error("Cannot have multiple units")] MultipleUnits, } @@ -420,6 +424,7 @@ impl Mint { Ok(SwapResponse::new(promises)) } + #[cfg(not(feature = "nut11"))] async fn verify_proof(&self, proof: &Proof) -> Result<(), Error> { let y = hash_to_curve(&proof.secret.to_bytes().unwrap()).unwrap(); if self.localstore.get_spent_proof_by_hash(&y).await?.is_some() { @@ -454,6 +459,54 @@ impl Mint { Ok(()) } + #[cfg(feature = "nut11")] + async fn verify_proof(&self, proof: &Proof) -> Result<(), Error> { + // Check if secret is a nut10 secret with conditions + if let Ok(secret) = + <&cashu::secret::Secret as TryInto>::try_into(&proof.secret) + { + // Verify if p2pk + if secret.kind.eq(&Kind::P2PK) { + proof.verify_p2pk()?; + } else { + return Err(Error::UnknownSecretKind); + } + } + + let y = hash_to_curve(&proof.secret.to_bytes()?)?; + + if self.localstore.get_spent_proof_by_hash(&y).await?.is_some() { + return Err(Error::TokenSpent); + } + + if self + .localstore + .get_pending_proof_by_hash(&y) + .await? + .is_some() + { + return Err(Error::TokenPending); + } + + let keyset = self + .localstore + .get_keyset(&proof.keyset_id) + .await? + .ok_or(Error::UnknownKeySet)?; + + let Some(keypair) = keyset.keys.0.get(&proof.amount) else { + return Err(Error::AmountKey); + }; + + verify_message( + keypair.secret_key.clone().into(), + proof.c.clone().into(), + &proof.secret, + )?; + + Ok(()) + } + #[cfg(feature = "nut07")] pub async fn check_state( &self,