mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-30 15:04:29 +01:00
Fix blind message already signed error (#828)
* get unsigned blinded messages for output duplicate check * bm regression tests (#827) * fix last entry * test for error from error struct * rename tests, fix second regression test, add descriptive comments. * check for error message * one more test --------- Co-authored-by: lollerfirst <43107113+lollerfirst@users.noreply.github.com> Co-authored-by: lollerfirst <lollerfirst@gmail.com>
This commit is contained in:
@@ -390,8 +390,8 @@ async def test_store_and_sign_blinded_message(ledger: Ledger):
|
||||
s=s.serialize(),
|
||||
)
|
||||
|
||||
# Assert: row is now a full promise and can be read back via get_promise
|
||||
promise = await ledger.crud.get_promise(db=ledger.db, b_=B_hex)
|
||||
# Assert: row is now a full promise and can be read back via get_blind_signature
|
||||
promise = await ledger.crud.get_blind_signature(db=ledger.db, b_=B_hex)
|
||||
assert promise is not None
|
||||
assert promise.amount == amount
|
||||
assert promise.C_ == C_point.serialize().hex()
|
||||
@@ -760,9 +760,9 @@ async def test_promises_fk_constraints_enforced(ledger: Ledger):
|
||||
async def test_concurrent_set_melt_quote_pending_same_checking_id(ledger: Ledger):
|
||||
"""Test that concurrent attempts to set quotes with same checking_id as pending are handled correctly."""
|
||||
from cashu.core.base import MeltQuote, MeltQuoteState
|
||||
|
||||
|
||||
checking_id = "test_checking_id_concurrent"
|
||||
|
||||
|
||||
# Create two quotes with the same checking_id
|
||||
quote1 = MeltQuote(
|
||||
quote="quote_id_conc_1",
|
||||
@@ -784,24 +784,24 @@ async def test_concurrent_set_melt_quote_pending_same_checking_id(ledger: Ledger
|
||||
fee_reserve=2,
|
||||
state=MeltQuoteState.unpaid,
|
||||
)
|
||||
|
||||
|
||||
await ledger.crud.store_melt_quote(quote=quote1, db=ledger.db)
|
||||
await ledger.crud.store_melt_quote(quote=quote2, db=ledger.db)
|
||||
|
||||
|
||||
# Try to set both as pending concurrently
|
||||
results = await asyncio.gather(
|
||||
ledger.db_write._set_melt_quote_pending(quote=quote1),
|
||||
ledger.db_write._set_melt_quote_pending(quote=quote2),
|
||||
return_exceptions=True
|
||||
return_exceptions=True,
|
||||
)
|
||||
|
||||
|
||||
# One should succeed, one should fail
|
||||
success_count = sum(1 for r in results if isinstance(r, MeltQuote))
|
||||
error_count = sum(1 for r in results if isinstance(r, Exception))
|
||||
|
||||
|
||||
assert success_count == 1, "Exactly one quote should be set as pending"
|
||||
assert error_count == 1, "Exactly one should fail"
|
||||
|
||||
|
||||
# The error should be about the quote already being pending
|
||||
error = next(r for r in results if isinstance(r, Exception))
|
||||
assert "Melt quote already paid or pending." in str(error)
|
||||
|
||||
@@ -4,7 +4,7 @@ import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cashu.core.base import MeltQuote, MeltQuoteState, Proof
|
||||
from cashu.core.errors import LightningPaymentFailedError
|
||||
from cashu.core.errors import LightningPaymentFailedError, OutputsAlreadySignedError
|
||||
from cashu.core.models import PostMeltQuoteRequest, PostMintQuoteRequest
|
||||
from cashu.core.settings import settings
|
||||
from cashu.lightning.base import PaymentResult
|
||||
@@ -13,6 +13,7 @@ from cashu.wallet.wallet import Wallet
|
||||
from tests.conftest import SERVER_ENDPOINT
|
||||
from tests.helpers import (
|
||||
get_real_invoice,
|
||||
is_deprecated_api_only,
|
||||
is_fake,
|
||||
is_regtest,
|
||||
pay_if_regtest,
|
||||
@@ -85,6 +86,174 @@ async def create_pending_melts(
|
||||
return pending_proof, quote
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(
|
||||
not is_fake or is_deprecated_api_only,
|
||||
reason="only fakewallet and non-deprecated api",
|
||||
)
|
||||
async def test_pending_melt_quote_outputs_registration_regression(
|
||||
wallet, ledger: Ledger
|
||||
):
|
||||
"""When paying a request results in a PENDING melt quote,
|
||||
the change outputs should be registered properly
|
||||
and further requests with the same outputs should result in an expected error.
|
||||
"""
|
||||
settings.fakewallet_payment_state = PaymentResult.PENDING.name
|
||||
settings.fakewallet_pay_invoice_state = PaymentResult.PENDING.name
|
||||
|
||||
mint_quote1 = await wallet.request_mint(100)
|
||||
mint_quote2 = await wallet.request_mint(100)
|
||||
# await pay_if_regtest(mint_quote1.request)
|
||||
# await pay_if_regtest(mint_quote2.request)
|
||||
|
||||
proofs1 = await wallet.mint(amount=100, quote_id=mint_quote1.quote)
|
||||
proofs2 = await wallet.mint(amount=100, quote_id=mint_quote2.quote)
|
||||
|
||||
invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
|
||||
# Get two melt quotes
|
||||
melt_quote1 = await wallet.melt_quote(invoice_64_sat)
|
||||
melt_quote2 = await wallet.melt_quote(invoice_62_sat)
|
||||
|
||||
n_change_outputs = 7
|
||||
(
|
||||
change_secrets,
|
||||
change_rs,
|
||||
change_derivation_paths,
|
||||
) = await wallet.generate_n_secrets(n_change_outputs, skip_bump=True)
|
||||
change_outputs, change_rs = wallet._construct_outputs(
|
||||
n_change_outputs * [1], change_secrets, change_rs
|
||||
)
|
||||
response1 = await ledger.melt(
|
||||
proofs=proofs1, quote=melt_quote1.quote, outputs=change_outputs
|
||||
)
|
||||
assert response1.state == "PENDING"
|
||||
|
||||
await assert_err(
|
||||
ledger.melt(
|
||||
proofs=proofs2,
|
||||
quote=melt_quote2.quote,
|
||||
outputs=change_outputs,
|
||||
),
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
# use get_melt_quote to verify that the quote state is updated
|
||||
melt_quote1_updated = await ledger.get_melt_quote(melt_quote1.quote)
|
||||
assert melt_quote1_updated.state == MeltQuoteState.pending
|
||||
|
||||
melt_quote2_updated = await ledger.get_melt_quote(melt_quote2.quote)
|
||||
assert melt_quote2_updated.state == MeltQuoteState.unpaid
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(
|
||||
not is_fake or is_deprecated_api_only,
|
||||
reason="only fakewallet and non-deprecated api",
|
||||
)
|
||||
async def test_settled_melt_quote_outputs_registration_regression(
|
||||
wallet, ledger: Ledger
|
||||
):
|
||||
"""Verify that if one melt request fails, we can still use the same outputs in another request"""
|
||||
|
||||
settings.fakewallet_payment_state = PaymentResult.FAILED.name
|
||||
settings.fakewallet_pay_invoice_state = PaymentResult.FAILED.name
|
||||
|
||||
mint_quote1 = await wallet.request_mint(100)
|
||||
mint_quote2 = await wallet.request_mint(100)
|
||||
# await pay_if_regtest(mint_quote1.request)
|
||||
# await pay_if_regtest(mint_quote2.request)
|
||||
|
||||
proofs1 = await wallet.mint(amount=100, quote_id=mint_quote1.quote)
|
||||
proofs2 = await wallet.mint(amount=100, quote_id=mint_quote2.quote)
|
||||
|
||||
invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
|
||||
# Get two melt quotes
|
||||
melt_quote1 = await wallet.melt_quote(invoice_64_sat)
|
||||
melt_quote2 = await wallet.melt_quote(invoice_62_sat)
|
||||
|
||||
n_change_outputs = 7
|
||||
(
|
||||
change_secrets,
|
||||
change_rs,
|
||||
change_derivation_paths,
|
||||
) = await wallet.generate_n_secrets(n_change_outputs, skip_bump=True)
|
||||
change_outputs, change_rs = wallet._construct_outputs(
|
||||
n_change_outputs * [1], change_secrets, change_rs
|
||||
)
|
||||
await assert_err(
|
||||
ledger.melt(proofs=proofs1, quote=melt_quote1.quote, outputs=change_outputs),
|
||||
"Lightning payment failed.",
|
||||
)
|
||||
|
||||
settings.fakewallet_payment_state = PaymentResult.SETTLED.name
|
||||
settings.fakewallet_pay_invoice_state = PaymentResult.SETTLED.name
|
||||
|
||||
response2 = await ledger.melt(
|
||||
proofs=proofs2,
|
||||
quote=melt_quote2.quote,
|
||||
outputs=change_outputs,
|
||||
)
|
||||
|
||||
assert response2.state == "PAID"
|
||||
|
||||
# use get_melt_quote to verify that the quote state is updated
|
||||
melt_quote2_updated = await ledger.get_melt_quote(melt_quote2.quote)
|
||||
assert melt_quote2_updated.state == MeltQuoteState.paid
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(
|
||||
not is_fake or is_deprecated_api_only,
|
||||
reason="only fakewallet and non-deprecated api",
|
||||
)
|
||||
async def test_melt_quote_reuse_same_outputs(wallet, ledger: Ledger):
|
||||
"""Verify that if the same outputs are used in two melt requests,
|
||||
the second one fails.
|
||||
"""
|
||||
|
||||
settings.fakewallet_payment_state = PaymentResult.SETTLED.name
|
||||
settings.fakewallet_pay_invoice_state = PaymentResult.SETTLED.name
|
||||
|
||||
mint_quote1 = await wallet.request_mint(100)
|
||||
mint_quote2 = await wallet.request_mint(100)
|
||||
# await pay_if_regtest(mint_quote1.request)
|
||||
# await pay_if_regtest(mint_quote2.request)
|
||||
|
||||
proofs1 = await wallet.mint(amount=100, quote_id=mint_quote1.quote)
|
||||
proofs2 = await wallet.mint(amount=100, quote_id=mint_quote2.quote)
|
||||
|
||||
invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
|
||||
# Get two melt quotes
|
||||
melt_quote1 = await wallet.melt_quote(invoice_64_sat)
|
||||
melt_quote2 = await wallet.melt_quote(invoice_62_sat)
|
||||
|
||||
n_change_outputs = 7
|
||||
(
|
||||
change_secrets,
|
||||
change_rs,
|
||||
change_derivation_paths,
|
||||
) = await wallet.generate_n_secrets(n_change_outputs, skip_bump=True)
|
||||
change_outputs, change_rs = wallet._construct_outputs(
|
||||
n_change_outputs * [1], change_secrets, change_rs
|
||||
)
|
||||
(ledger.melt(proofs=proofs1, quote=melt_quote1.quote, outputs=change_outputs),)
|
||||
|
||||
await assert_err(
|
||||
ledger.melt(
|
||||
proofs=proofs2,
|
||||
quote=melt_quote2.quote,
|
||||
outputs=change_outputs,
|
||||
),
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_regtest, reason="only fake wallet")
|
||||
async def test_fakewallet_pending_quote_get_melt_quote_success(ledger: Ledger):
|
||||
@@ -379,7 +548,7 @@ async def test_mint_melt_different_units(ledger: Ledger, wallet: Wallet):
|
||||
async def test_set_melt_quote_pending_without_checking_id(ledger: Ledger):
|
||||
"""Test that setting a melt quote as pending without a checking_id raises an error."""
|
||||
from cashu.core.errors import TransactionError
|
||||
|
||||
|
||||
quote = MeltQuote(
|
||||
quote="quote_id_no_checking",
|
||||
method="bolt11",
|
||||
@@ -391,10 +560,10 @@ async def test_set_melt_quote_pending_without_checking_id(ledger: Ledger):
|
||||
state=MeltQuoteState.unpaid,
|
||||
)
|
||||
await ledger.crud.store_melt_quote(quote=quote, db=ledger.db)
|
||||
|
||||
|
||||
# Set checking_id to empty to simulate the error condition
|
||||
quote.checking_id = ""
|
||||
|
||||
|
||||
try:
|
||||
await ledger.db_write._set_melt_quote_pending(quote=quote)
|
||||
raise AssertionError("Expected TransactionError")
|
||||
@@ -406,9 +575,9 @@ async def test_set_melt_quote_pending_without_checking_id(ledger: Ledger):
|
||||
async def test_set_melt_quote_pending_prevents_duplicate_checking_id(ledger: Ledger):
|
||||
"""Test that setting a melt quote as pending fails if another quote with same checking_id is already pending."""
|
||||
from cashu.core.errors import TransactionError
|
||||
|
||||
|
||||
checking_id = "test_checking_id_duplicate"
|
||||
|
||||
|
||||
quote1 = MeltQuote(
|
||||
quote="quote_id_dup_first",
|
||||
method="bolt11",
|
||||
@@ -429,26 +598,30 @@ async def test_set_melt_quote_pending_prevents_duplicate_checking_id(ledger: Led
|
||||
fee_reserve=2,
|
||||
state=MeltQuoteState.unpaid,
|
||||
)
|
||||
|
||||
|
||||
await ledger.crud.store_melt_quote(quote=quote1, db=ledger.db)
|
||||
await ledger.crud.store_melt_quote(quote=quote2, db=ledger.db)
|
||||
|
||||
|
||||
# Set the first quote as pending
|
||||
await ledger.db_write._set_melt_quote_pending(quote=quote1)
|
||||
|
||||
|
||||
# Verify the first quote is pending
|
||||
quote1_db = await ledger.crud.get_melt_quote(quote_id="quote_id_dup_first", db=ledger.db)
|
||||
quote1_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_dup_first", db=ledger.db
|
||||
)
|
||||
assert quote1_db.state == MeltQuoteState.pending
|
||||
|
||||
|
||||
# Attempt to set the second quote as pending should fail
|
||||
try:
|
||||
await ledger.db_write._set_melt_quote_pending(quote=quote2)
|
||||
raise AssertionError("Expected TransactionError")
|
||||
except TransactionError as e:
|
||||
assert "Melt quote already paid or pending." in str(e)
|
||||
|
||||
|
||||
# Verify the second quote is still unpaid
|
||||
quote2_db = await ledger.crud.get_melt_quote(quote_id="quote_id_dup_second", db=ledger.db)
|
||||
quote2_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_dup_second", db=ledger.db
|
||||
)
|
||||
assert quote2_db.state == MeltQuoteState.unpaid
|
||||
|
||||
|
||||
@@ -457,7 +630,7 @@ async def test_set_melt_quote_pending_allows_different_checking_id(ledger: Ledge
|
||||
"""Test that setting melt quotes as pending succeeds when they have different checking_ids."""
|
||||
checking_id_1 = "test_checking_id_allow_1"
|
||||
checking_id_2 = "test_checking_id_allow_2"
|
||||
|
||||
|
||||
quote1 = MeltQuote(
|
||||
quote="quote_id_allow_1",
|
||||
method="bolt11",
|
||||
@@ -478,17 +651,21 @@ async def test_set_melt_quote_pending_allows_different_checking_id(ledger: Ledge
|
||||
fee_reserve=2,
|
||||
state=MeltQuoteState.unpaid,
|
||||
)
|
||||
|
||||
|
||||
await ledger.crud.store_melt_quote(quote=quote1, db=ledger.db)
|
||||
await ledger.crud.store_melt_quote(quote=quote2, db=ledger.db)
|
||||
|
||||
|
||||
# Set both quotes as pending - should succeed
|
||||
await ledger.db_write._set_melt_quote_pending(quote=quote1)
|
||||
await ledger.db_write._set_melt_quote_pending(quote=quote2)
|
||||
|
||||
|
||||
# Verify both quotes are pending
|
||||
quote1_db = await ledger.crud.get_melt_quote(quote_id="quote_id_allow_1", db=ledger.db)
|
||||
quote2_db = await ledger.crud.get_melt_quote(quote_id="quote_id_allow_2", db=ledger.db)
|
||||
quote1_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_allow_1", db=ledger.db
|
||||
)
|
||||
quote2_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_allow_2", db=ledger.db
|
||||
)
|
||||
assert quote1_db.state == MeltQuoteState.pending
|
||||
assert quote2_db.state == MeltQuoteState.pending
|
||||
|
||||
@@ -497,7 +674,7 @@ async def test_set_melt_quote_pending_allows_different_checking_id(ledger: Ledge
|
||||
async def test_set_melt_quote_pending_after_unset(ledger: Ledger):
|
||||
"""Test that a quote can be set as pending again after being unset."""
|
||||
checking_id = "test_checking_id_unset_test"
|
||||
|
||||
|
||||
quote1 = MeltQuote(
|
||||
quote="quote_id_unset_first",
|
||||
method="bolt11",
|
||||
@@ -518,28 +695,38 @@ async def test_set_melt_quote_pending_after_unset(ledger: Ledger):
|
||||
fee_reserve=2,
|
||||
state=MeltQuoteState.unpaid,
|
||||
)
|
||||
|
||||
|
||||
await ledger.crud.store_melt_quote(quote=quote1, db=ledger.db)
|
||||
await ledger.crud.store_melt_quote(quote=quote2, db=ledger.db)
|
||||
|
||||
|
||||
# Set the first quote as pending
|
||||
quote1_pending = await ledger.db_write._set_melt_quote_pending(quote=quote1)
|
||||
assert quote1_pending.state == MeltQuoteState.pending
|
||||
|
||||
|
||||
# Unset the first quote (mark as paid)
|
||||
await ledger.db_write._unset_melt_quote_pending(quote=quote1_pending, state=MeltQuoteState.paid)
|
||||
|
||||
await ledger.db_write._unset_melt_quote_pending(
|
||||
quote=quote1_pending, state=MeltQuoteState.paid
|
||||
)
|
||||
|
||||
# Verify the first quote is no longer pending
|
||||
quote1_db = await ledger.crud.get_melt_quote(quote_id="quote_id_unset_first", db=ledger.db)
|
||||
quote1_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_unset_first", db=ledger.db
|
||||
)
|
||||
assert quote1_db.state == MeltQuoteState.paid
|
||||
|
||||
|
||||
# Now the second quote should still
|
||||
assert_err(ledger.db_write._set_melt_quote_pending(quote=quote2), "Melt quote already paid or pending.")
|
||||
|
||||
await assert_err(
|
||||
ledger.db_write._set_melt_quote_pending(quote=quote2),
|
||||
"Melt quote already paid or pending.",
|
||||
)
|
||||
|
||||
# Verify the second quote is unpaid
|
||||
quote2_db = await ledger.crud.get_melt_quote(quote_id="quote_id_unset_second", db=ledger.db)
|
||||
quote2_db = await ledger.crud.get_melt_quote(
|
||||
quote_id="quote_id_unset_second", db=ledger.db
|
||||
)
|
||||
assert quote2_db.state == MeltQuoteState.unpaid
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_mint_pay_with_duplicate_checking_id(wallet):
|
||||
@@ -551,18 +738,26 @@ async def test_mint_pay_with_duplicate_checking_id(wallet):
|
||||
proofs1 = await wallet.mint(amount=1024, quote_id=mint_quote1.quote)
|
||||
proofs2 = await wallet.mint(amount=1024, quote_id=mint_quote2.quote)
|
||||
|
||||
invoice = get_real_invoice(64)['payment_request']
|
||||
invoice = get_real_invoice(64)["payment_request"]
|
||||
|
||||
# Get two melt quotes for the same invoice
|
||||
melt_quote1 = await wallet.melt_quote(invoice)
|
||||
melt_quote2 = await wallet.melt_quote(invoice)
|
||||
|
||||
response1 = await wallet.melt(
|
||||
proofs=proofs1, invoice=invoice, fee_reserve_sat=melt_quote1.fee_reserve, quote_id=melt_quote1.quote
|
||||
)
|
||||
assert response1.state == 'PAID'
|
||||
proofs=proofs1,
|
||||
invoice=invoice,
|
||||
fee_reserve_sat=melt_quote1.fee_reserve,
|
||||
quote_id=melt_quote1.quote,
|
||||
)
|
||||
assert response1.state == "PAID"
|
||||
|
||||
assert_err(wallet.melt(
|
||||
proofs=proofs2, invoice=invoice, fee_reserve_sat=melt_quote2.fee_reserve, quote_id=melt_quote2.quote
|
||||
), "Melt quote already paid or pending.")
|
||||
|
||||
assert_err(
|
||||
wallet.melt(
|
||||
proofs=proofs2,
|
||||
invoice=invoice,
|
||||
fee_reserve_sat=melt_quote2.fee_reserve,
|
||||
quote_id=melt_quote2.quote,
|
||||
),
|
||||
"Melt quote already paid or pending.",
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cashu.core.base import MeltQuoteState, MintQuoteState
|
||||
from cashu.core.errors import OutputsAlreadySignedError
|
||||
from cashu.core.helpers import sum_proofs
|
||||
from cashu.core.models import PostMeltQuoteRequest, PostMintQuoteRequest
|
||||
from cashu.core.nuts import nut20
|
||||
@@ -145,7 +146,7 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
await assert_err(
|
||||
ledger.mint(outputs=outputs, quote_id=mint_quote.quote),
|
||||
"outputs have already been signed before.",
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
mint_quote_after_payment = await ledger.get_mint_quote(mint_quote.quote)
|
||||
@@ -294,7 +295,7 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
# try to spend other proofs with the same outputs again
|
||||
await assert_err(
|
||||
ledger.swap(proofs=inputs2, outputs=outputs),
|
||||
"outputs have already been signed before.",
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
# try to spend inputs2 again with new outputs
|
||||
@@ -328,7 +329,7 @@ async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
signature = nut20.sign_mint_quote(mint_quote_2.quote, outputs, mint_quote_2.privkey)
|
||||
await assert_err(
|
||||
ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote, signature=signature),
|
||||
"outputs have already been signed before.",
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
|
||||
@@ -358,7 +359,7 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
)
|
||||
await assert_err(
|
||||
ledger.melt(proofs=wallet1.proofs, quote=melt_quote.quote, outputs=outputs),
|
||||
"outputs have already been signed before.",
|
||||
OutputsAlreadySignedError.detail,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user