LCOV - code coverage report
Current view: top level - exchange-lib - exchange_api_deposit.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 104 146 71.2 %
Date: 2017-11-25 11:31:41 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014, 2015 GNUnet e.V.
       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 exchange-lib/exchange_api_deposit.c
      19             :  * @brief Implementation of the /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 <curl/curl.h>
      25             : #include <jansson.h>
      26             : #include <microhttpd.h> /* just for HTTP status codes */
      27             : #include <gnunet/gnunet_util_lib.h>
      28             : #include <gnunet/gnunet_json_lib.h>
      29             : #include <gnunet/gnunet_curl_lib.h>
      30             : #include "taler_json_lib.h"
      31             : #include "taler_exchange_service.h"
      32             : #include "exchange_api_handle.h"
      33             : #include "taler_signatures.h"
      34             : 
      35             : 
      36             : /**
      37             :  * @brief A Deposit Handle
      38             :  */
      39             : struct TALER_EXCHANGE_DepositHandle
      40             : {
      41             : 
      42             :   /**
      43             :    * The connection to exchange this request handle will use
      44             :    */
      45             :   struct TALER_EXCHANGE_Handle *exchange;
      46             : 
      47             :   /**
      48             :    * The url for this request.
      49             :    */
      50             :   char *url;
      51             : 
      52             :   /**
      53             :    * JSON encoding of the request to POST.
      54             :    */
      55             :   char *json_enc;
      56             : 
      57             :   /**
      58             :    * Handle for the request.
      59             :    */
      60             :   struct GNUNET_CURL_Job *job;
      61             : 
      62             :   /**
      63             :    * Function to call with the result.
      64             :    */
      65             :   TALER_EXCHANGE_DepositResultCallback cb;
      66             : 
      67             :   /**
      68             :    * Closure for @a cb.
      69             :    */
      70             :   void *cb_cls;
      71             : 
      72             :   /**
      73             :    * Information the exchange should sign in response.
      74             :    */
      75             :   struct TALER_DepositConfirmationPS depconf;
      76             : 
      77             :   /**
      78             :    * Value of the /deposit transaction, including fee.
      79             :    */
      80             :   struct TALER_Amount amount_with_fee;
      81             : 
      82             :   /**
      83             :    * Total value of the coin being transacted with.
      84             :    */
      85             :   struct TALER_Amount coin_value;
      86             : 
      87             : };
      88             : 
      89             : 
      90             : /**
      91             :  * Verify that the signature on the "200 OK" response
      92             :  * from the exchange is valid.
      93             :  *
      94             :  * @param dh deposit handle
      95             :  * @param json json reply with the signature
      96             :  * @param exchange_pub set to the exchange's public key
      97             :  * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
      98             :  */
      99             : static int
     100           7 : verify_deposit_signature_ok (const struct TALER_EXCHANGE_DepositHandle *dh,
     101             :                              const json_t *json,
     102             :                              struct TALER_ExchangePublicKeyP *exchange_pub)
     103             : {
     104             :   struct TALER_ExchangeSignatureP exchange_sig;
     105             : 
     106             :   const struct TALER_EXCHANGE_Keys *key_state;
     107           7 :   struct GNUNET_JSON_Specification spec[] = {
     108             :     GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
     109             :     GNUNET_JSON_spec_fixed_auto ("pub", exchange_pub),
     110             :     GNUNET_JSON_spec_end()
     111             :   };
     112             : 
     113           7 :   if (GNUNET_OK !=
     114           7 :       GNUNET_JSON_parse (json,
     115             :                          spec,
     116             :                          NULL, NULL))
     117             :   {
     118           0 :     GNUNET_break_op (0);
     119           0 :     return GNUNET_SYSERR;
     120             :   }
     121           7 :   key_state = TALER_EXCHANGE_get_keys (dh->exchange);
     122           7 :   if (GNUNET_OK !=
     123           7 :       TALER_EXCHANGE_test_signing_key (key_state,
     124             :                                        exchange_pub))
     125             :   {
     126           0 :     GNUNET_break_op (0);
     127           0 :     return GNUNET_SYSERR;
     128             :   }
     129           7 :   if (GNUNET_OK !=
     130           7 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
     131             :                                   &dh->depconf.purpose,
     132             :                                   &exchange_sig.eddsa_signature,
     133           7 :                                   &exchange_pub->eddsa_pub))
     134             :   {
     135           0 :     GNUNET_break_op (0);
     136           0 :     return GNUNET_SYSERR;
     137             :   }
     138           7 :   return GNUNET_OK;
     139             : }
     140             : 
     141             : 
     142             : /**
     143             :  * Verify that the signatures on the "403 FORBIDDEN" response from the
     144             :  * exchange demonstrating customer double-spending are valid.
     145             :  *
     146             :  * @param dh deposit handle
     147             :  * @param json json reply with the signature(s) and transaction history
     148             :  * @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
     149             :  */
     150             : static int
     151           3 : verify_deposit_signature_forbidden (const struct TALER_EXCHANGE_DepositHandle *dh,
     152             :                                     const json_t *json)
     153             : {
     154             :   json_t *history;
     155             :   struct TALER_Amount total;
     156             : 
     157           3 :   history = json_object_get (json,
     158             :                              "history");
     159           3 :   if (GNUNET_OK !=
     160           3 :       TALER_EXCHANGE_verify_coin_history (dh->coin_value.currency,
     161             :                                            &dh->depconf.coin_pub,
     162             :                                            history,
     163             :                                            &total))
     164             :   {
     165           0 :     GNUNET_break_op (0);
     166           0 :     return GNUNET_SYSERR;
     167             :   }
     168           3 :   if (GNUNET_OK !=
     169           3 :       TALER_amount_add (&total,
     170             :                         &total,
     171             :                         &dh->amount_with_fee))
     172             :   {
     173             :     /* clearly not OK if our transaction would have caused
     174             :        the overflow... */
     175           0 :     return GNUNET_OK;
     176             :   }
     177             : 
     178           3 :   if (0 >= TALER_amount_cmp (&total,
     179             :                              &dh->coin_value))
     180             :   {
     181             :     /* transaction should have still fit */
     182           0 :     GNUNET_break (0);
     183           0 :     return GNUNET_SYSERR;
     184             :   }
     185             :   /* everything OK, proof of double-spending was provided */
     186           3 :   return GNUNET_OK;
     187             : }
     188             : 
     189             : 
     190             : /**
     191             :  * Function called when we're done processing the
     192             :  * HTTP /deposit request.
     193             :  *
     194             :  * @param cls the `struct TALER_EXCHANGE_DepositHandle`
     195             :  * @param response_code HTTP response code, 0 on error
     196             :  * @param json parsed JSON result, NULL on error
     197             :  */
     198             : static void
     199          12 : handle_deposit_finished (void *cls,
     200             :                          long response_code,
     201             :                          const json_t *json)
     202             : {
     203          12 :   struct TALER_EXCHANGE_DepositHandle *dh = cls;
     204             :   struct TALER_ExchangePublicKeyP exchange_pub;
     205          12 :   struct TALER_ExchangePublicKeyP *ep = NULL;
     206             : 
     207          12 :   dh->job = NULL;
     208          12 :   switch (response_code)
     209             :   {
     210             :   case 0:
     211           0 :     break;
     212             :   case MHD_HTTP_OK:
     213           7 :     if (GNUNET_OK !=
     214           7 :         verify_deposit_signature_ok (dh,
     215             :                                      json,
     216             :                                      &exchange_pub))
     217             :     {
     218           0 :       GNUNET_break_op (0);
     219           0 :       response_code = 0;
     220             :     }
     221             :     else
     222             :     {
     223           7 :       ep = &exchange_pub;
     224             :     }
     225           7 :     break;
     226             :   case MHD_HTTP_BAD_REQUEST:
     227             :     /* This should never happen, either us or the exchange is buggy
     228             :        (or API version conflict); just pass JSON reply to the application */
     229           0 :     break;
     230             :   case MHD_HTTP_FORBIDDEN:
     231             :     /* Double spending; check signatures on transaction history */
     232           3 :     if (GNUNET_OK !=
     233           3 :         verify_deposit_signature_forbidden (dh,
     234             :                                             json))
     235             :     {
     236           0 :       GNUNET_break_op (0);
     237           0 :       response_code = 0;
     238             :     }
     239           3 :     break;
     240             :   case MHD_HTTP_UNAUTHORIZED:
     241             :     /* Nothing really to verify, exchange says one of the signatures is
     242             :        invalid; as we checked them, this should never happen, we
     243             :        should pass the JSON reply to the application */
     244           0 :     break;
     245             :   case MHD_HTTP_NOT_FOUND:
     246             :     /* Nothing really to verify, this should never
     247             :        happen, we should pass the JSON reply to the application */
     248           2 :     break;
     249             :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     250             :     /* Server had an internal issue; we should retry, but this API
     251             :        leaves this to the application */
     252           0 :     break;
     253             :   default:
     254             :     /* unexpected response code */
     255           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     256             :                 "Unexpected response code %u\n",
     257             :                 (unsigned int) response_code);
     258           0 :     GNUNET_break (0);
     259           0 :     response_code = 0;
     260           0 :     break;
     261             :   }
     262          12 :   dh->cb (dh->cb_cls,
     263             :           response_code,
     264             :           TALER_JSON_get_error_code (json),
     265             :           ep,
     266             :           json);
     267          12 :   TALER_EXCHANGE_deposit_cancel (dh);
     268          12 : }
     269             : 
     270             : 
     271             : /**
     272             :  * Verify signature information about the deposit.
     273             :  *
     274             :  * @param dki public key information
     275             :  * @param amount the amount to be deposited
     276             :  * @param h_wire hash of the merchant’s account details
     277             :  * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
     278             :  * @param coin_pub coin’s public key
     279             :  * @param denom_pub denomination key with which the coin is signed
     280             :  * @param denom_sig exchange’s unblinded signature of the coin
     281             :  * @param timestamp timestamp when the deposit was finalized
     282             :  * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
     283             :  * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed)
     284             :  * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key.
     285             :  * @return #GNUNET_OK if signatures are OK, #GNUNET_SYSERR if not
     286             :  */
     287             : static int
     288          12 : verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
     289             :                    const struct TALER_Amount *amount,
     290             :                    const struct GNUNET_HashCode *h_wire,
     291             :                    const struct GNUNET_HashCode *h_contract_terms,
     292             :                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
     293             :                    const struct TALER_DenominationSignature *denom_sig,
     294             :                    const struct TALER_DenominationPublicKey *denom_pub,
     295             :                    struct GNUNET_TIME_Absolute timestamp,
     296             :                    const struct TALER_MerchantPublicKeyP *merchant_pub,
     297             :                    struct GNUNET_TIME_Absolute refund_deadline,
     298             :                    const struct TALER_CoinSpendSignatureP *coin_sig)
     299             : {
     300             :   struct TALER_DepositRequestPS dr;
     301             :   struct TALER_CoinPublicInfo coin_info;
     302             : 
     303          12 :   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
     304          12 :   dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
     305          12 :   dr.h_contract_terms = *h_contract_terms;
     306          12 :   dr.h_wire = *h_wire;
     307          12 :   dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
     308          12 :   dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
     309          12 :   TALER_amount_hton (&dr.amount_with_fee,
     310             :                      amount);
     311          12 :   TALER_amount_hton (&dr.deposit_fee,
     312             :                      &dki->fee_deposit);
     313          12 :   dr.merchant = *merchant_pub;
     314          12 :   dr.coin_pub = *coin_pub;
     315          12 :   if (GNUNET_OK !=
     316          12 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
     317             :                                   &dr.purpose,
     318             :                                   &coin_sig->eddsa_signature,
     319             :                                   &coin_pub->eddsa_pub))
     320             :   {
     321           0 :     GNUNET_break_op (0);
     322           0 :     TALER_LOG_WARNING ("Invalid coin signature on /deposit request!\n");
     323             :     {
     324           0 :       TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
     325             :                        TALER_amount2s (amount));
     326           0 :       TALER_LOG_DEBUG ("... deposit_fee was %s\n",
     327             :                        TALER_amount2s (&dki->fee_deposit));
     328             :     }
     329             : 
     330           0 :     return GNUNET_SYSERR;
     331             :   }
     332             : 
     333             :   /* check coin signature */
     334          12 :   coin_info.coin_pub = *coin_pub;
     335          12 :   coin_info.denom_pub = *denom_pub;
     336          12 :   coin_info.denom_sig = *denom_sig;
     337          12 :   if (GNUNET_YES !=
     338          12 :       TALER_test_coin_valid (&coin_info))
     339             :   {
     340           0 :     GNUNET_break_op (0);
     341           0 :     TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
     342           0 :     return GNUNET_SYSERR;
     343             :   }
     344          12 :   if (0 < TALER_amount_cmp (&dki->fee_deposit,
     345             :                             amount))
     346             :   {
     347           0 :     GNUNET_break_op (0);
     348           0 :     TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
     349           0 :     return GNUNET_SYSERR;
     350             :   }
     351          12 :   return GNUNET_OK;
     352             : }
     353             : 
     354             : 
     355             : /**
     356             :  * Submit a deposit permission to the exchange and get the exchange's response.
     357             :  * Note that while we return the response verbatim to the caller for
     358             :  * further processing, we do already verify that the response is
     359             :  * well-formed (i.e. that signatures included in the response are all
     360             :  * valid).  If the exchange's reply is not well-formed, we return an
     361             :  * HTTP status code of zero to @a cb.
     362             :  *
     363             :  * We also verify that the @a coin_sig is valid for this deposit
     364             :  * request, and that the @a ub_sig is a valid signature for @a
     365             :  * coin_pub.  Also, the @a exchange must be ready to operate (i.e.  have
     366             :  * finished processing the /keys reply).  If either check fails, we do
     367             :  * NOT initiate the transaction with the exchange and instead return NULL.
     368             :  *
     369             :  * @param exchange the exchange handle; the exchange must be ready to operate
     370             :  * @param amount the amount to be deposited
     371             :  * @param wire_deadline date until which the merchant would like the exchange to settle the balance (advisory, the exchange cannot be
     372             :  *        forced to settle in the past or upon very short notice, but of course a well-behaved exchange will limit aggregation based on the advice received)
     373             :  * @param wire_details the merchant’s account details, in a format supported by the exchange
     374             :  * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
     375             :  * @param coin_pub coin’s public key
     376             :  * @param denom_pub denomination key with which the coin is signed
     377             :  * @param denom_sig exchange’s unblinded signature of the coin
     378             :  * @param timestamp timestamp when the contract was finalized, must not be too far in the future
     379             :  * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
     380             :  * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline
     381             :  * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key.
     382             :  * @param cb the callback to call when a reply for this request is available
     383             :  * @param cb_cls closure for the above callback
     384             :  * @return a handle for this request; NULL if the inputs are invalid (i.e.
     385             :  *         signatures fail to verify).  In this case, the callback is not called.
     386             :  */
     387             : struct TALER_EXCHANGE_DepositHandle *
     388          12 : TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
     389             :                         const struct TALER_Amount *amount,
     390             :                         struct GNUNET_TIME_Absolute wire_deadline,
     391             :                         json_t *wire_details,
     392             :                         const struct GNUNET_HashCode *h_contract_terms,
     393             :                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
     394             :                         const struct TALER_DenominationSignature *denom_sig,
     395             :                         const struct TALER_DenominationPublicKey *denom_pub,
     396             :                         struct GNUNET_TIME_Absolute timestamp,
     397             :                         const struct TALER_MerchantPublicKeyP *merchant_pub,
     398             :                         struct GNUNET_TIME_Absolute refund_deadline,
     399             :                         const struct TALER_CoinSpendSignatureP *coin_sig,
     400             :                         TALER_EXCHANGE_DepositResultCallback cb,
     401             :                         void *cb_cls)
     402             : {
     403             :   const struct TALER_EXCHANGE_Keys *key_state;
     404             :   const struct TALER_EXCHANGE_DenomPublicKey *dki;
     405             :   struct TALER_EXCHANGE_DepositHandle *dh;
     406             :   struct GNUNET_CURL_Context *ctx;
     407             :   json_t *deposit_obj;
     408             :   CURL *eh;
     409             :   struct GNUNET_HashCode h_wire;
     410             :   struct TALER_Amount amount_without_fee;
     411             : 
     412          12 :   (void) GNUNET_TIME_round_abs (&wire_deadline);
     413          12 :   (void) GNUNET_TIME_round_abs (&refund_deadline);
     414          12 :   GNUNET_assert (refund_deadline.abs_value_us <= wire_deadline.abs_value_us);
     415          12 :   GNUNET_assert (GNUNET_YES ==
     416             :                  MAH_handle_is_ready (exchange));
     417             :   /* initialize h_wire */
     418          12 :   if (GNUNET_OK !=
     419          12 :       TALER_JSON_hash (wire_details,
     420             :                        &h_wire))
     421             :   {
     422           0 :     GNUNET_break (0);
     423           0 :     return NULL;
     424             :   }
     425          12 :   key_sta4e = tALDR_EXCHANGE_get_keys (exchange);
     426          12 :   dki = TALER_EXCHANGE_get_denomination_key (key_state,
     427             :                                              denom_pub);
     428          12 :   GNUNET_assert (NULL != dki);
     429          12 :   GNUNET_assert (GNUNET_SYSERR !=
     430             :                  TALER_amount_subtract (&amount_without_fee,
     431             :                                         amount,
     432             :                                         &dki->fee_deposit));
     433          12 :   if (GNUNET_OK !=
     434          12 :       verify_signatures (dki,
     435             :                          amount,
     436             :                          &h_wire,
     437             :                          h_contract_terms,
     438             :                          coin_pub,
     439             :                          denom_sig,
     440             :                          denom_pub,
     441             :                          timestamp,
     442             :                          merchant_pub,
     443             :                          refund_deadline,
     444             :                          coin_sig))
     445             :   {
     446           0 :     GNUNET_break_op (0);
     447           0 :     return NULL;
     448             :   }
     449             : 
     450          36 :   deposit_obj = json_pack ("{s:o, s:O," /* f/wire */
     451             :                            " s:o, s:o," /* H_wire, h_contract_terms */
     452             :                            " s:o, s:o," /* coin_pub, denom_pub */
     453             :                            " s:o, s:o," /* ub_sig, timestamp */
     454             :                            " s:o," /* merchant_pub */
     455             :                            " s:o, s:o," /* refund_deadline, wire_deadline */
     456             :                            " s:o}",     /* coin_sig */
     457             :                            "f", TALER_JSON_from_amount (amount),
     458             :                            "wire", wire_details,
     459             :                            "H_wire", GNUNET_JSON_from_data_auto (&h_wire),
     460             :                            "h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
     461             :                            "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
     462          12 :                            "denom_pub", GNUNET_JSON_from_rsa_public_key (denom_pub->rsa_public_key),
     463          12 :                            "ub_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature),
     464             :                            "timestamp", GNUNET_JSON_from_time_abs (timestamp),
     465             :                            "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
     466             :                            "refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline),
     467             :                            "wire_transfer_deadline", GNUNET_JSON_from_time_abs (wire_deadline),
     468             :                            "coin_sig", GNUNET_JSON_from_data_auto (coin_sig)
     469             :                            );
     470          12 :   if (NULL == deposit_obj)
     471             :   {
     472           0 :     GNUNET_break (0);
     473           0 :     return NULL;
     474             :   }
     475             : 
     476          12 :   dh = GNUNET_new (struct TALER_EXCHANGE_DepositHandle);
     477          12 :   dh->exchange = exchange;
     478          12 :   dh->cb = cb;
     479          12 :   dh->cb_cls = cb_cls;
     480          12 :   dh->url = MAH_path_to_url (exchange, "/deposit");
     481          12 :   dh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
     482          12 :   dh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
     483          12 :   dh->depconf.h_contract_terms = *h_contract_terms;
     484          12 :   dh->depconf.h_wire = h_wire;
     485          12 :   dh->depconf.timestamp = GNUNET_TIME_absolute_hton (timestamp);
     486          12 :   dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
     487          12 :   TALER_amount_hton (&dh->depconf.amount_without_fee,
     488             :                      &amount_without_fee);
     489          12 :   dh->depconf.coin_pub = *coin_pub;
     490          12 :   dh->depconf.merchant = *merchant_pub;
     491          12 :   dh->amount_with_fee = *amount;
     492          12 :   dh->coin_value = dki->value;
     493             : 
     494          12 :   eh = curl_easy_init ();
     495          12 :   GNUNET_assert (NULL != (dh->json_enc =
     496             :                           json_dumps (deposit_obj,
     497             :                                       JSON_COMPACT)));
     498          12 :   json_decref (deposit_obj);
     499          12 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     500             :               "URL for deposit: `%s'\n",
     501             :               dh->url);
     502          12 :   GNUNET_assert (CURLE_OK ==
     503             :                  curl_easy_setopt (eh,
     504             :                                    CURLOPT_URL,
     505             :                                    dh->url));
     506          12 :   GNUNET_assert (CURLE_OK ==
     507             :                  curl_easy_setopt (eh,
     508             :                                    CURLOPT_POSTFIELDS,
     509             :                                    dh->json_enc));
     510          12 :   GNUNET_assert (CURLE_OK ==
     511             :                  curl_easy_setopt (eh,
     512             :                                    CURLOPT_POSTFIELDSIZE,
     513             :                                    strlen (dh->json_enc)));
     514          12 :   ctx = MAH_handle_to_context (exchange);
     515          12 :   dh->job = GNUNET_CURL_job_add (ctx,
     516             :                                  eh,
     517             :                                  GNUNET_YES,
     518             :                                  &handle_deposit_finished,
     519             :                                  dh);
     520          12 :   return dh;
     521             : }
     522             : 
     523             : 
     524             : /**
     525             :  * Cancel a deposit permission request.  This function cannot be used
     526             :  * on a request handle if a response is already served for it.
     527             :  *
     528             :  * @param deposit the deposit permission request handle
     529             :  */
     530             : void
     531          12 : TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit)
     532             : {
     533          12 :   if (NULL != deposit->job)
     534             :   {
     535           0 :     GNUNET_CURL_job_cancel (deposit->job);
     536           0 :     deposit->job = NULL;
     537             :   }
     538          12 :   GNUNET_free (deposit->url);
     539          12 :   GNUNET_free (deposit->json_enc);
     540          12 :   GNUNET_free (deposit);
     541          12 : }
     542             : 
     543             : 
     544             : /* end of exchange_api_deposit.c */

Generated by: LCOV version 1.13