overflow.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. use std::time::Duration;
  2. use anyhow::{bail, Result};
  3. use cdk::amount::SplitTarget;
  4. use cdk::dhke::construct_proofs;
  5. use cdk::nuts::{CurrencyUnit, MintQuoteState, PreMintSecrets, SwapRequest};
  6. use cdk::Amount;
  7. use cdk::HttpClient;
  8. use cdk_integration_tests::{create_backends_fake_wallet, start_mint, MINT_URL};
  9. use tokio::time::sleep;
  10. /// This attempts to swap for more outputs then inputs.
  11. /// This will work if the mint does not check for outputs amounts overflowing
  12. async fn attempt_to_swap_by_overflowing() -> Result<()> {
  13. let wallet_client = HttpClient::new();
  14. let mint_keys = wallet_client.get_mint_keys(MINT_URL.parse()?).await?;
  15. let mint_keys = mint_keys.first().unwrap();
  16. let keyset_id = mint_keys.id;
  17. let mint_quote = wallet_client
  18. .post_mint_quote(MINT_URL.parse()?, 100.into(), CurrencyUnit::Sat)
  19. .await?;
  20. loop {
  21. let status = wallet_client
  22. .get_mint_quote_status(MINT_URL.parse()?, &mint_quote.quote)
  23. .await?;
  24. if status.state == MintQuoteState::Paid {
  25. break;
  26. }
  27. println!("{:?}", status);
  28. sleep(Duration::from_secs(2)).await;
  29. }
  30. let premint_secrets =
  31. PreMintSecrets::random(keyset_id.clone(), 1.into(), &SplitTarget::default())?;
  32. let mint_response = wallet_client
  33. .post_mint(
  34. MINT_URL.parse()?,
  35. &mint_quote.quote,
  36. premint_secrets.clone(),
  37. )
  38. .await?;
  39. let pre_swap_proofs = construct_proofs(
  40. mint_response.signatures,
  41. premint_secrets.rs(),
  42. premint_secrets.secrets(),
  43. &mint_keys.clone().keys,
  44. )?;
  45. // Construct messages that will overflow
  46. let amount = 2_u64.pow(63);
  47. let pre_mint_amount =
  48. PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
  49. let pre_mint_amount_two =
  50. PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
  51. let mut pre_mint =
  52. PreMintSecrets::random(keyset_id.clone(), 1.into(), &SplitTarget::default())?;
  53. pre_mint.combine(pre_mint_amount);
  54. pre_mint.combine(pre_mint_amount_two);
  55. let swap_request = SwapRequest::new(pre_swap_proofs.clone(), pre_mint.blinded_messages());
  56. let swap_response = match wallet_client
  57. .post_swap(MINT_URL.parse()?, swap_request)
  58. .await
  59. {
  60. Ok(res) => res,
  61. // In the context of this test an error response here is good.
  62. // It means the mint does not allow us to swap for more then we should by overflowing
  63. Err(_err) => return Ok(()),
  64. };
  65. let post_swap_proofs = construct_proofs(
  66. swap_response.signatures,
  67. pre_mint.rs(),
  68. pre_mint.secrets(),
  69. &mint_keys.clone().keys,
  70. )?;
  71. println!(
  72. "Pre swap amount: {:?}",
  73. pre_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
  74. );
  75. println!(
  76. "Post swap amount: {:?}",
  77. post_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
  78. );
  79. println!(
  80. "Pre swap amounts: {:?}",
  81. pre_swap_proofs
  82. .iter()
  83. .map(|p| p.amount)
  84. .collect::<Vec<Amount>>()
  85. );
  86. println!(
  87. "Post swap amounts: {:?}",
  88. post_swap_proofs
  89. .iter()
  90. .map(|p| p.amount)
  91. .collect::<Vec<Amount>>()
  92. );
  93. bail!("Should not have been able to swap")
  94. }
  95. #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
  96. pub async fn test_overflow() -> Result<()> {
  97. tokio::spawn(async move {
  98. let ln_backends = create_backends_fake_wallet();
  99. start_mint(ln_backends).await.expect("Could not start mint")
  100. });
  101. // Wait for mint server to start
  102. tokio::time::sleep(Duration::from_millis(500)).await;
  103. let result = attempt_to_swap_by_overflowing().await;
  104. assert!(result.is_ok());
  105. Ok(())
  106. }