123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- use std::time::Duration;
- use anyhow::{bail, Result};
- use cdk::amount::SplitTarget;
- use cdk::dhke::construct_proofs;
- use cdk::nuts::{CurrencyUnit, MintQuoteState, PreMintSecrets, SwapRequest};
- use cdk::Amount;
- use cdk::HttpClient;
- use cdk_integration_tests::{create_backends_fake_wallet, start_mint, MINT_URL};
- use tokio::time::sleep;
- /// 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 mint_quote = wallet_client
- .post_mint_quote(MINT_URL.parse()?, 100.into(), CurrencyUnit::Sat)
- .await?;
- loop {
- let status = wallet_client
- .get_mint_quote_status(MINT_URL.parse()?, &mint_quote.quote)
- .await?;
- if status.state == MintQuoteState::Paid {
- break;
- }
- println!("{:?}", status);
- sleep(Duration::from_secs(2)).await;
- }
- let premint_secrets =
- PreMintSecrets::random(keyset_id.clone(), 1.into(), &SplitTarget::default())?;
- let mint_response = wallet_client
- .post_mint(
- MINT_URL.parse()?,
- &mint_quote.quote,
- premint_secrets.clone(),
- )
- .await?;
- let pre_swap_proofs = construct_proofs(
- mint_response.signatures,
- premint_secrets.rs(),
- premint_secrets.secrets(),
- &mint_keys.clone().keys,
- )?;
- // Construct messages that will overflow
- let amount = 2_u64.pow(63);
- let pre_mint_amount =
- PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
- let pre_mint_amount_two =
- PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
- let mut pre_mint =
- PreMintSecrets::random(keyset_id.clone(), 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: {:?}",
- pre_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
- );
- println!(
- "Post swap amount: {:?}",
- post_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
- );
- println!(
- "Pre swap amounts: {:?}",
- pre_swap_proofs
- .iter()
- .map(|p| p.amount)
- .collect::<Vec<Amount>>()
- );
- println!(
- "Post swap amounts: {:?}",
- post_swap_proofs
- .iter()
- .map(|p| p.amount)
- .collect::<Vec<Amount>>()
- );
- 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();
- start_mint(ln_backends).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(())
- }
|