Bladeren bron

fix: use Y

thesimplekid 1 jaar geleden
bovenliggende
commit
7c9d9fcf6a

+ 74 - 16
crates/cashu-sdk/src/mint/localstore/memory.rs

@@ -2,6 +2,8 @@ use std::collections::HashMap;
 use std::sync::Arc;
 
 use async_trait::async_trait;
+use cashu::dhke::hash_to_curve;
+use cashu::k256;
 use cashu::nuts::nut02::mint::KeySet;
 use cashu::nuts::{CurrencyUnit, Id, MintInfo, Proof, Proofs};
 use cashu::secret::Secret;
@@ -17,8 +19,8 @@ pub struct MemoryLocalStore {
     keysets: Arc<Mutex<HashMap<Id, KeySet>>>,
     mint_quotes: Arc<Mutex<HashMap<String, MintQuote>>>,
     melt_quotes: Arc<Mutex<HashMap<String, MeltQuote>>>,
-    pending_proofs: Arc<Mutex<HashMap<Secret, Proof>>>,
-    spent_proofs: Arc<Mutex<HashMap<Secret, Proof>>>,
+    pending_proofs: Arc<Mutex<HashMap<Vec<u8>, Proof>>>,
+    spent_proofs: Arc<Mutex<HashMap<Vec<u8>, Proof>>>,
 }
 
 impl MemoryLocalStore {
@@ -30,8 +32,8 @@ impl MemoryLocalStore {
         melt_quotes: Vec<MeltQuote>,
         pending_proofs: Proofs,
         spent_proofs: Proofs,
-    ) -> Self {
-        Self {
+    ) -> Result<Self, Error> {
+        Ok(Self {
             mint_info: Arc::new(Mutex::new(mint_info)),
             active_keysets: Arc::new(Mutex::new(active_keysets)),
             keysets: Arc::new(Mutex::new(keysets.into_iter().map(|k| (k.id, k)).collect())),
@@ -44,16 +46,30 @@ impl MemoryLocalStore {
             pending_proofs: Arc::new(Mutex::new(
                 pending_proofs
                     .into_iter()
-                    .map(|p| (p.secret.clone(), p))
+                    .map(|p| {
+                        (
+                            hash_to_curve(&p.secret.to_bytes().unwrap())
+                                .to_sec1_bytes()
+                                .to_vec(),
+                            p,
+                        )
+                    })
                     .collect(),
             )),
             spent_proofs: Arc::new(Mutex::new(
                 spent_proofs
                     .into_iter()
-                    .map(|p| (p.secret.clone(), p))
+                    .map(|p| {
+                        (
+                            hash_to_curve(&p.secret.to_bytes().unwrap())
+                                .to_sec1_bytes()
+                                .to_vec(),
+                            p,
+                        )
+                    })
                     .collect(),
             )),
-        }
+        })
     }
 }
 
@@ -138,31 +154,73 @@ impl LocalStore for MemoryLocalStore {
     }
 
     async fn add_spent_proof(&self, proof: Proof) -> Result<(), Error> {
+        let secret_point = hash_to_curve(&proof.secret.to_bytes()?);
         self.spent_proofs
             .lock()
             .await
-            .insert(proof.secret.clone(), proof);
+            .insert(secret_point.to_sec1_bytes().to_vec(), proof);
         Ok(())
     }
 
-    async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
-        Ok(self.spent_proofs.lock().await.get(secret).cloned())
+    async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+        Ok(self
+            .spent_proofs
+            .lock()
+            .await
+            .get(&hash_to_curve(&secret.to_bytes()?).to_sec1_bytes().to_vec())
+            .cloned())
     }
 
-    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error> {
-        self.pending_proofs
+    async fn get_spent_proof_by_hash(
+        &self,
+        secret: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error> {
+        Ok(self
+            .spent_proofs
             .lock()
             .await
-            .insert(proof.secret.clone(), proof);
+            .get(&secret.to_sec1_bytes().to_vec())
+            .cloned())
+    }
+
+    async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error> {
+        self.pending_proofs.lock().await.insert(
+            hash_to_curve(&proof.secret.to_bytes()?)
+                .to_sec1_bytes()
+                .to_vec(),
+            proof,
+        );
         Ok(())
     }
 
-    async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
-        Ok(self.pending_proofs.lock().await.get(secret).cloned())
+    async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+        let secret_point = hash_to_curve(&secret.to_bytes()?);
+        Ok(self
+            .pending_proofs
+            .lock()
+            .await
+            .get(&secret_point.to_sec1_bytes().to_vec())
+            .cloned())
+    }
+
+    async fn get_pending_proof_by_hash(
+        &self,
+        secret: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error> {
+        Ok(self
+            .pending_proofs
+            .lock()
+            .await
+            .get(&secret.to_sec1_bytes().to_vec())
+            .cloned())
     }
 
     async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error> {
-        self.pending_proofs.lock().await.remove(secret);
+        let secret_point = hash_to_curve(&secret.to_bytes()?);
+        self.pending_proofs
+            .lock()
+            .await
+            .remove(&secret_point.to_sec1_bytes().to_vec());
         Ok(())
     }
 }

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

@@ -5,6 +5,7 @@ pub mod redb_store;
 use std::collections::HashMap;
 
 use async_trait::async_trait;
+use cashu::k256;
 use cashu::nuts::nut02::mint::KeySet;
 use cashu::nuts::{CurrencyUnit, Id, MintInfo, Proof};
 use cashu::secret::Secret;
@@ -43,6 +44,8 @@ pub enum Error {
     Cashu(#[from] cashu::error::Error),
     #[error("`{0}`")]
     CashuNut02(#[from] cashu::nuts::nut02::Error),
+    #[error("`{0}`")]
+    Secret(#[from] cashu::secret::Error),
 }
 
 #[async_trait]
@@ -69,9 +72,17 @@ pub trait LocalStore {
     async fn get_keysets(&self) -> Result<Vec<KeySet>, Error>;
 
     async fn add_spent_proof(&self, proof: Proof) -> Result<(), Error>;
-    async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
+    async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
+    async fn get_spent_proof_by_hash(
+        &self,
+        secret: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error>;
 
     async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error>;
-    async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
+    async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error>;
+    async fn get_pending_proof_by_hash(
+        &self,
+        secret: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error>;
     async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error>;
 }

+ 49 - 12
crates/cashu-sdk/src/mint/localstore/redb_store.rs

@@ -3,6 +3,8 @@ use std::str::FromStr;
 use std::sync::Arc;
 
 use async_trait::async_trait;
+use cashu::dhke::hash_to_curve;
+use cashu::k256;
 use cashu::nuts::{CurrencyUnit, Id, MintInfo, MintKeySet as KeySet, Proof};
 use cashu::secret::Secret;
 use cashu::types::{MeltQuote, MintQuote};
@@ -16,8 +18,8 @@ const ACTIVE_KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("
 const KEYSETS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("keysets");
 const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
 const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
-const PENDING_PROOFS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("pending_proofs");
-const SPENT_PROOFS_TABLE: TableDefinition<&str, &str> = TableDefinition::new("spent_proofs");
+const PENDING_PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("pending_proofs");
+const SPENT_PROOFS_TABLE: TableDefinition<&[u8], &str> = TableDefinition::new("spent_proofs");
 const CONFIG_TABLE: TableDefinition<&str, &str> = TableDefinition::new("config");
 
 #[derive(Debug, Clone)]
@@ -275,7 +277,9 @@ impl LocalStore for RedbLocalStore {
         {
             let mut table = write_txn.open_table(SPENT_PROOFS_TABLE)?;
             table.insert(
-                proof.secret.to_string().as_str(),
+                hash_to_curve(&proof.secret.to_bytes()?)
+                    .to_sec1_bytes()
+                    .as_ref(),
                 serde_json::to_string(&proof)?.as_str(),
             )?;
         }
@@ -286,16 +290,31 @@ impl LocalStore for RedbLocalStore {
         Ok(())
     }
 
-    async fn get_spent_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+    async fn get_spent_proof_by_hash(
+        &self,
+        secret_point: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error> {
         let db = self.db.lock().await;
         let read_txn = db.begin_read()?;
         let table = read_txn.open_table(SPENT_PROOFS_TABLE)?;
 
-        let quote = table.get(secret.to_string().as_str())?;
+        let proof = table.get(secret_point.to_sec1_bytes().as_ref())?;
+
+        Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
+    }
+
+    async fn get_spent_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+        let db = self.db.lock().await;
+        let read_txn = db.begin_read()?;
+        let table = read_txn.open_table(SPENT_PROOFS_TABLE)?;
+
+        let secret_hash = hash_to_curve(&secret.to_bytes()?);
+
+        let proof = table.get(secret_hash.to_sec1_bytes().as_ref())?;
 
         debug!("Checking secret: {}", secret.to_string());
 
-        Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
+        Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
     }
 
     async fn add_pending_proof(&self, proof: Proof) -> Result<(), Error> {
@@ -306,7 +325,9 @@ impl LocalStore for RedbLocalStore {
         {
             let mut table = write_txn.open_table(PENDING_PROOFS_TABLE)?;
             table.insert(
-                proof.secret.to_string().as_str(),
+                hash_to_curve(&proof.secret.to_bytes()?)
+                    .to_sec1_bytes()
+                    .as_ref(),
                 serde_json::to_string(&proof)?.as_str(),
             )?;
         }
@@ -315,14 +336,29 @@ impl LocalStore for RedbLocalStore {
         Ok(())
     }
 
-    async fn get_pending_proof(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+    async fn get_pending_proof_by_hash(
+        &self,
+        secret_point: &k256::PublicKey,
+    ) -> Result<Option<Proof>, Error> {
         let db = self.db.lock().await;
         let read_txn = db.begin_read()?;
-        let table = read_txn.open_table(MELT_QUOTES_TABLE)?;
+        let table = read_txn.open_table(PENDING_PROOFS_TABLE)?;
 
-        let quote = table.get(secret.to_string().as_str())?;
+        let proof = table.get(secret_point.to_sec1_bytes().as_ref())?;
 
-        Ok(quote.map(|q| serde_json::from_str(q.value()).unwrap()))
+        Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
+    }
+
+    async fn get_pending_proof_by_secret(&self, secret: &Secret) -> Result<Option<Proof>, Error> {
+        let db = self.db.lock().await;
+        let read_txn = db.begin_read()?;
+        let table = read_txn.open_table(PENDING_PROOFS_TABLE)?;
+
+        let secret_hash = hash_to_curve(&secret.to_bytes()?);
+
+        let proof = table.get(secret_hash.to_sec1_bytes().as_ref())?;
+
+        Ok(proof.map(|p| serde_json::from_str(p.value()).unwrap()))
     }
 
     async fn remove_pending_proof(&self, secret: &Secret) -> Result<(), Error> {
@@ -332,7 +368,8 @@ impl LocalStore for RedbLocalStore {
 
         {
             let mut table = write_txn.open_table(PENDING_PROOFS_TABLE)?;
-            table.remove(secret.to_string().as_str())?;
+            let secret_hash = hash_to_curve(&secret.to_bytes()?);
+            table.remove(secret_hash.to_sec1_bytes().as_ref())?;
         }
         write_txn.commit()?;
 

+ 26 - 9
crates/cashu-sdk/src/mint/mod.rs

@@ -1,7 +1,7 @@
 use std::collections::HashSet;
 use std::sync::Arc;
 
-use cashu::dhke::{sign_message, verify_message};
+use cashu::dhke::{hash_to_curve, sign_message, verify_message};
 use cashu::error::ErrorResponse;
 #[cfg(feature = "nut07")]
 use cashu::nuts::nut07::{ProofState, State};
@@ -11,7 +11,6 @@ use cashu::nuts::{
 };
 #[cfg(feature = "nut07")]
 use cashu::nuts::{CheckStateRequest, CheckStateResponse};
-use cashu::secret::Secret;
 use cashu::types::{MeltQuote, MintQuote};
 use cashu::Amount;
 use http::StatusCode;
@@ -52,6 +51,8 @@ pub enum Error {
     Cashu(#[from] cashu::error::mint::Error),
     #[error("`{0}`")]
     Localstore(#[from] localstore::Error),
+    #[error("`{0}`")]
+    Secret(#[from] cashu::secret::Error),
     #[error("Unknown quote")]
     UnknownQuote,
     #[error("Cannot have multiple units")]
@@ -353,10 +354,11 @@ impl Mint {
 
         let proof_count = swap_request.inputs.len();
 
-        let secrets: HashSet<Secret> = swap_request
+        let secrets: HashSet<Vec<u8>> = swap_request
             .inputs
             .iter()
-            .map(|p| p.secret.clone())
+            .flat_map(|p| p.secret.to_bytes())
+            .map(|p| hash_to_curve(&p).to_sec1_bytes().to_vec())
             .collect();
 
         // Check that there are no duplicate proofs in request
@@ -420,7 +422,7 @@ impl Mint {
     async fn verify_proof(&self, proof: &Proof) -> Result<(), Error> {
         if self
             .localstore
-            .get_spent_proof(&proof.secret)
+            .get_spent_proof_by_secret(&proof.secret)
             .await?
             .is_some()
         {
@@ -429,7 +431,7 @@ impl Mint {
 
         if self
             .localstore
-            .get_pending_proof(&proof.secret)
+            .get_pending_proof_by_secret(&proof.secret)
             .await?
             .is_some()
         {
@@ -463,9 +465,19 @@ impl Mint {
         let mut states = Vec::with_capacity(check_state.secrets.len());
 
         for secret in &check_state.secrets {
-            let state = if self.localstore.get_spent_proof(secret).await?.is_some() {
+            let state = if self
+                .localstore
+                .get_spent_proof_by_secret(secret)
+                .await?
+                .is_some()
+            {
                 State::Spent
-            } else if self.localstore.get_pending_proof(secret).await?.is_some() {
+            } else if self
+                .localstore
+                .get_pending_proof_by_secret(secret)
+                .await?
+                .is_some()
+            {
                 State::Pending
             } else {
                 State::Unspent
@@ -545,7 +557,12 @@ impl Mint {
             return Err(Error::MultipleUnits);
         }
 
-        let secrets: HashSet<&Secret> = melt_request.inputs.iter().map(|p| &p.secret).collect();
+        let secrets: HashSet<Vec<u8>> = melt_request
+            .inputs
+            .iter()
+            .flat_map(|p| p.secret.to_bytes())
+            .map(|p| hash_to_curve(&p).to_sec1_bytes().to_vec())
+            .collect();
 
         // Ensure proofs are unique and not being double spent
         if melt_request.inputs.len().ne(&secrets.len()) {

+ 1 - 2
crates/cashu/src/lib.rs

@@ -11,7 +11,6 @@ pub mod utils;
 
 pub use amount::Amount;
 pub use bitcoin::hashes::sha256::Hash as Sha256;
-pub use lightning_invoice;
 pub use lightning_invoice::Bolt11Invoice;
-
+pub use {k256, lightning_invoice};
 pub type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;