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)
|
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):
|
async def store_keyset(*args, **kwags):
|
||||||
|
|
||||||
return await 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(
|
async def store_lightning_invoice(
|
||||||
db: Database,
|
db: Database,
|
||||||
invoice: Invoice,
|
invoice: Invoice,
|
||||||
|
|||||||
@@ -258,7 +258,10 @@ class Ledger:
|
|||||||
return ok, preimage
|
return ok, preimage
|
||||||
|
|
||||||
async def _invalidate_proofs(self, proofs: List[Proof]):
|
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
|
# Mark proofs as used and prepare new promises
|
||||||
proof_msgs = set([p.secret for p in proofs])
|
proof_msgs = set([p.secret for p in proofs])
|
||||||
self.proofs_used |= proof_msgs
|
self.proofs_used |= proof_msgs
|
||||||
@@ -266,6 +269,38 @@ 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]):
|
||||||
|
"""
|
||||||
|
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
|
# Public methods
|
||||||
def get_keyset(self, keyset_id: str = None):
|
def get_keyset(self, keyset_id: str = None):
|
||||||
keyset = self.keysets.keysets[keyset_id] if keyset_id else self.keyset
|
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):
|
async def melt(self, proofs: List[Proof], invoice: str):
|
||||||
"""Invalidates proofs and pays a Lightning invoice."""
|
"""Invalidates proofs and pays a Lightning invoice."""
|
||||||
|
|
||||||
|
# validate and set proofs as pending
|
||||||
|
await self._set_proofs_pending(proofs)
|
||||||
|
|
||||||
# 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.")
|
||||||
@@ -354,6 +393,10 @@ class Ledger:
|
|||||||
keyset: MintKeyset = None,
|
keyset: MintKeyset = None,
|
||||||
):
|
):
|
||||||
"""Consumes proofs and prepares new promises based on the amount split."""
|
"""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)
|
total = sum_proofs(proofs)
|
||||||
|
|
||||||
# verify that amount is kosher
|
# verify that amount is kosher
|
||||||
|
|||||||
@@ -128,3 +128,21 @@ async def m004_keysets_add_version(db: Database):
|
|||||||
await db.execute(
|
await db.execute(
|
||||||
f"ALTER TABLE {table_with_schema(db, 'keysets')} ADD COLUMN version TEXT"
|
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