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_contract_get.c (7919B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2022 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it
      6   under the terms of the GNU General Public License as published by
      7   the Free Software Foundation; either version 3, or (at your
      8   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 GNU
     13   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_contract_get.c
     21  * @brief command for testing GET /contracts/$CPUB
     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 #include "taler/taler_signatures.h"
     29 #include "taler/backoff.h"
     30 
     31 
     32 /**
     33  * State for a "contract get" CMD.
     34  */
     35 struct ContractGetState
     36 {
     37 
     38   /**
     39    * JSON string describing the resulting contract.
     40    */
     41   json_t *contract_terms;
     42 
     43   /**
     44    * Private key to decrypt the contract.
     45    */
     46   struct TALER_ContractDiffiePrivateP contract_priv;
     47 
     48   /**
     49    * Set to the returned merge key.
     50    */
     51   struct TALER_PurseMergePrivateKeyP merge_priv;
     52 
     53   /**
     54    * Public key of the purse.
     55    */
     56   struct TALER_PurseContractPublicKeyP purse_pub;
     57 
     58   /**
     59    * Reference to the command that uploaded the contract.
     60    */
     61   const char *contract_ref;
     62 
     63   /**
     64    * ContractGet handle while operation is running.
     65    */
     66   struct TALER_EXCHANGE_ContractsGetHandle *dh;
     67 
     68   /**
     69    * Interpreter state.
     70    */
     71   struct TALER_TESTING_Interpreter *is;
     72 
     73   /**
     74    * Expected HTTP response code.
     75    */
     76   unsigned int expected_response_code;
     77 
     78   /**
     79    * True if this is for a 'merge' operation,
     80    * 'false' if this is for a 'deposit' operation.
     81    */
     82   bool merge;
     83 
     84 };
     85 
     86 
     87 /**
     88  * Callback to analyze the /contracts/$CPUB response, just used to check if
     89  * the response code is acceptable.
     90  *
     91  * @param cls closure.
     92  * @param dr get response details
     93  */
     94 static void
     95 get_cb (void *cls,
     96         const struct TALER_EXCHANGE_ContractGetResponse *dr)
     97 {
     98   struct ContractGetState *ds = cls;
     99   const struct TALER_TESTING_Command *ref;
    100 
    101   ds->dh = NULL;
    102   if (ds->expected_response_code != dr->hr.http_status)
    103   {
    104     TALER_TESTING_unexpected_status (ds->is,
    105                                      dr->hr.http_status,
    106                                      ds->expected_response_code);
    107     return;
    108   }
    109   ref = TALER_TESTING_interpreter_lookup_command (ds->is,
    110                                                   ds->contract_ref);
    111   GNUNET_assert (NULL != ref);
    112   if (MHD_HTTP_OK == dr->hr.http_status)
    113   {
    114     const struct TALER_PurseMergePrivateKeyP *mp;
    115     const json_t *ct;
    116 
    117     ds->purse_pub = dr->details.ok.purse_pub;
    118     if (ds->merge)
    119     {
    120       if (GNUNET_OK !=
    121           TALER_TESTING_get_trait_merge_priv (ref,
    122                                               &mp))
    123       {
    124         GNUNET_break (0);
    125         TALER_TESTING_interpreter_fail (ds->is);
    126         return;
    127       }
    128       ds->contract_terms =
    129         TALER_CRYPTO_contract_decrypt_for_merge (
    130           &ds->contract_priv,
    131           &ds->purse_pub,
    132           dr->details.ok.econtract,
    133           dr->details.ok.econtract_size,
    134           &ds->merge_priv);
    135       if (0 !=
    136           GNUNET_memcmp (mp,
    137                          &ds->merge_priv))
    138       {
    139         GNUNET_break (0);
    140         TALER_TESTING_interpreter_fail (ds->is);
    141         return;
    142       }
    143     }
    144     else
    145     {
    146       ds->contract_terms =
    147         TALER_CRYPTO_contract_decrypt_for_deposit (
    148           &ds->contract_priv,
    149           dr->details.ok.econtract,
    150           dr->details.ok.econtract_size);
    151     }
    152     if (NULL == ds->contract_terms)
    153     {
    154       GNUNET_break (0);
    155       TALER_TESTING_interpreter_fail (ds->is);
    156       return;
    157     }
    158     if (GNUNET_OK !=
    159         TALER_TESTING_get_trait_contract_terms (ref,
    160                                                 &ct))
    161     {
    162       GNUNET_break (0);
    163       TALER_TESTING_interpreter_fail (ds->is);
    164       return;
    165     }
    166     if (1 != /* 1: equal, 0: not equal */
    167         json_equal (ct,
    168                     ds->contract_terms))
    169     {
    170       GNUNET_break (0);
    171       TALER_TESTING_interpreter_fail (ds->is);
    172       return;
    173     }
    174   }
    175   TALER_TESTING_interpreter_next (ds->is);
    176 }
    177 
    178 
    179 /**
    180  * Run the command.
    181  *
    182  * @param cls closure.
    183  * @param cmd the command to execute.
    184  * @param is the interpreter state.
    185  */
    186 static void
    187 get_run (void *cls,
    188          const struct TALER_TESTING_Command *cmd,
    189          struct TALER_TESTING_Interpreter *is)
    190 {
    191   struct ContractGetState *ds = cls;
    192   const struct TALER_ContractDiffiePrivateP *contract_priv;
    193   const struct TALER_TESTING_Command *ref;
    194   const char *exchange_url;
    195 
    196   (void) cmd;
    197   ds->is = is;
    198   exchange_url = TALER_TESTING_get_exchange_url (is);
    199   if (NULL == exchange_url)
    200   {
    201     GNUNET_break (0);
    202     return;
    203   }
    204   ref = TALER_TESTING_interpreter_lookup_command (ds->is,
    205                                                   ds->contract_ref);
    206   GNUNET_assert (NULL != ref);
    207   if (GNUNET_OK !=
    208       TALER_TESTING_get_trait_contract_priv (ref,
    209                                              &contract_priv))
    210   {
    211     GNUNET_break (0);
    212     TALER_TESTING_interpreter_fail (ds->is);
    213     return;
    214   }
    215   ds->contract_priv = *contract_priv;
    216   ds->dh = TALER_EXCHANGE_contract_get (
    217     TALER_TESTING_interpreter_get_context (is),
    218     exchange_url,
    219     contract_priv,
    220     &get_cb,
    221     ds);
    222   if (NULL == ds->dh)
    223   {
    224     GNUNET_break (0);
    225     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    226                 "Could not GET contract\n");
    227     TALER_TESTING_interpreter_fail (is);
    228     return;
    229   }
    230 }
    231 
    232 
    233 /**
    234  * Free the state of a "get" CMD, and possibly cancel a
    235  * pending operation thereof.
    236  *
    237  * @param cls closure, must be a `struct ContractGetState`.
    238  * @param cmd the command which is being cleaned up.
    239  */
    240 static void
    241 get_cleanup (void *cls,
    242              const struct TALER_TESTING_Command *cmd)
    243 {
    244   struct ContractGetState *ds = cls;
    245 
    246   if (NULL != ds->dh)
    247   {
    248     TALER_TESTING_command_incomplete (ds->is,
    249                                       cmd->label);
    250     TALER_EXCHANGE_contract_get_cancel (ds->dh);
    251     ds->dh = NULL;
    252   }
    253   json_decref (ds->contract_terms);
    254   GNUNET_free (ds);
    255 }
    256 
    257 
    258 /**
    259  * Offer internal data from a "get" CMD, to other commands.
    260  *
    261  * @param cls closure.
    262  * @param[out] ret result.
    263  * @param trait name of the trait.
    264  * @param index index number of the object to offer.
    265  * @return #GNUNET_OK on success.
    266  */
    267 static enum GNUNET_GenericReturnValue
    268 get_traits (void *cls,
    269             const void **ret,
    270             const char *trait,
    271             unsigned int index)
    272 {
    273   struct ContractGetState *ds = cls;
    274   struct TALER_TESTING_Trait traits[] = {
    275     TALER_TESTING_make_trait_merge_priv (&ds->merge_priv),
    276     TALER_TESTING_make_trait_purse_pub (&ds->purse_pub),
    277     TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
    278     TALER_TESTING_trait_end ()
    279   };
    280 
    281   /* skip 'merge_priv' if we are in 'merge' mode */
    282   return TALER_TESTING_get_trait (&traits[ds->merge ? 0 : 1],
    283                                   ret,
    284                                   trait,
    285                                   index);
    286 }
    287 
    288 
    289 struct TALER_TESTING_Command
    290 TALER_TESTING_cmd_contract_get (
    291   const char *label,
    292   unsigned int expected_http_status,
    293   bool for_merge,
    294   const char *contract_ref)
    295 {
    296   struct ContractGetState *ds;
    297 
    298   ds = GNUNET_new (struct ContractGetState);
    299   ds->expected_response_code = expected_http_status;
    300   ds->contract_ref = contract_ref;
    301   ds->merge = for_merge;
    302   {
    303     struct TALER_TESTING_Command cmd = {
    304       .cls = ds,
    305       .label = label,
    306       .run = &get_run,
    307       .cleanup = &get_cleanup,
    308       .traits = &get_traits
    309     };
    310 
    311     return cmd;
    312   }
    313 }
    314 
    315 
    316 /* end of testing_api_cmd_contract_get.c */