Переглянути джерело

fix: get spendable to return witness (#756)

thesimplekid 1 місяць тому
батько
коміт
df0de05571
2 змінених файлів з 31 додано та 20 видалено
  1. 2 1
      crates/cashu/src/nuts/nut07.rs
  2. 29 19
      crates/cdk/src/mint/check_spendable.rs

+ 2 - 1
crates/cashu/src/nuts/nut07.rs

@@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
 use thiserror::Error;
 
 use super::nut01::PublicKey;
+use super::Witness;
 
 /// NUT07 Error
 #[derive(Debug, Error, PartialEq, Eq)]
@@ -89,7 +90,7 @@ pub struct ProofState {
     /// State of proof
     pub state: State,
     /// Witness data if it is supplied
-    pub witness: Option<String>,
+    pub witness: Option<Witness>,
 }
 
 impl From<(PublicKey, State)> for ProofState {

+ 29 - 19
crates/cdk/src/mint/check_spendable.rs

@@ -1,5 +1,6 @@
 use std::collections::{HashMap, HashSet};
 
+use futures::future::try_join_all;
 use tracing::instrument;
 
 use super::{CheckStateRequest, CheckStateResponse, Mint, ProofState, PublicKey, State};
@@ -33,6 +34,7 @@ impl Mint {
 
         Ok(())
     }
+
     /// Check state
     #[instrument(skip_all)]
     pub async fn check_state(
@@ -40,25 +42,33 @@ impl Mint {
         check_state: &CheckStateRequest,
     ) -> Result<CheckStateResponse, Error> {
         let states = self.localstore.get_proofs_states(&check_state.ys).await?;
-
-        let states = states
-            .iter()
-            .zip(&check_state.ys)
-            .map(|(state, y)| {
-                let state = match state {
-                    Some(state) => *state,
-                    None => State::Unspent,
-                };
-
-                ProofState {
-                    y: *y,
-                    state,
-                    witness: None,
-                }
-            })
-            .collect();
-
-        Ok(CheckStateResponse { states })
+        assert_eq!(check_state.ys.len(), states.len());
+
+        let proof_states_futures =
+            check_state
+                .ys
+                .iter()
+                .zip(states.iter())
+                .map(|(y, state)| async move {
+                    let witness: Result<Option<cdk_common::Witness>, Error> = if state.is_some() {
+                        let proofs = self.localstore.get_proofs_by_ys(&[*y]).await?;
+                        Ok(proofs.first().cloned().flatten().and_then(|p| p.witness))
+                    } else {
+                        Ok(None)
+                    };
+
+                    witness.map(|w| ProofState {
+                        y: *y,
+                        state: state.unwrap_or(State::Unspent),
+                        witness: w,
+                    })
+                });
+
+        let proof_states = try_join_all(proof_states_futures).await?;
+
+        Ok(CheckStateResponse {
+            states: proof_states,
+        })
     }
 
     /// Check Tokens are not spent or pending