From 9ddd36fc194c5c7bb47bfd921b1fbd3ad1841d63 Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Mon, 4 Sep 2023 22:58:09 +0100 Subject: [PATCH] cashu-sdk/mint: improve: check proofs are unique `melt`/`split` --- crates/cashu-sdk/src/mint.rs | 31 ++++++++++++++++++++++--------- crates/cashu/src/error.rs | 3 +++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/crates/cashu-sdk/src/mint.rs b/crates/cashu-sdk/src/mint.rs index 57417e83..d039e08f 100644 --- a/crates/cashu-sdk/src/mint.rs +++ b/crates/cashu-sdk/src/mint.rs @@ -108,10 +108,17 @@ impl Mint { return Err(Error::Amount); } - let mut secrets = Vec::with_capacity(split_request.proofs.len()); - for proof in &split_request.proofs { - secrets.push(self.verify_proof(proof)?); - self.spent_secrets.insert(proof.secret.clone()); + let proof_count = split_request.proofs.len(); + + let secrets: HashSet = split_request.proofs.into_iter().map(|p| p.secret).collect(); + + // Check that there are no duplicate proofs in request + if secrets.len().ne(&proof_count) { + return Err(Error::DuplicateProofs); + } + + for secret in secrets { + self.spent_secrets.insert(secret); } match &split_request.amount { @@ -146,7 +153,7 @@ impl Mint { } } - pub fn verify_proof(&self, proof: &Proof) -> Result { + pub fn verify_proof(&self, proof: &Proof) -> Result<(), Error> { if self.spent_secrets.contains(&proof.secret) { return Err(Error::TokenSpent); } @@ -172,7 +179,7 @@ impl Mint { &proof.secret, )?; - Ok(proof.secret.clone()) + Ok(()) } pub fn check_spendable( @@ -202,9 +209,15 @@ impl Mint { return Err(Error::Amount); } - let mut secrets = Vec::with_capacity(melt_request.proofs.len()); - for proof in &melt_request.proofs { - secrets.push(self.verify_proof(proof)?); + let secrets: HashSet<&str> = melt_request + .proofs + .iter() + .map(|p| p.secret.as_str()) + .collect(); + + // Ensure proofs are unique and not being double spent + if melt_request.proofs.len().ne(&secrets.len()) { + return Err(Error::DuplicateProofs); } Ok(()) diff --git a/crates/cashu/src/error.rs b/crates/cashu/src/error.rs index 0b912310..c50e59be 100644 --- a/crates/cashu/src/error.rs +++ b/crates/cashu/src/error.rs @@ -162,6 +162,8 @@ pub mod mint { EllipticError(k256::elliptic_curve::Error), TokenNotVerifed, InvoiceAmountUndefined, + /// Duplicate Proofs sent in request + DuplicateProofs, CustomError(String), } @@ -177,6 +179,7 @@ pub mod mint { Error::CustomError(err) => write!(f, "{}", err), Error::TokenNotVerifed => write!(f, "Token Not Verified"), Error::InvoiceAmountUndefined => write!(f, "Invoice without amount"), + Error::DuplicateProofs => write!(f, "Request has duplicate proofs"), } } }