Skip to content

Commit

Permalink
Add Proofs trait to consolidate aggregate fns
Browse files Browse the repository at this point in the history
  • Loading branch information
ok300 committed Oct 16, 2024
1 parent cd9c098 commit e789a98
Show file tree
Hide file tree
Showing 15 changed files with 70 additions and 87 deletions.
6 changes: 2 additions & 4 deletions crates/cdk-redb/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use async_trait::async_trait;
use cdk::cdk_database::MintDatabase;
use cdk::dhke::hash_to_curve;
use cdk::mint::{MintKeySetInfo, MintQuote};
use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{
BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState, Proof,
Proofs, PublicKey, State,
Expand Down Expand Up @@ -603,10 +604,7 @@ impl MintDatabase for MintRedbDatabase {
.filter(|p| &p.keyset_id == keyset_id)
.collect::<Proofs>();

let proof_ys = proofs_for_id
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
let proof_ys = proofs_for_id.ys()?;

assert_eq!(proofs_for_id.len(), proof_ys.len());

Expand Down
6 changes: 2 additions & 4 deletions crates/cdk-sqlite/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use bitcoin::bip32::DerivationPath;
use cdk::cdk_database::{self, MintDatabase};
use cdk::mint::{MintKeySetInfo, MintQuote};
use cdk::mint_url::MintUrl;
use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::nut05::QuoteState;
use cdk::nuts::{
BlindSignature, BlindSignatureDleq, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState,
Expand Down Expand Up @@ -838,10 +839,7 @@ WHERE quote_id=?;
.map(sqlite_row_to_proof)
.collect::<Result<Vec<Proof>, _>>()?;

proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?
proofs.ys()?
}
Err(err) => match err {
sqlx::Error::RowNotFound => {
Expand Down
6 changes: 2 additions & 4 deletions crates/cdk/src/cdk_database/mint_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use tokio::sync::{Mutex, RwLock};
use super::{Error, MintDatabase};
use crate::dhke::hash_to_curve;
use crate::mint::{self, MintKeySetInfo, MintQuote};
use crate::nuts::nut00::ProofsMethods;
use crate::nuts::nut07::State;
use crate::nuts::{
nut07, BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState,
Expand Down Expand Up @@ -346,10 +347,7 @@ impl MintDatabase for MintMemoryDatabase {
.cloned()
.collect();

let proof_ys = proofs_for_id
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
let proof_ys = proofs_for_id.ys()?;

assert_eq!(proofs_for_id.len(), proof_ys.len());

Expand Down
20 changes: 4 additions & 16 deletions crates/cdk/src/mint/melt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tracing::instrument;
use crate::cdk_lightning;
use crate::cdk_lightning::MintLightning;
use crate::cdk_lightning::PayInvoiceResponse;
use crate::dhke::hash_to_curve;
use crate::nuts::nut00::ProofsMethods;
use crate::nuts::nut11::enforce_sig_flag;
use crate::nuts::nut11::EnforceSigFlag;
use crate::{
Expand Down Expand Up @@ -264,11 +264,7 @@ impl Mint {
}
}

let ys = melt_request
.inputs
.iter()
.map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?;
let ys = melt_request.inputs.ys()?;

// Ensure proofs are unique and not being double spent
if melt_request.inputs.len() != ys.iter().collect::<HashSet<_>>().len() {
Expand Down Expand Up @@ -374,11 +370,7 @@ impl Mint {
/// quote should be unpaid
#[instrument(skip_all)]
pub async fn process_unpaid_melt(&self, melt_request: &MeltBolt11Request) -> Result<(), Error> {
let input_ys = melt_request
.inputs
.iter()
.map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?;
let input_ys = melt_request.inputs.ys()?;

self.localstore
.update_proofs_states(&input_ys, State::Unspent)
Expand Down Expand Up @@ -615,11 +607,7 @@ impl Mint {
.await?
.ok_or(Error::UnknownQuote)?;

let input_ys = melt_request
.inputs
.iter()
.map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?;
let input_ys = melt_request.inputs.ys()?;

self.localstore
.update_proofs_states(&input_ys, State::Spent)
Expand Down
8 changes: 2 additions & 6 deletions crates/cdk/src/mint/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashSet;

use tracing::instrument;

use crate::dhke::hash_to_curve;
use crate::nuts::nut00::ProofsMethods;
use crate::Error;

use super::nut11::{enforce_sig_flag, EnforceSigFlag};
Expand Down Expand Up @@ -59,11 +59,7 @@ impl Mint {

let proof_count = swap_request.inputs.len();

let input_ys = swap_request
.inputs
.iter()
.map(|p| hash_to_curve(&p.secret.to_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?;
let input_ys = swap_request.inputs.ys()?;

self.localstore
.add_proofs(swap_request.inputs.clone(), None)
Expand Down
22 changes: 22 additions & 0 deletions crates/cdk/src/nuts/nut00/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@ pub use token::{Token, TokenV3, TokenV4};
/// List of [Proof]
pub type Proofs = Vec<Proof>;

/// Utility methods for [Proofs]
pub trait ProofsMethods {
/// Try to sum up the amounts of all [Proof]s
fn total_amount(&self) -> Result<Amount, Error>;

/// Try to fetch the pubkeys of all [Proof]s
fn ys(&self) -> Result<Vec<PublicKey>, Error>;
}

impl ProofsMethods for Proofs {
fn total_amount(&self) -> Result<Amount, Error> {
Amount::try_sum(self.iter().map(|p| p.amount)).map_err(Into::into)
}

fn ys(&self) -> Result<Vec<PublicKey>, Error> {
self.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()
.map_err(Into::into)
}
}

/// NUT00 Error
#[derive(Debug, Error)]
pub enum Error {
Expand Down
3 changes: 2 additions & 1 deletion crates/cdk/src/nuts/nut00/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use url::Url;

use super::{Error, Proof, ProofV4, Proofs};
use crate::mint_url::MintUrl;
use crate::nuts::nut00::ProofsMethods;
use crate::nuts::{CurrencyUnit, Id};
use crate::Amount;

Expand Down Expand Up @@ -211,7 +212,7 @@ impl TokenV3 {
Ok(Amount::try_sum(
self.token
.iter()
.map(|t| Amount::try_sum(t.proofs.iter().map(|p| p.amount)))
.map(|t| t.proofs.total_amount())
.collect::<Result<Vec<Amount>, _>>()?,
)?)
}
Expand Down
5 changes: 3 additions & 2 deletions crates/cdk/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize};

use crate::error::Error;
use crate::mint_url::MintUrl;
use crate::nuts::nut00::ProofsMethods;
use crate::nuts::{
CurrencyUnit, MeltQuoteState, PaymentMethod, Proof, Proofs, PublicKey, SpendingConditions,
State,
Expand Down Expand Up @@ -34,9 +35,9 @@ impl Melted {
proofs: Proofs,
change_proofs: Option<Proofs>,
) -> Result<Self, Error> {
let proofs_amount = Amount::try_sum(proofs.iter().map(|p| p.amount))?;
let proofs_amount = proofs.total_amount()?;
let change_amount = match &change_proofs {
Some(change_proofs) => Amount::try_sum(change_proofs.iter().map(|p| p.amount))?,
Some(change_proofs) => change_proofs.total_amount()?,
None => Amount::ZERO,
};
let fee_paid = proofs_amount
Expand Down
17 changes: 6 additions & 11 deletions crates/cdk/src/wallet/melt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::str::FromStr;
use lightning_invoice::Bolt11Invoice;
use tracing::instrument;

use crate::nuts::nut00::ProofsMethods;
use crate::{
dhke::construct_proofs,
nuts::{CurrencyUnit, MeltQuoteBolt11Response, PreMintSecrets, Proofs, PublicKey, State},
nuts::{CurrencyUnit, MeltQuoteBolt11Response, PreMintSecrets, Proofs, State},
types::{Melted, ProofInfo},
util::unix_time,
Amount, Error, Wallet,
Expand Down Expand Up @@ -121,15 +122,12 @@ impl Wallet {
return Err(Error::UnknownQuote);
};

let proofs_total = Amount::try_sum(proofs.iter().map(|p| p.amount))?;
let proofs_total = proofs.total_amount()?;
if proofs_total < quote_info.amount + quote_info.fee_reserve {
return Err(Error::InsufficientFunds);
}

let ys = proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
let ys = proofs.ys()?;
self.localstore.set_pending_proofs(ys).await?;

let active_keyset_id = self.get_active_mint_keyset().await?.id;
Expand Down Expand Up @@ -213,7 +211,7 @@ impl Wallet {
Some(change_proofs) => {
tracing::debug!(
"Change amount returned from melt: {}",
Amount::try_sum(change_proofs.iter().map(|p| p.amount))?
change_proofs.total_amount()?
);

// Update counter for keyset
Expand All @@ -238,10 +236,7 @@ impl Wallet {

self.localstore.remove_melt_quote(&quote_info.id).await?;

let deleted_ys = proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
let deleted_ys = proofs.ys()?;
self.localstore
.update_proofs(change_proof_infos, deleted_ys)
.await?;
Expand Down
3 changes: 2 additions & 1 deletion crates/cdk/src/wallet/mint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use tracing::instrument;

use super::MintQuote;
use crate::nuts::nut00::ProofsMethods;
use crate::{
amount::SplitTarget,
dhke::construct_proofs,
Expand Down Expand Up @@ -242,7 +243,7 @@ impl Wallet {
&keys,
)?;

let minted_amount = Amount::try_sum(proofs.iter().map(|p| p.amount))?;
let minted_amount = proofs.total_amount()?;

// Remove filled quote from store
self.localstore.remove_mint_quote(&quote_info.id).await?;
Expand Down
3 changes: 2 additions & 1 deletion crates/cdk/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod swap;
pub mod types;
pub mod util;

use crate::nuts::nut00::ProofsMethods;
pub use multi_mint_wallet::MultiMintWallet;
pub use types::{MeltQuote, MintQuote, SendKind};

Expand Down Expand Up @@ -327,7 +328,7 @@ impl Wallet {
.cloned()
.collect();

restored_value += Amount::try_sum(unspent_proofs.iter().map(|p| p.amount))?;
restored_value += unspent_proofs.total_amount()?;

let unspent_proofs = unspent_proofs
.into_iter()
Expand Down
25 changes: 7 additions & 18 deletions crates/cdk/src/wallet/proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::collections::HashSet;

use tracing::instrument;

use crate::nuts::nut00::ProofsMethods;
use crate::{
amount::SplitTarget,
dhke::hash_to_curve,
nuts::{Proof, ProofState, Proofs, PublicKey, State},
types::ProofInfo,
Amount, Error, Wallet,
Expand Down Expand Up @@ -73,11 +73,7 @@ impl Wallet {
/// Checks the stats of [`Proofs`] swapping for a new [`Proof`] if unspent
#[instrument(skip(self, proofs))]
pub async fn reclaim_unspent(&self, proofs: Proofs) -> Result<(), Error> {
let proof_ys = proofs
.iter()
// Find Y for the secret
.map(|p| hash_to_curve(p.secret.as_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?;
let proof_ys = proofs.ys()?;

let spendable = self
.client
Expand All @@ -102,14 +98,7 @@ impl Wallet {
pub async fn check_proofs_spent(&self, proofs: Proofs) -> Result<Vec<ProofState>, Error> {
let spendable = self
.client
.post_check_state(
self.mint_url.clone().try_into()?,
proofs
.iter()
// Find Y for the secret
.map(|p| hash_to_curve(p.secret.as_bytes()))
.collect::<Result<Vec<PublicKey>, _>>()?,
)
.post_check_state(self.mint_url.clone().try_into()?, proofs.ys()?)
.await?;
let spent_ys: Vec<_> = spendable
.states
Expand Down Expand Up @@ -186,7 +175,7 @@ impl Wallet {
) -> Result<Proofs, Error> {
// TODO: Check all proofs are same unit

if Amount::try_sum(proofs.iter().map(|p| p.amount))? < amount {
if proofs.total_amount()? < amount {
return Err(Error::InsufficientFunds);
}

Expand Down Expand Up @@ -226,7 +215,7 @@ impl Wallet {
}

remaining_amount = amount.checked_add(fees).ok_or(Error::AmountOverflow)?
- Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
- selected_proofs.total_amount()?;
(proofs_larger, proofs_smaller) = proofs_smaller
.into_iter()
.skip(1)
Expand Down Expand Up @@ -262,7 +251,7 @@ impl Wallet {

for inactive_proof in inactive_proofs {
selected_proofs.push(inactive_proof);
let selected_total = Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
let selected_total = selected_proofs.total_amount()?;
let fees = self.get_proofs_fee(&selected_proofs).await?;

if selected_total >= amount + fees {
Expand All @@ -274,7 +263,7 @@ impl Wallet {

for active_proof in active_proofs {
selected_proofs.push(active_proof);
let selected_total = Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
let selected_total = selected_proofs.total_amount()?;
let fees = self.get_proofs_fee(&selected_proofs).await?;

if selected_total >= amount + fees {
Expand Down
3 changes: 2 additions & 1 deletion crates/cdk/src/wallet/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bitcoin::hashes::Hash;
use bitcoin::{hashes::sha256::Hash as Sha256Hash, XOnlyPublicKey};
use tracing::instrument;

use crate::nuts::nut00::ProofsMethods;
use crate::nuts::nut10::Kind;
use crate::nuts::{Conditions, Token};
use crate::{
Expand Down Expand Up @@ -148,7 +149,7 @@ impl Wallet {
.increment_keyset_counter(&active_keyset_id, recv_proofs.len() as u32)
.await?;

let total_amount = Amount::try_sum(recv_proofs.iter().map(|p| p.amount))?;
let total_amount = recv_proofs.total_amount()?;

let recv_proof_infos = recv_proofs
.into_iter()
Expand Down
Loading

0 comments on commit e789a98

Please sign in to comment.