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


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