Pārlūkot izejas kodu

fix: improve Melted error handling and add debug logging (#1213)

Replace .unwrap() with proper error handling using ? operator and add
debug logging to help diagnose fee calculation issues in the melt flow.

Changes:
- Replace .unwrap() with ? for proper error propagation
- Add tracing log for proofs amount, amount, and change amount

feat: nut14-validation
tsk 1 nedēļu atpakaļ
vecāks
revīzija
ec6e1e2910

+ 13 - 2
crates/cashu/src/nuts/nut11/mod.rs

@@ -58,6 +58,9 @@ pub enum Error {
     /// HTLC hash invalid
     #[error("Invalid hash")]
     InvalidHash,
+    /// HTLC preimage too large
+    #[error("Preimage exceeds maximum size of 32 bytes (64 hex characters)")]
+    PreimageTooLarge,
     /// Witness Signatures not provided
     #[error("Witness signatures not provided")]
     SignaturesNotProvided,
@@ -329,7 +332,15 @@ pub enum SpendingConditions {
 impl SpendingConditions {
     /// New HTLC [SpendingConditions]
     pub fn new_htlc(preimage: String, conditions: Option<Conditions>) -> Result<Self, Error> {
-        let htlc = Sha256Hash::hash(&hex::decode(preimage)?);
+        const MAX_PREIMAGE_BYTES: usize = 32;
+
+        let preimage_bytes = hex::decode(preimage)?;
+
+        if preimage_bytes.len() != MAX_PREIMAGE_BYTES {
+            return Err(Error::PreimageTooLarge);
+        }
+
+        let htlc = Sha256Hash::hash(&preimage_bytes);
 
         Ok(Self::HTLCConditions {
             data: htlc,
@@ -2071,4 +2082,4 @@ mod tests {
             "Both signatures should verify"
         );
     }
-} // End of tests module
+}

+ 17 - 2
crates/cashu/src/nuts/nut14/mod.rs

@@ -15,7 +15,7 @@ use super::nut10::Secret;
 use super::nut11::valid_signatures;
 use super::{Conditions, Proof};
 use crate::ensure_cdk;
-use crate::util::unix_time;
+use crate::util::{hex, unix_time};
 
 pub mod serde_htlc_witness;
 
@@ -37,6 +37,12 @@ pub enum Error {
     /// Preimage does not match
     #[error("Preimage does not match")]
     Preimage,
+    /// HTLC preimage must be valid hex encoding
+    #[error("Preimage must be valid hex encoding")]
+    InvalidHexPreimage,
+    /// HTLC preimage must be exactly 32 bytes
+    #[error("Preimage must be exactly 32 bytes (64 hex characters)")]
+    PreimageInvalidSize,
     /// Witness Signatures not provided
     #[error("Witness did not provide signatures")]
     SignaturesNotProvided,
@@ -76,6 +82,15 @@ impl Proof {
             _ => return Err(Error::IncorrectSecretKind),
         };
 
+        const REQUIRED_PREIMAGE_BYTES: usize = 32;
+
+        let preimage_bytes =
+            hex::decode(&htlc_witness.preimage).map_err(|_| Error::InvalidHexPreimage)?;
+
+        if preimage_bytes.len() != REQUIRED_PREIMAGE_BYTES {
+            return Err(Error::PreimageInvalidSize);
+        }
+
         if let Some(conditions) = conditions {
             // Check locktime
             if let Some(locktime) = conditions.locktime {
@@ -127,7 +142,7 @@ impl Proof {
         let hash_lock =
             Sha256Hash::from_str(secret.secret_data().data()).map_err(|_| Error::InvalidHash)?;
 
-        let preimage_hash = Sha256Hash::hash(htlc_witness.preimage.as_bytes());
+        let preimage_hash = Sha256Hash::hash(&preimage_bytes);
 
         if hash_lock.ne(&preimage_hash) {
             return Err(Error::Preimage);

+ 8 - 2
crates/cdk-common/src/common.rs

@@ -41,10 +41,16 @@ impl Melted {
             None => Amount::ZERO,
         };
 
+        tracing::info!(
+            "Proofs amount: {} Amount: {} Change: {}",
+            proofs_amount,
+            amount,
+            change_amount
+        );
+
         let fee_paid = proofs_amount
             .checked_sub(amount + change_amount)
-            .ok_or(Error::AmountOverflow)
-            .unwrap();
+            .ok_or(Error::AmountOverflow)?;
 
         Ok(Self {
             state,

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

@@ -898,6 +898,10 @@ impl Mint {
             quote.id
         );
 
+        if total_spent < quote.amount {
+            return Err(Error::AmountUndefined);
+        }
+
         let update_proof_states_result = proof_writer
             .update_proofs_states(&mut tx, &input_ys, State::Spent)
             .await;