Kaynağa Gözat

Changes to the databases cdk-common (#1437)

* Remove lifetime parameter from mint transaction traits

Remove the 'a lifetime parameter from mint database transaction traits:
- QuotesTransaction
- ProofsTransaction
- SignaturesTransaction
- SagaTransaction
- CompletedOperationsTransaction
- Transaction

This simplifies the trait signatures and removes unnecessary lifetime
annotations that were not providing value.

* Move kvstore validation tests to common module

Move kvstore validation unit tests from mint/test/kvstore.rs to the
shared database/kvstore.rs module where the validation functions are
defined. This consolidates the tests with their implementation.
C 3 hafta önce
ebeveyn
işleme
38fd6ac9d1

+ 206 - 0
crates/cdk-common/src/database/kvstore.rs

@@ -133,3 +133,209 @@ pub trait KVStore: KVStoreDatabase {
         &self,
     ) -> Result<Box<dyn KVStoreTransaction<Self::Err> + Send + Sync>, Error>;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{
+        validate_kvstore_params, validate_kvstore_string, KVSTORE_NAMESPACE_KEY_ALPHABET,
+        KVSTORE_NAMESPACE_KEY_MAX_LEN,
+    };
+
+    #[test]
+    fn test_validate_kvstore_string_valid_inputs() {
+        // Test valid strings
+        assert!(validate_kvstore_string("").is_ok());
+        assert!(validate_kvstore_string("abc").is_ok());
+        assert!(validate_kvstore_string("ABC").is_ok());
+        assert!(validate_kvstore_string("123").is_ok());
+        assert!(validate_kvstore_string("test_key").is_ok());
+        assert!(validate_kvstore_string("test-key").is_ok());
+        assert!(validate_kvstore_string("test_KEY-123").is_ok());
+
+        // Test max length string
+        let max_length_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN);
+        assert!(validate_kvstore_string(&max_length_str).is_ok());
+    }
+
+    #[test]
+    fn test_validate_kvstore_string_invalid_length() {
+        // Test string too long
+        let too_long_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN + 1);
+        let result = validate_kvstore_string(&too_long_str);
+        assert!(result.is_err());
+        assert!(result
+            .unwrap_err()
+            .to_string()
+            .contains("exceeds maximum length"));
+    }
+
+    #[test]
+    fn test_validate_kvstore_string_invalid_characters() {
+        // Test invalid characters
+        let invalid_chars = vec![
+            "test@key",  // @
+            "test key",  // space
+            "test.key",  // .
+            "test/key",  // /
+            "test\\key", // \
+            "test+key",  // +
+            "test=key",  // =
+            "test!key",  // !
+            "test#key",  // #
+            "test$key",  // $
+            "test%key",  // %
+            "test&key",  // &
+            "test*key",  // *
+            "test(key",  // (
+            "test)key",  // )
+            "test[key",  // [
+            "test]key",  // ]
+            "test{key",  // {
+            "test}key",  // }
+            "test|key",  // |
+            "test;key",  // ;
+            "test:key",  // :
+            "test'key",  // '
+            "test\"key", // "
+            "test<key",  // <
+            "test>key",  // >
+            "test,key",  // ,
+            "test?key",  // ?
+            "test~key",  // ~
+            "test`key",  // `
+        ];
+
+        for invalid_str in invalid_chars {
+            let result = validate_kvstore_string(invalid_str);
+            assert!(result.is_err(), "Expected '{}' to be invalid", invalid_str);
+            assert!(result
+                .unwrap_err()
+                .to_string()
+                .contains("invalid characters"));
+        }
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_valid() {
+        // Test valid parameter combinations
+        assert!(validate_kvstore_params("primary", "secondary", Some("key")).is_ok());
+        assert!(validate_kvstore_params("primary", "", Some("key")).is_ok());
+        assert!(validate_kvstore_params("", "", Some("key")).is_ok());
+        assert!(validate_kvstore_params("p1", "s1", Some("different_key")).is_ok());
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_empty_namespace_rules() {
+        // Test empty namespace rules: if primary is empty, secondary must be empty too
+        let result = validate_kvstore_params("", "secondary", Some("key"));
+        assert!(result.is_err());
+        assert!(result
+            .unwrap_err()
+            .to_string()
+            .contains("If primary_namespace is empty"));
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_collision_prevention() {
+        // Test collision prevention between keys and namespaces
+        let test_cases = vec![
+            ("primary", "secondary", "primary"), // key matches primary namespace
+            ("primary", "secondary", "secondary"), // key matches secondary namespace
+        ];
+
+        for (primary, secondary, key) in test_cases {
+            let result = validate_kvstore_params(primary, secondary, Some(key));
+            assert!(
+                result.is_err(),
+                "Expected collision for key '{}' with namespaces '{}'/'{}'",
+                key,
+                primary,
+                secondary
+            );
+            let error_msg = result.unwrap_err().to_string();
+            assert!(error_msg.contains("conflicts with namespace"));
+        }
+
+        // Test that a combined namespace string would be invalid due to the slash character
+        let result = validate_kvstore_params("primary", "secondary", Some("primary_secondary"));
+        assert!(result.is_ok(), "This should be valid - no actual collision");
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_invalid_strings() {
+        // Test invalid characters in any parameter
+        let result = validate_kvstore_params("primary@", "secondary", Some("key"));
+        assert!(result.is_err());
+
+        let result = validate_kvstore_params("primary", "secondary!", Some("key"));
+        assert!(result.is_err());
+
+        let result = validate_kvstore_params("primary", "secondary", Some("key with space"));
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_alphabet_constants() {
+        // Verify the alphabet constant is as expected
+        assert_eq!(
+            KVSTORE_NAMESPACE_KEY_ALPHABET,
+            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
+        );
+        assert_eq!(KVSTORE_NAMESPACE_KEY_MAX_LEN, 120);
+    }
+
+    #[test]
+    fn test_alphabet_coverage() {
+        // Test that all valid characters are actually accepted
+        for ch in KVSTORE_NAMESPACE_KEY_ALPHABET.chars() {
+            let test_str = ch.to_string();
+            assert!(
+                validate_kvstore_string(&test_str).is_ok(),
+                "Character '{}' should be valid",
+                ch
+            );
+        }
+    }
+
+    #[test]
+    fn test_namespace_segmentation_examples() {
+        // Test realistic namespace segmentation scenarios
+
+        // Valid segmentation examples
+        let valid_examples = vec![
+            ("wallets", "user123", "balance"),
+            ("quotes", "mint", "quote_12345"),
+            ("keysets", "", "active_keyset"),
+            ("", "", "global_config"),
+            ("auth", "session_456", "token"),
+            ("mint_info", "", "version"),
+        ];
+
+        for (primary, secondary, key) in valid_examples {
+            assert!(
+                validate_kvstore_params(primary, secondary, Some(key)).is_ok(),
+                "Valid example should pass: '{}'/'{}'/'{}'",
+                primary,
+                secondary,
+                key
+            );
+        }
+    }
+
+    #[test]
+    fn test_per_namespace_uniqueness() {
+        // This test documents the requirement that implementations should ensure
+        // per-namespace key uniqueness. The validation function doesn't enforce
+        // database-level uniqueness (that's handled by the database schema),
+        // but ensures naming conflicts don't occur between keys and namespaces.
+
+        // These should be valid (different namespaces)
+        assert!(validate_kvstore_params("ns1", "sub1", Some("key1")).is_ok());
+        assert!(validate_kvstore_params("ns2", "sub1", Some("key1")).is_ok()); // same key, different primary namespace
+        assert!(validate_kvstore_params("ns1", "sub2", Some("key1")).is_ok()); // same key, different secondary namespace
+
+        // These should fail (collision within namespace)
+        assert!(validate_kvstore_params("ns1", "sub1", Some("ns1")).is_err()); // key conflicts with primary namespace
+        assert!(validate_kvstore_params("ns1", "sub1", Some("sub1")).is_err()); // key conflicts with secondary namespace
+    }
+}

+ 12 - 14
crates/cdk-common/src/database/mint/mod.rs

@@ -76,7 +76,7 @@ pub trait KeysDatabase {
 
 /// Mint Quote Database writer trait
 #[async_trait]
-pub trait QuotesTransaction<'a> {
+pub trait QuotesTransaction {
     /// Mint Quotes Database Error
     type Err: Into<Error> + From<Error>;
 
@@ -202,7 +202,7 @@ pub trait QuotesDatabase {
 
 /// Mint Proof Transaction trait
 #[async_trait]
-pub trait ProofsTransaction<'a> {
+pub trait ProofsTransaction {
     /// Mint Proof Database Error
     type Err: Into<Error> + From<Error>;
 
@@ -265,7 +265,7 @@ pub trait ProofsDatabase {
 
 #[async_trait]
 /// Mint Signatures Transaction trait
-pub trait SignaturesTransaction<'a> {
+pub trait SignaturesTransaction {
     /// Mint Signature Database Error
     type Err: Into<Error> + From<Error>;
 
@@ -314,7 +314,7 @@ pub trait SignaturesDatabase {
 
 #[async_trait]
 /// Saga Transaction trait
-pub trait SagaTransaction<'a> {
+pub trait SagaTransaction {
     /// Saga Database Error
     type Err: Into<Error> + From<Error>;
 
@@ -353,7 +353,7 @@ pub trait SagaDatabase {
 
 #[async_trait]
 /// Completed Operations Transaction trait
-pub trait CompletedOperationsTransaction<'a> {
+pub trait CompletedOperationsTransaction {
     /// Completed Operations Database Error
     type Err: Into<Error> + From<Error>;
 
@@ -388,14 +388,14 @@ pub trait CompletedOperationsDatabase {
 }
 
 /// Base database writer
-pub trait Transaction<'a, Error>:
+pub trait Transaction<Error>:
     DbTransactionFinalizer<Err = Error>
-    + QuotesTransaction<'a, Err = Error>
-    + SignaturesTransaction<'a, Err = Error>
-    + ProofsTransaction<'a, Err = Error>
+    + QuotesTransaction<Err = Error>
+    + SignaturesTransaction<Err = Error>
+    + ProofsTransaction<Err = Error>
     + KVStoreTransaction<Error>
-    + SagaTransaction<'a, Err = Error>
-    + CompletedOperationsTransaction<'a, Err = Error>
+    + SagaTransaction<Err = Error>
+    + CompletedOperationsTransaction<Err = Error>
 {
 }
 
@@ -410,9 +410,7 @@ pub trait Database<Error>:
     + CompletedOperationsDatabase<Err = Error>
 {
     /// Begins a transaction
-    async fn begin_transaction<'a>(
-        &'a self,
-    ) -> Result<Box<dyn Transaction<'a, Error> + Send + Sync + 'a>, Error>;
+    async fn begin_transaction(&self) -> Result<Box<dyn Transaction<Error> + Send + Sync>, Error>;
 }
 
 /// Type alias for Mint Database

+ 0 - 207
crates/cdk-common/src/database/mint/test/kvstore.rs

@@ -1,207 +0,0 @@
-//! Tests for KV store validation requirements
-
-#[cfg(test)]
-mod tests {
-    use crate::database::mint::{
-        validate_kvstore_params, validate_kvstore_string, KVSTORE_NAMESPACE_KEY_ALPHABET,
-        KVSTORE_NAMESPACE_KEY_MAX_LEN,
-    };
-
-    #[test]
-    fn test_validate_kvstore_string_valid_inputs() {
-        // Test valid strings
-        assert!(validate_kvstore_string("").is_ok());
-        assert!(validate_kvstore_string("abc").is_ok());
-        assert!(validate_kvstore_string("ABC").is_ok());
-        assert!(validate_kvstore_string("123").is_ok());
-        assert!(validate_kvstore_string("test_key").is_ok());
-        assert!(validate_kvstore_string("test-key").is_ok());
-        assert!(validate_kvstore_string("test_KEY-123").is_ok());
-
-        // Test max length string
-        let max_length_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN);
-        assert!(validate_kvstore_string(&max_length_str).is_ok());
-    }
-
-    #[test]
-    fn test_validate_kvstore_string_invalid_length() {
-        // Test string too long
-        let too_long_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN + 1);
-        let result = validate_kvstore_string(&too_long_str);
-        assert!(result.is_err());
-        assert!(result
-            .unwrap_err()
-            .to_string()
-            .contains("exceeds maximum length"));
-    }
-
-    #[test]
-    fn test_validate_kvstore_string_invalid_characters() {
-        // Test invalid characters
-        let invalid_chars = vec![
-            "test@key",  // @
-            "test key",  // space
-            "test.key",  // .
-            "test/key",  // /
-            "test\\key", // \
-            "test+key",  // +
-            "test=key",  // =
-            "test!key",  // !
-            "test#key",  // #
-            "test$key",  // $
-            "test%key",  // %
-            "test&key",  // &
-            "test*key",  // *
-            "test(key",  // (
-            "test)key",  // )
-            "test[key",  // [
-            "test]key",  // ]
-            "test{key",  // {
-            "test}key",  // }
-            "test|key",  // |
-            "test;key",  // ;
-            "test:key",  // :
-            "test'key",  // '
-            "test\"key", // "
-            "test<key",  // <
-            "test>key",  // >
-            "test,key",  // ,
-            "test?key",  // ?
-            "test~key",  // ~
-            "test`key",  // `
-        ];
-
-        for invalid_str in invalid_chars {
-            let result = validate_kvstore_string(invalid_str);
-            assert!(result.is_err(), "Expected '{}' to be invalid", invalid_str);
-            assert!(result
-                .unwrap_err()
-                .to_string()
-                .contains("invalid characters"));
-        }
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_valid() {
-        // Test valid parameter combinations
-        assert!(validate_kvstore_params("primary", "secondary", Some("key")).is_ok());
-        assert!(validate_kvstore_params("primary", "", Some("key")).is_ok());
-        assert!(validate_kvstore_params("", "", Some("key")).is_ok());
-        assert!(validate_kvstore_params("p1", "s1", Some("different_key")).is_ok());
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_empty_namespace_rules() {
-        // Test empty namespace rules: if primary is empty, secondary must be empty too
-        let result = validate_kvstore_params("", "secondary", Some("key"));
-        assert!(result.is_err());
-        assert!(result
-            .unwrap_err()
-            .to_string()
-            .contains("If primary_namespace is empty"));
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_collision_prevention() {
-        // Test collision prevention between keys and namespaces
-        let test_cases = vec![
-            ("primary", "secondary", "primary"), // key matches primary namespace
-            ("primary", "secondary", "secondary"), // key matches secondary namespace
-        ];
-
-        for (primary, secondary, key) in test_cases {
-            let result = validate_kvstore_params(primary, secondary, Some(key));
-            assert!(
-                result.is_err(),
-                "Expected collision for key '{}' with namespaces '{}'/'{}'",
-                key,
-                primary,
-                secondary
-            );
-            let error_msg = result.unwrap_err().to_string();
-            assert!(error_msg.contains("conflicts with namespace"));
-        }
-
-        // Test that a combined namespace string would be invalid due to the slash character
-        let result = validate_kvstore_params("primary", "secondary", Some("primary_secondary"));
-        assert!(result.is_ok(), "This should be valid - no actual collision");
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_invalid_strings() {
-        // Test invalid characters in any parameter
-        let result = validate_kvstore_params("primary@", "secondary", Some("key"));
-        assert!(result.is_err());
-
-        let result = validate_kvstore_params("primary", "secondary!", Some("key"));
-        assert!(result.is_err());
-
-        let result = validate_kvstore_params("primary", "secondary", Some("key with space"));
-        assert!(result.is_err());
-    }
-
-    #[test]
-    fn test_alphabet_constants() {
-        // Verify the alphabet constant is as expected
-        assert_eq!(
-            KVSTORE_NAMESPACE_KEY_ALPHABET,
-            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
-        );
-        assert_eq!(KVSTORE_NAMESPACE_KEY_MAX_LEN, 120);
-    }
-
-    #[test]
-    fn test_alphabet_coverage() {
-        // Test that all valid characters are actually accepted
-        for ch in KVSTORE_NAMESPACE_KEY_ALPHABET.chars() {
-            let test_str = ch.to_string();
-            assert!(
-                validate_kvstore_string(&test_str).is_ok(),
-                "Character '{}' should be valid",
-                ch
-            );
-        }
-    }
-
-    #[test]
-    fn test_namespace_segmentation_examples() {
-        // Test realistic namespace segmentation scenarios
-
-        // Valid segmentation examples
-        let valid_examples = vec![
-            ("wallets", "user123", "balance"),
-            ("quotes", "mint", "quote_12345"),
-            ("keysets", "", "active_keyset"),
-            ("", "", "global_config"),
-            ("auth", "session_456", "token"),
-            ("mint_info", "", "version"),
-        ];
-
-        for (primary, secondary, key) in valid_examples {
-            assert!(
-                validate_kvstore_params(primary, secondary, Some(key)).is_ok(),
-                "Valid example should pass: '{}'/'{}'/'{}'",
-                primary,
-                secondary,
-                key
-            );
-        }
-    }
-
-    #[test]
-    fn test_per_namespace_uniqueness() {
-        // This test documents the requirement that implementations should ensure
-        // per-namespace key uniqueness. The validation function doesn't enforce
-        // database-level uniqueness (that's handled by the database schema),
-        // but ensures naming conflicts don't occur between keys and namespaces.
-
-        // These should be valid (different namespaces)
-        assert!(validate_kvstore_params("ns1", "sub1", Some("key1")).is_ok());
-        assert!(validate_kvstore_params("ns2", "sub1", Some("key1")).is_ok()); // same key, different primary namespace
-        assert!(validate_kvstore_params("ns1", "sub2", Some("key1")).is_ok()); // same key, different secondary namespace
-
-        // These should fail (collision within namespace)
-        assert!(validate_kvstore_params("ns1", "sub1", Some("ns1")).is_err()); // key conflicts with primary namespace
-        assert!(validate_kvstore_params("ns1", "sub1", Some("sub1")).is_err()); // key conflicts with secondary namespace
-    }
-}

+ 0 - 1
crates/cdk-common/src/database/mint/test/mod.rs

@@ -17,7 +17,6 @@ use crate::database::KVStoreDatabase;
 use crate::mint::MintKeySetInfo;
 
 mod keys;
-mod kvstore;
 mod mint;
 mod proofs;
 mod saga;

+ 9 - 10
crates/cdk-sql-common/src/mint/mod.rs

@@ -131,7 +131,7 @@ where
 }
 
 #[async_trait]
-impl<RM> database::MintProofsTransaction<'_> for SQLTransaction<RM>
+impl<RM> database::MintProofsTransaction for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
@@ -328,8 +328,7 @@ where
 }
 
 #[async_trait]
-impl<RM> database::MintTransaction<'_, Error> for SQLTransaction<RM> where RM: DatabasePool + 'static
-{}
+impl<RM> database::MintTransaction<Error> for SQLTransaction<RM> where RM: DatabasePool + 'static {}
 
 #[async_trait]
 impl<RM> DbTransactionFinalizer for SQLTransaction<RM>
@@ -779,7 +778,7 @@ where
 }
 
 #[async_trait]
-impl<RM> MintQuotesTransaction<'_> for SQLTransaction<RM>
+impl<RM> MintQuotesTransaction for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
@@ -1662,7 +1661,7 @@ where
 }
 
 #[async_trait]
-impl<RM> MintSignatureTransaction<'_> for SQLTransaction<RM>
+impl<RM> MintSignatureTransaction for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
@@ -2100,7 +2099,7 @@ where
 }
 
 #[async_trait]
-impl<RM> SagaTransaction<'_> for SQLTransaction<RM>
+impl<RM> SagaTransaction for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
@@ -2244,7 +2243,7 @@ where
 }
 
 #[async_trait]
-impl<RM> CompletedOperationsTransaction<'_> for SQLTransaction<RM>
+impl<RM> CompletedOperationsTransaction for SQLTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
@@ -2392,9 +2391,9 @@ impl<RM> MintDatabase<Error> for SQLMintDatabase<RM>
 where
     RM: DatabasePool + 'static,
 {
-    async fn begin_transaction<'a>(
-        &'a self,
-    ) -> Result<Box<dyn database::MintTransaction<'a, Error> + Send + Sync + 'a>, Error> {
+    async fn begin_transaction(
+        &self,
+    ) -> Result<Box<dyn database::MintTransaction<Error> + Send + Sync>, Error> {
         let tx = SQLTransaction {
             inner: ConnectionWithTransaction::new(
                 self.pool.get().map_err(|e| Error::Database(Box::new(e)))?,

+ 1 - 1
crates/cdk/src/mint/issue/mod.rs

@@ -451,7 +451,7 @@ impl Mint {
     #[instrument(skip_all)]
     pub async fn pay_mint_quote(
         &self,
-        tx: &mut Box<dyn database::MintTransaction<'_, database::Error> + Send + Sync + '_>,
+        tx: &mut Box<dyn database::MintTransaction<database::Error> + Send + Sync>,
         mint_quote: &MintQuote,
         wait_payment_response: WaitPaymentResponse,
     ) -> Result<(), Error> {

+ 4 - 4
crates/cdk/src/mint/melt/shared.rs

@@ -176,9 +176,9 @@ pub async fn rollback_melt_quote(
 /// - Change calculation fails
 /// - Blind signing fails
 /// - Database operations fail
-pub async fn process_melt_change<'a>(
+pub async fn process_melt_change(
     mint: &super::super::Mint,
-    db: &'a DynMintDatabase,
+    db: &DynMintDatabase,
     quote_id: &QuoteId,
     inputs_amount: Amount,
     total_spent: Amount,
@@ -187,7 +187,7 @@ pub async fn process_melt_change<'a>(
 ) -> Result<
     (
         Option<Vec<BlindSignature>>,
-        Box<dyn database::MintTransaction<'a, database::Error> + Send + Sync + 'a>,
+        Box<dyn database::MintTransaction<database::Error> + Send + Sync>,
     ),
     Error,
 > {
@@ -281,7 +281,7 @@ pub async fn process_melt_change<'a>(
 /// - Database operations fail
 #[allow(clippy::too_many_arguments)]
 pub async fn finalize_melt_core(
-    tx: &mut Box<dyn database::MintTransaction<'_, database::Error> + Send + Sync + '_>,
+    tx: &mut Box<dyn database::MintTransaction<database::Error> + Send + Sync>,
     pubsub: &PubSubManager,
     quote: &MeltQuote,
     input_ys: &[PublicKey],

+ 1 - 1
crates/cdk/src/mint/mod.rs

@@ -709,7 +709,7 @@ impl Mint {
     /// Handle payment for a specific mint quote (extracted from pay_mint_quote)
     #[instrument(skip_all)]
     async fn handle_mint_quote_payment(
-        tx: &mut Box<dyn database::MintTransaction<'_, database::Error> + Send + Sync + '_>,
+        tx: &mut Box<dyn database::MintTransaction<database::Error> + Send + Sync>,
         mint_quote: &MintQuote,
         wait_payment_response: WaitPaymentResponse,
         pubsub_manager: &Arc<PubSubManager>,

+ 3 - 3
crates/cdk/src/mint/verification.rs

@@ -147,7 +147,7 @@ impl Mint {
     #[instrument(skip_all)]
     pub async fn check_output_already_signed(
         &self,
-        tx: &mut Box<dyn cdk_database::MintTransaction<'_, cdk_database::Error> + Send + Sync + '_>,
+        tx: &mut Box<dyn cdk_database::MintTransaction<cdk_database::Error> + Send + Sync>,
         outputs: &[BlindedMessage],
     ) -> Result<(), Error> {
         let blinded_messages: Vec<PublicKey> = outputs.iter().map(|o| o.blinded_secret).collect();
@@ -173,7 +173,7 @@ impl Mint {
     #[instrument(skip_all)]
     pub async fn verify_outputs(
         &self,
-        tx: &mut Box<dyn cdk_database::MintTransaction<'_, cdk_database::Error> + Send + Sync + '_>,
+        tx: &mut Box<dyn cdk_database::MintTransaction<cdk_database::Error> + Send + Sync>,
         outputs: &[BlindedMessage],
     ) -> Result<Verification, Error> {
         if outputs.is_empty() {
@@ -217,7 +217,7 @@ impl Mint {
     #[instrument(skip_all)]
     pub async fn verify_transaction_balanced(
         &self,
-        tx: &mut Box<dyn cdk_database::MintTransaction<'_, cdk_database::Error> + Send + Sync + '_>,
+        tx: &mut Box<dyn cdk_database::MintTransaction<cdk_database::Error> + Send + Sync>,
         input_verification: Verification,
         inputs: &Proofs,
         outputs: &[BlindedMessage],