testing_api_cmd_reserve_close.c (7422B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as 7 published by the Free Software Foundation; either version 3, or 8 (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file testing/testing_api_cmd_reserve_close.c 21 * @brief Implement the /reserve/$RID/close test command. 22 * @author Christian Grothoff 23 */ 24 #include "taler/taler_json_lib.h" 25 #include <gnunet/gnunet_curl_lib.h> 26 struct CloseState; 27 #define TALER_EXCHANGE_POST_RESERVES_CLOSE_RESULT_CLOSURE struct CloseState 28 #include "taler/exchange/post-reserves-RESERVE_PUB-close.h" 29 #include "taler/taler_testing_lib.h" 30 31 32 /** 33 * State for a "close" CMD. 34 */ 35 struct CloseState 36 { 37 /** 38 * Label to the command which created the reserve to check, 39 * needed to resort the reserve key. 40 */ 41 const char *reserve_reference; 42 43 /** 44 * Handle to the "reserve close" operation. 45 */ 46 struct TALER_EXCHANGE_PostReservesCloseHandle *rsh; 47 48 /** 49 * payto://-URI where to wire the funds. 50 */ 51 struct TALER_FullPayto target_account; 52 53 /** 54 * Private key of the reserve being analyzed. 55 */ 56 const struct TALER_ReservePrivateKeyP *reserve_priv; 57 58 /** 59 * Public key of the reserve being analyzed. 60 */ 61 struct TALER_ReservePublicKeyP reserve_pub; 62 63 /** 64 * Expected HTTP response code. 65 */ 66 unsigned int expected_response_code; 67 68 /** 69 * Interpreter state. 70 */ 71 struct TALER_TESTING_Interpreter *is; 72 73 /** 74 * Set to the KYC requirement payto hash *if* the exchange replied with a 75 * request for KYC. 76 */ 77 struct TALER_NormalizedPaytoHashP h_payto; 78 79 /** 80 * Set to the KYC requirement row *if* the exchange replied with 81 * a request for KYC. 82 */ 83 uint64_t requirement_row; 84 }; 85 86 87 /** 88 * Check that the reserve balance and HTTP response code are 89 * both acceptable. 90 * 91 * @param ss closure. 92 * @param rs HTTP response details 93 */ 94 static void 95 reserve_close_cb (struct CloseState *ss, 96 const struct TALER_EXCHANGE_PostReservesCloseResponse *rs) 97 { 98 struct TALER_TESTING_Interpreter *is = ss->is; 99 100 ss->rsh = NULL; 101 if (ss->expected_response_code != rs->hr.http_status) 102 { 103 TALER_TESTING_unexpected_status (ss->is, 104 rs->hr.http_status, 105 ss->expected_response_code); 106 json_dumpf (rs->hr.reply, 107 stderr, 108 JSON_INDENT (2)); 109 return; 110 } 111 switch (rs->hr.http_status) 112 { 113 case MHD_HTTP_OK: 114 break; 115 case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: 116 /* nothing to check */ 117 ss->requirement_row 118 = rs->details.unavailable_for_legal_reasons.requirement_row; 119 ss->h_payto 120 = rs->details.unavailable_for_legal_reasons.h_payto; 121 break; 122 default: 123 break; 124 } 125 TALER_TESTING_interpreter_next (is); 126 } 127 128 129 /** 130 * Run the command. 131 * 132 * @param cls closure. 133 * @param cmd the command being executed. 134 * @param is the interpreter state. 135 */ 136 static void 137 close_run (void *cls, 138 const struct TALER_TESTING_Command *cmd, 139 struct TALER_TESTING_Interpreter *is) 140 { 141 struct CloseState *ss = cls; 142 const struct TALER_TESTING_Command *create_reserve; 143 144 ss->is = is; 145 create_reserve 146 = TALER_TESTING_interpreter_lookup_command (is, 147 ss->reserve_reference); 148 149 if (NULL == create_reserve) 150 { 151 GNUNET_break (0); 152 TALER_TESTING_interpreter_fail (is); 153 return; 154 } 155 if (GNUNET_OK != 156 TALER_TESTING_get_trait_reserve_priv (create_reserve, 157 &ss->reserve_priv)) 158 { 159 GNUNET_break (0); 160 TALER_LOG_ERROR ("Failed to find reserve_priv for close query\n"); 161 TALER_TESTING_interpreter_fail (is); 162 return; 163 } 164 GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv, 165 &ss->reserve_pub.eddsa_pub); 166 ss->rsh = TALER_EXCHANGE_post_reserves_close_create ( 167 TALER_TESTING_interpreter_get_context (is), 168 TALER_TESTING_get_exchange_url (is), 169 ss->reserve_priv); 170 if (NULL == ss->rsh) 171 { 172 GNUNET_break (0); 173 TALER_TESTING_interpreter_fail (is); 174 return; 175 } 176 if (NULL != ss->target_account.full_payto) 177 { 178 TALER_EXCHANGE_post_reserves_close_set_options ( 179 ss->rsh, 180 TALER_EXCHANGE_post_reserves_close_option_payto_uri ( 181 ss->target_account)); 182 } 183 { 184 enum TALER_ErrorCode ec; 185 186 ec = TALER_EXCHANGE_post_reserves_close_start (ss->rsh, 187 &reserve_close_cb, 188 ss); 189 if (TALER_EC_NONE != ec) 190 { 191 GNUNET_break (0); 192 ss->rsh = NULL; 193 TALER_TESTING_interpreter_fail (is); 194 return; 195 } 196 } 197 } 198 199 200 /** 201 * Cleanup the state from a "reserve close" CMD, and possibly 202 * cancel a pending operation thereof. 203 * 204 * @param cls closure. 205 * @param cmd the command which is being cleaned up. 206 */ 207 static void 208 close_cleanup (void *cls, 209 const struct TALER_TESTING_Command *cmd) 210 { 211 struct CloseState *ss = cls; 212 213 if (NULL != ss->rsh) 214 { 215 TALER_TESTING_command_incomplete (ss->is, 216 cmd->label); 217 TALER_EXCHANGE_post_reserves_close_cancel (ss->rsh); 218 ss->rsh = NULL; 219 } 220 GNUNET_free (ss); 221 } 222 223 224 /** 225 * Offer internal data to a "close" CMD state to other 226 * commands. 227 * 228 * @param cls closure 229 * @param[out] ret result (could be anything) 230 * @param trait name of the trait 231 * @param index index number of the object to offer. 232 * @return #GNUNET_OK on success 233 */ 234 static enum GNUNET_GenericReturnValue 235 close_traits (void *cls, 236 const void **ret, 237 const char *trait, 238 unsigned int index) 239 { 240 struct CloseState *cs = cls; 241 struct TALER_TESTING_Trait traits[] = { 242 TALER_TESTING_make_trait_legi_requirement_row ( 243 &cs->requirement_row), 244 TALER_TESTING_make_trait_h_normalized_payto ( 245 &cs->h_payto), 246 TALER_TESTING_trait_end () 247 }; 248 249 if (cs->expected_response_code != MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS) 250 return GNUNET_NO; 251 return TALER_TESTING_get_trait (traits, 252 ret, 253 trait, 254 index); 255 } 256 257 258 struct TALER_TESTING_Command 259 TALER_TESTING_cmd_reserve_close (const char *label, 260 const char *reserve_reference, 261 struct TALER_FullPayto target_account, 262 unsigned int expected_response_code) 263 { 264 struct CloseState *ss; 265 266 GNUNET_assert (NULL != reserve_reference); 267 ss = GNUNET_new (struct CloseState); 268 ss->reserve_reference = reserve_reference; 269 ss->target_account = target_account; 270 ss->expected_response_code = expected_response_code; 271 { 272 struct TALER_TESTING_Command cmd = { 273 .cls = ss, 274 .label = label, 275 .run = &close_run, 276 .cleanup = &close_cleanup, 277 .traits = &close_traits 278 }; 279 280 return cmd; 281 } 282 }