mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-23 23:55:01 +01:00
refactor: get proofs by spending condition
This commit is contained in:
@@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use cdk::cdk_database;
|
||||
use cdk::cdk_database::WalletDatabase;
|
||||
use cdk::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, State};
|
||||
use cdk::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State};
|
||||
use cdk::types::{MeltQuote, MintQuote, ProofInfo};
|
||||
use cdk::url::UncheckedUrl;
|
||||
use redb::{Database, MultimapTableDefinition, ReadableTable, TableDefinition};
|
||||
@@ -400,6 +400,7 @@ impl WalletDatabase for RedbWalletDatabase {
|
||||
&self,
|
||||
mint_url: Option<UncheckedUrl>,
|
||||
state: Option<Vec<State>>,
|
||||
spending_conditions: Option<Vec<SpendingConditions>>,
|
||||
) -> Result<Option<Proofs>, Self::Err> {
|
||||
let db = self.db.lock().await;
|
||||
let read_txn = db.begin_read().map_err(Error::from)?;
|
||||
@@ -414,25 +415,10 @@ impl WalletDatabase for RedbWalletDatabase {
|
||||
let mut proof = None;
|
||||
|
||||
if let Ok(proof_info) = serde_json::from_str::<ProofInfo>(v.value()) {
|
||||
match (&mint_url, &state) {
|
||||
(Some(mint_url), Some(state)) => {
|
||||
if state.contains(&proof_info.state)
|
||||
&& mint_url.eq(&proof_info.mint_url)
|
||||
{
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(Some(mint_url), None) => {
|
||||
if mint_url.eq(&proof_info.mint_url) {
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(None, Some(state)) => {
|
||||
if state.contains(&proof_info.state) {
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(None, None) => proof = Some(proof_info.proof),
|
||||
match proof_info.matches_conditions(&mint_url, &state, &spending_conditions) {
|
||||
Ok(true) => proof = Some(proof_info.proof),
|
||||
Ok(false) => (),
|
||||
Err(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::result::Result;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cdk::cdk_database::WalletDatabase;
|
||||
use cdk::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, State};
|
||||
use cdk::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State};
|
||||
use cdk::types::{MeltQuote, MintQuote, ProofInfo};
|
||||
use cdk::url::UncheckedUrl;
|
||||
use rexie::*;
|
||||
@@ -449,6 +449,7 @@ impl WalletDatabase for RexieWalletDatabase {
|
||||
&self,
|
||||
mint_url: Option<UncheckedUrl>,
|
||||
state: Option<Vec<State>>,
|
||||
spending_conditions: Option<Vec<SpendingConditions>>,
|
||||
) -> Result<Option<Proofs>, Self::Err> {
|
||||
let rexie = self.db.lock().await;
|
||||
|
||||
@@ -469,26 +470,15 @@ impl WalletDatabase for RexieWalletDatabase {
|
||||
let mut proof = None;
|
||||
|
||||
if let Ok(proof_info) = serde_wasm_bindgen::from_value::<ProofInfo>(v) {
|
||||
match (&mint_url, &state) {
|
||||
(Some(mint_url), Some(state)) => {
|
||||
if state.contains(&proof_info.state)
|
||||
&& mint_url.eq(&proof_info.mint_url)
|
||||
{
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(Some(mint_url), None) => {
|
||||
if mint_url.eq(&proof_info.mint_url) {
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(None, Some(state)) => {
|
||||
if state.contains(&proof_info.state) {
|
||||
proof = Some(proof_info.proof);
|
||||
}
|
||||
}
|
||||
(None, None) => proof = Some(proof_info.proof),
|
||||
}
|
||||
proof = match proof_info.matches_conditions(
|
||||
&mint_url,
|
||||
&state,
|
||||
&spending_conditions,
|
||||
) {
|
||||
Ok(true) => Some(proof_info.proof),
|
||||
Ok(false) => None,
|
||||
Err(_) => None,
|
||||
};
|
||||
}
|
||||
|
||||
proof
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::nuts::{BlindSignature, CurrencyUnit, Proof};
|
||||
#[cfg(any(feature = "wallet", feature = "mint"))]
|
||||
use crate::nuts::{Id, MintInfo, PublicKey};
|
||||
#[cfg(feature = "wallet")]
|
||||
use crate::nuts::{KeySetInfo, Keys, Proofs};
|
||||
use crate::nuts::{KeySetInfo, Keys, Proofs, SpendingConditions};
|
||||
#[cfg(feature = "mint")]
|
||||
use crate::secret::Secret;
|
||||
#[cfg(feature = "wallet")]
|
||||
@@ -82,6 +82,7 @@ pub trait WalletDatabase {
|
||||
&self,
|
||||
mint_url: Option<UncheckedUrl>,
|
||||
state: Option<Vec<State>>,
|
||||
spending_conditions: Option<Vec<SpendingConditions>>,
|
||||
) -> Result<Option<Proofs>, Self::Err>;
|
||||
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Self::Err>;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use tokio::sync::RwLock;
|
||||
|
||||
use super::WalletDatabase;
|
||||
use crate::cdk_database::Error;
|
||||
use crate::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, State};
|
||||
use crate::nuts::{Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State};
|
||||
use crate::types::{MeltQuote, MintQuote, ProofInfo};
|
||||
use crate::url::UncheckedUrl;
|
||||
|
||||
@@ -170,35 +170,19 @@ impl WalletDatabase for WalletMemoryDatabase {
|
||||
&self,
|
||||
mint_url: Option<UncheckedUrl>,
|
||||
state: Option<Vec<State>>,
|
||||
spending_conditions: Option<Vec<SpendingConditions>>,
|
||||
) -> Result<Option<Proofs>, Error> {
|
||||
let proofs = self.proofs.read().await;
|
||||
|
||||
let proofs: Proofs = proofs
|
||||
.clone()
|
||||
.into_values()
|
||||
.filter_map(|proof_info| match (mint_url.clone(), state.clone()) {
|
||||
(Some(mint_url), Some(state)) => {
|
||||
if state.contains(&proof_info.state) && mint_url.eq(&proof_info.mint_url) {
|
||||
Some(proof_info.proof)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.filter_map(|proof_info| {
|
||||
match proof_info.matches_conditions(&mint_url, &state, &spending_conditions) {
|
||||
Ok(true) => Some(proof_info.proof),
|
||||
Ok(false) => None,
|
||||
Err(_) => None,
|
||||
}
|
||||
(Some(mint_url), None) => {
|
||||
if proof_info.mint_url.eq(&mint_url) {
|
||||
Some(proof_info.proof)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(None, Some(state)) => {
|
||||
if state.contains(&proof_info.state) {
|
||||
Some(proof_info.proof)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(None, None) => Some(proof_info.proof),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use super::nut00::Witness;
|
||||
use super::nut01::PublicKey;
|
||||
use super::{Kind, Nut10Secret, Proof, Proofs, SecretKey};
|
||||
use crate::nuts::nut00::BlindedMessage;
|
||||
use crate::secret::Secret;
|
||||
use crate::util::{hex, unix_time};
|
||||
|
||||
pub mod serde_p2pk_witness;
|
||||
@@ -323,6 +324,15 @@ impl SpendingConditions {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Secret> for SpendingConditions {
|
||||
type Error = Error;
|
||||
fn try_from(secret: &Secret) -> Result<SpendingConditions, Error> {
|
||||
let nut10_secret: Nut10Secret = secret.try_into()?;
|
||||
|
||||
nut10_secret.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Nut10Secret> for SpendingConditions {
|
||||
type Error = Error;
|
||||
fn try_from(secret: Nut10Secret) -> Result<SpendingConditions, Error> {
|
||||
|
||||
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::nuts::{CurrencyUnit, Proof, Proofs, PublicKey, State};
|
||||
use crate::nuts::{CurrencyUnit, Proof, Proofs, PublicKey, SpendingConditions, State};
|
||||
use crate::url::UncheckedUrl;
|
||||
use crate::Amount;
|
||||
|
||||
@@ -99,6 +99,7 @@ pub struct ProofInfo {
|
||||
pub y: PublicKey,
|
||||
pub mint_url: UncheckedUrl,
|
||||
pub state: State,
|
||||
pub spending_condition: Option<SpendingConditions>,
|
||||
}
|
||||
|
||||
impl ProofInfo {
|
||||
@@ -107,11 +108,46 @@ impl ProofInfo {
|
||||
.y()
|
||||
.map_err(|_| Error::CustomError("Could not find y".to_string()))?;
|
||||
|
||||
let spending_condition: Option<SpendingConditions> = (&proof.secret).try_into().ok();
|
||||
|
||||
Ok(Self {
|
||||
proof,
|
||||
y,
|
||||
mint_url,
|
||||
state,
|
||||
spending_condition,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn matches_conditions(
|
||||
&self,
|
||||
mint_url: &Option<UncheckedUrl>,
|
||||
state: &Option<Vec<State>>,
|
||||
spending_conditions: &Option<Vec<SpendingConditions>>,
|
||||
) -> Result<bool, Error> {
|
||||
if let Some(mint_url) = mint_url {
|
||||
if mint_url.ne(&self.mint_url) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(state) = state {
|
||||
if !state.contains(&self.state) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(spending_conditions) = spending_conditions {
|
||||
match &self.spending_condition {
|
||||
None => return Ok(false),
|
||||
Some(s) => {
|
||||
if !spending_conditions.contains(s) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ impl Wallet {
|
||||
|
||||
if let Some(proofs) = self
|
||||
.localstore
|
||||
.get_proofs(None, Some(vec![State::Unspent]))
|
||||
.get_proofs(None, Some(vec![State::Unspent]), None)
|
||||
.await?
|
||||
{
|
||||
let amount = proofs.iter().map(|p| p.amount).sum();
|
||||
@@ -161,7 +161,7 @@ impl Wallet {
|
||||
|
||||
if let Some(proofs) = self
|
||||
.localstore
|
||||
.get_proofs(None, Some(vec![State::Pending]))
|
||||
.get_proofs(None, Some(vec![State::Pending]), None)
|
||||
.await?
|
||||
{
|
||||
let amount = proofs.iter().map(|p| p.amount).sum();
|
||||
@@ -179,7 +179,11 @@ impl Wallet {
|
||||
let mut balances = HashMap::new();
|
||||
|
||||
for (mint, _) in mints {
|
||||
if let Some(proofs) = self.localstore.get_proofs(Some(mint.clone()), None).await? {
|
||||
if let Some(proofs) = self
|
||||
.localstore
|
||||
.get_proofs(Some(mint.clone()), None, None)
|
||||
.await?
|
||||
{
|
||||
let amount = proofs.iter().map(|p| p.amount).sum();
|
||||
|
||||
balances.insert(mint, amount);
|
||||
@@ -195,7 +199,7 @@ impl Wallet {
|
||||
pub async fn get_proofs(&self, mint_url: UncheckedUrl) -> Result<Option<Proofs>, Error> {
|
||||
Ok(self
|
||||
.localstore
|
||||
.get_proofs(Some(mint_url), Some(vec![State::Unspent]))
|
||||
.get_proofs(Some(mint_url), Some(vec![State::Unspent]), None)
|
||||
.await?)
|
||||
}
|
||||
|
||||
@@ -357,6 +361,7 @@ impl Wallet {
|
||||
.get_proofs(
|
||||
Some(mint.clone()),
|
||||
Some(vec![State::Unspent, State::Pending]),
|
||||
None,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
@@ -935,7 +940,7 @@ impl Wallet {
|
||||
) -> Result<Proofs, Error> {
|
||||
let mint_proofs = self
|
||||
.localstore
|
||||
.get_proofs(Some(mint_url.clone()), Some(vec![State::Unspent]))
|
||||
.get_proofs(Some(mint_url.clone()), Some(vec![State::Unspent]), None)
|
||||
.await?
|
||||
.ok_or(Error::InsufficientFunds)?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user