index on db and read spent proofs from db (#370)

* index on db and read spent proofs from db

* add benchmark for testing

* remove benchmark

* add option to disable cached secrets

* disable python 3.9 tests
This commit is contained in:
callebtc
2023-11-26 06:07:38 -03:00
committed by GitHub
parent bff30d493d
commit fa5193cd8f
14 changed files with 253 additions and 164 deletions

View File

@@ -11,6 +11,7 @@ from ..core.base import (
)
from ..core.crypto import b_dhke
from ..core.crypto.secp import PublicKey
from ..core.db import Database
from ..core.errors import (
NoSecretInProofsError,
NotAllowedError,
@@ -19,16 +20,19 @@ from ..core.errors import (
TransactionError,
)
from ..core.settings import settings
from ..mint.crud import LedgerCrud
from .conditions import LedgerSpendingConditions
from .protocols import SupportsKeysets
from .protocols import SupportsDb, SupportsKeysets
class LedgerVerification(LedgerSpendingConditions, SupportsKeysets):
class LedgerVerification(LedgerSpendingConditions, SupportsKeysets, SupportsDb):
"""Verification functions for the ledger."""
keyset: MintKeyset
keysets: MintKeysets
secrets_used: Set[str]
secrets_used: Set[str] = set()
crud: LedgerCrud
db: Database
async def verify_inputs_and_outputs(
self, proofs: List[Proof], outputs: Optional[List[BlindedMessage]] = None
@@ -48,7 +52,9 @@ class LedgerVerification(LedgerSpendingConditions, SupportsKeysets):
"""
# Verify inputs
# Verify proofs are spendable
self._check_proofs_spendable(proofs)
spendable = await self._check_proofs_spendable(proofs)
if not all(spendable):
raise TokenAlreadySpentError()
# Verify amounts of inputs
if not all([self._verify_amount(p.amount) for p in proofs]):
raise TransactionError("invalid amount.")
@@ -87,10 +93,24 @@ class LedgerVerification(LedgerSpendingConditions, SupportsKeysets):
if not self._verify_no_duplicate_outputs(outputs):
raise TransactionError("duplicate outputs.")
def _check_proofs_spendable(self, proofs: List[Proof]):
"""Checks whether the proofs were already spent."""
if not all([p.secret not in self.secrets_used for p in proofs]):
raise TokenAlreadySpentError()
async def _check_proofs_spendable(self, proofs: List[Proof]) -> List[bool]:
"""Checks whether the proof was already spent."""
spendable_states = []
if settings.mint_cache_secrets:
# check used secrets in memory
for p in proofs:
spendable_state = p.secret not in self.secrets_used
spendable_states.append(spendable_state)
else:
# check used secrets in database
async with self.db.connect() as conn:
for p in proofs:
spendable_state = (
await self.crud.get_proof_used(db=self.db, proof=p, conn=conn)
is None
)
spendable_states.append(spendable_state)
return spendable_states
def _verify_secret_criteria(self, proof: Proof) -> Literal[True]:
"""Verifies that a secret is present and is not too long (DOS prevention)."""