mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-02-23 17:44:30 +01:00
Mint: table locks (#566)
* clean up db * db: table lock * db.table_with_schema * fix encrypt.py * postgres nowait * add timeout to lock * melt quote state in db * kinda working * kinda working with postgres * remove dispose * getting there * porperly clean up db for tests * faster tests * configure connection pooling * try github with connection pool * invoice dispatcher does not lock db * fakewallet: pay_if_regtest waits * pay fakewallet invoices * add more * faster * slower * pay_if_regtest async * do not lock the invoice dispatcher * test: do I get disk I/O errors if we disable the invoice_callback_dispatcher? * fix fake so it workss without a callback dispatchert * test on github * readd tasks * refactor * increase time for lock invoice disatcher * try avoiding a race * remove task * github actions: test regtest with postgres * mint per module * no connection pool for testing * enable pool * do not resend paid event * reuse connection * close db connections * sessions * enable debug * dispose engine * disable connection pool for tests * enable connection pool for postgres only * clean up shutdown routine * remove wait for lightning fakewallet lightning invoice * cancel invoice listener tasks on shutdown * fakewallet conftest: decrease outgoing delay * delay payment and set postgres only if needed * disable fail fast for regtest * clean up regtest.yml * change order of tests_db.py * row-specific mint_quote locking * refactor * fix lock statement * refactor swap * refactor * remove psycopg2 * add connection string example to .env.example * remove unnecessary pay * shorter sleep in test_wallet_subscription_swap
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from cashu.core.base import MeltQuoteState, MintQuoteState
|
||||
from cashu.core.helpers import sum_proofs
|
||||
from cashu.core.models import PostMeltQuoteRequest, PostMintQuoteRequest
|
||||
from cashu.mint.ledger import Ledger
|
||||
@@ -37,7 +38,9 @@ async def wallet1(ledger: Ledger):
|
||||
async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
# create a mint quote so that we can melt to it internally
|
||||
@@ -48,17 +51,21 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
|
||||
)
|
||||
assert not melt_quote.paid
|
||||
assert melt_quote.state == MeltQuoteState.unpaid.value
|
||||
|
||||
assert melt_quote.amount == 64
|
||||
assert melt_quote.fee_reserve == 0
|
||||
|
||||
melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote)
|
||||
assert not melt_quote_pre_payment.paid, "melt quote should not be paid"
|
||||
assert melt_quote_pre_payment.state == MeltQuoteState.unpaid
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 64)
|
||||
await ledger.melt(proofs=send_proofs, quote=melt_quote.quote)
|
||||
|
||||
melt_quote_post_payment = await ledger.get_melt_quote(melt_quote.quote)
|
||||
assert melt_quote_post_payment.paid, "melt quote should be paid"
|
||||
assert melt_quote_post_payment.state == MeltQuoteState.paid
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -66,7 +73,7 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
@@ -74,6 +81,9 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
invoice_payment_request = invoice_dict["payment_request"]
|
||||
|
||||
mint_quote = await wallet1.melt_quote(invoice_payment_request)
|
||||
assert not mint_quote.paid, "mint quote should not be paid"
|
||||
assert mint_quote.state == MeltQuoteState.unpaid.value
|
||||
|
||||
total_amount = mint_quote.amount + mint_quote.fee_reserve
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
@@ -82,22 +92,25 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote)
|
||||
assert not melt_quote_pre_payment.paid, "melt quote should not be paid"
|
||||
assert melt_quote_pre_payment.state == MeltQuoteState.unpaid
|
||||
|
||||
assert not melt_quote.paid, "melt quote should not be paid"
|
||||
await ledger.melt(proofs=send_proofs, quote=melt_quote.quote)
|
||||
|
||||
melt_quote_post_payment = await ledger.get_melt_quote(melt_quote.quote)
|
||||
assert melt_quote_post_payment.paid, "melt quote should be paid"
|
||||
assert melt_quote_post_payment.state == MeltQuoteState.paid
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
|
||||
async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
mint_quote = await ledger.get_mint_quote(invoice.id)
|
||||
|
||||
assert mint_quote.paid, "mint quote should be paid"
|
||||
assert mint_quote.state == MintQuoteState.paid
|
||||
|
||||
output_amounts = [128]
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
|
||||
@@ -111,24 +124,32 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
|
||||
"outputs have already been signed before.",
|
||||
)
|
||||
|
||||
mint_quote_after_payment = await ledger.get_mint_quote(invoice.id)
|
||||
assert mint_quote_after_payment.paid, "mint quote should be paid"
|
||||
assert mint_quote_after_payment.state == MintQuoteState.issued
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_fake, reason="only works with Regtest")
|
||||
async def test_mint_external(wallet1: Wallet, ledger: Ledger):
|
||||
quote = await ledger.mint_quote(PostMintQuoteRequest(amount=128, unit="sat"))
|
||||
assert not quote.paid, "mint quote should not be paid"
|
||||
assert quote.state == MintQuoteState.unpaid
|
||||
|
||||
mint_quote = await ledger.get_mint_quote(quote.quote)
|
||||
assert not mint_quote.paid, "mint quote already paid"
|
||||
assert mint_quote.state == MintQuoteState.unpaid
|
||||
|
||||
await assert_err(
|
||||
wallet1.mint(128, id=quote.quote),
|
||||
"quote not paid",
|
||||
)
|
||||
|
||||
pay_if_regtest(quote.request)
|
||||
await pay_if_regtest(quote.request)
|
||||
|
||||
mint_quote = await ledger.get_mint_quote(quote.quote)
|
||||
assert mint_quote.paid, "mint quote should be paid"
|
||||
assert mint_quote.state == MintQuoteState.paid
|
||||
|
||||
output_amounts = [128]
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
|
||||
@@ -137,11 +158,15 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
await ledger.mint(outputs=outputs, quote_id=quote.quote)
|
||||
|
||||
mint_quote_after_payment = await ledger.get_mint_quote(quote.quote)
|
||||
assert mint_quote_after_payment.paid, "mint quote should be paid"
|
||||
assert mint_quote_after_payment.state == MintQuoteState.issued
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
|
||||
@@ -158,7 +183,7 @@ async def test_split(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10, set_reserved=False)
|
||||
await assert_err(
|
||||
@@ -170,7 +195,7 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(
|
||||
@@ -199,7 +224,7 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
|
||||
inputs = wallet1.proofs
|
||||
@@ -223,7 +248,7 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, split=[64, 64], id=invoice.id)
|
||||
inputs1 = wallet1.proofs[:1]
|
||||
inputs2 = wallet1.proofs[1:]
|
||||
@@ -258,7 +283,7 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
output_amounts = [128]
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
|
||||
len(output_amounts)
|
||||
@@ -268,7 +293,7 @@ async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
# now try to mint with the same outputs again
|
||||
invoice2 = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice2.bolt11)
|
||||
await pay_if_regtest(invoice2.bolt11)
|
||||
|
||||
await assert_err(
|
||||
ledger.mint(outputs=outputs, quote_id=invoice2.id),
|
||||
@@ -279,7 +304,7 @@ 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 pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(130, id=invoice.id)
|
||||
|
||||
output_amounts = [128]
|
||||
@@ -290,7 +315,7 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
# we use the outputs once for minting
|
||||
invoice2 = await wallet1.request_mint(128)
|
||||
pay_if_regtest(invoice2.bolt11)
|
||||
await pay_if_regtest(invoice2.bolt11)
|
||||
await ledger.mint(outputs=outputs, quote_id=invoice2.id)
|
||||
|
||||
# use the same outputs for melting
|
||||
@@ -307,7 +332,7 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(32)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(32, id=invoice.id)
|
||||
|
||||
# outputs for fee return
|
||||
@@ -336,7 +361,7 @@ async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(130)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(130, split=[64, 64, 2], id=invoice.id)
|
||||
|
||||
# outputs for fee return
|
||||
@@ -368,7 +393,7 @@ async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
pay_if_regtest(invoice.bolt11)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
|
||||
@@ -385,7 +410,7 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
|
||||
# f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}"
|
||||
# )
|
||||
# await asyncio.sleep(0.1)
|
||||
# pay_if_regtest(invoice.bolt11)
|
||||
# await pay_if_regtest(invoice.bolt11)
|
||||
# await wallet1.mint(64, id=invoice.id)
|
||||
# await asyncio.sleep(0.1)
|
||||
# data = str(ws.recv())
|
||||
|
||||
Reference in New Issue
Block a user