LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_pay_order.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.6 % 390 291
Test Date: 2025-11-06 19:31:41 Functions: 100.0 % 9 9

            Line data    Source code
       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_api_cmd_pay_order.c
      21              :  * @brief command to test the /orders/ID/pay feature.
      22              :  * @author Marcello Stanisci
      23              :  * @author Christian Grothoff
      24              :  */
      25              : #include "platform.h"
      26              : #include <gnunet/gnunet_common.h>
      27              : #include <gnunet/gnunet_json_lib.h>
      28              : #include <gnunet/gnunet_time_lib.h>
      29              : #include <jansson.h>
      30              : #include <stddef.h>
      31              : #include <stdint.h>
      32              : #include <taler/taler_exchange_service.h>
      33              : #include <taler/taler_testing_lib.h>
      34              : #include <taler/taler_signatures.h>
      35              : #include "taler_merchant_service.h"
      36              : #include "taler_merchant_pay_service.h"
      37              : #include "taler_merchant_testing_lib.h"
      38              : 
      39              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
      40              : #include <donau/donau_service.h>
      41              : #include <donau/donau_testing_lib.h>
      42              : #include <donau/donau_json_lib.h>
      43              : #endif /* HAVE_DONAU_DONAU_SERVICE_H */
      44              : 
      45              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
      46              : /**
      47              :  * Struct for handling the CS approach in signing of the bkps
      48              :  */
      49              : struct CSR_Data
      50              : {
      51              :   /**
      52              :    * Handle to the "batch issue receipt status" operation.
      53              :    */
      54              :   struct DONAU_CsRBatchIssueHandle *csr_handle;
      55              : 
      56              :   /**
      57              :    * CS-Nonce
      58              :    */
      59              :   union GNUNET_CRYPTO_BlindSessionNonce nonce;
      60              : 
      61              :   /**
      62              :    * batch issue receipt status state
      63              :    */
      64              :   struct StatusState *ss;
      65              : 
      66              :   /**
      67              :    * array position in batch issue receipt request (first position is zero)
      68              :    */
      69              :   size_t position;
      70              : };
      71              : 
      72              : /**
      73              :  * Handling all data needed for the /pay DONAU CMD.
      74              :  */
      75              : struct MerchantDonauPayData
      76              : {
      77              :   /**
      78              :    * Donau URL.
      79              :    */
      80              :   const char *donau_url;
      81              : 
      82              :   /**
      83              :    * Donau keys
      84              :    */
      85              :   struct DONAU_Keys *keys;
      86              : 
      87              :   /**
      88              :    * Charity reference
      89              :    */
      90              :   const char *charity_reference;
      91              : 
      92              :   /**
      93              :    * Charity id
      94              :    */
      95              :   uint64_t charity_id;
      96              : 
      97              :   /**
      98              :    * Amount of the donation
      99              :    */
     100              :   struct TALER_Amount donation_amount;
     101              : 
     102              :   /**
     103              :    * Number of BUDIs to create or fetch. Example only.
     104              :    */
     105              :   uint32_t num_bkps;
     106              : 
     107              :   /**
     108              :    * Year of the donation
     109              :    */
     110              :   uint64_t year;
     111              : 
     112              :   /**
     113              :    * Selected donation unit pub keys for this pay order request
     114              :    */
     115              :   struct DONAU_DonationUnitPublicKey *selected_pks;
     116              : 
     117              :   /**
     118              :    * BUDI key pairs used in the payment (blinded_udi + pubkey).
     119              :    */
     120              :   struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps;
     121              : 
     122              :   /**
     123              :    * Blinding secrets, if needed for each BUDI (CS vs. RSA).
     124              :    */
     125              :   union GNUNET_CRYPTO_BlindingSecretP *blinding_secrets;
     126              : 
     127              :   /**
     128              :    * Blinding values. Cs-nonces, cipher.
     129              :    */
     130              :   const struct DONAU_BatchIssueValues **alg_values;
     131              : 
     132              :   /**
     133              :    * Hash of the salted donor tax id, if relevant.
     134              :    */
     135              :   struct DONAU_HashDonorTaxId h_donor_tax_id;
     136              : 
     137              :   /**
     138              :    * Array of donation receipts;
     139              :    */
     140              :   struct DONAU_DonationReceipt *receipts;
     141              : 
     142              :   /**
     143              :    * Array of hashed udis.
     144              :    */
     145              :   struct DONAU_UniqueDonorIdentifierHashP *h_udis;
     146              : 
     147              :   /**
     148              :    * If using the CS approach, we might track how many
     149              :    * asynchronous calls are still pending, etc.
     150              :    */
     151              :   unsigned int cs_pending;
     152              : 
     153              :   /**
     154              :    * Budis Key Pairs json
     155              :    */
     156              :   json_t *budis_json;
     157              : };
     158              : 
     159              : 
     160              : /**
     161              :  * Prepares the donau data for the /pay CMD.
     162              :  *
     163              :  * @param is interpreter state
     164              :  * @param ss donau data to prepare
     165              :  */
     166              : static enum GNUNET_GenericReturnValue
     167              : prepare_donau_data (struct TALER_TESTING_Interpreter *is,
     168              :                     struct MerchantDonauPayData *ss)
     169              : {
     170              :   /* Get charity id and the charity private key from trait */
     171              :   {
     172              :     const struct TALER_TESTING_Command *charity_post_cmd;
     173              :     const uint64_t *charity_id;
     174              : 
     175              :     charity_post_cmd = TALER_TESTING_interpreter_lookup_command (
     176              :       is,
     177              :       ss->charity_reference);
     178              : 
     179              :     if (GNUNET_OK !=
     180              :         TALER_TESTING_get_trait_charity_id (charity_post_cmd,
     181              :                                             &charity_id))
     182              :     {
     183              :       GNUNET_break (0);
     184              :       return GNUNET_SYSERR;
     185              :     }
     186              :     ss->charity_id = (uint64_t) *(charity_id);
     187              :   }
     188              : 
     189              :   /* Get donau keys from trait */
     190              :   {
     191              :     const struct TALER_TESTING_Command *keys_cmd;
     192              :     struct DONAU_Keys *keys;
     193              : 
     194              :     keys_cmd = TALER_TESTING_interpreter_get_command (is,
     195              :                                                       "donau");
     196              : 
     197              :     if (GNUNET_OK !=
     198              :         TALER_TESTING_get_trait_donau_keys (keys_cmd,
     199              :                                             &keys))
     200              :     {
     201              :       GNUNET_break (0);
     202              :       return GNUNET_SYSERR;
     203              :     }
     204              :     ss->keys = keys;
     205              :   }
     206              : 
     207              :   /* Get selected_pks + num_bkps*/
     208              :   {
     209              :     enum GNUNET_GenericReturnValue sret;
     210              : 
     211              :     sret = DONAU_select_donation_unit_keys_for_amount (
     212              :       ss->keys,
     213              :       &ss->donation_amount,
     214              :       ss->year,
     215              :       &ss->selected_pks,
     216              :       &ss->num_bkps);
     217              : 
     218              :     if (GNUNET_SYSERR == sret)
     219              :     {
     220              :       GNUNET_break (0);
     221              :       TALER_TESTING_interpreter_fail (is);
     222              :       return GNUNET_SYSERR;
     223              :     }
     224              :     if ((GNUNET_NO == sret) || (0 == ss->num_bkps))
     225              :     {
     226              :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     227              :                   "Could not compose exact amount from donation units\n");
     228              :       TALER_TESTING_interpreter_fail (is);
     229              :       return GNUNET_NO;
     230              :     }
     231              :   }
     232              : 
     233              :   /* Get BUDIsKP */
     234              :   {
     235              :     ss->bkps
     236              :       = GNUNET_new_array (ss->num_bkps,
     237              :                           struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
     238              :     ss->blinding_secrets
     239              :       = GNUNET_new_array (ss->num_bkps,
     240              :                           union GNUNET_CRYPTO_BlindingSecretP);
     241              :     ss->receipts
     242              :       = GNUNET_new_array (ss->num_bkps,
     243              :                           struct DONAU_DonationReceipt);
     244              :     ss->alg_values
     245              :       = GNUNET_new_array (ss->num_bkps,
     246              :                           const struct DONAU_BatchIssueValues *);
     247              :     ss->h_udis
     248              :       = GNUNET_new_array (ss->num_bkps,
     249              :                           struct DONAU_UniqueDonorIdentifierHashP);
     250              : 
     251              :     for (size_t cnt = 0; cnt < ss->num_bkps; cnt++)
     252              :     {
     253              :       struct DONAU_UniqueDonorIdentifierNonce *udi_nonce;
     254              :       struct DONAU_BudiMasterSecretP ps;
     255              :       const struct DONAU_BatchIssueValues *alg_values;
     256              :       struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi;
     257              :       struct DONAU_UniqueDonorIdentifierHashP *udi_hash;
     258              : 
     259              :       DONAU_donation_unit_pub_hash (&ss->selected_pks[cnt],
     260              :                                     &ss->bkps[cnt].h_donation_unit_pub);
     261              : 
     262              :       ss->receipts[cnt].h_donation_unit_pub
     263              :         = ss->bkps[cnt].h_donation_unit_pub;
     264              :       udi_nonce
     265              :         = &ss->receipts[cnt].nonce;
     266              :       blinded_udi
     267              :         = &ss->bkps[cnt].blinded_udi;
     268              :       udi_hash = &ss->h_udis[cnt];
     269              : 
     270              :       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
     271              :                                   &ps,
     272              :                                   sizeof (ps));
     273              :       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     274              :                                   udi_nonce,
     275              :                                   sizeof (*udi_nonce));
     276              :       switch (ss->selected_pks[cnt].bsign_pub_key->cipher)
     277              :       {
     278              :       case GNUNET_CRYPTO_BSA_RSA:
     279              :         alg_values = DONAU_donation_unit_ewv_rsa_singleton ();
     280              :         DONAU_budi_secret_create (&ps,
     281              :                                   alg_values,
     282              :                                   &ss->blinding_secrets[cnt]);
     283              :         GNUNET_assert (GNUNET_OK ==
     284              :                        DONAU_donation_unit_blind (
     285              :                          &ss->selected_pks[cnt],
     286              :                          &ss->blinding_secrets[cnt],
     287              :                          NULL,                    /* no cs-nonce needed for rsa */
     288              :                          udi_nonce,
     289              :                          &ss->h_donor_tax_id,
     290              :                          alg_values,
     291              :                          udi_hash,
     292              :                          blinded_udi));
     293              :         ss->alg_values[cnt] = alg_values;
     294              :         break;
     295              :       case GNUNET_CRYPTO_BSA_CS:
     296              :         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     297              :                     "CS donation-unit key not yet supported – skip");
     298              :         return GNUNET_NO;
     299              :         /* FIXME: BUG-#### Cs support missing/broken for donau
     300              :         struct CSR_Data *csr_data = GNUNET_new (struct CSR_Data);
     301              :         TALER_cs_withdraw_nonce_derive ( // FIXME: write new method
     302              :           (struct TALER_PlanchetMasterSecretP *) &ps,
     303              :           &csr_data->nonce.cs_nonce);
     304              :         csr_data->ss = is;
     305              :         csr_data->position = cnt;
     306              : 
     307              :         csr_data->csr_handle = DONAU_csr_issue (
     308              :           TALER_TESTING_interpreter_get_context (is),
     309              :           TALER_TESTING_get_donau_url (is),
     310              :           &ss->selected_pks[cnt],
     311              :           &csr_data->nonce.cs_nonce,
     312              :           &cs_stage_two_callback,
     313              :           csr_data);
     314              :         if (NULL == csr_data->csr_handle)
     315              :         {
     316              :           GNUNET_break (0);
     317              :         }
     318              :         ss->cs_pending++; */
     319              :         break;
     320              :       default:
     321              :         GNUNET_break (0);
     322              :       }
     323              :     }
     324              : 
     325              :     {
     326              :       json_t *budikeypairs = json_array ();
     327              : 
     328              :       GNUNET_assert (NULL != budikeypairs);
     329              :       for (size_t i = 0; i < ss->num_bkps; i++)
     330              :       {
     331              :         json_t *budikeypair = GNUNET_JSON_PACK (
     332              :           GNUNET_JSON_pack_data_auto ("h_donation_unit_pub",
     333              :                                       &ss->bkps[i].h_donation_unit_pub),
     334              :           DONAU_JSON_pack_blinded_donation_identifier ("blinded_udi",
     335              :                                                        &ss->bkps[i].blinded_udi)
     336              :           );
     337              : 
     338              :         /* steal the reference into the array */
     339              :         GNUNET_assert (0 == json_array_append_new (budikeypairs,
     340              :                                                    budikeypair));
     341              :       }
     342              :       ss->budis_json = budikeypairs;
     343              :     }
     344              :   }
     345              :   return GNUNET_OK;
     346              : };
     347              : #endif /* HAVE_DONAU_DONAU_SERVICE_H */
     348              : 
     349              : /**
     350              :  * State for a /pay CMD.
     351              :  */
     352              : struct PayState
     353              : {
     354              :   /**
     355              :    * Contract terms hash code.
     356              :    */
     357              :   struct TALER_PrivateContractHashP h_contract_terms;
     358              : 
     359              :   /**
     360              :    * The interpreter state.
     361              :    */
     362              :   struct TALER_TESTING_Interpreter *is;
     363              : 
     364              :   /**
     365              :    * Expected HTTP response status code.
     366              :    */
     367              :   unsigned int http_status;
     368              : 
     369              :   /**
     370              :    * Reference to a command that can provide a order id,
     371              :    * typically a /proposal test command.
     372              :    */
     373              :   const char *proposal_reference;
     374              : 
     375              :   /**
     376              :    * Reference to a command that can provide a coin, so
     377              :    * we can pay here.
     378              :    */
     379              :   const char *coin_reference;
     380              : 
     381              :   /**
     382              :    * Reference to a command that can provide one or
     383              :    * multiple tokens used as inputs for the payment.
     384              :    * In the form "LABEL0[/INDEX];LABEL1[/INDEX];..."
     385              :    */
     386              :   const char *token_reference;
     387              : 
     388              :   /**
     389              :    * The merchant base URL.
     390              :    */
     391              :   const char *merchant_url;
     392              : 
     393              :   /**
     394              :    * Total amount to be paid.
     395              :    */
     396              :   struct TALER_Amount total_amount;
     397              : 
     398              :   /**
     399              :    * Amount to be paid, plus the deposit fee.
     400              :    */
     401              :   const char *amount_with_fee;
     402              : 
     403              :   /**
     404              :    * Amount to be paid, including NO fees.
     405              :    */
     406              :   const char *amount_without_fee;
     407              : 
     408              :   /**
     409              :    * Handle to the pay operation.
     410              :    */
     411              :   struct TALER_MERCHANT_OrderPayHandle *oph;
     412              : 
     413              :   /**
     414              :    * Signature from the merchant, set on success.
     415              :    */
     416              :   struct TALER_MerchantSignatureP merchant_sig;
     417              : 
     418              :   /**
     419              :    * Array of issued tokens, set on success.
     420              :    */
     421              :   struct TALER_MERCHANT_PrivateTokenDetails *issued_tokens;
     422              : 
     423              :   /**
     424              :    * Number of tokens in @e issued_tokens.
     425              :    */
     426              :   unsigned int num_issued_tokens;
     427              : 
     428              :   /**
     429              :    * Number of donau_tokens in @e issued_tokens.
     430              :    */
     431              :   unsigned int num_donau_tokens;
     432              : 
     433              :   /**
     434              :    * The session for which the payment is made.
     435              :    */
     436              :   const char *session_id;
     437              : 
     438              :   /**
     439              :    * base64-encoded key
     440              :    */
     441              :   const char *pos_key;
     442              : 
     443              :   /**
     444              :    * Option that add amount of the order
     445              :    */
     446              :   enum TALER_MerchantConfirmationAlgorithm pos_alg;
     447              : 
     448              :   /**
     449              :    * Index of the choice to be used in the payment. -1 for orders without choices.
     450              :    */
     451              :   int choice_index;
     452              : 
     453              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
     454              :   /**
     455              :    * Donau data, if required.
     456              :    */
     457              :   struct MerchantDonauPayData donau_data;
     458              : #endif /* HAVE_DONAU_DONAU_SERVICE_H */
     459              : };
     460              : 
     461              : 
     462              : /**
     463              :  * Find the token issue public key for a given token family @a slug and
     464              :  * @a valid_after timestamp.
     465              :  *
     466              :  * @param token_families json object of token families where the key is the slug
     467              :  * @param slug the slug of the token family
     468              :  * @param key_index index of the key within the token family
     469              :  * @param[out] pub the token issue public key of the token family
     470              :  * @return #GNUNET_OK on success and #GNUNET_SYSERR if not found
     471              :  */
     472              : static enum GNUNET_GenericReturnValue
     473            6 : find_token_public_key (const json_t *token_families,
     474              :                        const char *slug,
     475              :                        unsigned int key_index,
     476              :                        struct TALER_TokenIssuePublicKey *pub)
     477              : 
     478              : {
     479            6 :   const json_t *tf = json_object_get (token_families, slug);
     480              :   const json_t *keys;
     481              :   struct GNUNET_JSON_Specification spec[] = {
     482            6 :     GNUNET_JSON_spec_array_const ("keys",
     483              :                                   &keys),
     484            6 :     GNUNET_JSON_spec_end ()
     485              :   };
     486              :   const json_t *key;
     487              :   const char *error_name;
     488              :   unsigned int error_line;
     489              :   struct GNUNET_JSON_Specification ispec[] = {
     490            6 :     TALER_JSON_spec_token_pub (NULL,
     491              :                                pub),
     492            6 :     GNUNET_JSON_spec_end ()
     493              :   };
     494              : 
     495            6 :   if (NULL == tf)
     496              :   {
     497            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     498              :                 "Token family `%s' not found\n",
     499              :                 slug);
     500            0 :     return GNUNET_SYSERR;
     501              :   }
     502            6 :   if (GNUNET_OK !=
     503            6 :       GNUNET_JSON_parse (tf,
     504              :                          spec,
     505              :                          NULL,
     506              :                          NULL))
     507              :   {
     508            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     509              :                 "Failed to parse token family `%s'\n",
     510              :                 slug);
     511            0 :     return GNUNET_SYSERR;
     512              :   }
     513              : 
     514            6 :   key = json_array_get (keys,
     515              :                         key_index);
     516            6 :   if (NULL == key)
     517              :   {
     518            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     519              :                 "Key with index %u for token family '%s' not found\n",
     520              :                 key_index,
     521              :                 slug);
     522            0 :     return GNUNET_SYSERR;
     523              :   }
     524            6 :   if (GNUNET_OK !=
     525            6 :       GNUNET_JSON_parse (key,
     526              :                          ispec,
     527              :                          &error_name,
     528              :                          &error_line))
     529              :   {
     530            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     531              :                 "Failed to parse %s at %u: %s\n",
     532              :                 ispec[error_line].field,
     533              :                 error_line,
     534              :                 error_name);
     535            0 :     return GNUNET_SYSERR;
     536              :   }
     537            6 :   return GNUNET_OK;
     538              : }
     539              : 
     540              : 
     541              : /**
     542              :  * Parse the @a coins specification and grow the @a pc
     543              :  * array with the coins found, updating @a npc.
     544              :  *
     545              :  * @param[in,out] pc pointer to array of coins found
     546              :  * @param[in,out] npc length of array at @a pc
     547              :  * @param[in] coins string specifying coins to add to @a pc,
     548              :  *            clobbered in the process
     549              :  * @param is interpreter state
     550              :  * @param amount_with_fee total amount to be paid for a contract.
     551              :  * @param amount_without_fee to be removed, there is no
     552              :  *        per-contract fee, only per-coin exists.
     553              :  * @return #GNUNET_OK on success
     554              :  */
     555              : static enum GNUNET_GenericReturnValue
     556           35 : build_coins (struct TALER_MERCHANT_PayCoin **pc,
     557              :              unsigned int *npc,
     558              :              char *coins,
     559              :              struct TALER_TESTING_Interpreter *is,
     560              :              const char *amount_with_fee,
     561              :              const char *amount_without_fee)
     562              : {
     563              :   char *token;
     564              :   struct TALER_EXCHANGE_Keys *keys;
     565              : 
     566           35 :   keys = TALER_TESTING_get_keys (is);
     567           35 :   if (NULL == keys)
     568              :   {
     569            0 :     GNUNET_break (0);
     570            0 :     return GNUNET_SYSERR;
     571              :   }
     572              : 
     573           35 :   for (token = strtok (coins, ";");
     574           76 :        NULL != token;
     575           41 :        token = strtok (NULL, ";"))
     576              :   {
     577              :     const struct TALER_TESTING_Command *coin_cmd;
     578              :     char *ctok;
     579              :     unsigned int ci;
     580              :     struct TALER_MERCHANT_PayCoin *icoin;
     581              :     const struct TALER_EXCHANGE_DenomPublicKey *dpk;
     582              :     const char *exchange_url;
     583              : 
     584              :     /* Token syntax is "LABEL[/NUMBER]" */
     585           41 :     ctok = strchr (token, '/');
     586              :     /* FIXME: Check why ci variable is parsed but not used? */
     587           41 :     ci = 0;
     588           41 :     if (NULL != ctok)
     589              :     {
     590            0 :       *ctok = '\0';
     591            0 :       ctok++;
     592            0 :       if (1 != sscanf (ctok,
     593              :                        "%u",
     594              :                        &ci))
     595              :       {
     596            0 :         GNUNET_break (0);
     597            0 :         return GNUNET_SYSERR;
     598              :       }
     599              :     }
     600              : 
     601           41 :     coin_cmd = TALER_TESTING_interpreter_lookup_command
     602              :                  (is, token);
     603              : 
     604           41 :     if (NULL == coin_cmd)
     605              :     {
     606            0 :       GNUNET_break (0);
     607            0 :       return GNUNET_SYSERR;
     608              :     }
     609              : 
     610           41 :     GNUNET_array_grow (*pc,
     611              :                        *npc,
     612              :                        (*npc) + 1);
     613              : 
     614           41 :     icoin = &((*pc)[(*npc) - 1]);
     615              : 
     616              :     {
     617              :       const struct TALER_CoinSpendPrivateKeyP *coin_priv;
     618              :       const struct TALER_DenominationSignature *denom_sig;
     619              :       const struct TALER_Amount *denom_value;
     620              :       const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
     621              :       const struct TALER_AgeCommitmentHashP *h_age_commitment;
     622              : 
     623           41 :       GNUNET_assert (GNUNET_OK ==
     624              :                      TALER_TESTING_get_trait_coin_priv (coin_cmd,
     625              :                                                         0,
     626              :                                                         &coin_priv));
     627           41 :       GNUNET_assert (GNUNET_OK ==
     628              :                      TALER_TESTING_get_trait_denom_pub (coin_cmd,
     629              :                                                         0,
     630              :                                                         &denom_pub));
     631           41 :       GNUNET_assert (GNUNET_OK ==
     632              :                      TALER_TESTING_get_trait_denom_sig (coin_cmd,
     633              :                                                         0,
     634              :                                                         &denom_sig));
     635           41 :       GNUNET_assert (GNUNET_OK ==
     636              :                      TALER_TESTING_get_trait_amount (coin_cmd,
     637              :                                                      &denom_value));
     638           41 :       GNUNET_assert (GNUNET_OK ==
     639              :                      TALER_TESTING_get_trait_h_age_commitment (coin_cmd,
     640              :                                                                0,
     641              :                                                                &h_age_commitment
     642              :                                                                ));
     643           41 :       icoin->coin_priv = *coin_priv;
     644           41 :       icoin->denom_pub = denom_pub->key;
     645           41 :       icoin->denom_sig = *denom_sig;
     646           41 :       icoin->denom_value = *denom_value;
     647           41 :       icoin->amount_with_fee = *denom_value;
     648           41 :       icoin->h_age_commitment = h_age_commitment;
     649              :     }
     650           41 :     GNUNET_assert (NULL != (dpk =
     651              :                               TALER_TESTING_find_pk (keys,
     652              :                                                      &icoin->denom_value,
     653              :                                                      false)));
     654              : 
     655           41 :     GNUNET_assert (0 <=
     656              :                    TALER_amount_subtract (&icoin->amount_without_fee,
     657              :                                           &icoin->denom_value,
     658              :                                           &dpk->fees.deposit));
     659           41 :     GNUNET_assert (GNUNET_OK ==
     660              :                    TALER_TESTING_get_trait_exchange_url (coin_cmd,
     661              :                                                          &exchange_url));
     662           41 :     icoin->exchange_url = exchange_url;
     663              :   }
     664              : 
     665           35 :   return GNUNET_OK;
     666              : }
     667              : 
     668              : 
     669              : /**
     670              :  * Parse the @a pay_references specification and grow the @a tokens
     671              :  * array with the tokens found, updating @a tokens_num.
     672              :  *
     673              :  * @param[in,out] tokens array of tokens found
     674              :  * @param[in,out] tokens_num length of @a tokens array
     675              :  * @param[in] pay_references string of ; separated references to pay commands
     676              :               that issued the tokens.
     677              :  * @param is interpreter state
     678              :  * @return #GNUNET_OK on success
     679              :  */
     680              : static enum GNUNET_GenericReturnValue
     681            4 : build_tokens (struct TALER_MERCHANT_UseToken **tokens,
     682              :               unsigned int *tokens_num,
     683              :               char *pay_references,
     684              :               struct TALER_TESTING_Interpreter *is)
     685              : {
     686              :   char *ref;
     687              : 
     688            4 :   for (ref = strtok (pay_references, ";");
     689            8 :        NULL != ref;
     690            4 :        ref = strtok (NULL, ";"))
     691              :   {
     692              :     const struct TALER_TESTING_Command *pay_cmd;
     693              :     char *slash;
     694              :     unsigned int index;
     695              :     struct TALER_MERCHANT_UseToken *token;
     696              : 
     697              :     /* Reference syntax is "LABEL[/NUMBER]" */
     698            4 :     slash = strchr (ref, '/');
     699            4 :     index = 0;
     700            4 :     if (NULL != slash)
     701              :     {
     702            0 :       *slash = '\0';
     703            0 :       slash++;
     704            0 :       if (1 != sscanf (slash,
     705              :                        "%u",
     706              :                        &index))
     707              :       {
     708            0 :         GNUNET_break (0);
     709            0 :         return GNUNET_SYSERR;
     710              :       }
     711              :     }
     712              : 
     713            4 :     pay_cmd = TALER_TESTING_interpreter_lookup_command (is, ref);
     714              : 
     715            4 :     if (NULL == pay_cmd)
     716              :     {
     717            0 :       GNUNET_break (0);
     718            0 :       return GNUNET_SYSERR;
     719              :     }
     720              : 
     721            4 :     GNUNET_array_grow (*tokens,
     722              :                        *tokens_num,
     723              :                        (*tokens_num) + 1);
     724              : 
     725            4 :     token = &((*tokens)[(*tokens_num) - 1]);
     726              : 
     727              :     {
     728              :       const struct TALER_TokenUsePrivateKeyP *token_priv;
     729              :       const struct TALER_TokenIssueSignature *issue_sig;
     730              :       const struct TALER_TokenIssuePublicKey *issue_pub;
     731              : 
     732            4 :       GNUNET_assert (GNUNET_OK ==
     733              :                      TALER_TESTING_get_trait_token_priv (pay_cmd,
     734              :                                                          index,
     735              :                                                          &token_priv));
     736              : 
     737            4 :       GNUNET_assert (GNUNET_OK ==
     738              :                      TALER_TESTING_get_trait_token_issue_sig (pay_cmd,
     739              :                                                               index,
     740              :                                                               &issue_sig));
     741              : 
     742            4 :       GNUNET_assert (GNUNET_OK ==
     743              :                      TALER_TESTING_get_trait_token_issue_pub (pay_cmd,
     744              :                                                               index,
     745              :                                                               &issue_pub));
     746              : 
     747            4 :       token->token_priv = *token_priv;
     748            4 :       token->ub_sig = *issue_sig;
     749            4 :       token->issue_pub = *issue_pub;
     750              :     }
     751              :   }
     752              : 
     753            4 :   return GNUNET_OK;
     754              : }
     755              : 
     756              : 
     757              : /**
     758              :  * Function called with the result of a /pay operation.
     759              :  * Checks whether the merchant signature is valid and the
     760              :  * HTTP response code matches our expectation.
     761              :  *
     762              :  * @param cls closure with the interpreter state
     763              :  * @param pr HTTP response
     764              :  */
     765              : static void
     766           35 : pay_cb (void *cls,
     767              :         const struct TALER_MERCHANT_PayResponse *pr)
     768              : {
     769           35 :   struct PayState *ps = cls;
     770              : 
     771           35 :   ps->oph = NULL;
     772           35 :   if (ps->http_status != pr->hr.http_status)
     773              :   {
     774            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     775              :                 "Unexpected response code %u (%d) to command (%s) %s\n",
     776              :                 pr->hr.http_status,
     777              :                 (int) pr->hr.ec,
     778              :                 pr->hr.hint,
     779              :                 TALER_TESTING_interpreter_get_current_label (ps->is));
     780            0 :     TALER_TESTING_FAIL (ps->is);
     781              :   }
     782           35 :   if (MHD_HTTP_OK == pr->hr.http_status)
     783              :   {
     784           23 :     ps->merchant_sig = pr->details.ok.merchant_sig;
     785           23 :     if (ps->num_issued_tokens + ps->num_donau_tokens !=
     786           23 :         pr->details.ok.num_tokens)
     787              :     {
     788            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     789              :                   "Unexpected number of tokens issued. "
     790              :                   "Sent %d envelopes but got %d tokens issued.\n",
     791              :                   ps->num_issued_tokens,
     792              :                   pr->details.ok.num_tokens);
     793            0 :       GNUNET_break (0);
     794            0 :       TALER_TESTING_interpreter_fail (ps->is);
     795            0 :       return;
     796              :     }
     797           27 :     for (unsigned int i = 0; i < ps->num_issued_tokens; i++)
     798              :     {
     799            4 :       struct TALER_MERCHANT_PrivateTokenDetails *details =
     800            4 :         &ps->issued_tokens[i];
     801              : 
     802              :       /* The issued tokens should be in the
     803              :          same order as the provided envelopes. */
     804            4 :       ps->issued_tokens[i].blinded_sig = pr->details.ok.tokens[i].blinded_sig;
     805              : 
     806            4 :       if (GNUNET_OK !=
     807            4 :           TALER_token_issue_sig_unblind (&details->issue_sig,
     808            4 :                                          &details->blinded_sig,
     809            4 :                                          &details->blinding_secret,
     810            4 :                                          &details->h_token_pub,
     811            4 :                                          &details->blinding_inputs,
     812            4 :                                          &details->issue_pub))
     813              :       {
     814            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     815              :                     "Failed to unblind token signature\n");
     816            0 :         GNUNET_break (0);
     817            0 :         TALER_TESTING_interpreter_fail (ps->is);
     818            0 :         return;
     819              :       }
     820              :     }
     821           23 :     if (NULL != ps->pos_key)
     822              :     {
     823              :       char *pc;
     824            2 :       bool found = false;
     825              : 
     826            2 :       if (NULL == pr->details.ok.pos_confirmation)
     827              :       {
     828            0 :         GNUNET_break (0);
     829            0 :         TALER_TESTING_interpreter_fail (ps->is);
     830            0 :         return;
     831              :       }
     832            2 :       pc = TALER_build_pos_confirmation (ps->pos_key,
     833              :                                          ps->pos_alg,
     834            2 :                                          &ps->total_amount,
     835              :                                          GNUNET_TIME_timestamp_get ());
     836              :       /* Check if *any* of our TOTP codes overlaps
     837              :          with any of the returned TOTP codes. */
     838            2 :       for (const char *tok = strtok (pc, "\n");
     839            2 :            NULL != tok;
     840            0 :            tok = strtok (NULL, "\n"))
     841              :       {
     842            2 :         if (NULL != strstr (pr->details.ok.pos_confirmation,
     843              :                             tok))
     844              :         {
     845            2 :           found = true;
     846            2 :           break;
     847              :         }
     848              :       }
     849            2 :       GNUNET_free (pc);
     850            2 :       if (! found)
     851              :       {
     852            0 :         GNUNET_break (0);
     853            0 :         TALER_TESTING_interpreter_fail (ps->is);
     854            0 :         return;
     855              :       }
     856              :     }
     857              :   }
     858           35 :   TALER_TESTING_interpreter_next (ps->is);
     859              : }
     860              : 
     861              : 
     862              : /**
     863              :  * Run a "pay" CMD.
     864              :  *
     865              :  * @param cls closure.
     866              :  * @param cmd current CMD being run.
     867              :  * @param is interpreter state.
     868              :  */
     869              : static void
     870           35 : pay_run (void *cls,
     871              :          const struct TALER_TESTING_Command *cmd,
     872              :          struct TALER_TESTING_Interpreter *is)
     873              : {
     874           35 :   struct PayState *ps = cls;
     875              :   const struct TALER_TESTING_Command *proposal_cmd;
     876              :   const json_t *contract_terms;
     877              :   const char *order_id;
     878              :   struct GNUNET_TIME_Timestamp refund_deadline;
     879              :   struct GNUNET_TIME_Timestamp pay_deadline;
     880              :   struct GNUNET_TIME_Timestamp timestamp;
     881              :   struct TALER_MerchantPublicKeyP merchant_pub;
     882              :   struct TALER_MerchantWireHashP h_wire;
     883              :   const struct TALER_PrivateContractHashP *h_proposal;
     884              :   struct TALER_Amount max_fee;
     885           35 :   const char *error_name = NULL;
     886           35 :   unsigned int error_line = 0;
     887              :   struct TALER_MERCHANT_PayCoin *pay_coins;
     888              :   unsigned int npay_coins;
     889           35 :   struct TALER_MERCHANT_UseToken *use_tokens = NULL;
     890           35 :   unsigned int len_use_tokens = 0;
     891           35 :   struct TALER_MERCHANT_OutputToken *output_tokens = NULL;
     892           35 :   unsigned int len_output_tokens = 0;
     893              :   const struct TALER_MerchantSignatureP *merchant_sig;
     894              :   const enum TALER_MerchantConfirmationAlgorithm *alg_ptr;
     895              : 
     896           35 :   ps->is = is;
     897           35 :   proposal_cmd = TALER_TESTING_interpreter_lookup_command (
     898              :     is,
     899              :     ps->proposal_reference);
     900              : 
     901           35 :   if (NULL == proposal_cmd)
     902            0 :     TALER_TESTING_FAIL (is);
     903              : 
     904           35 :   if (GNUNET_OK !=
     905           35 :       TALER_TESTING_get_trait_contract_terms (proposal_cmd,
     906              :                                               &contract_terms))
     907            0 :     TALER_TESTING_FAIL (is);
     908           35 :   if (NULL == contract_terms)
     909            0 :     TALER_TESTING_FAIL (is);
     910           35 :   if (GNUNET_OK !=
     911           35 :       TALER_TESTING_get_trait_otp_key (proposal_cmd,
     912              :                                        &ps->pos_key))
     913           31 :     ps->pos_key = NULL;
     914           35 :   if ( (GNUNET_OK ==
     915           35 :         TALER_TESTING_get_trait_otp_alg (proposal_cmd,
     916            4 :                                          &alg_ptr)) &&
     917            4 :        (NULL != alg_ptr) )
     918            2 :     ps->pos_alg = *alg_ptr;
     919              :   {
     920              :     /* Get information that needs to be put verbatim in the
     921              :      * deposit permission */
     922           35 :     uint64_t version = 0;
     923              :     struct GNUNET_JSON_Specification spec[] = {
     924           35 :       GNUNET_JSON_spec_mark_optional (
     925              :         GNUNET_JSON_spec_uint64 ("version",
     926              :                                  &version),
     927              :         NULL),
     928           35 :       GNUNET_JSON_spec_string ("order_id",
     929              :                                &order_id),
     930           35 :       GNUNET_JSON_spec_timestamp ("refund_deadline",
     931              :                                   &refund_deadline),
     932           35 :       GNUNET_JSON_spec_timestamp ("pay_deadline",
     933              :                                   &pay_deadline),
     934           35 :       GNUNET_JSON_spec_timestamp ("timestamp",
     935              :                                   &timestamp),
     936           35 :       GNUNET_JSON_spec_fixed_auto ("merchant_pub",
     937              :                                    &merchant_pub),
     938           35 :       GNUNET_JSON_spec_fixed_auto ("h_wire",
     939              :                                    &h_wire),
     940              :       /* FIXME oec: parse minimum age, use data later? */
     941           35 :       GNUNET_JSON_spec_end ()
     942              :     };
     943              : 
     944           35 :     if (GNUNET_OK !=
     945           35 :         GNUNET_JSON_parse (contract_terms,
     946              :                            spec,
     947              :                            &error_name,
     948              :                            &error_line))
     949              :     {
     950              :       char *js;
     951              : 
     952            0 :       js = json_dumps (contract_terms,
     953              :                        JSON_INDENT (1));
     954            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     955              :                   "Parser failed on %s:%u for input `%s'\n",
     956              :                   error_name,
     957              :                   error_line,
     958              :                   js);
     959            0 :       free (js);
     960            0 :       TALER_TESTING_FAIL (is);
     961              :     }
     962           35 :     switch (version)
     963              :     {
     964           29 :     case 0:
     965              :       {
     966              :         struct GNUNET_JSON_Specification v0spec[] = {
     967           29 :           TALER_JSON_spec_amount_any ("amount",
     968              :                                       &ps->total_amount),
     969           29 :           TALER_JSON_spec_amount_any ("max_fee",
     970              :                                       &max_fee),
     971           29 :           GNUNET_JSON_spec_end ()
     972              :         };
     973              : 
     974           29 :         if (GNUNET_OK !=
     975           29 :             GNUNET_JSON_parse (contract_terms,
     976              :                                v0spec,
     977              :                                &error_name,
     978              :                                &error_line))
     979              :         {
     980              :           char *js;
     981              : 
     982            0 :           js = json_dumps (contract_terms,
     983              :                            JSON_INDENT (1));
     984            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     985              :                       "Parser failed on %s:%u for input `%s'\n",
     986              :                       error_name,
     987              :                       error_line,
     988              :                       js);
     989            0 :           free (js);
     990            0 :           TALER_TESTING_FAIL (is);
     991              :         }
     992              :       }
     993           29 :       if (0 < ps->choice_index)
     994            0 :         TALER_TESTING_FAIL (is);
     995           29 :       break;
     996            6 :     case 1:
     997              :       {
     998              :         const json_t *choices;
     999              :         const json_t *token_families;
    1000              :         struct GNUNET_JSON_Specification v1spec[] = {
    1001            6 :           GNUNET_JSON_spec_object_const ("token_families",
    1002              :                                          &token_families),
    1003            6 :           GNUNET_JSON_spec_array_const ("choices",
    1004              :                                         &choices),
    1005            6 :           GNUNET_JSON_spec_end ()
    1006              :         };
    1007              :         const json_t *outputs;
    1008              :         json_t *output;
    1009              :         unsigned int output_index;
    1010              :         const json_t *choice;
    1011              : 
    1012            6 :         if (GNUNET_OK !=
    1013            6 :             GNUNET_JSON_parse (contract_terms,
    1014              :                                v1spec,
    1015              :                                &error_name,
    1016              :                                &error_line))
    1017              :         {
    1018              :           char *js;
    1019              : 
    1020            0 :           js = json_dumps (contract_terms,
    1021              :                            JSON_INDENT (1));
    1022            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1023              :                       "Parser failed on %s:%u for input `%s'\n",
    1024              :                       error_name,
    1025              :                       error_line,
    1026              :                       js);
    1027            0 :           free (js);
    1028            0 :           TALER_TESTING_FAIL (is);
    1029              :         }
    1030              : 
    1031            6 :         choice = json_array_get (choices,
    1032            6 :                                  ps->choice_index);
    1033            6 :         if (NULL == choice)
    1034              :         {
    1035            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1036              :                       "No choice found at index %d\n",
    1037              :                       ps->choice_index);
    1038            0 :           TALER_TESTING_FAIL (is);
    1039              :         }
    1040              : 
    1041              :         {
    1042            6 :           const char *ierror_name = NULL;
    1043            6 :           unsigned int ierror_line = 0;
    1044              : 
    1045              :           struct GNUNET_JSON_Specification ispec[] = {
    1046            6 :             TALER_JSON_spec_amount_any ("amount",
    1047              :                                         &ps->total_amount),
    1048            6 :             TALER_JSON_spec_amount_any ("max_fee",
    1049              :                                         &max_fee),
    1050            6 :             GNUNET_JSON_spec_array_const ("outputs",
    1051              :                                           &outputs),
    1052            6 :             GNUNET_JSON_spec_end ()
    1053              :           };
    1054              : 
    1055            6 :           if (GNUNET_OK !=
    1056            6 :               GNUNET_JSON_parse (choice,
    1057              :                                  ispec,
    1058              :                                  &ierror_name,
    1059              :                                  &ierror_line))
    1060              :           {
    1061            0 :             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1062              :                         "Parser failed on %s:%u for input `%s'\n",
    1063              :                         ierror_name,
    1064              :                         ierror_line,
    1065              :                         json_dumps (choice,
    1066              :                                     JSON_INDENT (2)));
    1067            0 :             TALER_TESTING_FAIL (is);
    1068              :           }
    1069              :         }
    1070              : 
    1071           12 :         json_array_foreach (outputs, output_index, output)
    1072              :         {
    1073              :           const char *slug;
    1074              :           const char *kind;
    1075              :           uint32_t key_index;
    1076            6 :           uint32_t count = 1;
    1077            6 :           const char *ierror_name = NULL;
    1078            6 :           unsigned int ierror_line = 0;
    1079              : 
    1080              :           struct GNUNET_JSON_Specification typespec[] = {
    1081            6 :             GNUNET_JSON_spec_string ("type",
    1082              :                                      &kind),
    1083            6 :             GNUNET_JSON_spec_end ()
    1084              :           };
    1085              : 
    1086            6 :           if (GNUNET_OK !=
    1087            6 :               GNUNET_JSON_parse (output,
    1088              :                                  typespec,
    1089              :                                  &ierror_name,
    1090              :                                  &ierror_line))
    1091              :           {
    1092            0 :             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1093              :                         "Parser failed on %s:%u for input `%s'\n",
    1094              :                         ierror_name,
    1095              :                         ierror_line,
    1096              :                         json_dumps (output,
    1097              :                                     JSON_INDENT (2)));
    1098            0 :             TALER_TESTING_FAIL (is);
    1099              :           }
    1100              : 
    1101            6 :           if (0 == strcmp ("tax-receipt",
    1102              :                            kind))
    1103              :           {
    1104              :             const json_t *donau_urls;
    1105              : 
    1106              :             // For test, we care only about the presence of it
    1107              :             struct GNUNET_JSON_Specification donauspec[] = {
    1108            0 :               GNUNET_JSON_spec_array_const ("donau_urls",
    1109              :                                             &donau_urls),
    1110            0 :               GNUNET_JSON_spec_end ()
    1111              :             };
    1112              : 
    1113            0 :             if (GNUNET_OK !=
    1114            0 :                 GNUNET_JSON_parse (output,
    1115              :                                    donauspec,
    1116              :                                    &ierror_name,
    1117              :                                    &ierror_line))
    1118              :             {
    1119            0 :               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1120              :                           "Parser failed on %s:%u for input `%s'\n",
    1121              :                           ierror_name,
    1122              :                           ierror_line,
    1123              :                           json_dumps (output,
    1124              :                                       JSON_INDENT (2)));
    1125            0 :               TALER_TESTING_FAIL (is);
    1126              :             }
    1127              : 
    1128              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
    1129              :             {
    1130              :               const char   *donau_url_str;
    1131              : 
    1132              :               if ( (NULL == donau_urls) ||
    1133              :                    (0 == json_array_size (donau_urls)) )
    1134              :               {
    1135              :                 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1136              :                             "No donau_urls found in output\n");
    1137              :                 TALER_TESTING_FAIL (is);
    1138              :               }
    1139              : 
    1140              :               donau_url_str = json_string_value (json_array_get (donau_urls,
    1141              :                                                                  0));
    1142              :               if (NULL == donau_url_str)
    1143              :               {
    1144              :                 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1145              :                             "First entry in donau_urls is not a string\n");
    1146              :                 TALER_TESTING_FAIL (is);
    1147              :               }
    1148              : 
    1149              :               ps->donau_data.donau_url = GNUNET_strdup (donau_url_str);
    1150              : 
    1151              :               if (NULL != ps->donau_data.charity_reference)
    1152              :               {
    1153              :                 switch (prepare_donau_data (is,
    1154              :                                             &ps->donau_data))
    1155              :                 {
    1156              :                 case GNUNET_OK:
    1157              :                   break;
    1158              :                 case GNUNET_NO:
    1159              :                   TALER_TESTING_interpreter_next (ps->is);
    1160              :                   return;
    1161              :                 case GNUNET_SYSERR:
    1162              :                   TALER_TESTING_FAIL (is);
    1163              :                   return;
    1164              :                 }
    1165              :                 ps->num_donau_tokens = ps->donau_data.num_bkps;
    1166              :               }
    1167              :             }
    1168              : #else /* HAVE_DONAU_DONAU_SERVICE_H */
    1169              :             /* SIMPLY NOTHING */
    1170              : #endif /* HAVE_DONAU_DONAU_SERVICE_H */
    1171              :           }
    1172              : 
    1173            6 :           if (0 == strcmp ("token",
    1174              :                            kind))
    1175              :           {
    1176              :             struct GNUNET_JSON_Specification ispec[] = {
    1177            6 :               GNUNET_JSON_spec_string ("token_family_slug",
    1178              :                                        &slug),
    1179            6 :               GNUNET_JSON_spec_uint32 ("key_index",
    1180              :                                        &key_index),
    1181            6 :               GNUNET_JSON_spec_mark_optional (
    1182              :                 GNUNET_JSON_spec_uint32 ("count",
    1183              :                                          &count),
    1184              :                 NULL),
    1185            6 :               GNUNET_JSON_spec_end ()
    1186              :             };
    1187              : 
    1188            6 :             if (GNUNET_OK !=
    1189            6 :                 GNUNET_JSON_parse (output,
    1190              :                                    ispec,
    1191              :                                    &ierror_name,
    1192              :                                    &ierror_line))
    1193              :             {
    1194            0 :               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1195              :                           "Parser failed on %s:%u for input `%s'\n",
    1196              :                           ierror_name,
    1197              :                           ierror_line,
    1198              :                           json_dumps (output,
    1199              :                                       JSON_INDENT (2)));
    1200            0 :               TALER_TESTING_FAIL (is);
    1201              :             }
    1202              : 
    1203            6 :             if (0 != strcmp ("token",
    1204              :                              kind))
    1205              :             {
    1206            0 :               continue;
    1207              :             }
    1208              : 
    1209            6 :             GNUNET_array_grow (
    1210              :               ps->issued_tokens,
    1211              :               ps->num_issued_tokens,
    1212              :               ps->num_issued_tokens + count + ps->num_donau_tokens);
    1213              : 
    1214           12 :             for (unsigned int k = 0; k < count; k++)
    1215              :             {
    1216            6 :               struct TALER_MERCHANT_PrivateTokenDetails *details =
    1217            6 :                 &ps->issued_tokens[ps->num_issued_tokens - count + k
    1218            6 :                                    + ps->num_donau_tokens];
    1219              : 
    1220            6 :               if (GNUNET_OK !=
    1221            6 :                   find_token_public_key (token_families,
    1222              :                                          slug,
    1223              :                                          key_index,
    1224              :                                          &details->issue_pub))
    1225              :               {
    1226            0 :                 TALER_TESTING_FAIL (is);
    1227              :               }
    1228              : 
    1229              :               /* Only RSA is supported for now. */
    1230            6 :               GNUNET_assert (GNUNET_CRYPTO_BSA_RSA ==
    1231              :                              details->issue_pub.public_key->cipher);
    1232              : 
    1233            6 :               TALER_token_blind_input_copy (&details->blinding_inputs,
    1234              :                                             TALER_token_blind_input_rsa_singleton ()
    1235              :                                             );
    1236              :               /* FIXME: Where to get details->blinding_inputs from? */
    1237            6 :               TALER_token_use_setup_random (&details->master);
    1238            6 :               TALER_token_use_setup_priv (&details->master,
    1239            6 :                                           &details->blinding_inputs,
    1240              :                                           &details->token_priv);
    1241            6 :               TALER_token_use_blinding_secret_create (&details->master,
    1242            6 :                                                       &details->blinding_inputs,
    1243              :                                                       &details->blinding_secret)
    1244              :               ;
    1245            6 :               GNUNET_CRYPTO_eddsa_key_get_public (
    1246            6 :                 &details->token_priv.private_key,
    1247              :                 &details->token_pub.public_key);
    1248            6 :               GNUNET_CRYPTO_hash (&details->token_pub.public_key,
    1249              :                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
    1250              :                                   &details->h_token_pub.hash);
    1251            6 :               details->envelope.blinded_pub =
    1252            6 :                 GNUNET_CRYPTO_message_blind_to_sign
    1253              :                 (
    1254            6 :                   details->issue_pub.public_key,
    1255            6 :                   &details->blinding_secret,
    1256              :                   NULL,   /* FIXME: Add session nonce to support CS tokens */
    1257            6 :                   &details->h_token_pub.hash,
    1258              :                   sizeof (details->h_token_pub.hash),
    1259            6 :                   details->blinding_inputs.blinding_inputs);
    1260              : 
    1261            6 :               if (NULL == details->envelope.blinded_pub)
    1262              :               {
    1263            0 :                 GNUNET_break (0);
    1264            0 :                 TALER_TESTING_FAIL (is);
    1265              :               }
    1266              :             }
    1267              :           }
    1268              :         }
    1269              :       }
    1270              : 
    1271            6 :       break;
    1272            0 :     default:
    1273            0 :       TALER_TESTING_FAIL (is);
    1274              :     }
    1275              :   }
    1276              : 
    1277              :   {
    1278              :     char *cr;
    1279              : 
    1280           35 :     cr = GNUNET_strdup (ps->coin_reference);
    1281           35 :     pay_coins = NULL;
    1282           35 :     npay_coins = 0;
    1283           35 :     if (GNUNET_OK !=
    1284           35 :         build_coins (&pay_coins,
    1285              :                      &npay_coins,
    1286              :                      cr,
    1287              :                      is,
    1288              :                      ps->amount_with_fee,
    1289              :                      ps->amount_without_fee))
    1290              :     {
    1291            0 :       GNUNET_array_grow (pay_coins,
    1292              :                          npay_coins,
    1293              :                          0);
    1294            0 :       GNUNET_free (cr);
    1295            0 :       TALER_TESTING_FAIL (is);
    1296              :     }
    1297           35 :     GNUNET_free (cr);
    1298              :   }
    1299           35 :   if (NULL != ps->token_reference)
    1300              :   {
    1301              :     char *tr;
    1302              : 
    1303            4 :     tr = GNUNET_strdup (ps->token_reference);
    1304            4 :     if (GNUNET_OK !=
    1305            4 :         build_tokens (&use_tokens,
    1306              :                       &len_use_tokens,
    1307              :                       tr,
    1308              :                       is))
    1309              :     {
    1310            0 :       GNUNET_array_grow (use_tokens,
    1311              :                          len_use_tokens,
    1312              :                          0);
    1313            0 :       GNUNET_free (tr);
    1314            0 :       TALER_TESTING_FAIL (is);
    1315              :     }
    1316            4 :     GNUNET_free (tr);
    1317              :   }
    1318              : 
    1319           35 :   GNUNET_array_grow (output_tokens,
    1320              :                      len_output_tokens,
    1321              :                      ps->num_issued_tokens);
    1322           41 :   for (unsigned int i = 0; i<len_output_tokens; i++)
    1323              :   {
    1324            6 :     output_tokens[i].envelope.blinded_pub
    1325            6 :       = ps->issued_tokens[i].envelope.blinded_pub;
    1326              :   }
    1327              : 
    1328           35 :   if (GNUNET_OK !=
    1329           35 :       TALER_TESTING_get_trait_merchant_sig (proposal_cmd,
    1330              :                                             &merchant_sig))
    1331            0 :     TALER_TESTING_FAIL (is);
    1332              : 
    1333           35 :   if (GNUNET_OK !=
    1334           35 :       TALER_TESTING_get_trait_h_contract_terms (proposal_cmd,
    1335              :                                                 &h_proposal))
    1336            0 :     TALER_TESTING_FAIL (is);
    1337           35 :   ps->h_contract_terms = *h_proposal;
    1338              : 
    1339              :   /* New logic of setting pay params */
    1340              :   {
    1341              :     struct GNUNET_CURL_Context *ctx =
    1342           35 :       TALER_TESTING_interpreter_get_context (is);
    1343              :     struct TALER_MERCHANT_OrderPayOption opts[32];
    1344           35 :     size_t oi = 0;
    1345              : 
    1346           35 :     ps->oph = TALER_MERCHANT_order_pay_create (ctx,
    1347              :                                                &pay_cb,
    1348              :                                                ps);
    1349              : 
    1350           35 :     if (NULL == ps->oph)
    1351            0 :       TALER_TESTING_FAIL (is);
    1352              : 
    1353              : #define ADD(_opt)  opts[oi++] = (_opt)
    1354           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL (ps->merchant_url));
    1355           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID      (order_id));
    1356           35 :     if (NULL != ps->session_id)
    1357            9 :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID  (ps->session_id));
    1358           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT    (h_proposal));
    1359           35 :     if (ps->choice_index >= 0)
    1360            6 :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX (ps->choice_index));
    1361           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT        (&ps->total_amount));
    1362           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE       (&max_fee));
    1363           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB  (&merchant_pub));
    1364           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP     (timestamp));
    1365           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE (refund_deadline));
    1366           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE  (pay_deadline));
    1367           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE        (&h_wire));
    1368           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_COINS         (npay_coins,
    1369              :                                                         pay_coins));
    1370           35 :     if (len_use_tokens > 0)
    1371            4 :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS (len_use_tokens,
    1372              :                                                          use_tokens));
    1373           35 :     if (len_output_tokens > 0)
    1374            6 :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS (len_output_tokens,
    1375              :                                                           output_tokens));
    1376              : 
    1377              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
    1378              :     if (ps->donau_data.charity_reference)
    1379              :     {
    1380              :       ADD (
    1381              :         TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL  (ps->donau_data.donau_url));
    1382              :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR (ps->donau_data.year));
    1383              :       ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS (
    1384              :              ps->donau_data.budis_json));
    1385              :     }
    1386              : #endif
    1387           35 :     ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ());
    1388              : #undef ADD
    1389              : 
    1390           35 :     if (TALER_MERCHANT_OPOEC_OK !=
    1391           35 :         TALER_MERCHANT_order_pay_set_options (ps->oph,
    1392              :                                               opts,
    1393              :                                               oi))
    1394            0 :       TALER_TESTING_FAIL (is);
    1395              : 
    1396           35 :     if (TALER_MERCHANT_OPOEC_OK !=
    1397           35 :         TALER_MERCHANT_order_pay_start (ps->oph))
    1398            0 :       TALER_TESTING_FAIL (is);
    1399              :   }
    1400              : 
    1401           35 :   GNUNET_array_grow (pay_coins,
    1402              :                      npay_coins,
    1403              :                      0);
    1404              : 
    1405           35 :   GNUNET_array_grow (use_tokens,
    1406              :                      len_use_tokens,
    1407              :                      0);
    1408              : 
    1409           35 :   GNUNET_array_grow (output_tokens,
    1410              :                      len_output_tokens,
    1411              :                      0);
    1412              : }
    1413              : 
    1414              : 
    1415              : /**
    1416              :  * Free a "pay" CMD, and cancel it if need be.
    1417              :  *
    1418              :  * @param cls closure.
    1419              :  * @param cmd command currently being freed.
    1420              :  */
    1421              : static void
    1422           35 : pay_cleanup (void *cls,
    1423              :              const struct TALER_TESTING_Command *cmd)
    1424              : {
    1425           35 :   struct PayState *ps = cls;
    1426              : 
    1427           35 :   if (NULL != ps->oph)
    1428              :   {
    1429            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1430              :                 "Command `%s' did not complete.\n",
    1431              :                 TALER_TESTING_interpreter_get_current_label (
    1432              :                   ps->is));
    1433            0 :     TALER_MERCHANT_order_pay_cancel1 (ps->oph);
    1434              :   }
    1435              : 
    1436           35 :   GNUNET_free (ps);
    1437           35 : }
    1438              : 
    1439              : 
    1440              : /**
    1441              :  * Offer internal data useful to other commands.
    1442              :  *
    1443              :  * @param cls closure
    1444              :  * @param[out] ret result
    1445              :  * @param trait name of the trait
    1446              :  * @param index index number of the object to extract.
    1447              :  * @return #GNUNET_OK on success
    1448              :  */
    1449              : static enum GNUNET_GenericReturnValue
    1450           24 : pay_traits (void *cls,
    1451              :             const void **ret,
    1452              :             const char *trait,
    1453              :             unsigned int index)
    1454              : {
    1455              : 
    1456           24 :   struct PayState *ps = cls;
    1457              :   const char *order_id;
    1458              :   const struct TALER_TESTING_Command *proposal_cmd;
    1459              :   const struct TALER_MerchantPublicKeyP *merchant_pub;
    1460              : 
    1461           24 :   if (NULL != ps->token_reference &&
    1462            0 :       index >= ps->num_issued_tokens)
    1463              :   {
    1464            0 :     GNUNET_break (0);
    1465            0 :     return GNUNET_NO;
    1466              :   }
    1467              : 
    1468           24 :   if (NULL ==
    1469              :       (proposal_cmd =
    1470           24 :          TALER_TESTING_interpreter_lookup_command (ps->is,
    1471              :                                                    ps->proposal_reference)))
    1472              :   {
    1473            0 :     GNUNET_break (0);
    1474            0 :     return GNUNET_SYSERR;
    1475              :   }
    1476              : 
    1477           24 :   if (GNUNET_OK !=
    1478           24 :       TALER_TESTING_get_trait_order_id (proposal_cmd,
    1479              :                                         &order_id))
    1480              :   {
    1481            0 :     GNUNET_break (0);
    1482            0 :     return GNUNET_SYSERR;
    1483              :   }
    1484              : 
    1485           24 :   if (GNUNET_OK !=
    1486           24 :       TALER_TESTING_get_trait_merchant_pub (proposal_cmd,
    1487              :                                             &merchant_pub))
    1488              :   {
    1489            0 :     GNUNET_break (0);
    1490            0 :     return GNUNET_SYSERR;
    1491              :   }
    1492              :   {
    1493              :     struct TALER_Amount amount_with_fee;
    1494              : 
    1495           24 :     GNUNET_assert (GNUNET_OK ==
    1496              :                    TALER_string_to_amount (ps->amount_with_fee,
    1497              :                                            &amount_with_fee));
    1498              :     {
    1499              :       struct TALER_TESTING_Trait traits[] = {
    1500           24 :         TALER_TESTING_make_trait_proposal_reference (ps->proposal_reference),
    1501           24 :         TALER_TESTING_make_trait_coin_reference (0,
    1502              :                                                  ps->coin_reference),
    1503           24 :         TALER_TESTING_make_trait_order_id (order_id),
    1504           24 :         TALER_TESTING_make_trait_merchant_pub (merchant_pub),
    1505           24 :         TALER_TESTING_make_trait_merchant_sig (&ps->merchant_sig),
    1506           24 :         TALER_TESTING_make_trait_amount (&amount_with_fee),
    1507           24 :         TALER_TESTING_make_trait_otp_key (ps->pos_key),
    1508           24 :         TALER_TESTING_make_trait_otp_alg (&ps->pos_alg),
    1509           24 :         TALER_TESTING_make_trait_token_priv (index,
    1510           24 :                                              &ps->issued_tokens[index].
    1511              :                                              token_priv),
    1512           24 :         TALER_TESTING_make_trait_token_issue_pub (index,
    1513           24 :                                                   &ps->issued_tokens[index].
    1514              :                                                   issue_pub),
    1515           24 :         TALER_TESTING_make_trait_token_issue_sig (index,
    1516           24 :                                                   &ps->issued_tokens[index].
    1517              :                                                   issue_sig),
    1518           24 :         TALER_TESTING_trait_end ()
    1519              :       };
    1520              : 
    1521           24 :       return TALER_TESTING_get_trait (traits,
    1522              :                                       ret,
    1523              :                                       trait,
    1524              :                                       index);
    1525              :     }
    1526              :   }
    1527              : }
    1528              : 
    1529              : 
    1530              : struct TALER_TESTING_Command
    1531           35 : TALER_TESTING_cmd_merchant_pay_order_choices (
    1532              :   const char *label,
    1533              :   const char *merchant_url,
    1534              :   unsigned int http_status,
    1535              :   const char *proposal_reference,
    1536              :   const char *coin_reference,
    1537              :   const char *amount_with_fee,
    1538              :   const char *amount_without_fee,
    1539              :   const char *session_id,
    1540              :   int choice_index,
    1541              :   const char *token_reference)
    1542              : {
    1543              :   struct PayState *ps;
    1544              : 
    1545           35 :   ps = GNUNET_new (struct PayState);
    1546           35 :   ps->http_status = http_status;
    1547           35 :   ps->proposal_reference = proposal_reference;
    1548           35 :   ps->coin_reference = coin_reference;
    1549           35 :   ps->merchant_url = merchant_url;
    1550           35 :   ps->amount_with_fee = amount_with_fee;
    1551           35 :   ps->amount_without_fee = amount_without_fee;
    1552           35 :   ps->session_id = session_id;
    1553           35 :   ps->token_reference = token_reference;
    1554           35 :   ps->choice_index = choice_index;
    1555              :   {
    1556           35 :     struct TALER_TESTING_Command cmd = {
    1557              :       .cls = ps,
    1558              :       .label = label,
    1559              :       .run = &pay_run,
    1560              :       .cleanup = &pay_cleanup,
    1561              :       .traits = &pay_traits
    1562              :     };
    1563              : 
    1564           35 :     return cmd;
    1565              :   }
    1566              : }
    1567              : 
    1568              : 
    1569              : #ifdef HAVE_DONAU_DONAU_SERVICE_H
    1570              : 
    1571              : struct TALER_TESTING_Command
    1572              : TALER_TESTING_cmd_merchant_pay_order_donau (
    1573              :   const char *label,
    1574              :   const char *merchant_url,
    1575              :   unsigned int http_status,
    1576              :   const char *proposal_reference,
    1577              :   const char *coin_reference,
    1578              :   const char *amount_with_fee,
    1579              :   const char *amount_without_fee,
    1580              :   const char *amount_donation,
    1581              :   const char *session_id,
    1582              :   int choice_index,
    1583              :   const char *charity_reference,
    1584              :   uint64_t year,
    1585              :   const char *donor_tax_id,
    1586              :   const char *salt)
    1587              : {
    1588              :   struct PayState *ps;
    1589              : 
    1590              :   ps = GNUNET_new (struct PayState);
    1591              :   ps->http_status = http_status;
    1592              :   ps->proposal_reference = proposal_reference;
    1593              :   ps->coin_reference = coin_reference;
    1594              :   ps->merchant_url = merchant_url;
    1595              :   ps->amount_with_fee = amount_with_fee;
    1596              :   ps->amount_without_fee = amount_without_fee;
    1597              :   ps->session_id = session_id;
    1598              :   ps->token_reference = NULL;
    1599              :   ps->choice_index = choice_index;
    1600              :   ps->donau_data.year = year;
    1601              :   ps->donau_data.num_bkps = 5;
    1602              :   ps->donau_data.charity_reference = charity_reference;
    1603              :   if (GNUNET_OK !=
    1604              :       TALER_string_to_amount (amount_donation,
    1605              :                               &ps->donau_data.donation_amount))
    1606              :   {
    1607              :     GNUNET_assert (0);
    1608              :   }
    1609              : 
    1610              :   /* Compute h_donor_tax_id directly into ps->donau_data: */
    1611              :   if (! DONAU_compute_salted_tax_id_hash (donor_tax_id,
    1612              :                                           salt,
    1613              :                                           ps->donau_data.h_donor_tax_id.hash))
    1614              :   {
    1615              :     GNUNET_assert (0);
    1616              :   }
    1617              : 
    1618              :   {
    1619              :     struct TALER_TESTING_Command cmd = {
    1620              :       .cls = ps,
    1621              :       .label = label,
    1622              :       .run = &pay_run,
    1623              :       .cleanup = &pay_cleanup,
    1624              :       .traits = &pay_traits
    1625              :     };
    1626              : 
    1627              :     return cmd;
    1628              :   }
    1629              : }
    1630              : 
    1631              : 
    1632              : #endif /* HAVE_DONAU_DONAU_SERVICE_H */
    1633              : 
    1634              : 
    1635              : struct TALER_TESTING_Command
    1636           29 : TALER_TESTING_cmd_merchant_pay_order (
    1637              :   const char *label,
    1638              :   const char *merchant_url,
    1639              :   unsigned int http_status,
    1640              :   const char *proposal_reference,
    1641              :   const char *coin_reference,
    1642              :   const char *amount_with_fee,
    1643              :   const char *amount_without_fee,
    1644              :   const char *session_id)
    1645              : {
    1646           29 :   return TALER_TESTING_cmd_merchant_pay_order_choices (
    1647              :     label,
    1648              :     merchant_url,
    1649              :     http_status,
    1650              :     proposal_reference,
    1651              :     coin_reference,
    1652              :     amount_with_fee,
    1653              :     amount_without_fee,
    1654              :     session_id,
    1655              :     -1,
    1656              :     NULL);
    1657              : }
    1658              : 
    1659              : 
    1660              : /* end of testing_api_cmd_pay_order.c */
        

Generated by: LCOV version 2.0-1