defer unpending

This commit is contained in:
callebtc
2022-12-14 23:27:40 +01:00
parent d08b8a00f6
commit cdabc86ba9
2 changed files with 57 additions and 42 deletions

View File

@@ -110,9 +110,11 @@ class Ledger:
return not proof.secret in self.proofs_used return not proof.secret in self.proofs_used
def _verify_secret_criteria(self, proof: Proof): def _verify_secret_criteria(self, proof: Proof):
"""Verifies that a secret is present""" """Verifies that a secret is present and is not too long (DOS prevention)."""
if proof.secret is None or proof.secret == "": if proof.secret is None or proof.secret == "":
raise Exception("no secret in proof.") raise Exception("no secret in proof.")
if len(proof.secret) > 64:
raise Exception("secret too long.")
return True return True
def _verify_proof(self, proof: Proof): def _verify_proof(self, proof: Proof):
@@ -269,9 +271,6 @@ class Ledger:
for p in proofs: for p in proofs:
await self.crud.invalidate_proof(proof=p, db=self.db) await self.crud.invalidate_proof(proof=p, db=self.db)
# delete proofs from pending list
await self._unset_proofs_pending(proofs)
async def _set_proofs_pending(self, proofs: List[Proof]): async def _set_proofs_pending(self, proofs: List[Proof]):
""" """
If none of the proofs is in the pending table (_validate_proofs_pending), adds proofs to If none of the proofs is in the pending table (_validate_proofs_pending), adds proofs to
@@ -280,7 +279,10 @@ class Ledger:
# first we check whether these proofs are pending aready # first we check whether these proofs are pending aready
await self._validate_proofs_pending(proofs) await self._validate_proofs_pending(proofs)
for p in proofs: for p in proofs:
await self.crud.set_proof_pending(proof=p, db=self.db) try:
await self.crud.set_proof_pending(proof=p, db=self.db)
except:
raise Exception("proofs already pending.")
async def _unset_proofs_pending(self, proofs: List[Proof]): async def _unset_proofs_pending(self, proofs: List[Proof]):
"""Deletes proofs from pending table.""" """Deletes proofs from pending table."""
@@ -347,24 +349,31 @@ class Ledger:
# validate and set proofs as pending # validate and set proofs as pending
await self._set_proofs_pending(proofs) await self._set_proofs_pending(proofs)
# Verify proofs try:
if not all([self._verify_proof(p) for p in proofs]): # Verify proofs
raise Exception("could not verify proofs.") if not all([self._verify_proof(p) for p in proofs]):
raise Exception("could not verify proofs.")
total_provided = sum_proofs(proofs) total_provided = sum_proofs(proofs)
invoice_obj = bolt11.decode(invoice) invoice_obj = bolt11.decode(invoice)
amount = math.ceil(invoice_obj.amount_msat / 1000) amount = math.ceil(invoice_obj.amount_msat / 1000)
fees_msat = await self.check_fees(invoice) fees_msat = await self.check_fees(invoice)
assert total_provided >= amount + fees_msat / 1000, Exception( assert total_provided >= amount + fees_msat / 1000, Exception(
"provided proofs not enough for Lightning payment." "provided proofs not enough for Lightning payment."
) )
if LIGHTNING:
status, preimage = await self._pay_lightning_invoice(invoice, fees_msat)
else:
status, preimage = True, "preimage"
if status == True:
await self._invalidate_proofs(proofs)
except Exception as e:
raise e
finally:
# delete proofs from pending list
await self._unset_proofs_pending(proofs)
if LIGHTNING:
status, preimage = await self._pay_lightning_invoice(invoice, fees_msat)
else:
status, preimage = True, "preimage"
if status == True:
await self._invalidate_proofs(proofs)
return status, preimage return status, preimage
async def check_spendable(self, proofs: List[Proof]): async def check_spendable(self, proofs: List[Proof]):
@@ -399,27 +408,33 @@ class Ledger:
total = sum_proofs(proofs) total = sum_proofs(proofs)
# verify that amount is kosher try:
self._verify_split_amount(amount) # verify that amount is kosher
# verify overspending attempt self._verify_split_amount(amount)
if amount > total: # verify overspending attempt
raise Exception("split amount is higher than the total sum.") if amount > total:
raise Exception("split amount is higher than the total sum.")
# Verify scripts # Verify scripts
if not all([self._verify_script(i, p) for i, p in enumerate(proofs)]): if not all([self._verify_script(i, p) for i, p in enumerate(proofs)]):
raise Exception("script verification failed.") raise Exception("script verification failed.")
# Verify secret criteria # Verify secret criteria
if not all([self._verify_secret_criteria(p) for p in proofs]): if not all([self._verify_secret_criteria(p) for p in proofs]):
raise Exception("secrets do not match criteria.") raise Exception("secrets do not match criteria.")
# verify that only unique proofs and outputs were used # verify that only unique proofs and outputs were used
if not self._verify_no_duplicates(proofs, outputs): if not self._verify_no_duplicates(proofs, outputs):
raise Exception("duplicate proofs or promises.") raise Exception("duplicate proofs or promises.")
# verify that outputs have the correct amount # verify that outputs have the correct amount
if not self._verify_outputs(total, amount, outputs): if not self._verify_outputs(total, amount, outputs):
raise Exception("split of promises is not as expected.") raise Exception("split of promises is not as expected.")
# Verify proofs # Verify proofs
if not all([self._verify_proof(p) for p in proofs]): if not all([self._verify_proof(p) for p in proofs]):
raise Exception("could not verify proofs.") raise Exception("could not verify proofs.")
except Exception as e:
raise e
finally:
# delete proofs from pending list
await self._unset_proofs_pending(proofs)
# Mark proofs as used and prepare new promises # Mark proofs as used and prepare new promises
await self._invalidate_proofs(proofs) await self._invalidate_proofs(proofs)

View File

@@ -137,7 +137,7 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
doublespend = await wallet1.mint(64) doublespend = await wallet1.mint(64)
await assert_err( await assert_err(
wallet1.split(wallet1.proofs + doublespend, 20), wallet1.split(wallet1.proofs + doublespend, 20),
"Mint Error: duplicate proofs or promises.", "Mint Error: proofs already pending.",
) )
assert wallet1.balance == 64 assert wallet1.balance == 64
assert wallet1.available_balance == 64 assert wallet1.available_balance == 64