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_attest.c (7061B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2022 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_attest.c
     21  * @brief Implement the /reserve/$RID/attest test command.
     22  * @author Christian Grothoff
     23  */
     24 #include "taler/taler_json_lib.h"
     25 #include <gnunet/gnunet_curl_lib.h>
     26 #include "taler/taler_testing_lib.h"
     27 
     28 /**
     29  * State for a "attest" CMD.
     30  */
     31 struct AttestState
     32 {
     33   /**
     34    * Label to the command which created the reserve to check,
     35    * needed to resort the reserve key.
     36    */
     37   const char *reserve_reference;
     38 
     39   /**
     40    * Handle to the "reserve attest" operation.
     41    */
     42   struct TALER_EXCHANGE_PostReservesAttestHandle *rsh;
     43 
     44   /**
     45    * Private key of the reserve being analyzed.
     46    */
     47   const struct TALER_ReservePrivateKeyP *reserve_priv;
     48 
     49   /**
     50    * Public key of the reserve being analyzed.
     51    */
     52   struct TALER_ReservePublicKeyP reserve_pub;
     53 
     54   /**
     55    * Array of attributes to request, of length @e attrs_len.
     56    */
     57   const char **attrs;
     58 
     59   /**
     60    * Length of the @e attrs array.
     61    */
     62   unsigned int attrs_len;
     63 
     64   /**
     65    * Expected HTTP response code.
     66    */
     67   unsigned int expected_response_code;
     68 
     69   /**
     70    * Interpreter state.
     71    */
     72   struct TALER_TESTING_Interpreter *is;
     73 
     74   /* FIXME: expose fields below as traits... */
     75 
     76   /**
     77    * Attested attributes returned by the exchange.
     78    */
     79   json_t *attributes;
     80 
     81   /**
     82    * Expiration time of the attested attributes.
     83    */
     84   struct GNUNET_TIME_Timestamp expiration_time;
     85 
     86   /**
     87    * Signature by the exchange affirming the attributes.
     88    */
     89   struct TALER_ExchangeSignatureP exchange_sig;
     90 
     91   /**
     92    * Online signing key used by the exchange.
     93    */
     94   struct TALER_ExchangePublicKeyP exchange_pub;
     95 };
     96 
     97 
     98 /**
     99  * Check that the reserve balance and HTTP response code are
    100  * both acceptable.
    101  *
    102  * @param cls closure.
    103  * @param rs HTTP response details
    104  */
    105 static void
    106 reserve_attest_cb (
    107   void *cls,
    108   const struct TALER_EXCHANGE_PostReservesAttestResponse *rs)
    109 {
    110   struct AttestState *ss = cls;
    111   struct TALER_TESTING_Interpreter *is = ss->is;
    112 
    113   ss->rsh = NULL;
    114   if (ss->expected_response_code != rs->hr.http_status)
    115   {
    116     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    117                 "Unexpected HTTP response code: %d in %s:%u\n",
    118                 rs->hr.http_status,
    119                 __FILE__,
    120                 __LINE__);
    121     json_dumpf (rs->hr.reply,
    122                 stderr,
    123                 JSON_INDENT (2));
    124     TALER_TESTING_interpreter_fail (ss->is);
    125     return;
    126   }
    127   if (MHD_HTTP_OK != rs->hr.http_status)
    128   {
    129     TALER_TESTING_interpreter_next (is);
    130     return;
    131   }
    132   ss->attributes = json_incref ((json_t*) rs->details.ok.attributes);
    133   ss->expiration_time = rs->details.ok.expiration_time;
    134   ss->exchange_pub = rs->details.ok.exchange_pub;
    135   ss->exchange_sig = rs->details.ok.exchange_sig;
    136   TALER_TESTING_interpreter_next (is);
    137 }
    138 
    139 
    140 /**
    141  * Run the command.
    142  *
    143  * @param cls closure.
    144  * @param cmd the command being executed.
    145  * @param is the interpreter state.
    146  */
    147 static void
    148 attest_run (void *cls,
    149             const struct TALER_TESTING_Command *cmd,
    150             struct TALER_TESTING_Interpreter *is)
    151 {
    152   struct AttestState *ss = cls;
    153   const struct TALER_TESTING_Command *create_reserve;
    154   const char *exchange_url;
    155 
    156   ss->is = is;
    157   exchange_url = TALER_TESTING_get_exchange_url (is);
    158   if (NULL == exchange_url)
    159   {
    160     GNUNET_break (0);
    161     return;
    162   }
    163   create_reserve
    164     = TALER_TESTING_interpreter_lookup_command (is,
    165                                                 ss->reserve_reference);
    166 
    167   if (NULL == create_reserve)
    168   {
    169     GNUNET_break (0);
    170     TALER_TESTING_interpreter_fail (is);
    171     return;
    172   }
    173   if (GNUNET_OK !=
    174       TALER_TESTING_get_trait_reserve_priv (create_reserve,
    175                                             &ss->reserve_priv))
    176   {
    177     GNUNET_break (0);
    178     TALER_LOG_ERROR ("Failed to find reserve_priv for attest query\n");
    179     TALER_TESTING_interpreter_fail (is);
    180     return;
    181   }
    182   GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
    183                                       &ss->reserve_pub.eddsa_pub);
    184   ss->rsh = TALER_EXCHANGE_post_reserves_attest_create (
    185     TALER_TESTING_interpreter_get_context (is),
    186     exchange_url,
    187     TALER_TESTING_get_keys (is),
    188     ss->reserve_priv,
    189     ss->attrs_len,
    190     ss->attrs);
    191   if (NULL == ss->rsh)
    192   {
    193     GNUNET_break (0);
    194     TALER_TESTING_interpreter_fail (is);
    195     return;
    196   }
    197   {
    198     enum TALER_ErrorCode ec;
    199 
    200     ec = TALER_EXCHANGE_post_reserves_attest_start (ss->rsh,
    201                                                     &reserve_attest_cb,
    202                                                     ss);
    203     if (TALER_EC_NONE != ec)
    204     {
    205       GNUNET_break (0);
    206       ss->rsh = NULL;
    207       TALER_TESTING_interpreter_fail (is);
    208       return;
    209     }
    210   }
    211 }
    212 
    213 
    214 /**
    215  * Cleanup the state from a "reserve attest" CMD, and possibly
    216  * cancel a pending operation thereof.
    217  *
    218  * @param cls closure.
    219  * @param cmd the command which is being cleaned up.
    220  */
    221 static void
    222 attest_cleanup (void *cls,
    223                 const struct TALER_TESTING_Command *cmd)
    224 {
    225   struct AttestState *ss = cls;
    226 
    227   if (NULL != ss->rsh)
    228   {
    229     TALER_TESTING_command_incomplete (ss->is,
    230                                       cmd->label);
    231     TALER_EXCHANGE_post_reserves_attest_cancel (ss->rsh);
    232     ss->rsh = NULL;
    233   }
    234   json_decref (ss->attributes);
    235   GNUNET_free (ss->attrs);
    236   GNUNET_free (ss);
    237 }
    238 
    239 
    240 struct TALER_TESTING_Command
    241 TALER_TESTING_cmd_reserve_attest (const char *label,
    242                                   const char *reserve_reference,
    243                                   unsigned int expected_response_code,
    244                                   ...)
    245 {
    246   struct AttestState *ss;
    247   unsigned int num_args;
    248   const char *ea;
    249   va_list ap;
    250 
    251   num_args = 0;
    252   va_start (ap, expected_response_code);
    253   while (NULL != va_arg (ap, const char *))
    254     num_args++;
    255   va_end (ap);
    256 
    257   GNUNET_assert (NULL != reserve_reference);
    258   ss = GNUNET_new (struct AttestState);
    259   ss->reserve_reference = reserve_reference;
    260   ss->expected_response_code = expected_response_code;
    261   ss->attrs_len = num_args;
    262   ss->attrs = GNUNET_new_array (num_args,
    263                                 const char *);
    264   num_args = 0;
    265   va_start (ap, expected_response_code);
    266   while (NULL != (ea = va_arg (ap, const char *)))
    267     ss->attrs[num_args++] = ea;
    268   va_end (ap);
    269 
    270   {
    271     struct TALER_TESTING_Command cmd = {
    272       .cls = ss,
    273       .label = label,
    274       .run = &attest_run,
    275       .cleanup = &attest_cleanup
    276     };
    277 
    278     return cmd;
    279   }
    280 }