exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

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 }