testing_api_cmd_reserve_close.c (6657B)
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_ReservesCloseHandle *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_ReserveCloseResult *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_reserves_close ( 166 TALER_TESTING_interpreter_get_context (is), 167 TALER_TESTING_get_exchange_url (is), 168 ss->reserve_priv, 169 ss->target_account, 170 &reserve_close_cb, 171 ss); 172 } 173 174 175 /** 176 * Cleanup the state from a "reserve close" CMD, and possibly 177 * cancel a pending operation thereof. 178 * 179 * @param cls closure. 180 * @param cmd the command which is being cleaned up. 181 */ 182 static void 183 close_cleanup (void *cls, 184 const struct TALER_TESTING_Command *cmd) 185 { 186 struct CloseState *ss = cls; 187 188 if (NULL != ss->rsh) 189 { 190 TALER_TESTING_command_incomplete (ss->is, 191 cmd->label); 192 TALER_EXCHANGE_reserves_close_cancel (ss->rsh); 193 ss->rsh = NULL; 194 } 195 GNUNET_free (ss); 196 } 197 198 199 /** 200 * Offer internal data to a "close" CMD state to other 201 * commands. 202 * 203 * @param cls closure 204 * @param[out] ret result (could be anything) 205 * @param trait name of the trait 206 * @param index index number of the object to offer. 207 * @return #GNUNET_OK on success 208 */ 209 static enum GNUNET_GenericReturnValue 210 close_traits (void *cls, 211 const void **ret, 212 const char *trait, 213 unsigned int index) 214 { 215 struct CloseState *cs = cls; 216 struct TALER_TESTING_Trait traits[] = { 217 TALER_TESTING_make_trait_legi_requirement_row ( 218 &cs->requirement_row), 219 TALER_TESTING_make_trait_h_normalized_payto ( 220 &cs->h_payto), 221 TALER_TESTING_trait_end () 222 }; 223 224 if (cs->expected_response_code != MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS) 225 return GNUNET_NO; 226 return TALER_TESTING_get_trait (traits, 227 ret, 228 trait, 229 index); 230 } 231 232 233 struct TALER_TESTING_Command 234 TALER_TESTING_cmd_reserve_close (const char *label, 235 const char *reserve_reference, 236 struct TALER_FullPayto target_account, 237 unsigned int expected_response_code) 238 { 239 struct CloseState *ss; 240 241 GNUNET_assert (NULL != reserve_reference); 242 ss = GNUNET_new (struct CloseState); 243 ss->reserve_reference = reserve_reference; 244 ss->target_account = target_account; 245 ss->expected_response_code = expected_response_code; 246 { 247 struct TALER_TESTING_Command cmd = { 248 .cls = ss, 249 .label = label, 250 .run = &close_run, 251 .cleanup = &close_cleanup, 252 .traits = &close_traits 253 }; 254 255 return cmd; 256 } 257 }