diff --git a/crates/cdk-integration-tests/Cargo.toml b/crates/cdk-integration-tests/Cargo.toml index aa5a53ad..858ce55b 100644 --- a/crates/cdk-integration-tests/Cargo.toml +++ b/crates/cdk-integration-tests/Cargo.toml @@ -23,6 +23,8 @@ cdk-axum = { path = "../cdk-axum"} cdk-fake-wallet = { path = "../cdk-fake-wallet" } tower-http = { version = "0.4.4", features = ["cors"] } futures = { version = "0.3.28", default-features = false } +once_cell = "1.19.0" +uuid = { version = "1", features = ["v4"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { version = "1", features = [ diff --git a/crates/cdk-integration-tests/tests/fees.rs b/crates/cdk-integration-tests/tests/fees.rs deleted file mode 100644 index aaf075c3..00000000 --- a/crates/cdk-integration-tests/tests/fees.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Test calc fee - -use std::collections::HashMap; -use std::str::FromStr; -use std::sync::Arc; -use std::time::Duration; - -use anyhow::Result; -use bip39::Mnemonic; -use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; -use cdk::mint_url::MintUrl; -use cdk::nuts::CurrencyUnit; -use cdk::Wallet; -use cdk_integration_tests::{create_backends_fake_wallet, start_mint, wallet_mint, MINT_URL}; - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_mint_fee() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); - - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (1, 32)); - - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); - - tokio::time::sleep(Duration::from_millis(500)).await; - - let mnemonic = Mnemonic::generate(12)?; - - let wallet = Wallet::new( - MINT_URL, - CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), - &mnemonic.to_seed_normalized(""), - None, - )?; - - let wallet = Arc::new(wallet); - - wallet_mint( - Arc::clone(&wallet), - 10000.into(), - SplitTarget::Value(1.into()), - ) - .await - .unwrap(); - println!("Minted"); - - let proofs = wallet - .localstore - .get_proofs(Some(MintUrl::from_str(MINT_URL)?), None, None, None) - .await?; - - let proofs: Vec = proofs.into_iter().map(|p| p.proof).collect(); - - let five_proofs = proofs[..5].to_vec(); - - let fee = wallet.get_proofs_fee(&five_proofs).await?; - - // Check wallet gets fee calc correct - assert_eq!(fee, 1.into()); - - let _swap = wallet - .swap(None, SplitTarget::Value(1.into()), five_proofs, None, false) - .await?; - - let wallet_bal = wallet.total_balance().await?; - - // Check 1 sat was paid in fees for the swap - assert_eq!(wallet_bal, 9999.into()); - - let proofs = wallet - .localstore - .get_proofs(Some(MintUrl::from_str(MINT_URL)?), None, None, None) - .await?; - - let proofs: Vec = proofs.into_iter().map(|p| p.proof).collect(); - - let thousand_proofs = proofs[..1001].to_vec(); - - let fee = wallet.get_proofs_fee(&thousand_proofs).await?; - - // Check wallet gets fee calc correct - assert_eq!(fee, 2.into()); - - let _swap = wallet - .swap( - None, - SplitTarget::Value(1.into()), - thousand_proofs, - None, - false, - ) - .await?; - - let wallet_bal = wallet.total_balance().await?; - - // Check 1 sat was paid in fees for the swap - assert_eq!(wallet_bal, 9997.into()); - - Ok(()) -} diff --git a/crates/cdk-integration-tests/tests/mint.rs b/crates/cdk-integration-tests/tests/mint.rs index 9c83e067..1e696b10 100644 --- a/crates/cdk-integration-tests/tests/mint.rs +++ b/crates/cdk-integration-tests/tests/mint.rs @@ -1,88 +1,370 @@ -//! Mint integration tests +//! Mint tests +use cdk::amount::{Amount, SplitTarget}; +use cdk::dhke::construct_proofs; +use cdk::util::unix_time; use std::collections::HashMap; use std::sync::Arc; -use std::time::Duration; +use tokio::sync::OnceCell; use anyhow::{bail, Result}; use bip39::Mnemonic; -use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; -use cdk::nuts::CurrencyUnit; -use cdk::wallet::SendKind; -use cdk::Error; -use cdk::Wallet; -use cdk_integration_tests::{create_backends_fake_wallet, start_mint, wallet_mint, MINT_URL}; +use cdk::cdk_database::mint_memory::MintMemoryDatabase; +use cdk::nuts::{ + CurrencyUnit, Id, MintBolt11Request, MintInfo, Nuts, PreMintSecrets, Proofs, SecretKey, + SpendingConditions, SwapRequest, +}; +use cdk::Mint; -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_mint_double_receive() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); +pub const MINT_URL: &str = "http://127.0.0.1:8088"; - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (0, 64)); +static INSTANCE: OnceCell = OnceCell::const_new(); - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); +async fn new_mint(fee: u64) -> Mint { + let mut supported_units = HashMap::new(); + supported_units.insert(CurrencyUnit::Sat, (fee, 32)); - tokio::time::sleep(Duration::from_millis(500)).await; + let nuts = Nuts::new() + .nut07(true) + .nut08(true) + .nut09(true) + .nut10(true) + .nut11(true) + .nut12(true) + .nut14(true); - let mnemonic = Mnemonic::generate(12)?; + let mint_info = MintInfo::new().nuts(nuts); - let wallet = Wallet::new( + let mnemonic = Mnemonic::generate(12).unwrap(); + + let mint = Mint::new( MINT_URL, - CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), &mnemonic.to_seed_normalized(""), - None, - )?; + mint_info, + Arc::new(MintMemoryDatabase::default()), + supported_units, + ) + .await + .unwrap(); - let wallet = Arc::new(wallet); + mint +} - wallet_mint(Arc::clone(&wallet), 100.into(), SplitTarget::default()).await?; - println!("Minted"); +async fn initialize() -> &'static Mint { + INSTANCE.get_or_init(|| new_mint(0)).await +} - let token = wallet - .send( - 10.into(), - None, - None, - &SplitTarget::default(), - &SendKind::default(), - false, +async fn mint_proofs( + mint: &Mint, + amount: Amount, + split_target: &SplitTarget, + keys: cdk::nuts::Keys, +) -> Result { + let request_lookup = uuid::Uuid::new_v4().to_string(); + + let mint_quote = mint + .new_mint_quote( + MINT_URL.parse()?, + "".to_string(), + CurrencyUnit::Sat, + amount, + unix_time() + 36000, + request_lookup.to_string(), ) .await?; - let mnemonic = Mnemonic::generate(12)?; + mint.pay_mint_quote_for_request_id(&request_lookup).await?; + let keyset_id = Id::from(&keys); - let wallet_two = Wallet::new( - MINT_URL, - CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), - &mnemonic.to_seed_normalized(""), - None, + let premint = PreMintSecrets::random(keyset_id, amount, split_target)?; + + let mint_request = MintBolt11Request { + quote: mint_quote.id, + outputs: premint.blinded_messages(), + }; + + let after_mint = mint.process_mint_request(mint_request).await?; + + let proofs = construct_proofs( + after_mint.signatures, + premint.rs(), + premint.secrets(), + &keys, )?; - let rec = wallet_two - .receive(&token.to_string(), SplitTarget::default(), &[], &[]) - .await?; - println!("Received: {}", rec); + Ok(proofs) +} - // Attempt to receive again - if let Err(err) = wallet - .receive(&token.to_string(), SplitTarget::default(), &[], &[]) - .await - { - match err { - Error::TokenAlreadySpent => (), - _ => { - println!("{}", err); - bail!("Expected an already spent error"); - } - } +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_mint_double_spend() -> Result<()> { + let mint = initialize().await; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + + let preswap = PreMintSecrets::random(keyset_id, 100.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), preswap.blinded_messages()); + + let swap = mint.process_swap_request(swap_request).await; + + assert!(swap.is_ok()); + + let preswap_two = PreMintSecrets::random(keyset_id, 100.into(), &SplitTarget::default())?; + + let swap_two_request = SwapRequest::new(proofs, preswap_two.blinded_messages()); + + match mint.process_swap_request(swap_two_request).await { + Ok(_) => bail!("Proofs double spent"), + Err(err) => match err { + cdk::Error::TokenAlreadySpent => (), + _ => bail!("Wrong error returned"), + }, } Ok(()) } + +/// This attempts to swap for more outputs then inputs. +/// This will work if the mint does not check for outputs amounts overflowing +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_attempt_to_swap_by_overflowing() -> Result<()> { + let mint = initialize().await; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + + let amount = 2_u64.pow(63); + + let pre_mint_amount = + PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?; + let pre_mint_amount_two = + PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?; + + let mut pre_mint = PreMintSecrets::random(keyset_id, 1.into(), &SplitTarget::default())?; + + pre_mint.combine(pre_mint_amount); + pre_mint.combine(pre_mint_amount_two); + + let swap_request = SwapRequest::new(proofs.clone(), pre_mint.blinded_messages()); + + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap occurred with overflow"), + Err(err) => match err { + cdk::Error::NUT03(cdk::nuts::nut03::Error::Amount(_)) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned in swap overflow") + } + }, + } + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +pub async fn test_p2pk_swap() -> Result<()> { + let mint = initialize().await; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + + let secret = SecretKey::generate(); + + let spending_conditions = SpendingConditions::new_p2pk(secret.public_key(), None); + + let pre_swap = PreMintSecrets::with_conditions( + keyset_id, + 100.into(), + &SplitTarget::default(), + &spending_conditions, + )?; + + let swap_request = SwapRequest::new(proofs.clone(), pre_swap.blinded_messages()); + + let keys = mint.pubkeys().await?.keysets.first().cloned().unwrap().keys; + + let post_swap = mint.process_swap_request(swap_request).await?; + + let mut proofs = construct_proofs( + post_swap.signatures, + pre_swap.rs(), + pre_swap.secrets(), + &keys, + )?; + + let pre_swap = PreMintSecrets::random(keyset_id, 100.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), pre_swap.blinded_messages()); + + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Proofs spent without sig"), + Err(err) => match err { + cdk::Error::NUT11(cdk::nuts::nut11::Error::SignaturesNotProvided) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned") + } + }, + } + + for proof in &mut proofs { + proof.sign_p2pk(secret.clone())?; + } + + let swap_request = SwapRequest::new(proofs.clone(), pre_swap.blinded_messages()); + + let attempt_swap = mint.process_swap_request(swap_request).await; + + assert!(attempt_swap.is_ok()); + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_swap_unbalanced() -> Result<()> { + let mint = initialize().await; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + + let preswap = PreMintSecrets::random(keyset_id, 95.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), preswap.blinded_messages()); + + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => bail!("Wrong error returned"), + }, + } + + let preswap = PreMintSecrets::random(keyset_id, 101.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), preswap.blinded_messages()); + + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => bail!("Wrong error returned"), + }, + } + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_swap_overpay_underpay_fee() -> Result<()> { + let mint = new_mint(1).await; + + mint.rotate_keyset(CurrencyUnit::Sat, 1, 32, 1).await?; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let proofs = mint_proofs(&mint, 1000.into(), &SplitTarget::default(), keys).await?; + + let preswap = PreMintSecrets::random(keyset_id, 9998.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), preswap.blinded_messages()); + + // Attempt to swap overpaying fee + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned") + } + }, + } + + let preswap = PreMintSecrets::random(keyset_id, 1000.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(proofs.clone(), preswap.blinded_messages()); + + // Attempt to swap underpaying fee + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned") + } + }, + } + + Ok(()) +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_mint_enforce_fee() -> Result<()> { + let mint = new_mint(1).await; + + let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; + let keyset_id = Id::from(&keys); + + let mut proofs = mint_proofs(&mint, 1010.into(), &SplitTarget::Value(1.into()), keys).await?; + + let five_proofs: Vec<_> = proofs.drain(..5).collect(); + + let preswap = PreMintSecrets::random(keyset_id, 5.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(five_proofs.clone(), preswap.blinded_messages()); + + // Attempt to swap underpaying fee + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned") + } + }, + } + + let preswap = PreMintSecrets::random(keyset_id, 4.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(five_proofs.clone(), preswap.blinded_messages()); + + let _ = mint.process_swap_request(swap_request).await?; + + let thousnad_proofs: Vec<_> = proofs.drain(..1001).collect(); + + let preswap = PreMintSecrets::random(keyset_id, 1000.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(thousnad_proofs.clone(), preswap.blinded_messages()); + + // Attempt to swap underpaying fee + match mint.process_swap_request(swap_request).await { + Ok(_) => bail!("Swap was allowed unbalanced"), + Err(err) => match err { + cdk::Error::TransactionUnbalanced(_, _, _) => (), + _ => { + println!("{:?}", err); + bail!("Wrong error returned") + } + }, + } + + let preswap = PreMintSecrets::random(keyset_id, 999.into(), &SplitTarget::default())?; + + let swap_request = SwapRequest::new(thousnad_proofs.clone(), preswap.blinded_messages()); + + let _ = mint.process_swap_request(swap_request).await?; + + Ok(()) +} diff --git a/crates/cdk-integration-tests/tests/overflow.rs b/crates/cdk-integration-tests/tests/overflow.rs deleted file mode 100644 index 46bf0423..00000000 --- a/crates/cdk-integration-tests/tests/overflow.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::collections::HashMap; -use std::time::Duration; - -use anyhow::{bail, Result}; -use cdk::amount::SplitTarget; -use cdk::dhke::construct_proofs; -use cdk::nuts::{CurrencyUnit, PreMintSecrets, SwapRequest}; -use cdk::Amount; -use cdk::HttpClient; -use cdk_integration_tests::{create_backends_fake_wallet, mint_proofs, start_mint, MINT_URL}; - -/// This attempts to swap for more outputs then inputs. -/// This will work if the mint does not check for outputs amounts overflowing -async fn attempt_to_swap_by_overflowing() -> Result<()> { - let wallet_client = HttpClient::new(); - let mint_keys = wallet_client.get_mint_keys(MINT_URL.parse()?).await?; - - let mint_keys = mint_keys.first().unwrap(); - - let keyset_id = mint_keys.id; - - let pre_swap_proofs = mint_proofs(MINT_URL, 1.into(), keyset_id, mint_keys).await?; - - println!( - "Pre swap amount: {:?}", - Amount::try_sum(pre_swap_proofs.iter().map(|p| p.amount))? - ); - - println!( - "Pre swap amounts: {:?}", - pre_swap_proofs - .iter() - .map(|p| p.amount) - .collect::>() - ); - - // Construct messages that will overflow - - let amount = 2_u64.pow(63); - - let pre_mint_amount = - PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?; - let pre_mint_amount_two = - PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?; - - let mut pre_mint = PreMintSecrets::random(keyset_id, 1.into(), &SplitTarget::default())?; - - pre_mint.combine(pre_mint_amount); - pre_mint.combine(pre_mint_amount_two); - - let swap_request = SwapRequest::new(pre_swap_proofs.clone(), pre_mint.blinded_messages()); - - let swap_response = match wallet_client - .post_swap(MINT_URL.parse()?, swap_request) - .await - { - Ok(res) => res, - // In the context of this test an error response here is good. - // It means the mint does not allow us to swap for more then we should by overflowing - Err(_err) => return Ok(()), - }; - - let post_swap_proofs = construct_proofs( - swap_response.signatures, - pre_mint.rs(), - pre_mint.secrets(), - &mint_keys.clone().keys, - )?; - - println!( - "Pre swap amount: {:?}", - Amount::try_sum(pre_swap_proofs.iter().map(|p| p.amount)).expect("Amount overflowed") - ); - println!( - "Post swap amount: {:?}", - Amount::try_sum(post_swap_proofs.iter().map(|p| p.amount)).expect("Amount Overflowed") - ); - - println!( - "Pre swap amounts: {:?}", - pre_swap_proofs - .iter() - .map(|p| p.amount) - .collect::>() - ); - println!( - "Post swap amounts: {:?}", - post_swap_proofs - .iter() - .map(|p| p.amount) - .collect::>() - ); - - bail!("Should not have been able to swap") -} - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_overflow() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); - - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (0, 32)); - - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); - - // Wait for mint server to start - tokio::time::sleep(Duration::from_millis(500)).await; - - let result = attempt_to_swap_by_overflowing().await; - - assert!(result.is_ok()); - - Ok(()) -} diff --git a/crates/cdk-integration-tests/tests/p2pk.rs b/crates/cdk-integration-tests/tests/p2pk.rs deleted file mode 100644 index ec19f532..00000000 --- a/crates/cdk-integration-tests/tests/p2pk.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; -use std::time::Duration; - -use anyhow::Result; -use bip39::Mnemonic; -use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; -use cdk::nuts::{CurrencyUnit, SecretKey, SpendingConditions}; -use cdk::wallet::SendKind; -use cdk::{Amount, Wallet}; -use cdk_integration_tests::{create_backends_fake_wallet, start_mint, wallet_mint, MINT_URL}; - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_p2pk_swap() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); - - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (0, 32)); - - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); - tokio::time::sleep(Duration::from_millis(500)).await; - - let mnemonic = Mnemonic::generate(12)?; - - let wallet = Wallet::new( - MINT_URL, - CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), - &mnemonic.to_seed_normalized(""), - None, - )?; - - let wallet = Arc::new(wallet); - - // Mint 100 sats for the wallet - wallet_mint(Arc::clone(&wallet), 100.into(), SplitTarget::default()).await?; - - let secret = SecretKey::generate(); - - let spending_conditions = SpendingConditions::new_p2pk(secret.public_key(), None); - - let amount = Amount::from(10); - - let token = wallet - .send( - amount, - None, - Some(spending_conditions), - &SplitTarget::None, - &SendKind::default(), - false, - ) - .await?; - - let attempt_amount = wallet - .receive(&token.to_string(), SplitTarget::default(), &[], &[]) - .await; - - // This should fail since the token is not signed - assert!(attempt_amount.is_err()); - - let wrong_secret = SecretKey::generate(); - - let received_amount = wallet - .receive( - &token.to_string(), - SplitTarget::default(), - &[wrong_secret], - &[], - ) - .await; - - assert!(received_amount.is_err()); - - let received_amount = wallet - .receive(&token.to_string(), SplitTarget::default(), &[secret], &[]) - .await - .unwrap(); - - assert_eq!(received_amount, amount); - - Ok(()) -} diff --git a/crates/cdk-integration-tests/tests/unbalanced.rs b/crates/cdk-integration-tests/tests/unbalanced.rs deleted file mode 100644 index 374e6f03..00000000 --- a/crates/cdk-integration-tests/tests/unbalanced.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Test that if a wallet attempts to swap for less outputs then inputs correct error is returned - -use std::collections::HashMap; -use std::time::Duration; - -use anyhow::{bail, Result}; -use cdk::amount::SplitTarget; -use cdk::nuts::{CurrencyUnit, PreMintSecrets, SwapRequest}; -use cdk::Error; -use cdk::HttpClient; -use cdk_integration_tests::{create_backends_fake_wallet, mint_proofs, start_mint, MINT_URL}; - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_unbalanced_swap() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); - - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (0, 32)); - - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); - - // Wait for mint server to start - tokio::time::sleep(Duration::from_millis(500)).await; - - let wallet_client = HttpClient::new(); - let mint_keys = wallet_client.get_mint_keys(MINT_URL.parse()?).await?; - - let mint_keys = mint_keys.first().unwrap(); - - let keyset_id = mint_keys.id; - - let pre_swap_proofs = mint_proofs(MINT_URL, 10.into(), keyset_id, mint_keys).await?; - - let pre_mint = PreMintSecrets::random(keyset_id, 9.into(), &SplitTarget::default())?; - - let swap_request = SwapRequest::new(pre_swap_proofs.clone(), pre_mint.blinded_messages()); - - let _swap_response = match wallet_client - .post_swap(MINT_URL.parse()?, swap_request) - .await - { - Ok(res) => res, - // In the context of this test an error response here is good. - // It means the mint does not allow us to swap for more then we should by overflowing - Err(err) => match err { - Error::TransactionUnbalanced(_, _, _) => { - return Ok(()); - } - _ => { - println!("{}", err); - bail!("Wrong error code returned"); - } - }, - }; - - bail!("Transaction should not have succeeded") -} diff --git a/crates/cdk-integration-tests/tests/wrong_fee.rs b/crates/cdk-integration-tests/tests/wrong_fee.rs deleted file mode 100644 index c5391bcd..00000000 --- a/crates/cdk-integration-tests/tests/wrong_fee.rs +++ /dev/null @@ -1,113 +0,0 @@ -//! Fee tests for over and underpaying - -use std::collections::HashMap; -use std::str::FromStr; -use std::sync::Arc; -use std::time::Duration; - -use anyhow::{bail, Result}; -use bip39::Mnemonic; -use cdk::cdk_database::WalletMemoryDatabase; -use cdk::mint_url::MintUrl; -use cdk::nuts::{CurrencyUnit, SwapRequest}; -use cdk::wallet::client::HttpClient; -use cdk::Wallet; -use cdk::{amount::SplitTarget, nuts::PreMintSecrets}; -use cdk_integration_tests::{create_backends_fake_wallet, start_mint, wallet_mint, MINT_URL}; - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -pub async fn test_swap_overpay_underpay() -> Result<()> { - tokio::spawn(async move { - let ln_backends = create_backends_fake_wallet(); - - let mut supported_units = HashMap::new(); - supported_units.insert(CurrencyUnit::Sat, (1, 32)); - - start_mint(ln_backends, supported_units) - .await - .expect("Could not start mint") - }); - - tokio::time::sleep(Duration::from_millis(500)).await; - - let mnemonic = Mnemonic::generate(12)?; - - let wallet = Wallet::new( - MINT_URL, - CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), - &mnemonic.to_seed_normalized(""), - None, - )?; - - let wallet = Arc::new(wallet); - - wallet_mint( - Arc::clone(&wallet), - 10000.into(), - SplitTarget::Value(1.into()), - ) - .await - .unwrap(); - println!("Minted"); - - let proofs = wallet - .localstore - .get_proofs(Some(MintUrl::from_str(MINT_URL)?), None, None, None) - .await?; - - let proofs: Vec = proofs.into_iter().map(|p| p.proof).collect(); - - let keyset_id = proofs.first().unwrap().keyset_id; - - let pre_swap_proofs = proofs[..1000].to_vec(); - - // Attempt to swap while overpaying fee - - let pre_swap_secret = PreMintSecrets::random(keyset_id, 450.into(), &SplitTarget::default())?; - - let swap_request = - SwapRequest::new(pre_swap_proofs.clone(), pre_swap_secret.blinded_messages()); - - let wallet_client = HttpClient::new(); - - match wallet_client - .post_swap(MINT_URL.parse()?, swap_request) - .await - { - Ok(_res) => { - bail!("Swap should not have succeeded"); - } - Err(err) => match err { - cdk::error::Error::TransactionUnbalanced(_, _, _) => (), - _ => { - println!("{:?}", err); - bail!("Swap returned the wrong error when overpaying fee"); - } - }, - }; - - // Attempt to swap while underpaying fee - - let pre_swap_secret = PreMintSecrets::random(keyset_id, 1000.into(), &SplitTarget::default())?; - let swap_request = - SwapRequest::new(pre_swap_proofs.clone(), pre_swap_secret.blinded_messages()); - match wallet_client - .post_swap(MINT_URL.parse()?, swap_request) - .await - { - Ok(_res) => { - bail!("Swap should not have succeeded"); - } - // In the context of this test an error response here is good. - // It means the mint does not allow us to swap for more then we should by overflowing - Err(err) => match err { - cdk::error::Error::TransactionUnbalanced(_, _, _) => (), - _ => { - println!("{:?}", err); - bail!("Swap returned the wrong error when underpaying fee"); - } - }, - }; - Ok(()) -} diff --git a/crates/cdk/src/mint/mod.rs b/crates/cdk/src/mint/mod.rs index 3edce084..a7400dd6 100644 --- a/crates/cdk/src/mint/mod.rs +++ b/crates/cdk/src/mint/mod.rs @@ -511,8 +511,10 @@ impl Mint { Ok(KeysResponse { keysets: keysets .values() - .filter(|k| active_keysets.contains(&k.id)) - .map(|k| k.clone().into()) + .filter_map(|k| match active_keysets.contains(&k.id) { + true => Some(k.clone().into()), + false => None, + }) .collect(), }) } @@ -1648,4 +1650,9 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_over_pay_fee() -> anyhow::Result<()> { + Ok(()) + } }