mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-29 18:45:23 +01:00
Merge pull request #655 from thesimplekid/fix_output_verification
fix: verification of melt quote with empty outputs
This commit is contained in:
@@ -256,42 +256,54 @@ async fn test_restore() -> Result<()> {
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||
async fn test_pay_invoice_twice() -> Result<()> {
|
||||
async fn test_pay_invoice_twice() -> anyhow::Result<()> {
|
||||
let lnd_client = init_lnd_client().await;
|
||||
|
||||
let seed = Mnemonic::generate(12)?.to_seed_normalized("");
|
||||
let seed = Mnemonic::generate(12).unwrap().to_seed_normalized("");
|
||||
let wallet = Wallet::new(
|
||||
&get_mint_url("0"),
|
||||
CurrencyUnit::Sat,
|
||||
Arc::new(memory::empty().await?),
|
||||
Arc::new(memory::empty().await.unwrap()),
|
||||
&seed,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let mint_quote = wallet.mint_quote(100.into(), None).await?;
|
||||
let mint_quote = wallet
|
||||
.mint_quote(100.into(), None)
|
||||
.await
|
||||
.expect("Get mint quote");
|
||||
|
||||
lnd_client
|
||||
.pay_invoice(mint_quote.request)
|
||||
.await
|
||||
.expect("Could not pay invoice");
|
||||
|
||||
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?;
|
||||
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60)
|
||||
.await
|
||||
.expect("Mint invoice timeout not paid");
|
||||
|
||||
let proofs = wallet
|
||||
.mint(&mint_quote.id, SplitTarget::default(), None)
|
||||
.await?;
|
||||
.await
|
||||
.expect("Could not mint");
|
||||
|
||||
let mint_amount = proofs.total_amount()?;
|
||||
let mint_amount = proofs.total_amount().unwrap();
|
||||
|
||||
assert_eq!(mint_amount, 100.into());
|
||||
|
||||
let invoice = lnd_client.create_invoice(Some(10)).await?;
|
||||
let invoice = lnd_client
|
||||
.create_invoice(Some(10))
|
||||
.await
|
||||
.expect("Could not create invoice");
|
||||
|
||||
let melt_quote = wallet.melt_quote(invoice.clone(), None).await?;
|
||||
let melt_quote = wallet
|
||||
.melt_quote(invoice.clone(), None)
|
||||
.await
|
||||
.expect("Could not get melt quote");
|
||||
|
||||
let melt = wallet.melt(&melt_quote.id).await.unwrap();
|
||||
|
||||
let melt_two = wallet.melt_quote(invoice, None).await?;
|
||||
let melt_two = wallet.melt_quote(invoice, None).await.unwrap();
|
||||
|
||||
let melt_two = wallet.melt(&melt_two.id).await;
|
||||
|
||||
@@ -307,7 +319,7 @@ async fn test_pay_invoice_twice() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let balance = wallet.total_balance().await?;
|
||||
let balance = wallet.total_balance().await.unwrap();
|
||||
|
||||
assert_eq!(balance, (Amount::from(100) - melt.fee_paid - melt.amount));
|
||||
|
||||
|
||||
@@ -310,6 +310,8 @@ impl Mint {
|
||||
unit: input_unit,
|
||||
} = self.verify_inputs(&melt_request.inputs).await?;
|
||||
|
||||
ensure_cdk!(input_unit.is_some(), Error::UnsupportedUnit);
|
||||
|
||||
let input_ys = melt_request.inputs.ys()?;
|
||||
|
||||
let fee = self.get_proofs_fee(&melt_request.inputs).await?;
|
||||
@@ -343,12 +345,14 @@ impl Mint {
|
||||
ensure_cdk!(sig_flag.ne(&SigFlag::SigAll), Error::SigAllUsedInMelt);
|
||||
|
||||
if let Some(outputs) = &melt_request.outputs {
|
||||
let Verification {
|
||||
amount: _,
|
||||
unit: output_unit,
|
||||
} = self.verify_outputs(outputs).await?;
|
||||
if !outputs.is_empty() {
|
||||
let Verification {
|
||||
amount: _,
|
||||
unit: output_unit,
|
||||
} = self.verify_outputs(outputs).await?;
|
||||
|
||||
ensure_cdk!(input_unit == output_unit, Error::UnsupportedUnit);
|
||||
ensure_cdk!(input_unit == output_unit, Error::UnsupportedUnit);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!("Verified melt quote: {}", melt_request.quote);
|
||||
|
||||
@@ -327,6 +327,7 @@ impl Mint {
|
||||
));
|
||||
}
|
||||
|
||||
let unit = unit.ok_or(Error::UnsupportedUnit)?;
|
||||
ensure_cdk!(unit == mint_quote.unit, Error::UnsupportedUnit);
|
||||
|
||||
let mut blind_signatures = Vec::with_capacity(mint_request.outputs.len());
|
||||
|
||||
@@ -8,7 +8,7 @@ use super::{Error, Mint};
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct Verification {
|
||||
pub amount: Amount,
|
||||
pub unit: CurrencyUnit,
|
||||
pub unit: Option<CurrencyUnit>,
|
||||
}
|
||||
|
||||
impl Mint {
|
||||
@@ -171,6 +171,13 @@ impl Mint {
|
||||
/// Checks outputs are unique, of the same unit and not signed before
|
||||
#[instrument(skip_all)]
|
||||
pub async fn verify_outputs(&self, outputs: &[BlindedMessage]) -> Result<Verification, Error> {
|
||||
if outputs.is_empty() {
|
||||
return Ok(Verification {
|
||||
amount: Amount::ZERO,
|
||||
unit: None,
|
||||
});
|
||||
}
|
||||
|
||||
Mint::check_outputs_unique(outputs)?;
|
||||
self.check_output_already_signed(outputs).await?;
|
||||
|
||||
@@ -178,7 +185,10 @@ impl Mint {
|
||||
|
||||
let amount = Amount::try_sum(outputs.iter().map(|o| o.amount).collect::<Vec<Amount>>())?;
|
||||
|
||||
Ok(Verification { amount, unit })
|
||||
Ok(Verification {
|
||||
amount,
|
||||
unit: Some(unit),
|
||||
})
|
||||
}
|
||||
|
||||
/// Verifies inputs
|
||||
@@ -194,7 +204,10 @@ impl Mint {
|
||||
self.verify_proof(proof).await?;
|
||||
}
|
||||
|
||||
Ok(Verification { amount, unit })
|
||||
Ok(Verification {
|
||||
amount,
|
||||
unit: Some(unit),
|
||||
})
|
||||
}
|
||||
|
||||
/// Verify that inputs and outputs are valid and balanced
|
||||
@@ -215,7 +228,7 @@ impl Mint {
|
||||
|
||||
if output_verification.unit != input_verification.unit {
|
||||
tracing::debug!(
|
||||
"Output unit {} does not match input unit {}",
|
||||
"Output unit {:?} does not match input unit {:?}",
|
||||
output_verification.unit,
|
||||
input_verification.unit
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user