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 (8231B)


      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_GetContractsHandle *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_GetContractsResponse *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_get_contracts_create (
    217     TALER_TESTING_interpreter_get_context (is),
    218     exchange_url,
    219     contract_priv);
    220   if (NULL == ds->dh)
    221   {
    222     GNUNET_break (0);
    223     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    224                 "Could not GET contract\n");
    225     TALER_TESTING_interpreter_fail (is);
    226     return;
    227   }
    228   if (TALER_EC_NONE !=
    229       TALER_EXCHANGE_get_contracts_start (ds->dh,
    230                                           &get_cb,
    231                                           ds))
    232   {
    233     GNUNET_break (0);
    234     TALER_EXCHANGE_get_contracts_cancel (ds->dh);
    235     ds->dh = NULL;
    236     TALER_TESTING_interpreter_fail (is);
    237     return;
    238   }
    239 }
    240 
    241 
    242 /**
    243  * Free the state of a "get" CMD, and possibly cancel a
    244  * pending operation thereof.
    245  *
    246  * @param cls closure, must be a `struct ContractGetState`.
    247  * @param cmd the command which is being cleaned up.
    248  */
    249 static void
    250 get_cleanup (void *cls,
    251              const struct TALER_TESTING_Command *cmd)
    252 {
    253   struct ContractGetState *ds = cls;
    254 
    255   if (NULL != ds->dh)
    256   {
    257     TALER_TESTING_command_incomplete (ds->is,
    258                                       cmd->label);
    259     TALER_EXCHANGE_get_contracts_cancel (ds->dh);
    260     ds->dh = NULL;
    261   }
    262   json_decref (ds->contract_terms);
    263   GNUNET_free (ds);
    264 }
    265 
    266 
    267 /**
    268  * Offer internal data from a "get" CMD, to other commands.
    269  *
    270  * @param cls closure.
    271  * @param[out] ret result.
    272  * @param trait name of the trait.
    273  * @param index index number of the object to offer.
    274  * @return #GNUNET_OK on success.
    275  */
    276 static enum GNUNET_GenericReturnValue
    277 get_traits (void *cls,
    278             const void **ret,
    279             const char *trait,
    280             unsigned int index)
    281 {
    282   struct ContractGetState *ds = cls;
    283   struct TALER_TESTING_Trait traits[] = {
    284     TALER_TESTING_make_trait_merge_priv (&ds->merge_priv),
    285     TALER_TESTING_make_trait_purse_pub (&ds->purse_pub),
    286     TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
    287     TALER_TESTING_trait_end ()
    288   };
    289 
    290   /* skip 'merge_priv' if we are in 'merge' mode */
    291   return TALER_TESTING_get_trait (&traits[ds->merge ? 0 : 1],
    292                                   ret,
    293                                   trait,
    294                                   index);
    295 }
    296 
    297 
    298 struct TALER_TESTING_Command
    299 TALER_TESTING_cmd_contract_get (
    300   const char *label,
    301   unsigned int expected_http_status,
    302   bool for_merge,
    303   const char *contract_ref)
    304 {
    305   struct ContractGetState *ds;
    306 
    307   ds = GNUNET_new (struct ContractGetState);
    308   ds->expected_response_code = expected_http_status;
    309   ds->contract_ref = contract_ref;
    310   ds->merge = for_merge;
    311   {
    312     struct TALER_TESTING_Command cmd = {
    313       .cls = ds,
    314       .label = label,
    315       .run = &get_run,
    316       .cleanup = &get_cleanup,
    317       .traits = &get_traits
    318     };
    319 
    320     return cmd;
    321   }
    322 }
    323 
    324 
    325 /* end of testing_api_cmd_contract_get.c */