overflow.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use std::collections::HashMap;
  2. use std::time::Duration;
  3. use anyhow::{bail, Result};
  4. use cdk::amount::SplitTarget;
  5. use cdk::dhke::construct_proofs;
  6. use cdk::nuts::{CurrencyUnit, PreMintSecrets, SwapRequest};
  7. use cdk::Amount;
  8. use cdk::HttpClient;
  9. use cdk_integration_tests::{create_backends_fake_wallet, mint_proofs, start_mint, MINT_URL};
  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 pre_swap_proofs = mint_proofs(MINT_URL, 1.into(), keyset_id, mint_keys).await?;
  18. println!(
  19. "Pre swap amount: {:?}",
  20. Amount::try_sum(pre_swap_proofs.iter().map(|p| p.amount))?
  21. );
  22. println!(
  23. "Pre swap amounts: {:?}",
  24. pre_swap_proofs
  25. .iter()
  26. .map(|p| p.amount)
  27. .collect::<Vec<Amount>>()
  28. );
  29. // Construct messages that will overflow
  30. let amount = 2_u64.pow(63);
  31. let pre_mint_amount =
  32. PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?;
  33. let pre_mint_amount_two =
  34. PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?;
  35. let mut pre_mint = PreMintSecrets::random(keyset_id, 1.into(), &SplitTarget::default())?;
  36. pre_mint.combine(pre_mint_amount);
  37. pre_mint.combine(pre_mint_amount_two);
  38. let swap_request = SwapRequest::new(pre_swap_proofs.clone(), pre_mint.blinded_messages());
  39. let swap_response = match wallet_client
  40. .post_swap(MINT_URL.parse()?, swap_request)
  41. .await
  42. {
  43. Ok(res) => res,
  44. // In the context of this test an error response here is good.
  45. // It means the mint does not allow us to swap for more then we should by overflowing
  46. Err(_err) => return Ok(()),
  47. };
  48. let post_swap_proofs = construct_proofs(
  49. swap_response.signatures,
  50. pre_mint.rs(),
  51. pre_mint.secrets(),
  52. &mint_keys.clone().keys,
  53. )?;
  54. println!(
  55. "Pre swap amount: {:?}",
  56. Amount::try_sum(pre_swap_proofs.iter().map(|p| p.amount)).expect("Amount overflowed")
  57. );
  58. println!(
  59. "Post swap amount: {:?}",
  60. Amount::try_sum(post_swap_proofs.iter().map(|p| p.amount)).expect("Amount Overflowed")
  61. );
  62. println!(
  63. "Pre swap amounts: {:?}",
  64. pre_swap_proofs
  65. .iter()
  66. .map(|p| p.amount)
  67. .collect::<Vec<Amount>>()
  68. );
  69. println!(
  70. "Post swap amounts: {:?}",
  71. post_swap_proofs
  72. .iter()
  73. .map(|p| p.amount)
  74. .collect::<Vec<Amount>>()
  75. );
  76. bail!("Should not have been able to swap")
  77. }
  78. #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
  79. pub async fn test_overflow() -> Result<()> {
  80. tokio::spawn(async move {
  81. let ln_backends = create_backends_fake_wallet();
  82. let mut supported_units = HashMap::new();
  83. supported_units.insert(CurrencyUnit::Sat, (0, 32));
  84. start_mint(ln_backends, supported_units)
  85. .await
  86. .expect("Could not start mint")
  87. });
  88. // Wait for mint server to start
  89. tokio::time::sleep(Duration::from_millis(500)).await;
  90. let result = attempt_to_swap_by_overflowing().await;
  91. assert!(result.is_ok());
  92. Ok(())
  93. }