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 (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 }