From 2245becfecfecec8231b46074dc97f07f711f204 Mon Sep 17 00:00:00 2001 From: Rob Woodgate Date: Tue, 31 Mar 2026 08:54:58 +0100 Subject: [PATCH 1/2] fix: verify_proofs_dleq should not early return --- cashu/wallet/wallet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 1b63b8eab..9fb4eae4b 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -937,7 +937,7 @@ def verify_proofs_dleq(self, proofs: List[Proof]): for proof in proofs: if not proof.dleq: logger.trace("No DLEQ proof in proof.") - return + continue logger.trace("Verifying DLEQ proof.") assert proof.id assert ( From 950fdf6ee3da498f2a65372a1029f4f197b1097b Mon Sep 17 00:00:00 2001 From: Rob Woodgate Date: Thu, 2 Apr 2026 12:21:59 +0100 Subject: [PATCH 2/2] chore: add test --- tests/wallet/test_wallet.py | 46 ++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/tests/wallet/test_wallet.py b/tests/wallet/test_wallet.py index 192f6335b..7fc4261b8 100644 --- a/tests/wallet/test_wallet.py +++ b/tests/wallet/test_wallet.py @@ -5,7 +5,15 @@ import pytest import pytest_asyncio -from cashu.core.base import MeltQuote, MeltQuoteState, MintQuoteState, Proof +from cashu.core.base import ( + DLEQWallet, + MeltQuote, + MeltQuoteState, + MintQuoteState, + Proof, + WalletKeyset, +) +from cashu.core.crypto import b_dhke from cashu.core.errors import CashuError, KeysetNotFoundError, ProofsAlreadySpentError from cashu.core.helpers import sum_proofs from cashu.core.settings import settings @@ -487,6 +495,42 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet): assert wallet1.available_balance == 32 +def test_verify_proofs_dleq_mixed_missing_and_invalid_dleq_proofs(): + class MockWallet: + verify_proofs_dleq = Wallet.verify_proofs_dleq + + def __init__(self, keysets): + self.keysets = keysets + + mint_private_key = b_dhke.PrivateKey() + mint_public_key = mint_private_key.public_key + assert mint_public_key + keyset = WalletKeyset(public_keys={1: mint_public_key}, unit="sat") + wallet = MockWallet({keyset.id: keyset}) + + def make_proof(secret: str) -> Proof: + B_, r = b_dhke.step1_alice(secret) + C_, e, s = b_dhke.step2_bob(B_, mint_private_key) + C = b_dhke.step3_alice(C_, r, mint_public_key) + return Proof( + id=keyset.id, + amount=1, + secret=secret, + C=C.format().hex(), + dleq=DLEQWallet(r=r.to_hex(), e=e.to_hex(), s=s.to_hex()), + ) + + proofs = [make_proof("missing-dleq"), make_proof("invalid-dleq")] + proofs[0].dleq = None + assert proofs[1].dleq + proofs[1].dleq.e = ( + ("0" if proofs[1].dleq.e[0] != "0" else "1") + proofs[1].dleq.e[1:] + ) + + with pytest.raises(Exception, match="DLEQ proof invalid."): + wallet.verify_proofs_dleq(proofs) + + @pytest.mark.asyncio async def test_invalidate_all_proofs(wallet1: Wallet): """Try to invalidate proofs that have not been spent yet. Should not work!"""