Mint: verify outputs first during mint (#379)

* verify outputs first during mint

* verify outputs during melt as well
This commit is contained in:
callebtc
2023-12-03 19:57:49 +01:00
committed by GitHub
parent 7d4ed959e3
commit e6ed8fdb46
2 changed files with 40 additions and 9 deletions

View File

@@ -302,6 +302,8 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerLightning):
logger.trace("called mint") logger.trace("called mint")
amount_outputs = sum([b.amount for b in B_s]) amount_outputs = sum([b.amount for b in B_s])
await self._verify_outputs(B_s)
if settings.lightning: if settings.lightning:
if not id: if not id:
raise NotAllowedError("no id provided.") raise NotAllowedError("no id provided.")
@@ -317,8 +319,6 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerLightning):
await self.crud.update_lightning_invoice(id=id, issued=True, db=self.db) await self.crud.update_lightning_invoice(id=id, issued=True, db=self.db)
del self.locks[id] del self.locks[id]
await self._verify_outputs(B_s)
promises = await self._generate_promises(B_s, keyset) promises = await self._generate_promises(B_s, keyset)
logger.trace("generated promises") logger.trace("generated promises")
return promises return promises
@@ -368,6 +368,12 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerLightning):
f" {total_provided}, needed: {invoice_amount + reserve_fees_sat}" f" {total_provided}, needed: {invoice_amount + reserve_fees_sat}"
) )
if outputs:
# verify the outputs. note: we don't verify inputs
# and outputs simultaneously with verify_inputs_and_outputs() as we do
# in split() because we do not expect the amounts to be equal here.
await self._verify_outputs(outputs)
# verify spending inputs and their spending conditions # verify spending inputs and their spending conditions
await self.verify_inputs_and_outputs(proofs) await self.verify_inputs_and_outputs(proofs)

View File

@@ -37,19 +37,19 @@ async def test_melt(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11) pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, id=invoice.id)
invoice = await wallet1.request_mint(64) invoice2 = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11) pay_if_regtest(invoice2.bolt11)
await wallet1.mint(64, id=invoice.id) await wallet1.mint(64, id=invoice2.id)
assert wallet1.balance == 128 assert wallet1.balance == 128
total_amount, fee_reserve_sat = await wallet1.get_pay_amount_with_fees( total_amount, fee_reserve_sat = await wallet1.get_pay_amount_with_fees(
invoice.bolt11 invoice2.bolt11
) )
mint_fees = await ledger.get_melt_fees(invoice.bolt11) melt_fees = await ledger.get_melt_fees(invoice2.bolt11)
assert mint_fees == fee_reserve_sat assert melt_fees == fee_reserve_sat
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount) keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)
await ledger.melt(send_proofs, invoice.bolt11, outputs=None) await ledger.melt(send_proofs, invoice2.bolt11, outputs=None)
@pytest.mark.asyncio @pytest.mark.asyncio
@@ -176,6 +176,31 @@ async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
) )
@pytest.mark.asyncio
async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(130, id=invoice.id)
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
len(output_amounts)
)
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
# we use the outputs once for minting
invoice2 = await wallet1.request_mint(128)
pay_if_regtest(invoice2.bolt11)
await ledger.mint(outputs, id=invoice2.id)
# use the same outputs for melting
invoice3 = await wallet1.request_mint(128)
await assert_err(
ledger.melt(wallet1.proofs, invoice3.bolt11, outputs=outputs),
"outputs have already been signed before.",
)
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_check_proof_state(wallet1: Wallet, ledger: Ledger): async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64) invoice = await wallet1.request_mint(64)