LCOV - code coverage report
Current view: top level - lib - exchange_api_batch_deposit.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 251 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    This file is part of TALER
       3             :    Copyright (C) 2014-2022 Taler Systems SA
       4             : 
       5             :    TALER is free software; you can redistribute it and/or modify it under the
       6             :    terms of the GNU General Public License as published by the Free Software
       7             :    Foundation; either version 3, or (at your option) any later version.
       8             : 
       9             :    TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10             :    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11             :    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12             : 
      13             :    You should have received a copy of the GNU General Public License along with
      14             :    TALER; see the file COPYING.  If not, see
      15             :    <http://www.gnu.org/licenses/>
      16             :  */
      17             : /**
      18             :  * @file lib/exchange_api_batch_deposit.c
      19             :  * @brief Implementation of the /batch-deposit request of the exchange's HTTP API
      20             :  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
      21             :  * @author Christian Grothoff
      22             :  */
      23             : #include "platform.h"
      24             : #include <jansson.h>
      25             : #include <microhttpd.h> /* just for HTTP status codes */
      26             : #include <gnunet/gnunet_util_lib.h>
      27             : #include <gnunet/gnunet_json_lib.h>
      28             : #include <gnunet/gnunet_curl_lib.h>
      29             : #include "taler_json_lib.h"
      30             : #include "taler_auditor_service.h"
      31             : #include "taler_exchange_service.h"
      32             : #include "exchange_api_common.h"
      33             : #include "exchange_api_handle.h"
      34             : #include "taler_signatures.h"
      35             : #include "exchange_api_curl_defaults.h"
      36             : 
      37             : 
      38             : /**
      39             :  * 1:#AUDITOR_CHANCE is the probability that we report deposits
      40             :  * to the auditor.
      41             :  *
      42             :  * 20==5% of going to auditor. This is possibly still too high, but set
      43             :  * deliberately this high for testing
      44             :  */
      45             : #define AUDITOR_CHANCE 20
      46             : 
      47             : /**
      48             :  * @brief A Deposit Handle
      49             :  */
      50             : struct TALER_EXCHANGE_BatchDepositHandle
      51             : {
      52             : 
      53             :   /**
      54             :    * The connection to exchange this request handle will use
      55             :    */
      56             :   struct TALER_EXCHANGE_Handle *exchange;
      57             : 
      58             :   /**
      59             :    * The url for this request.
      60             :    */
      61             :   char *url;
      62             : 
      63             :   /**
      64             :    * Context for #TEH_curl_easy_post(). Keeps the data that must
      65             :    * persist for Curl to make the upload.
      66             :    */
      67             :   struct TALER_CURL_PostContext ctx;
      68             : 
      69             :   /**
      70             :    * Handle for the request.
      71             :    */
      72             :   struct GNUNET_CURL_Job *job;
      73             : 
      74             :   /**
      75             :    * Function to call with the result.
      76             :    */
      77             :   TALER_EXCHANGE_BatchDepositResultCallback cb;
      78             : 
      79             :   /**
      80             :    * Closure for @a cb.
      81             :    */
      82             :   void *cb_cls;
      83             : 
      84             :   /**
      85             :    * Details about the contract.
      86             :    */
      87             :   struct TALER_EXCHANGE_DepositContractDetail dcd;
      88             : 
      89             :   /**
      90             :    * Array with details about the coins.
      91             :    */
      92             :   struct TALER_EXCHANGE_CoinDepositDetail *cdds;
      93             : 
      94             :   /**
      95             :    * Hash of the merchant's wire details.
      96             :    */
      97             :   struct TALER_MerchantWireHashP h_wire;
      98             : 
      99             :   /**
     100             :    * Hash over the extensions, or all zero.
     101             :    */
     102             :   struct TALER_ExtensionContractHashP h_extensions;
     103             : 
     104             :   /**
     105             :    * Time when this confirmation was generated / when the exchange received
     106             :    * the deposit request.
     107             :    */
     108             :   struct GNUNET_TIME_Timestamp exchange_timestamp;
     109             : 
     110             :   /**
     111             :    * Exchange signatures, set for #auditor_cb.
     112             :    */
     113             :   struct TALER_ExchangeSignatureP *exchange_sigs;
     114             : 
     115             :   /**
     116             :    * Exchange signing public key, set for #auditor_cb.
     117             :    */
     118             :   struct TALER_ExchangePublicKeyP exchange_pub;
     119             : 
     120             :   /**
     121             :    * Chance that we will inform the auditor about the deposit
     122             :    * is 1:n, where the value of this field is "n".
     123             :    */
     124             :   unsigned int auditor_chance;
     125             : 
     126             :   /**
     127             :    * Length of the @e cdds array.
     128             :    */
     129             :   unsigned int num_cdds;
     130             : 
     131             : };
     132             : 
     133             : 
     134             : /**
     135             :  * Function called for each auditor to give us a chance to possibly
     136             :  * launch a deposit confirmation interaction.
     137             :  *
     138             :  * @param cls closure
     139             :  * @param ah handle to the auditor
     140             :  * @param auditor_pub public key of the auditor
     141             :  * @return NULL if no deposit confirmation interaction was launched
     142             :  */
     143             : static struct TEAH_AuditorInteractionEntry *
     144           0 : auditor_cb (void *cls,
     145             :             struct TALER_AUDITOR_Handle *ah,
     146             :             const struct TALER_AuditorPublicKeyP *auditor_pub)
     147             : {
     148           0 :   struct TALER_EXCHANGE_BatchDepositHandle *dh = cls;
     149             :   const struct TALER_EXCHANGE_Keys *key_state;
     150             :   const struct TALER_EXCHANGE_SigningPublicKey *spk;
     151             :   struct TEAH_AuditorInteractionEntry *aie;
     152             :   struct TALER_Amount amount_without_fee;
     153             :   const struct TALER_EXCHANGE_DenomPublicKey *dki;
     154             :   unsigned int coin;
     155             : 
     156           0 :   if (0 !=
     157           0 :       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
     158             :                                 dh->auditor_chance))
     159             :   {
     160           0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     161             :                 "Not providing deposit confirmation to auditor\n");
     162           0 :     return NULL;
     163             :   }
     164           0 :   coin = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
     165             :                                    dh->num_cdds);
     166           0 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     167             :               "Will provide deposit confirmation to auditor `%s'\n",
     168             :               TALER_B2S (auditor_pub));
     169           0 :   key_state = TALER_EXCHANGE_get_keys (dh->exchange);
     170           0 :   dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
     171           0 :                                                      &dh->cdds[coin].h_denom_pub);
     172           0 :   GNUNET_assert (NULL != dki);
     173           0 :   spk = TALER_EXCHANGE_get_signing_key_info (key_state,
     174           0 :                                              &dh->exchange_pub);
     175           0 :   if (NULL == spk)
     176             :   {
     177           0 :     GNUNET_break_op (0);
     178           0 :     return NULL;
     179             :   }
     180           0 :   GNUNET_assert (0 <=
     181             :                  TALER_amount_subtract (&amount_without_fee,
     182             :                                         &dh->cdds[coin].amount,
     183             :                                         &dki->fees.deposit));
     184           0 :   aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
     185           0 :   aie->dch = TALER_AUDITOR_deposit_confirmation (
     186             :     ah,
     187           0 :     &dh->h_wire,
     188           0 :     &dh->h_extensions,
     189           0 :     &dh->dcd.h_contract_terms,
     190             :     dh->exchange_timestamp,
     191             :     dh->dcd.wire_deadline,
     192             :     dh->dcd.refund_deadline,
     193             :     &amount_without_fee,
     194           0 :     &dh->cdds[coin].coin_pub,
     195           0 :     &dh->dcd.merchant_pub,
     196           0 :     &dh->exchange_pub,
     197           0 :     &dh->exchange_sigs[coin],
     198             :     &key_state->master_pub,
     199             :     spk->valid_from,
     200             :     spk->valid_until,
     201             :     spk->valid_legal,
     202             :     &spk->master_sig,
     203             :     &TEAH_acc_confirmation_cb,
     204             :     aie);
     205           0 :   return aie;
     206             : }
     207             : 
     208             : 
     209             : /**
     210             :  * Function called when we're done processing the
     211             :  * HTTP /deposit request.
     212             :  *
     213             :  * @param cls the `struct TALER_EXCHANGE_BatchDepositHandle`
     214             :  * @param response_code HTTP response code, 0 on error
     215             :  * @param response parsed JSON result, NULL on error
     216             :  */
     217             : static void
     218           0 : handle_deposit_finished (void *cls,
     219             :                          long response_code,
     220             :                          const void *response)
     221             : {
     222           0 :   struct TALER_EXCHANGE_BatchDepositHandle *dh = cls;
     223           0 :   const json_t *j = response;
     224           0 :   struct TALER_EXCHANGE_BatchDepositResult dr = {
     225             :     .hr.reply = j,
     226           0 :     .hr.http_status = (unsigned int) response_code
     227             :   };
     228             :   const struct TALER_EXCHANGE_Keys *keys;
     229             : 
     230           0 :   dh->job = NULL;
     231           0 :   keys = TALER_EXCHANGE_get_keys (dh->exchange);
     232           0 :   switch (response_code)
     233             :   {
     234           0 :   case 0:
     235           0 :     dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     236           0 :     break;
     237           0 :   case MHD_HTTP_OK:
     238             :     {
     239             :       const struct TALER_EXCHANGE_Keys *key_state;
     240             :       json_t *sigs;
     241             :       json_t *sig;
     242             :       unsigned int idx;
     243             :       struct GNUNET_JSON_Specification spec[] = {
     244           0 :         GNUNET_JSON_spec_json ("exchange_sigs",
     245             :                                &sigs),
     246           0 :         GNUNET_JSON_spec_fixed_auto ("exchange_pub",
     247             :                                      &dh->exchange_pub),
     248           0 :         GNUNET_JSON_spec_mark_optional (
     249             :           GNUNET_JSON_spec_string ("transaction_base_url",
     250             :                                    &dr.details.success.transaction_base_url),
     251             :           NULL),
     252           0 :         GNUNET_JSON_spec_timestamp ("exchange_timestamp",
     253             :                                     &dh->exchange_timestamp),
     254           0 :         GNUNET_JSON_spec_end ()
     255             :       };
     256             : 
     257           0 :       if (GNUNET_OK !=
     258           0 :           GNUNET_JSON_parse (j,
     259             :                              spec,
     260             :                              NULL, NULL))
     261             :       {
     262           0 :         GNUNET_break_op (0);
     263           0 :         dr.hr.http_status = 0;
     264           0 :         dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     265           0 :         break;
     266             :       }
     267           0 :       if (json_array_size (sigs) != dh->num_cdds)
     268             :       {
     269           0 :         GNUNET_break_op (0);
     270           0 :         dr.hr.http_status = 0;
     271           0 :         dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     272           0 :         break;
     273             :       }
     274           0 :       dh->exchange_sigs = GNUNET_new_array (dh->num_cdds,
     275             :                                             struct TALER_ExchangeSignatureP);
     276           0 :       key_state = TALER_EXCHANGE_get_keys (dh->exchange);
     277           0 :       if (GNUNET_OK !=
     278           0 :           TALER_EXCHANGE_test_signing_key (key_state,
     279           0 :                                            &dh->exchange_pub))
     280             :       {
     281           0 :         GNUNET_break_op (0);
     282           0 :         dr.hr.http_status = 0;
     283           0 :         dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
     284           0 :         break;
     285             :       }
     286           0 :       json_array_foreach (sigs, idx, sig)
     287             :       {
     288             :         struct GNUNET_JSON_Specification ispec[] = {
     289           0 :           GNUNET_JSON_spec_fixed_auto ("exchange_sig",
     290             :                                        &dh->exchange_sigs[idx]),
     291           0 :           GNUNET_JSON_spec_end ()
     292             :         };
     293             :         struct TALER_Amount amount_without_fee;
     294             :         const struct TALER_EXCHANGE_DenomPublicKey *dki;
     295             : 
     296           0 :         if (GNUNET_OK !=
     297           0 :             GNUNET_JSON_parse (sig,
     298             :                                ispec,
     299             :                                NULL, NULL))
     300             :         {
     301           0 :           GNUNET_break_op (0);
     302           0 :           dr.hr.http_status = 0;
     303           0 :           dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     304           0 :           GNUNET_JSON_parse_free (spec);
     305           0 :           break;
     306             :         }
     307           0 :         dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
     308           0 :                                                            &dh->cdds[idx].
     309             :                                                            h_denom_pub);
     310           0 :         GNUNET_assert (NULL != dki);
     311           0 :         GNUNET_assert (0 <=
     312             :                        TALER_amount_subtract (&amount_without_fee,
     313             :                                               &dh->cdds[idx].amount,
     314             :                                               &dki->fees.deposit));
     315             : 
     316           0 :         if (GNUNET_OK !=
     317           0 :             TALER_exchange_online_deposit_confirmation_verify (
     318           0 :               &dh->dcd.h_contract_terms,
     319           0 :               &dh->h_wire,
     320           0 :               &dh->h_extensions,
     321             :               dh->exchange_timestamp,
     322             :               dh->dcd.wire_deadline,
     323             :               dh->dcd.refund_deadline,
     324             :               &amount_without_fee,
     325           0 :               &dh->cdds[idx].coin_pub,
     326           0 :               &dh->dcd.merchant_pub,
     327           0 :               &dh->exchange_pub,
     328           0 :               &dh->exchange_sigs[idx]))
     329             :         {
     330           0 :           GNUNET_break_op (0);
     331           0 :           dr.hr.http_status = 0;
     332           0 :           dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
     333           0 :           break;
     334             :         }
     335             :       }
     336           0 :       TEAH_get_auditors_for_dc (dh->exchange,
     337             :                                 &auditor_cb,
     338             :                                 dh);
     339             :     }
     340           0 :     dr.details.success.exchange_sigs = dh->exchange_sigs;
     341           0 :     dr.details.success.exchange_pub = &dh->exchange_pub;
     342           0 :     dr.details.success.deposit_timestamp = dh->exchange_timestamp;
     343           0 :     dr.details.success.num_signatures = dh->num_cdds;
     344           0 :     break;
     345           0 :   case MHD_HTTP_BAD_REQUEST:
     346             :     /* This should never happen, either us or the exchange is buggy
     347             :        (or API version conflict); just pass JSON reply to the application */
     348           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     349           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     350           0 :     break;
     351           0 :   case MHD_HTTP_FORBIDDEN:
     352           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     353           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     354             :     /* Nothing really to verify, exchange says one of the signatures is
     355             :        invalid; as we checked them, this should never happen, we
     356             :        should pass the JSON reply to the application */
     357           0 :     break;
     358           0 :   case MHD_HTTP_NOT_FOUND:
     359           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     360           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     361             :     /* Nothing really to verify, this should never
     362             :        happen, we should pass the JSON reply to the application */
     363           0 :     break;
     364           0 :   case MHD_HTTP_CONFLICT:
     365             :     {
     366             :       const struct TALER_EXCHANGE_Keys *key_state;
     367             :       struct TALER_CoinSpendPublicKeyP coin_pub;
     368             :       struct GNUNET_JSON_Specification spec[] = {
     369           0 :         GNUNET_JSON_spec_fixed_auto ("coin_pub",
     370             :                                      &coin_pub),
     371           0 :         GNUNET_JSON_spec_end ()
     372             :       };
     373             :       const struct TALER_EXCHANGE_DenomPublicKey *dki;
     374           0 :       bool found = false;
     375             : 
     376           0 :       if (GNUNET_OK !=
     377           0 :           GNUNET_JSON_parse (j,
     378             :                              spec,
     379             :                              NULL, NULL))
     380             :       {
     381           0 :         GNUNET_break_op (0);
     382           0 :         dr.hr.http_status = 0;
     383           0 :         dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     384           0 :         break;
     385             :       }
     386           0 :       for (unsigned int i = 0; i<dh->num_cdds; i++)
     387             :       {
     388           0 :         if (0 !=
     389           0 :             GNUNET_memcmp (&coin_pub,
     390             :                            &dh->cdds[i].coin_pub))
     391           0 :           continue;
     392           0 :         key_state = TALER_EXCHANGE_get_keys (dh->exchange);
     393           0 :         dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
     394           0 :                                                            &dh->cdds[i].
     395             :                                                            h_denom_pub);
     396           0 :         GNUNET_assert (NULL != dki);
     397           0 :         if (GNUNET_OK !=
     398           0 :             TALER_EXCHANGE_check_coin_conflict_ (
     399             :               keys,
     400             :               j,
     401             :               dki,
     402           0 :               &dh->cdds[i].coin_pub,
     403           0 :               &dh->cdds[i].coin_sig,
     404           0 :               &dh->cdds[i].amount))
     405             :         {
     406           0 :           GNUNET_break_op (0);
     407           0 :           dr.hr.http_status = 0;
     408           0 :           dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     409           0 :           break;
     410             :         }
     411           0 :         found = true;
     412           0 :         break;
     413             :       }
     414           0 :       if (! found)
     415             :       {
     416           0 :         GNUNET_break_op (0);
     417           0 :         dr.hr.http_status = 0;
     418           0 :         dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
     419           0 :         break;
     420             :       }
     421           0 :       dr.hr.ec = TALER_JSON_get_error_code (j);
     422           0 :       dr.hr.hint = TALER_JSON_get_error_hint (j);
     423             :     }
     424           0 :     break;
     425           0 :   case MHD_HTTP_GONE:
     426             :     /* could happen if denomination was revoked */
     427             :     /* Note: one might want to check /keys for revocation
     428             :        signature here, alas tricky in case our /keys
     429             :        is outdated => left to clients */
     430           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     431           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     432           0 :     break;
     433           0 :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     434           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     435           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     436             :     /* Server had an internal issue; we should retry, but this API
     437             :        leaves this to the application */
     438           0 :     break;
     439           0 :   default:
     440             :     /* unexpected response code */
     441           0 :     dr.hr.ec = TALER_JSON_get_error_code (j);
     442           0 :     dr.hr.hint = TALER_JSON_get_error_hint (j);
     443           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     444             :                 "Unexpected response code %u/%d for exchange deposit\n",
     445             :                 (unsigned int) response_code,
     446             :                 dr.hr.ec);
     447           0 :     GNUNET_break_op (0);
     448           0 :     break;
     449             :   }
     450           0 :   dh->cb (dh->cb_cls,
     451             :           &dr);
     452           0 :   TALER_EXCHANGE_batch_deposit_cancel (dh);
     453           0 : }
     454             : 
     455             : 
     456             : struct TALER_EXCHANGE_BatchDepositHandle *
     457           0 : TALER_EXCHANGE_batch_deposit (
     458             :   struct TALER_EXCHANGE_Handle *exchange,
     459             :   const struct TALER_EXCHANGE_DepositContractDetail *dcd,
     460             :   unsigned int num_cdds,
     461             :   const struct TALER_EXCHANGE_CoinDepositDetail *cdds,
     462             :   TALER_EXCHANGE_BatchDepositResultCallback cb,
     463             :   void *cb_cls,
     464             :   enum TALER_ErrorCode *ec)
     465             : {
     466             :   const struct TALER_EXCHANGE_Keys *key_state;
     467             :   struct TALER_EXCHANGE_BatchDepositHandle *dh;
     468             :   struct GNUNET_CURL_Context *ctx;
     469             :   json_t *deposit_obj;
     470             :   json_t *deposits;
     471             :   CURL *eh;
     472             :   struct TALER_Amount amount_without_fee;
     473             : 
     474           0 :   GNUNET_assert (GNUNET_YES ==
     475             :                  TEAH_handle_is_ready (exchange));
     476           0 :   if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline,
     477             :                                  >,
     478             :                                  dcd->wire_deadline))
     479             :   {
     480           0 :     GNUNET_break_op (0);
     481           0 :     *ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE;
     482           0 :     return NULL;
     483             :   }
     484           0 :   key_state = TALER_EXCHANGE_get_keys (exchange);
     485           0 :   dh = GNUNET_new (struct TALER_EXCHANGE_BatchDepositHandle);
     486           0 :   dh->auditor_chance = AUDITOR_CHANCE;
     487           0 :   dh->exchange = exchange;
     488           0 :   dh->cb = cb;
     489           0 :   dh->cb_cls = cb_cls;
     490           0 :   dh->cdds = GNUNET_memdup (cdds,
     491             :                             num_cdds
     492             :                             * sizeof (*cdds));
     493           0 :   dh->num_cdds = num_cdds;
     494           0 :   dh->dcd = *dcd;
     495           0 :   if (NULL != dcd->extension_details)
     496           0 :     TALER_deposit_extension_hash (dcd->extension_details,
     497             :                                   &dh->h_extensions);
     498           0 :   TALER_merchant_wire_signature_hash (dcd->merchant_payto_uri,
     499             :                                       &dcd->wire_salt,
     500             :                                       &dh->h_wire);
     501           0 :   deposits = json_array ();
     502           0 :   GNUNET_assert (NULL != deposits);
     503           0 :   for (unsigned int i = 0; i<num_cdds; i++)
     504             :   {
     505           0 :     const struct TALER_EXCHANGE_CoinDepositDetail *cdd = &cdds[i];
     506             :     const struct TALER_EXCHANGE_DenomPublicKey *dki;
     507             : 
     508           0 :     dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
     509             :                                                        &cdd->h_denom_pub);
     510           0 :     if (NULL == dki)
     511             :     {
     512           0 :       *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
     513           0 :       GNUNET_break_op (0);
     514           0 :       return NULL;
     515             :     }
     516           0 :     if (0 >
     517           0 :         TALER_amount_subtract (&amount_without_fee,
     518             :                                &cdd->amount,
     519             :                                &dki->fees.deposit))
     520             :     {
     521           0 :       *ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
     522           0 :       GNUNET_break_op (0);
     523           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     524             :                   "Amount: %s\n",
     525             :                   TALER_amount2s (&cdd->amount));
     526           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     527             :                   "Fee: %s\n",
     528             :                   TALER_amount2s (&dki->fees.deposit));
     529           0 :       GNUNET_free (dh->cdds);
     530           0 :       GNUNET_free (dh);
     531           0 :       return NULL;
     532             :     }
     533             : 
     534           0 :     if (GNUNET_OK !=
     535           0 :         TALER_EXCHANGE_verify_deposit_signature_ (dcd,
     536           0 :                                                   &dh->h_extensions,
     537           0 :                                                   &dh->h_wire,
     538             :                                                   cdd,
     539             :                                                   dki))
     540             :     {
     541           0 :       *ec = TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID;
     542           0 :       GNUNET_break_op (0);
     543           0 :       GNUNET_free (dh->cdds);
     544           0 :       GNUNET_free (dh);
     545           0 :       return NULL;
     546             :     }
     547           0 :     GNUNET_assert (
     548             :       0 ==
     549             :       json_array_append_new (
     550             :         deposits,
     551             :         GNUNET_JSON_PACK (
     552             :           TALER_JSON_pack_amount ("contribution",
     553             :                                   &cdd->amount),
     554             :           GNUNET_JSON_pack_data_auto ("denom_pub_hash",
     555             :                                       &cdd->h_denom_pub),
     556             :           TALER_JSON_pack_denom_sig ("ub_sig",
     557             :                                      &cdd->denom_sig),
     558             :           GNUNET_JSON_pack_data_auto ("coin_pub",
     559             :                                       &cdd->coin_pub),
     560             :           GNUNET_JSON_pack_allow_null (
     561             :             GNUNET_JSON_pack_data_auto ("h_age_commitment",
     562             :                                         &cdd->h_age_commitment)),
     563             :           GNUNET_JSON_pack_data_auto ("coin_sig",
     564             :                                       &cdd->coin_sig)
     565             :           )));
     566             :   }
     567           0 :   dh->url = TEAH_path_to_url (exchange,
     568             :                               "/batch-deposit");
     569           0 :   if (NULL == dh->url)
     570             :   {
     571           0 :     GNUNET_break (0);
     572           0 :     *ec = TALER_EC_GENERIC_ALLOCATION_FAILURE;
     573           0 :     GNUNET_free (dh->url);
     574           0 :     GNUNET_free (dh->cdds);
     575           0 :     GNUNET_free (dh);
     576           0 :     return NULL;
     577             :   }
     578             : 
     579           0 :   deposit_obj = GNUNET_JSON_PACK (
     580             :     GNUNET_JSON_pack_string ("merchant_payto_uri",
     581             :                              dcd->merchant_payto_uri),
     582             :     GNUNET_JSON_pack_data_auto ("wire_salt",
     583             :                                 &dcd->wire_salt),
     584             :     GNUNET_JSON_pack_data_auto ("h_contract_terms",
     585             :                                 &dcd->h_contract_terms),
     586             :     GNUNET_JSON_pack_array_steal ("coins",
     587             :                                   deposits),
     588             :     GNUNET_JSON_pack_allow_null (
     589             :       GNUNET_JSON_pack_object_steal ("extension_details",
     590             :                                      NULL)), /* FIXME #7270-Oec */
     591             :     GNUNET_JSON_pack_timestamp ("timestamp",
     592             :                                 dcd->timestamp),
     593             :     GNUNET_JSON_pack_data_auto ("merchant_pub",
     594             :                                 &dcd->merchant_pub),
     595             :     GNUNET_JSON_pack_allow_null (
     596             :       GNUNET_JSON_pack_timestamp ("refund_deadline",
     597             :                                   dcd->refund_deadline)),
     598             :     GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
     599             :                                 dcd->wire_deadline));
     600           0 :   GNUNET_assert (NULL != deposit_obj);
     601           0 :   eh = TALER_EXCHANGE_curl_easy_get_ (dh->url);
     602           0 :   if ( (NULL == eh) ||
     603             :        (GNUNET_OK !=
     604           0 :         TALER_curl_easy_post (&dh->ctx,
     605             :                               eh,
     606             :                               deposit_obj)) )
     607             :   {
     608           0 :     *ec = TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE;
     609           0 :     GNUNET_break (0);
     610           0 :     if (NULL != eh)
     611           0 :       curl_easy_cleanup (eh);
     612           0 :     json_decref (deposit_obj);
     613           0 :     GNUNET_free (dh->cdds);
     614           0 :     GNUNET_free (dh->url);
     615           0 :     GNUNET_free (dh);
     616           0 :     return NULL;
     617             :   }
     618           0 :   json_decref (deposit_obj);
     619           0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     620             :               "URL for deposit: `%s'\n",
     621             :               dh->url);
     622           0 :   ctx = TEAH_handle_to_context (exchange);
     623           0 :   dh->job = GNUNET_CURL_job_add2 (ctx,
     624             :                                   eh,
     625           0 :                                   dh->ctx.headers,
     626             :                                   &handle_deposit_finished,
     627             :                                   dh);
     628           0 :   return dh;
     629             : }
     630             : 
     631             : 
     632             : void
     633           0 : TALER_EXCHANGE_batch_deposit_force_dc (
     634             :   struct TALER_EXCHANGE_BatchDepositHandle *deposit)
     635             : {
     636           0 :   deposit->auditor_chance = 1;
     637           0 : }
     638             : 
     639             : 
     640             : void
     641           0 : TALER_EXCHANGE_batch_deposit_cancel (
     642             :   struct TALER_EXCHANGE_BatchDepositHandle *deposit)
     643             : {
     644           0 :   if (NULL != deposit->job)
     645             :   {
     646           0 :     GNUNET_CURL_job_cancel (deposit->job);
     647           0 :     deposit->job = NULL;
     648             :   }
     649           0 :   GNUNET_free (deposit->url);
     650           0 :   GNUNET_free (deposit->cdds);
     651           0 :   GNUNET_free (deposit->exchange_sigs);
     652           0 :   TALER_curl_easy_post_finished (&deposit->ctx);
     653           0 :   GNUNET_free (deposit);
     654           0 : }
     655             : 
     656             : 
     657             : /* end of exchange_api_batch_deposit.c */

Generated by: LCOV version 1.14