@@ -88,18 +88,44 @@ async fn post_mint_request_with_legacy_fallback(
8888 {
8989 Ok ( response) => Ok ( response) ,
9090 Err ( error) if should_retry_with_legacy_quote_signature ( & error) => {
91- let Some ( secret_key) = wallet. mint_quote_signing_key ( quote_info) . await ? else {
92- return Err ( error) ;
91+ let secret_key = match wallet. mint_quote_signing_key ( quote_info) . await {
92+ Ok ( Some ( secret_key) ) => secret_key,
93+ Ok ( None ) => return Err ( error) ,
94+ Err ( fallback_error) => {
95+ tracing:: warn!(
96+ original_error = %error,
97+ fallback_error = %fallback_error,
98+ "Could not prepare legacy mint quote signature retry; returning original mint error"
99+ ) ;
100+ return Err ( error) ;
101+ }
93102 } ;
94103
95104 tracing:: info!(
96105 "Mint request rejected with new NUT-20 signature format; retrying legacy format"
97106 ) ;
98107
99108 let mut retry_request = request. clone ( ) ;
100- retry_request. sign_legacy ( secret_key) ?;
109+ if let Err ( fallback_error) = retry_request. sign_legacy ( secret_key) {
110+ tracing:: warn!(
111+ original_error = %error,
112+ fallback_error = %fallback_error,
113+ "Could not sign legacy mint quote retry; returning original mint error"
114+ ) ;
115+ return Err ( error) ;
116+ }
101117
102- wallet. client . post_mint ( payment_method, retry_request) . await
118+ match wallet. client . post_mint ( payment_method, retry_request) . await {
119+ Ok ( response) => Ok ( response) ,
120+ Err ( fallback_error) => {
121+ tracing:: warn!(
122+ original_error = %error,
123+ fallback_error = %fallback_error,
124+ "Legacy mint quote signature retry failed; returning original mint error"
125+ ) ;
126+ Err ( error)
127+ }
128+ }
103129 }
104130 Err ( error) => Err ( error) ,
105131 } ,
@@ -115,10 +141,23 @@ async fn post_mint_request_with_legacy_fallback(
115141 {
116142 Ok ( response) => Ok ( response) ,
117143 Err ( error) if should_retry_with_legacy_quote_signature ( & error) => {
118- let Some ( legacy_signatures) =
119- legacy_batch_signatures ( wallet, request, quote_infos) . await ?
120- else {
121- return Err ( error) ;
144+ let legacy_signatures = match legacy_batch_signatures (
145+ wallet,
146+ request,
147+ quote_infos,
148+ )
149+ . await
150+ {
151+ Ok ( Some ( legacy_signatures) ) => legacy_signatures,
152+ Ok ( None ) => return Err ( error) ,
153+ Err ( fallback_error) => {
154+ tracing:: warn!(
155+ original_error = %error,
156+ fallback_error = %fallback_error,
157+ "Could not prepare legacy batch mint quote signature retry; returning original mint error"
158+ ) ;
159+ return Err ( error) ;
160+ }
122161 } ;
123162
124163 tracing:: info!(
@@ -132,6 +171,14 @@ async fn post_mint_request_with_legacy_fallback(
132171 . client
133172 . post_batch_mint ( payment_method, retry_request)
134173 . await
174+ . map_err ( |fallback_error| {
175+ tracing:: warn!(
176+ original_error = %error,
177+ fallback_error = %fallback_error,
178+ "Legacy batch mint quote signature retry failed; returning original mint error"
179+ ) ;
180+ error
181+ } )
135182 }
136183 Err ( error) => Err ( error) ,
137184 }
@@ -156,6 +203,10 @@ async fn legacy_batch_signatures(
156203 for ( ( quote_id, quote_info) , signature) in
157204 request. quotes . iter ( ) . zip ( quote_infos) . zip ( signatures)
158205 {
206+ if quote_info. id . as_str ( ) != quote_id. as_str ( ) {
207+ return Ok ( None ) ;
208+ }
209+
159210 if signature. is_some ( ) {
160211 let Some ( secret_key) = wallet. mint_quote_signing_key ( quote_info) . await ? else {
161212 return Ok ( None ) ;
@@ -964,7 +1015,7 @@ mod tests {
9641015 use cdk_common:: nuts:: MintQuoteState ;
9651016
9661017 use super :: * ;
967- use crate :: nuts:: { BlindSignature , BlindedMessage , MintResponse } ;
1018+ use crate :: nuts:: { BatchMintRequest , BlindSignature , BlindedMessage , MintResponse } ;
9681019 use crate :: wallet:: test_utils:: {
9691020 create_test_db, create_test_wallet_with_mock, test_mint_quote, test_mint_url,
9701021 MockMintConnector ,
@@ -1022,7 +1073,9 @@ mod tests {
10221073 . expect ( "prepare mint saga" ) ;
10231074
10241075 mock_client. push_post_mint_response ( Err ( Error :: SignatureMissingOrInvalid ) ) ;
1025- mock_client. push_post_mint_response ( Err ( Error :: SignatureMissingOrInvalid ) ) ;
1076+ mock_client. push_post_mint_response ( Err ( Error :: Custom (
1077+ "legacy retry should not replace original error" . to_string ( ) ,
1078+ ) ) ) ;
10261079
10271080 let result = prepared. execute ( ) . await ;
10281081
@@ -1079,7 +1132,9 @@ mod tests {
10791132 . expect ( "prepare batch mint saga" ) ;
10801133
10811134 mock_client. push_post_batch_mint_response ( Err ( Error :: SignatureMissingOrInvalid ) ) ;
1082- mock_client. push_post_batch_mint_response ( Err ( Error :: SignatureMissingOrInvalid ) ) ;
1135+ mock_client. push_post_batch_mint_response ( Err ( Error :: Custom (
1136+ "legacy retry should not replace original error" . to_string ( ) ,
1137+ ) ) ) ;
10831138
10841139 let result = prepared. execute ( ) . await ;
10851140
@@ -1126,6 +1181,28 @@ mod tests {
11261181 assert_eq ! ( first_request. outputs, legacy_request. outputs) ;
11271182 }
11281183
1184+ #[ tokio:: test]
1185+ async fn test_legacy_batch_signatures_rejects_misaligned_quote_infos ( ) {
1186+ let db = create_test_db ( ) . await ;
1187+ let mint_url = test_mint_url ( ) ;
1188+ let mock_client = Arc :: new ( MockMintConnector :: new ( ) ) ;
1189+ let wallet = create_test_wallet_with_mock ( db, mock_client) . await ;
1190+
1191+ let request = BatchMintRequest {
1192+ quotes : vec ! [ "request-quote-id" . to_string( ) ] ,
1193+ quote_amounts : None ,
1194+ outputs : vec ! [ ] ,
1195+ signatures : Some ( vec ! [ Some ( "signature-placeholder" . to_string( ) ) ] ) ,
1196+ } ;
1197+ let quote_infos = vec ! [ test_mint_quote( mint_url) ] ;
1198+
1199+ let result = legacy_batch_signatures ( & wallet, & request, & quote_infos)
1200+ . await
1201+ . expect ( "alignment check should not fail" ) ;
1202+
1203+ assert ! ( result. is_none( ) ) ;
1204+ }
1205+
11291206 #[ tokio:: test]
11301207 async fn test_execute_rejects_signature_with_mismatched_amount ( ) {
11311208 let db = create_test_db ( ) . await ;
0 commit comments