mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-02-09 18:54:30 +01:00
Fix race condition (#586)
* `_set_proofs_pending` performs DB related "proofs are spendable" check inside the lock. * move _verify_spent_proofs_and_set_pending to write.py * edit logging --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
This commit is contained in:
@@ -184,7 +184,9 @@ async def test_db_get_connection_lock_row(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_set_proofs_pending_race_condition(wallet: Wallet, ledger: Ledger):
|
||||
async def test_db_verify_spent_proofs_and_set_pending_race_condition(
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
@@ -193,8 +195,8 @@ async def test_db_set_proofs_pending_race_condition(wallet: Wallet, ledger: Ledg
|
||||
|
||||
await assert_err_multiple(
|
||||
asyncio.gather(
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs),
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs),
|
||||
),
|
||||
[
|
||||
"failed to acquire database lock",
|
||||
@@ -204,7 +206,7 @@ async def test_db_set_proofs_pending_race_condition(wallet: Wallet, ledger: Ledg
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_set_proofs_pending_delayed_no_race_condition(
|
||||
async def test_db_verify_spent_proofs_and_set_pending_delayed_no_race_condition(
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
@@ -213,21 +215,21 @@ async def test_db_set_proofs_pending_delayed_no_race_condition(
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
assert wallet.balance == 64
|
||||
|
||||
async def delayed_set_proofs_pending():
|
||||
async def delayed_verify_spent_proofs_and_set_pending():
|
||||
await asyncio.sleep(0.1)
|
||||
await ledger.db_write._set_proofs_pending(wallet.proofs)
|
||||
await ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs)
|
||||
|
||||
await assert_err(
|
||||
asyncio.gather(
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs),
|
||||
delayed_set_proofs_pending(),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs),
|
||||
delayed_verify_spent_proofs_and_set_pending(),
|
||||
),
|
||||
"proofs are pending",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_set_proofs_pending_no_race_condition_different_proofs(
|
||||
async def test_db_verify_spent_proofs_and_set_pending_no_race_condition_different_proofs(
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
@@ -238,8 +240,8 @@ async def test_db_set_proofs_pending_no_race_condition_different_proofs(
|
||||
assert len(wallet.proofs) == 2
|
||||
|
||||
asyncio.gather(
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs[:1]),
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs[1:]),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs[:1]),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs[1:]),
|
||||
)
|
||||
|
||||
|
||||
@@ -300,6 +302,6 @@ async def test_db_lock_table(wallet: Wallet, ledger: Ledger):
|
||||
async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn:
|
||||
assert isinstance(conn, Connection)
|
||||
await assert_err(
|
||||
ledger.db_write._set_proofs_pending(wallet.proofs),
|
||||
ledger.db_write._verify_spent_proofs_and_set_pending(wallet.proofs),
|
||||
"failed to acquire database lock",
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ async def test_mint_proofs_pending(wallet1: Wallet, ledger: Ledger):
|
||||
[s.state == ProofSpentState.unspent for s in proofs_states_before_split.states]
|
||||
)
|
||||
|
||||
await ledger.db_write._set_proofs_pending(proofs)
|
||||
await ledger.db_write._verify_spent_proofs_and_set_pending(proofs)
|
||||
|
||||
proof_states = await wallet1.check_proof_state(proofs)
|
||||
assert all([s.state == ProofSpentState.pending for s in proof_states.states])
|
||||
|
||||
@@ -363,7 +363,7 @@ async def test_double_spend(wallet1: Wallet):
|
||||
await wallet1.split(wallet1.proofs, 20)
|
||||
await assert_err(
|
||||
wallet1.split(doublespend, 20),
|
||||
"Mint Error: Token already spent.",
|
||||
"Token already spent.",
|
||||
)
|
||||
assert wallet1.balance == 64
|
||||
assert wallet1.available_balance == 64
|
||||
|
||||
Reference in New Issue
Block a user