Skip to content

Commit

Permalink
Merge branch 'main' into ok300-mintd-swagger-ui
Browse files Browse the repository at this point in the history
# Conflicts:
#	crates/cdk/src/nuts/nut01/mod.rs
  • Loading branch information
ok300 committed Oct 21, 2024
2 parents 3c795d6 + 84428a9 commit 2047ea8
Show file tree
Hide file tree
Showing 24 changed files with 245 additions and 112 deletions.
9 changes: 7 additions & 2 deletions crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ enum Commands {
Restore(sub_commands::restore::RestoreSubCommand),
/// Update Mint Url
UpdateMintUrl(sub_commands::update_mint_url::UpdateMintUrlSubCommand),
/// Get proofs from mint.
ListMintProofs,
}

#[tokio::main]
Expand Down Expand Up @@ -123,10 +125,10 @@ async fn main() -> Result<()> {
let mut rng = rand::thread_rng();
let random_bytes: [u8; 32] = rng.gen();

let mnemnic = Mnemonic::from_entropy(&random_bytes)?;
let mnemonic = Mnemonic::from_entropy(&random_bytes)?;
tracing::info!("Using randomly generated seed you will not be able to restore");

mnemnic
mnemonic
}
};

Expand Down Expand Up @@ -199,5 +201,8 @@ async fn main() -> Result<()> {
sub_commands::update_mint_url::update_mint_url(&multi_mint_wallet, sub_command_args)
.await
}
Commands::ListMintProofs => {
sub_commands::list_mint_proofs::proofs(&multi_mint_wallet).await
}
}
}
41 changes: 41 additions & 0 deletions crates/cdk-cli/src/sub_commands/list_mint_proofs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::collections::BTreeMap;

use anyhow::Result;
use cdk::{
mint_url::MintUrl,
nuts::{CurrencyUnit, Proof},
wallet::multi_mint_wallet::MultiMintWallet,
};

pub async fn proofs(multi_mint_wallet: &MultiMintWallet) -> Result<()> {
list_proofs(multi_mint_wallet).await?;
Ok(())
}

async fn list_proofs(
multi_mint_wallet: &MultiMintWallet,
) -> Result<Vec<(MintUrl, (Vec<Proof>, CurrencyUnit))>> {
let wallets_proofs: BTreeMap<MintUrl, (Vec<Proof>, CurrencyUnit)> =
multi_mint_wallet.list_proofs().await?;

let mut proofs_vec = Vec::with_capacity(wallets_proofs.len());

for (i, (mint_url, proofs)) in wallets_proofs.iter().enumerate() {
let mint_url = mint_url.clone();
println!("{i}: {mint_url}");
println!("| Amount | Unit | Secret | DLEQ proof included");
println!("|----------|------|------------------------------------------------------------------|--------------------");
for proof in &proofs.0 {
println!(
"| {:8} | {:4} | {:64} | {}",
proof.amount,
proofs.1,
proof.secret,
proof.dleq.is_some()
);
}
println!();
proofs_vec.push((mint_url, proofs.clone()))
}
Ok(proofs_vec)
}
1 change: 1 addition & 0 deletions crates/cdk-cli/src/sub_commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod balance;
pub mod burn;
pub mod check_spent;
pub mod decode_token;
pub mod list_mint_proofs;
pub mod melt;
pub mod mint;
pub mod mint_info;
Expand Down
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
57 changes: 55 additions & 2 deletions crates/cdk/src/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
use std::cmp::Ordering;
use std::fmt;
use std::str::FromStr;

use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use thiserror::Error;

use crate::nuts::CurrencyUnit;
Expand Down Expand Up @@ -139,7 +140,11 @@ impl Default for &Amount {

impl fmt::Display for Amount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
if let Some(width) = f.width() {
write!(f, "{:width$}", self.0, width = width)
} else {
write!(f, "{}", self.0)
}
}
}

Expand Down Expand Up @@ -211,6 +216,54 @@ impl std::ops::Div for Amount {
}
}

/// String wrapper for an [Amount].
///
/// It ser-/deserializes the inner [Amount] to a string, while at the same time using the [u64]
/// value of the [Amount] for comparison and ordering. This helps automatically sort the keys of
/// a [BTreeMap] when [AmountStr] is used as key.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AmountStr(Amount);

impl AmountStr {
pub(crate) fn from(amt: Amount) -> Self {
Self(amt)
}
}

impl PartialOrd<Self> for AmountStr {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for AmountStr {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}

impl<'de> Deserialize<'de> for AmountStr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
u64::from_str(&s)
.map(Amount)
.map(Self)
.map_err(serde::de::Error::custom)
}
}

impl Serialize for AmountStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.0.to_string())
}
}

/// Kinds of targeting that are supported
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub enum SplitTarget {
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
37 changes: 32 additions & 5 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 Expand Up @@ -387,11 +409,16 @@ impl FromStr for CurrencyUnit {

impl fmt::Display for CurrencyUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CurrencyUnit::Sat => write!(f, "sat"),
CurrencyUnit::Msat => write!(f, "msat"),
CurrencyUnit::Usd => write!(f, "usd"),
CurrencyUnit::Eur => write!(f, "eur"),
let s = match self {
CurrencyUnit::Sat => "sat",
CurrencyUnit::Msat => "msat",
CurrencyUnit::Usd => "usd",
CurrencyUnit::Eur => "eur",
};
if let Some(width) = f.width() {
write!(f, "{:width$}", s, width = width)
} else {
write!(f, "{}", s)
}
}
}
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
Loading

0 comments on commit 2047ea8

Please sign in to comment.