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