Enhance add_proofs to fail with a custom error when the proof already exists

This commit is contained in:
Cesar Rodas
2025-06-17 17:49:31 -03:00
parent 7146cb8934
commit 150f2596e7
4 changed files with 36 additions and 10 deletions

View File

@@ -114,6 +114,9 @@ pub trait ProofsDatabase {
type Err: Into<Error> + From<Error>;
/// Add [`Proofs`]
///
/// Adds proofs to the database. The database should error if the proof already exits, with a
/// `AttemptUpdateSpentProof` if the proof is already spent or a `Duplicate` error otherwise.
async fn add_proofs(&self, proof: Proofs, quote_id: Option<Uuid>) -> Result<(), Self::Err>;
/// Remove [`Proofs`]
async fn remove_proofs(

View File

@@ -816,6 +816,26 @@ impl MintProofsDatabase for MintSqliteDatabase {
let current_time = unix_time();
// Check any previous proof, this query should return None in order to proceed storing
// Any result here would error
match query(r#"SELECT state FROM proof WHERE y IN (:ys) LIMIT 1"#)
.bind_vec(
":ys",
proofs
.iter()
.map(|y| y.y().map(|y| y.to_bytes().to_vec()))
.collect::<Result<_, _>>()?,
)
.pluck(&transaction)
.await?
.map(|state| Ok::<_, Error>(column_as_string!(&state, State::from_str)))
.transpose()?
{
Some(State::Spent) => Err(database::Error::AttemptUpdateSpentProof),
Some(_) => Err(database::Error::Duplicate),
None => Ok(()), // no previous record
}?;
for proof in proofs {
query(
r#"

View File

@@ -347,15 +347,17 @@ impl Mint {
.await
.err()
{
match err {
cdk_common::database::Error::Duplicate => {
// the proofs already exits, it will be errored by `check_ys_spendable`
return match err {
cdk_common::database::Error::Duplicate => Err(Error::TokenPending),
cdk_common::database::Error::AttemptUpdateSpentProof => {
Err(Error::TokenAlreadySpent)
}
err => return Err(Error::Database(err)),
}
err => Err(Error::Database(err)),
};
}
self.check_ys_spendable(&input_ys, State::Pending).await?;
for proof in melt_request.inputs() {
self.pubsub_manager
.proof_state((proof.y()?, State::Pending));

View File

@@ -30,12 +30,13 @@ impl Mint {
.await
.err()
{
match err {
cdk_common::database::Error::Duplicate => {
// the proofs already exits, it will be errored by `check_ys_spendable`
return match err {
cdk_common::database::Error::Duplicate => Err(Error::TokenPending),
cdk_common::database::Error::AttemptUpdateSpentProof => {
Err(Error::TokenAlreadySpent)
}
err => return Err(Error::Database(err)),
}
err => Err(Error::Database(err)),
};
}
self.check_ys_spendable(&input_ys, State::Pending).await?;