refactor: get proofs by spending condition

This commit is contained in:
thesimplekid
2024-05-22 22:21:34 +01:00
parent 10a38247ce
commit 44e39bd3ee
7 changed files with 83 additions and 71 deletions

View File

@@ -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(_) => (),
}
}

View File

@@ -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

View File

@@ -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>;

View File

@@ -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();

View File

@@ -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> {

View File

@@ -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)
}
}

View File

@@ -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)?;