From 983157b7a973d5e5b8c875434cedee05cf0c39e4 Mon Sep 17 00:00:00 2001 From: kbizikav <132550763+kbizikav@users.noreply.github.com> Date: Tue, 11 Nov 2025 16:51:37 +0700 Subject: [PATCH] fix(client): consume only invalid (#473) --- client-sdk/src/client/fee_payment.rs | 12 ++++++++++-- client-sdk/src/client/receive_validation.rs | 8 ++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client-sdk/src/client/fee_payment.rs b/client-sdk/src/client/fee_payment.rs index a7147f64..d668459b 100644 --- a/client-sdk/src/client/fee_payment.rs +++ b/client-sdk/src/client/fee_payment.rs @@ -32,6 +32,7 @@ use super::{ pub const WITHDRAWAL_FEE_MEMO: &str = "withdrawal_fee_memo"; pub const CLAIM_FEE_MEMO: &str = "claim_fee_memo"; pub const USED_OR_INVALID_MEMO: &str = "used_or_invalid_memo"; +pub const TX_TIMEOUT_BUFFER_SECS: u64 = 600; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum FeeType { @@ -302,16 +303,23 @@ pub async fn select_unused_fees( collected_total_fee += transfer.amount; } Err(ReceiveValidationError::TxIsNotSettled(timestamp)) => { - if timestamp + tx_timeout < chrono::Utc::now().timestamp() as u64 { + if timestamp + tx_timeout + TX_TIMEOUT_BUFFER_SECS + < chrono::Utc::now().timestamp() as u64 + { consume_payment(store_vault_server, view_pair, &memo, "tx is timeout").await?; } log::info!("fee: {} is not settled yet", memo.meta.digest); continue; } - Err(e) => { + Err(ReceiveValidationError::ValidationError(e)) => { log::warn!("invalid fee: {} reason: {}", memo.meta.digest, e,); consume_payment(store_vault_server, view_pair, &memo, &e.to_string()).await?; } + Err(e) => { + return Err(SyncError::FeeError(format!( + "failed to validate fee memo: {e}", + ))); + } } if collected_total_fee >= fee.amount { break; diff --git a/client-sdk/src/client/receive_validation.rs b/client-sdk/src/client/receive_validation.rs index 1e0d233a..14c744a3 100644 --- a/client-sdk/src/client/receive_validation.rs +++ b/client-sdk/src/client/receive_validation.rs @@ -50,11 +50,11 @@ pub async fn validate_receive( ) -> Result { transfer_data .validate() - .map_err(|e| StrategyError::ValidationError(e.to_string()))?; + .map_err(|e| ReceiveValidationError::ValidationError(e.to_string()))?; let recipient = transfer_data.transfer.recipient; if recipient != recipient_spend_pub.0.into() { - return Err(ReceiveValidationError::GeneralError( + return Err(ReceiveValidationError::ValidationError( "Recipient is not the same as the key".to_string(), )); } @@ -80,7 +80,7 @@ pub async fn validate_receive( ReceiveValidationError::ValidationError(format!("Failed to decompress spent proof: {e}")) })?; if spent_pis.tx != transfer_data.tx { - return Err(ReceiveValidationError::GeneralError( + return Err(ReceiveValidationError::ValidationError( "Tx in spent proof is not the same as transfer witness tx".to_string(), )); } @@ -88,7 +88,7 @@ pub async fn validate_receive( .insufficient_flags .random_access(transfer_data.transfer_index as usize); if insufficient_flag { - return Err(ReceiveValidationError::GeneralError( + return Err(ReceiveValidationError::ValidationError( "Insufficient flag is on in spent proof".to_string(), )); }