From 9b35158a8a8e357ad928b665099e4bd35e9929f8 Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Sat, 6 Sep 2025 16:04:29 +0100 Subject: [PATCH] fix: sig error code (#1038) --- crates/cdk-axum/src/router_handlers.rs | 1 + crates/cdk-common/src/error.rs | 35 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/crates/cdk-axum/src/router_handlers.rs b/crates/cdk-axum/src/router_handlers.rs index 541d1d50..207f34c7 100644 --- a/crates/cdk-axum/src/router_handlers.rs +++ b/crates/cdk-axum/src/router_handlers.rs @@ -561,6 +561,7 @@ where | ErrorCode::TransactionUnbalanced | ErrorCode::AmountOutofLimitRange | ErrorCode::WitnessMissingOrInvalid + | ErrorCode::DuplicateSignature | ErrorCode::DuplicateInputs | ErrorCode::DuplicateOutputs | ErrorCode::MultipleUnits diff --git a/crates/cdk-common/src/error.rs b/crates/cdk-common/src/error.rs index 0b782f99..9e0f8fd7 100644 --- a/crates/cdk-common/src/error.rs +++ b/crates/cdk-common/src/error.rs @@ -209,6 +209,9 @@ pub enum Error { /// P2PK spending conditions not met #[error("P2PK condition not met `{0}`")] P2PKConditionsNotMet(String), + /// Duplicate signature from same pubkey in P2PK + #[error("Duplicate signature from same pubkey in P2PK")] + DuplicateSignatureError, /// Spending Locktime not provided #[error("Spending condition locktime not provided")] LocktimeNotProvided, @@ -438,6 +441,16 @@ impl ErrorResponse { } } +/// Maps NUT11 errors to appropriate error codes +fn map_nut11_error(nut11_error: &crate::nuts::nut11::Error) -> ErrorCode { + match nut11_error { + crate::nuts::nut11::Error::SignaturesNotProvided => ErrorCode::WitnessMissingOrInvalid, + crate::nuts::nut11::Error::InvalidSignature => ErrorCode::WitnessMissingOrInvalid, + crate::nuts::nut11::Error::DuplicateSignature => ErrorCode::DuplicateSignature, + _ => ErrorCode::Unknown(9999), // Parsing/validation errors + } +} + impl From for ErrorResponse { fn from(err: Error) -> ErrorResponse { match err { @@ -555,6 +568,23 @@ impl From for ErrorResponse { error: Some(err.to_string()), detail: None }, + Error::NUT11(err) => { + let code = map_nut11_error(&err); + let mut detail = None; + if matches!(err, crate::nuts::nut11::Error::SignaturesNotProvided) { + detail = Some("P2PK signatures are required but not provided".to_string()); + } + ErrorResponse { + code, + error: Some(err.to_string()), + detail, + } + }, + Error::DuplicateSignatureError => ErrorResponse { + code: ErrorCode::DuplicateSignature, + error: Some(err.to_string()), + detail: None, + }, _ => ErrorResponse { code: ErrorCode::Unknown(9999), error: Some(err.to_string()), @@ -612,6 +642,7 @@ impl From for Error { ErrorCode::UnitMismatch => Self::UnitMismatch, ErrorCode::ClearAuthRequired => Self::ClearAuthRequired, ErrorCode::BlindAuthRequired => Self::BlindAuthRequired, + ErrorCode::DuplicateSignature => Self::DuplicateSignatureError, _ => Self::UnknownErrorResponse(err.to_string()), } } @@ -671,6 +702,8 @@ pub enum ErrorCode { BlindAuthRequired, /// Blind Auth Failed BlindAuthFailed, + /// Duplicate signature from same pubkey + DuplicateSignature, /// Unknown error code Unknown(u16), } @@ -700,6 +733,7 @@ impl ErrorCode { 20006 => Self::InvoiceAlreadyPaid, 20007 => Self::QuoteExpired, 20008 => Self::WitnessMissingOrInvalid, + 20009 => Self::DuplicateSignature, 30001 => Self::ClearAuthRequired, 30002 => Self::ClearAuthFailed, 31001 => Self::BlindAuthRequired, @@ -732,6 +766,7 @@ impl ErrorCode { Self::InvoiceAlreadyPaid => 20006, Self::QuoteExpired => 20007, Self::WitnessMissingOrInvalid => 20008, + Self::DuplicateSignature => 20009, Self::ClearAuthRequired => 30001, Self::ClearAuthFailed => 30002, Self::BlindAuthRequired => 31001,