Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Proofs trait to consolidate aggregate fns #408

Merged
merged 1 commit into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading