mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-22 19:34:18 +01:00
check pending proofs
This commit is contained in:
@@ -29,6 +29,18 @@ class LedgerCrud:
|
||||
|
||||
return await invalidate_proof(*args, **kwags)
|
||||
|
||||
async def get_proofs_pending(*args, **kwags):
|
||||
|
||||
return await get_proofs_pending(*args, **kwags)
|
||||
|
||||
async def set_proof_pending(*args, **kwags):
|
||||
|
||||
return await set_proof_pending(*args, **kwags)
|
||||
|
||||
async def unset_proof_pending(*args, **kwags):
|
||||
|
||||
return await unset_proof_pending(*args, **kwags)
|
||||
|
||||
async def store_keyset(*args, **kwags):
|
||||
|
||||
return await store_keyset(*args, **kwags)
|
||||
@@ -102,6 +114,55 @@ async def invalidate_proof(
|
||||
)
|
||||
|
||||
|
||||
async def get_proofs_pending(
|
||||
db: Database,
|
||||
conn: Optional[Connection] = None,
|
||||
):
|
||||
|
||||
rows = await (conn or db).fetchall(
|
||||
f"""
|
||||
SELECT * from {table_with_schema(db, 'proofs_pending')}
|
||||
"""
|
||||
)
|
||||
return [Proof(**r) for r in rows]
|
||||
|
||||
|
||||
async def set_proof_pending(
|
||||
db: Database,
|
||||
proof: Proof,
|
||||
conn: Optional[Connection] = None,
|
||||
):
|
||||
|
||||
# we add the proof and secret to the used list
|
||||
await (conn or db).execute(
|
||||
f"""
|
||||
INSERT INTO {table_with_schema(db, 'proofs_pending')}
|
||||
(amount, C, secret)
|
||||
VALUES (?, ?, ?)
|
||||
""",
|
||||
(
|
||||
proof.amount,
|
||||
str(proof.C),
|
||||
str(proof.secret),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def unset_proof_pending(
|
||||
proof: Proof,
|
||||
db: Database,
|
||||
conn: Optional[Connection] = None,
|
||||
):
|
||||
|
||||
await (conn or db).execute(
|
||||
f"""
|
||||
DELETE FROM {table_with_schema(db, 'proofs_pending')}
|
||||
WHERE secret = ?
|
||||
""",
|
||||
(str(proof["secret"]),),
|
||||
)
|
||||
|
||||
|
||||
async def store_lightning_invoice(
|
||||
db: Database,
|
||||
invoice: Invoice,
|
||||
|
||||
@@ -258,7 +258,10 @@ class Ledger:
|
||||
return ok, preimage
|
||||
|
||||
async def _invalidate_proofs(self, proofs: List[Proof]):
|
||||
"""Adds secrets of proofs to the list of knwon secrets and stores them in the db."""
|
||||
"""
|
||||
Adds secrets of proofs to the list of known secrets and stores them in the db.
|
||||
Removes proofs from pending table.
|
||||
"""
|
||||
# Mark proofs as used and prepare new promises
|
||||
proof_msgs = set([p.secret for p in proofs])
|
||||
self.proofs_used |= proof_msgs
|
||||
@@ -266,6 +269,38 @@ class Ledger:
|
||||
for p in proofs:
|
||||
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]):
|
||||
"""
|
||||
If none of the proofs is in the pending table (_validate_proofs_pending), adds proofs to
|
||||
the list of pending proofs or removes them. Used as a mutex for proofs.
|
||||
"""
|
||||
# first we check whether these proofs are pending aready
|
||||
await self._validate_proofs_pending(proofs)
|
||||
for p in proofs:
|
||||
await self.crud.set_proof_pending(proof=p, db=self.db)
|
||||
|
||||
async def _unset_proofs_pending(self, proofs: List[Proof]):
|
||||
"""Deletes proofs from pending table."""
|
||||
# we try: except: this block in order to avoid that any errors here
|
||||
# could block the _invalidate_proofs() call that happens afterwards.
|
||||
try:
|
||||
for p in proofs:
|
||||
await self.crud.unset_proof_pending(proof=p, db=self.db)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
|
||||
async def _validate_proofs_pending(self, proofs: List[Proof]):
|
||||
"""Checks if any of the provided proofs is in the pending proofs table. Raises exception for at least one match."""
|
||||
proofs_pending = await self.crud.get_proofs_pending(db=self.db)
|
||||
for p in proofs:
|
||||
for pp in proofs_pending:
|
||||
if p.secret == pp.secret:
|
||||
raise Exception("proofs are pending.")
|
||||
|
||||
# Public methods
|
||||
def get_keyset(self, keyset_id: str = None):
|
||||
keyset = self.keysets.keysets[keyset_id] if keyset_id else self.keyset
|
||||
@@ -308,6 +343,10 @@ class Ledger:
|
||||
|
||||
async def melt(self, proofs: List[Proof], invoice: str):
|
||||
"""Invalidates proofs and pays a Lightning invoice."""
|
||||
|
||||
# validate and set proofs as pending
|
||||
await self._set_proofs_pending(proofs)
|
||||
|
||||
# Verify proofs
|
||||
if not all([self._verify_proof(p) for p in proofs]):
|
||||
raise Exception("could not verify proofs.")
|
||||
@@ -354,6 +393,10 @@ class Ledger:
|
||||
keyset: MintKeyset = None,
|
||||
):
|
||||
"""Consumes proofs and prepares new promises based on the amount split."""
|
||||
|
||||
# set proofs as pending
|
||||
await self._set_proofs_pending(proofs)
|
||||
|
||||
total = sum_proofs(proofs)
|
||||
|
||||
# verify that amount is kosher
|
||||
|
||||
@@ -128,3 +128,21 @@ async def m004_keysets_add_version(db: Database):
|
||||
await db.execute(
|
||||
f"ALTER TABLE {table_with_schema(db, 'keysets')} ADD COLUMN version TEXT"
|
||||
)
|
||||
|
||||
|
||||
async def m005_pending_proofs_table(db: Database) -> None:
|
||||
"""
|
||||
Store pending proofs.
|
||||
"""
|
||||
await db.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'proofs_pending')} (
|
||||
amount INTEGER NOT NULL,
|
||||
C TEXT NOT NULL,
|
||||
secret TEXT NOT NULL,
|
||||
|
||||
UNIQUE (secret)
|
||||
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user