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

          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 1.16