LCOV - code coverage report
Current view: top level - exchange - taler-exchange-httpd_responses.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 0 283 0.0 %
Date: 2019-12-06 06:02:21 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2017 Inria & GNUnet e.V.
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU Affero 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 Affero General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU Affero General Public License along with
      14             :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15             : */
      16             : /**
      17             :  * @file taler-exchange-httpd_responses.c
      18             :  * @brief API for generating genric replies of the exchange; these
      19             :  *        functions are called TEH_RESPONSE_reply_ and they generate
      20             :  *        and queue MHD response objects for a given connection.
      21             :  * @author Florian Dold
      22             :  * @author Benedikt Mueller
      23             :  * @author Christian Grothoff
      24             :  */
      25             : #include "platform.h"
      26             : #include <zlib.h>
      27             : #include "taler-exchange-httpd_responses.h"
      28             : #include "taler_util.h"
      29             : #include "taler_json_lib.h"
      30             : #include "taler_mhd_lib.h"
      31             : #include "taler-exchange-httpd_keystate.h"
      32             : 
      33             : /**
      34             :  * Enable checking signatures before we hand them out
      35             :  * (even though we should have checked them before).
      36             :  * So technically these checks are redundant, but good
      37             :  * during testing.
      38             :  */
      39             : #define SANITY_CHECKS_ON 1
      40             : 
      41             : 
      42             : /**
      43             :  * Compile the transaction history of a coin into a JSON object.
      44             :  *
      45             :  * @param tl transaction history to JSON-ify
      46             :  * @return json representation of the @a rh, NULL on error
      47             :  */
      48             : json_t *
      49           0 : TEH_RESPONSE_compile_transaction_history (const struct
      50             :                                           TALER_EXCHANGEDB_TransactionList *tl)
      51             : {
      52             :   json_t *history;
      53             : 
      54           0 :   history = json_array ();
      55           0 :   if (NULL == history)
      56             :   {
      57           0 :     GNUNET_break (0); /* out of memory!? */
      58           0 :     return NULL;
      59             :   }
      60           0 :   for (const struct TALER_EXCHANGEDB_TransactionList *pos = tl;
      61             :        NULL != pos;
      62           0 :        pos = pos->next)
      63             :   {
      64           0 :     switch (pos->type)
      65             :     {
      66           0 :     case TALER_EXCHANGEDB_TT_DEPOSIT:
      67             :       {
      68             :         struct TALER_DepositRequestPS dr;
      69           0 :         const struct TALER_EXCHANGEDB_Deposit *deposit = pos->details.deposit;
      70             : 
      71           0 :         dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
      72           0 :         dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
      73           0 :         dr.h_contract_terms = deposit->h_contract_terms;
      74           0 :         dr.h_wire = deposit->h_wire;
      75           0 :         dr.timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp);
      76           0 :         dr.refund_deadline = GNUNET_TIME_absolute_hton (
      77             :           deposit->refund_deadline);
      78           0 :         TALER_amount_hton (&dr.amount_with_fee,
      79             :                            &deposit->amount_with_fee);
      80           0 :         TALER_amount_hton (&dr.deposit_fee,
      81             :                            &deposit->deposit_fee);
      82           0 :         dr.merchant = deposit->merchant_pub;
      83           0 :         dr.coin_pub = deposit->coin.coin_pub;
      84             : #if SANITY_CHECKS_ON
      85             :         /* internal sanity check before we hand out a bogus sig... */
      86           0 :         if (GNUNET_OK !=
      87           0 :             GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
      88             :                                         &dr.purpose,
      89             :                                         &deposit->csig.eddsa_signature,
      90             :                                         &deposit->coin.coin_pub.eddsa_pub))
      91             :         {
      92           0 :           GNUNET_break (0);
      93           0 :           json_decref (history);
      94           0 :           return NULL;
      95             :         }
      96             : #endif
      97           0 :         if (0 !=
      98           0 :             json_array_append_new (history,
      99             :                                    json_pack (
     100             :                                      "{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
     101             :                                      "type", "DEPOSIT",
     102             :                                      "amount", TALER_JSON_from_amount (
     103             :                                        &deposit->amount_with_fee),
     104             :                                      "deposit_fee",
     105             :                                      TALER_JSON_from_amount (
     106             :                                        &deposit->deposit_fee),
     107             :                                      "timestamp",
     108             :                                      GNUNET_JSON_from_time_abs (
     109             :                                        deposit->timestamp),
     110             :                                      "refund_deadline",
     111             :                                      GNUNET_JSON_from_time_abs (
     112             :                                        deposit->refund_deadline),
     113             :                                      "merchant_pub",
     114           0 :                                      GNUNET_JSON_from_data_auto (
     115             :                                        &deposit->merchant_pub),
     116             :                                      "h_contract_terms",
     117           0 :                                      GNUNET_JSON_from_data_auto (
     118             :                                        &deposit->h_contract_terms),
     119             :                                      "h_wire",
     120           0 :                                      GNUNET_JSON_from_data_auto (
     121             :                                        &deposit->h_wire),
     122             :                                      "coin_sig",
     123           0 :                                      GNUNET_JSON_from_data_auto (
     124             :                                        &deposit->csig))))
     125             :         {
     126           0 :           GNUNET_break (0);
     127           0 :           json_decref (history);
     128           0 :           return NULL;
     129             :         }
     130           0 :         break;
     131             :       }
     132           0 :     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
     133             :       {
     134             :         struct TALER_RefreshMeltCoinAffirmationPS ms;
     135           0 :         const struct TALER_EXCHANGEDB_RefreshMelt *melt = pos->details.melt;
     136             : 
     137           0 :         ms.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
     138           0 :         ms.purpose.size = htonl (sizeof (struct
     139             :                                          TALER_RefreshMeltCoinAffirmationPS));
     140           0 :         ms.rc = melt->session.rc;
     141           0 :         TALER_amount_hton (&ms.amount_with_fee,
     142             :                            &melt->session.amount_with_fee);
     143           0 :         TALER_amount_hton (&ms.melt_fee,
     144             :                            &melt->melt_fee);
     145           0 :         ms.coin_pub = melt->session.coin.coin_pub;
     146             : #if SANITY_CHECKS_ON
     147             :         /* internal sanity check before we hand out a bogus sig... */
     148           0 :         if (GNUNET_OK !=
     149           0 :             GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
     150             :                                         &ms.purpose,
     151             :                                         &melt->session.coin_sig.eddsa_signature,
     152             :                                         &melt->session.coin.coin_pub.eddsa_pub))
     153             :         {
     154           0 :           GNUNET_break (0);
     155           0 :           json_decref (history);
     156           0 :           return NULL;
     157             :         }
     158             : #endif
     159           0 :         if (0 !=
     160           0 :             json_array_append_new (history,
     161             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o}",
     162             :                                               "type", "MELT",
     163             :                                               "amount", TALER_JSON_from_amount (
     164             :                                                 &melt->session.amount_with_fee),
     165             :                                               "melt_fee",
     166             :                                               TALER_JSON_from_amount (
     167             :                                                 &melt->melt_fee),
     168           0 :                                               "rc", GNUNET_JSON_from_data_auto (
     169             :                                                 &melt->session.rc),
     170             :                                               "coin_sig",
     171           0 :                                               GNUNET_JSON_from_data_auto (
     172             :                                                 &melt->session.coin_sig))))
     173             :         {
     174           0 :           GNUNET_break (0);
     175           0 :           json_decref (history);
     176           0 :           return NULL;
     177             :         }
     178             :       }
     179           0 :       break;
     180           0 :     case TALER_EXCHANGEDB_TT_REFUND:
     181             :       {
     182             :         struct TALER_RefundRequestPS rr;
     183           0 :         const struct TALER_EXCHANGEDB_Refund *refund = pos->details.refund;
     184             :         struct TALER_Amount value;
     185             : 
     186           0 :         if (GNUNET_OK !=
     187           0 :             TALER_amount_subtract (&value,
     188             :                                    &refund->refund_amount,
     189             :                                    &refund->refund_fee))
     190             :         {
     191           0 :           GNUNET_break (0);
     192           0 :           json_decref (history);
     193           0 :           return NULL;
     194             :         }
     195           0 :         rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
     196           0 :         rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
     197           0 :         rr.h_contract_terms = refund->h_contract_terms;
     198           0 :         rr.coin_pub = refund->coin.coin_pub;
     199           0 :         rr.merchant = refund->merchant_pub;
     200           0 :         rr.rtransaction_id = GNUNET_htonll (refund->rtransaction_id);
     201           0 :         TALER_amount_hton (&rr.refund_amount,
     202             :                            &refund->refund_amount);
     203           0 :         TALER_amount_hton (&rr.refund_fee,
     204             :                            &refund->refund_fee);
     205             : #if SANITY_CHECKS_ON
     206             :         /* internal sanity check before we hand out a bogus sig... */
     207           0 :         if (GNUNET_OK !=
     208           0 :             GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
     209             :                                         &rr.purpose,
     210             :                                         &refund->merchant_sig.eddsa_sig,
     211             :                                         &refund->merchant_pub.eddsa_pub))
     212             :         {
     213           0 :           GNUNET_break (0);
     214           0 :           json_decref (history);
     215           0 :           return NULL;
     216             :         }
     217             : #endif
     218           0 :         if (0 !=
     219           0 :             json_array_append_new (history,
     220             :                                    json_pack (
     221             :                                      "{s:s, s:o, s:o, s:o, s:o, s:I, s:o}",
     222             :                                      "type", "REFUND",
     223             :                                      "amount", TALER_JSON_from_amount (
     224             :                                        &value),
     225             :                                      "refund_fee",
     226             :                                      TALER_JSON_from_amount (
     227             :                                        &refund->refund_fee),
     228             :                                      "h_contract_terms",
     229           0 :                                      GNUNET_JSON_from_data_auto (
     230             :                                        &refund->h_contract_terms),
     231             :                                      "merchant_pub",
     232           0 :                                      GNUNET_JSON_from_data_auto (
     233             :                                        &refund->merchant_pub),
     234             :                                      "rtransaction_id",
     235           0 :                                      (json_int_t) refund->rtransaction_id,
     236             :                                      "merchant_sig",
     237           0 :                                      GNUNET_JSON_from_data_auto (
     238             :                                        &refund->merchant_sig))))
     239             :         {
     240           0 :           GNUNET_break (0);
     241           0 :           json_decref (history);
     242           0 :           return NULL;
     243             :         }
     244             :       }
     245           0 :       break;
     246           0 :     case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
     247             :       {
     248           0 :         struct TALER_EXCHANGEDB_PaybackRefresh *pr =
     249             :           pos->details.old_coin_payback;
     250             :         struct TALER_PaybackRefreshConfirmationPS pc;
     251             :         struct TALER_ExchangePublicKeyP epub;
     252             :         struct TALER_ExchangeSignatureP esig;
     253             : 
     254           0 :         pc.purpose.purpose = htonl (
     255             :           TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH);
     256           0 :         pc.purpose.size = htonl (sizeof (pc));
     257           0 :         pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
     258           0 :         TALER_amount_hton (&pc.payback_amount,
     259           0 :                            &pr->value);
     260           0 :         pc.coin_pub = pr->coin.coin_pub;
     261           0 :         pc.old_coin_pub = pr->old_coin_pub;
     262           0 :         if (GNUNET_OK !=
     263           0 :             TEH_KS_sign (&pc.purpose,
     264             :                          &epub,
     265             :                          &esig))
     266             :         {
     267           0 :           GNUNET_break (0);
     268           0 :           json_decref (history);
     269           0 :           return NULL;
     270             :         }
     271             :         /* NOTE: we could also provide coin_pub's coin_sig, denomination key hash and
     272             :            the denomination key's RSA signature over coin_pub, but as the
     273             :            wallet should really already have this information (and cannot
     274             :            check or do anything with it anyway if it doesn't), it seems
     275           0 :            strictly unnecessary. */if (0 !=
     276           0 :             json_array_append_new (history,
     277             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
     278             :                                               "type", "OLD-COIN-PAYBACK",
     279             :                                               "amount", TALER_JSON_from_amount (
     280           0 :                                                 &pr->value),
     281             :                                               "exchange_sig",
     282             :                                               GNUNET_JSON_from_data_auto (
     283             :                                                 &esig),
     284             :                                               "exchange_pub",
     285             :                                               GNUNET_JSON_from_data_auto (
     286             :                                                 &epub),
     287             :                                               "coin_pub",
     288           0 :                                               GNUNET_JSON_from_data_auto (
     289             :                                                 &pr->coin.coin_pub),
     290             :                                               "timestamp",
     291             :                                               GNUNET_JSON_from_time_abs (
     292             :                                                 pr->timestamp))))
     293             :         {
     294           0 :           GNUNET_break (0);
     295           0 :           json_decref (history);
     296           0 :           return NULL;
     297             :         }
     298           0 :         break;
     299             :       }
     300           0 :     case TALER_EXCHANGEDB_TT_PAYBACK:
     301             :       {
     302           0 :         const struct TALER_EXCHANGEDB_Payback *payback = pos->details.payback;
     303             :         struct TALER_PaybackConfirmationPS pc;
     304             :         struct TALER_ExchangePublicKeyP epub;
     305             :         struct TALER_ExchangeSignatureP esig;
     306             : 
     307           0 :         pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
     308           0 :         pc.purpose.size = htonl (sizeof (pc));
     309           0 :         pc.timestamp = GNUNET_TIME_absolute_hton (payback->timestamp);
     310           0 :         TALER_amount_hton (&pc.payback_amount,
     311             :                            &payback->value);
     312           0 :         pc.coin_pub = payback->coin.coin_pub;
     313           0 :         pc.reserve_pub = payback->reserve_pub;
     314           0 :         if (GNUNET_OK !=
     315           0 :             TEH_KS_sign (&pc.purpose,
     316             :                          &epub,
     317             :                          &esig))
     318             :         {
     319           0 :           GNUNET_break (0);
     320           0 :           json_decref (history);
     321           0 :           return NULL;
     322             :         }
     323           0 :         if (0 !=
     324           0 :             json_array_append_new (history,
     325             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
     326             :                                               "type", "PAYBACK",
     327             :                                               "amount", TALER_JSON_from_amount (
     328             :                                                 &payback->value),
     329             :                                               "exchange_sig",
     330             :                                               GNUNET_JSON_from_data_auto (
     331             :                                                 &esig),
     332             :                                               "exchange_pub",
     333             :                                               GNUNET_JSON_from_data_auto (
     334             :                                                 &epub),
     335             :                                               "reserve_pub",
     336           0 :                                               GNUNET_JSON_from_data_auto (
     337             :                                                 &payback->reserve_pub),
     338             :                                               "timestamp",
     339             :                                               GNUNET_JSON_from_time_abs (
     340             :                                                 payback->timestamp))))
     341             :         {
     342           0 :           GNUNET_break (0);
     343           0 :           json_decref (history);
     344           0 :           return NULL;
     345             :         }
     346             :       }
     347           0 :       break;
     348           0 :     case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
     349             :       {
     350           0 :         struct TALER_EXCHANGEDB_PaybackRefresh *pr =
     351             :           pos->details.payback_refresh;
     352             :         struct TALER_PaybackRefreshConfirmationPS pc;
     353             :         struct TALER_ExchangePublicKeyP epub;
     354             :         struct TALER_ExchangeSignatureP esig;
     355             : 
     356           0 :         pc.purpose.purpose = htonl (
     357             :           TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH);
     358           0 :         pc.purpose.size = htonl (sizeof (pc));
     359           0 :         pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
     360           0 :         TALER_amount_hton (&pc.payback_amount,
     361           0 :                            &pr->value);
     362           0 :         pc.coin_pub = pr->coin.coin_pub;
     363           0 :         pc.old_coin_pub = pr->old_coin_pub;
     364           0 :         if (GNUNET_OK !=
     365           0 :             TEH_KS_sign (&pc.purpose,
     366             :                          &epub,
     367             :                          &esig))
     368             :         {
     369           0 :           GNUNET_break (0);
     370           0 :           json_decref (history);
     371           0 :           return NULL;
     372             :         }
     373             :         /* NOTE: we could also provide coin_pub's coin_sig, denomination key
     374             :            hash and the denomination key's RSA signature over coin_pub, but as
     375             :            the wallet should really already have this information (and cannot
     376             :            check or do anything with it anyway if it doesn't), it seems
     377           0 :            strictly unnecessary. */if (0 !=
     378           0 :             json_array_append_new (history,
     379             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
     380             :                                               "type", "PAYBACK-REFRESH",
     381             :                                               "amount", TALER_JSON_from_amount (
     382           0 :                                                 &pr->value),
     383             :                                               "exchange_sig",
     384             :                                               GNUNET_JSON_from_data_auto (
     385             :                                                 &esig),
     386             :                                               "exchange_pub",
     387             :                                               GNUNET_JSON_from_data_auto (
     388             :                                                 &epub),
     389             :                                               "old_coin_pub",
     390           0 :                                               GNUNET_JSON_from_data_auto (
     391             :                                                 &pr->old_coin_pub),
     392             :                                               "timestamp",
     393             :                                               GNUNET_JSON_from_time_abs (
     394             :                                                 pr->timestamp))))
     395             :         {
     396           0 :           GNUNET_break (0);
     397           0 :           json_decref (history);
     398           0 :           return NULL;
     399             :         }
     400           0 :         break;
     401             :       }
     402           0 :     default:
     403           0 :       GNUNET_assert (0);
     404             :     }
     405             :   }
     406           0 :   return history;
     407             : }
     408             : 
     409             : 
     410             : /**
     411             :  * Send proof that a request is invalid to client because of
     412             :  * insufficient funds.  This function will create a message with all
     413             :  * of the operations affecting the coin that demonstrate that the coin
     414             :  * has insufficient value.
     415             :  *
     416             :  * @param connection connection to the client
     417             :  * @param ec error code to return
     418             :  * @param tl transaction list to use to build reply
     419             :  * @return MHD result code
     420             :  */
     421             : int
     422           0 : TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection,
     423             :                                             enum TALER_ErrorCode ec,
     424             :                                             const struct
     425             :                                             TALER_EXCHANGEDB_TransactionList *tl)
     426             : {
     427             :   json_t *history;
     428             : 
     429           0 :   history = TEH_RESPONSE_compile_transaction_history (tl);
     430           0 :   if (NULL == history)
     431           0 :     return TALER_MHD_reply_with_error (connection,
     432             :                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
     433             :                                        TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
     434             :                                        "failed to convert transaction history to JSON");
     435           0 :   return TALER_MHD_reply_json_pack (connection,
     436             :                                     MHD_HTTP_CONFLICT,
     437             :                                     "{s:s, s:I, s:o}",
     438             :                                     "error", "insufficient funds",
     439             :                                     "code", (json_int_t) ec,
     440             :                                     "history", history);
     441             : }
     442             : 
     443             : 
     444             : /**
     445             :  * Compile the history of a reserve into a JSON object
     446             :  * and calculate the total balance.
     447             :  *
     448             :  * @param rh reserve history to JSON-ify
     449             :  * @param[out] balance set to current reserve balance
     450             :  * @return json representation of the @a rh, NULL on error
     451             :  */
     452             : json_t *
     453           0 : TEH_RESPONSE_compile_reserve_history (const struct
     454             :                                       TALER_EXCHANGEDB_ReserveHistory *rh,
     455             :                                       struct TALER_Amount *balance)
     456             : {
     457             :   struct TALER_Amount deposit_total;
     458             :   struct TALER_Amount withdraw_total;
     459             :   json_t *json_history;
     460             :   int ret;
     461             : 
     462           0 :   json_history = json_array ();
     463           0 :   ret = 0;
     464           0 :   for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
     465             :        NULL != pos;
     466           0 :        pos = pos->next)
     467             :   {
     468           0 :     switch (pos->type)
     469             :     {
     470           0 :     case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
     471           0 :       if (0 == (1 & ret))
     472           0 :         deposit_total = pos->details.bank->amount;
     473           0 :       else if (GNUNET_OK !=
     474           0 :                TALER_amount_add (&deposit_total,
     475             :                                  &deposit_total,
     476           0 :                                  &pos->details.bank->amount))
     477             :       {
     478           0 :         GNUNET_break (0);
     479           0 :         json_decref (json_history);
     480           0 :         return NULL;
     481             :       }
     482           0 :       ret |= 1;
     483           0 :       if (0 !=
     484           0 :           json_array_append_new (json_history,
     485             :                                  json_pack ("{s:s, s:o, s:s, s:o, s:o}",
     486             :                                             "type", "DEPOSIT",
     487             :                                             "timestamp",
     488             :                                             GNUNET_JSON_from_time_abs (
     489           0 :                                               pos->details.bank->execution_date),
     490             :                                             "sender_account_url",
     491           0 :                                             pos->details.bank->
     492             :                                             sender_account_details,
     493             :                                             "wire_reference",
     494             :                                             GNUNET_JSON_from_data (
     495           0 :                                               pos->details.bank->wire_reference,
     496             :                                               pos
     497           0 :                                               ->details.
     498             :                                               bank->wire_reference_size),
     499             :                                             "amount", TALER_JSON_from_amount (
     500           0 :                                               &pos->details.bank->amount))))
     501             :       {
     502           0 :         GNUNET_break (0);
     503           0 :         json_decref (json_history);
     504           0 :         return NULL;
     505             :       }
     506           0 :       break;
     507           0 :     case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
     508             :       {
     509             :         struct TALER_Amount value;
     510             : 
     511           0 :         value = pos->details.withdraw->amount_with_fee;
     512           0 :         if (0 == (2 & ret))
     513             :         {
     514           0 :           withdraw_total = value;
     515             :         }
     516             :         else
     517             :         {
     518           0 :           if (GNUNET_OK !=
     519           0 :               TALER_amount_add (&withdraw_total,
     520             :                                 &withdraw_total,
     521             :                                 &value))
     522             :           {
     523           0 :             GNUNET_break (0);
     524           0 :             json_decref (json_history);
     525           0 :             return NULL;
     526             :           }
     527             :         }
     528           0 :         ret |= 2;
     529           0 :         if (0 !=
     530           0 :             json_array_append_new (json_history,
     531             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
     532             :                                               "type", "WITHDRAW",
     533             :                                               "reserve_sig",
     534           0 :                                               GNUNET_JSON_from_data_auto (
     535             :                                                 &pos->details.withdraw->
     536             :                                                 reserve_sig),
     537             :                                               "h_coin_envelope",
     538           0 :                                               GNUNET_JSON_from_data_auto (
     539             :                                                 &pos->details.withdraw->
     540             :                                                 h_coin_envelope),
     541             :                                               "h_denom_pub",
     542           0 :                                               GNUNET_JSON_from_data_auto (
     543             :                                                 &pos->details.withdraw->
     544             :                                                 denom_pub_hash),
     545             :                                               "withdraw_fee",
     546             :                                               TALER_JSON_from_amount (
     547           0 :                                                 &pos->details.withdraw->
     548             :                                                 withdraw_fee),
     549             :                                               "amount", TALER_JSON_from_amount (
     550             :                                                 &value))))
     551             :         {
     552           0 :           GNUNET_break (0);
     553           0 :           json_decref (json_history);
     554           0 :           return NULL;
     555             :         }
     556             :       }
     557           0 :       break;
     558           0 :     case TALER_EXCHANGEDB_RO_PAYBACK_COIN:
     559             :       {
     560             :         const struct TALER_EXCHANGEDB_Payback *payback;
     561             :         struct TALER_PaybackConfirmationPS pc;
     562             :         struct TALER_ExchangePublicKeyP pub;
     563             :         struct TALER_ExchangeSignatureP sig;
     564             : 
     565           0 :         payback = pos->details.payback;
     566           0 :         if (0 == (1 & ret))
     567           0 :           deposit_total = payback->value;
     568           0 :         else if (GNUNET_OK !=
     569           0 :                  TALER_amount_add (&deposit_total,
     570             :                                    &deposit_total,
     571             :                                    &payback->value))
     572             :         {
     573           0 :           GNUNET_break (0);
     574           0 :           json_decref (json_history);
     575           0 :           return NULL;
     576             :         }
     577           0 :         ret |= 1;
     578           0 :         pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
     579           0 :         pc.purpose.size = htonl (sizeof (struct TALER_PaybackConfirmationPS));
     580           0 :         pc.timestamp = GNUNET_TIME_absolute_hton (payback->timestamp);
     581           0 :         TALER_amount_hton (&pc.payback_amount,
     582             :                            &payback->value);
     583           0 :         pc.coin_pub = payback->coin.coin_pub;
     584           0 :         pc.reserve_pub = payback->reserve_pub;
     585           0 :         if (GNUNET_OK !=
     586           0 :             TEH_KS_sign (&pc.purpose,
     587             :                          &pub,
     588             :                          &sig))
     589             :         {
     590           0 :           GNUNET_break (0);
     591           0 :           json_decref (json_history);
     592           0 :           return NULL;
     593             :         }
     594             : 
     595           0 :         if (0 !=
     596           0 :             json_array_append_new (json_history,
     597             :                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
     598             :                                               "type", "PAYBACK",
     599             :                                               "exchange_pub",
     600             :                                               GNUNET_JSON_from_data_auto (&pub),
     601             :                                               "exchange_sig",
     602             :                                               GNUNET_JSON_from_data_auto (&sig),
     603             :                                               "timestamp",
     604             :                                               GNUNET_JSON_from_time_abs (
     605             :                                                 payback->timestamp),
     606             :                                               "amount", TALER_JSON_from_amount (
     607             :                                                 &payback->value),
     608             :                                               "coin_pub",
     609           0 :                                               GNUNET_JSON_from_data_auto (
     610             :                                                 &payback->coin.coin_pub))))
     611             :         {
     612           0 :           GNUNET_break (0);
     613           0 :           json_decref (json_history);
     614           0 :           return NULL;
     615             :         }
     616             :       }
     617           0 :       break;
     618           0 :     case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
     619             :       {
     620             :         struct TALER_ReserveCloseConfirmationPS rcc;
     621             :         struct TALER_ExchangePublicKeyP pub;
     622             :         struct TALER_ExchangeSignatureP sig;
     623             :         struct TALER_Amount value;
     624             : 
     625           0 :         value = pos->details.closing->amount;
     626           0 :         if (0 == (2 & ret))
     627             :         {
     628           0 :           withdraw_total = value;
     629             :         }
     630             :         else
     631             :         {
     632           0 :           if (GNUNET_OK !=
     633           0 :               TALER_amount_add (&withdraw_total,
     634             :                                 &withdraw_total,
     635             :                                 &value))
     636             :           {
     637           0 :             GNUNET_break (0);
     638           0 :             json_decref (json_history);
     639           0 :             return NULL;
     640             :           }
     641             :         }
     642           0 :         ret |= 2;
     643           0 :         rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
     644           0 :         rcc.purpose.size = htonl (sizeof (struct
     645             :                                           TALER_ReserveCloseConfirmationPS));
     646           0 :         rcc.timestamp = GNUNET_TIME_absolute_hton (
     647           0 :           pos->details.closing->execution_date);
     648           0 :         TALER_amount_hton (&rcc.closing_amount,
     649             :                            &value);
     650           0 :         TALER_amount_hton (&rcc.closing_fee,
     651           0 :                            &pos->details.closing->closing_fee);
     652           0 :         rcc.reserve_pub = pos->details.closing->reserve_pub;
     653           0 :         GNUNET_CRYPTO_hash (pos->details.closing->receiver_account_details,
     654           0 :                             strlen (
     655           0 :                               pos->details.closing->receiver_account_details)
     656             :                             + 1,
     657             :                             &rcc.h_wire);
     658           0 :         rcc.wtid = pos->details.closing->wtid;
     659           0 :         if (GNUNET_OK !=
     660           0 :             TEH_KS_sign (&rcc.purpose,
     661             :                          &pub,
     662             :                          &sig))
     663             :         {
     664           0 :           GNUNET_break (0);
     665           0 :           json_decref (json_history);
     666           0 :           return NULL;
     667             :         }
     668           0 :         if (0 !=
     669           0 :             json_array_append_new (json_history,
     670             :                                    json_pack (
     671             :                                      "{s:s, s:s, s:o, s:o, s:o, s:o, s:o, s:o}",
     672             :                                      "type", "CLOSING",
     673             :                                      "receiver_account_details",
     674           0 :                                      pos->details.closing->
     675             :                                      receiver_account_details,
     676             :                                      "wtid",
     677           0 :                                      GNUNET_JSON_from_data_auto (
     678             :                                        &pos->details.closing->wtid),
     679             :                                      "exchange_pub",
     680             :                                      GNUNET_JSON_from_data_auto (&pub),
     681             :                                      "exchange_sig",
     682             :                                      GNUNET_JSON_from_data_auto (&sig),
     683             :                                      "timestamp",
     684             :                                      GNUNET_JSON_from_time_abs (
     685           0 :                                        pos->details.closing->execution_date),
     686             :                                      "amount", TALER_JSON_from_amount (
     687             :                                        &value),
     688             :                                      "closing_fee",
     689             :                                      TALER_JSON_from_amount (
     690           0 :                                        &pos->details.closing->closing_fee))))
     691             :         {
     692           0 :           GNUNET_break (0);
     693           0 :           json_decref (json_history);
     694           0 :           return NULL;
     695             :         }
     696             :       }
     697           0 :       break;
     698             :     }
     699           0 :   }
     700             : 
     701           0 :   if (0 == (1 & ret))
     702             :   {
     703           0 :     GNUNET_break (0);
     704           0 :     json_decref (json_history);
     705           0 :     return NULL;
     706             :   }
     707           0 :   if (0 == (2 & ret))
     708             :   {
     709             :     /* did not encounter any withdraw operations, set to zero */
     710           0 :     GNUNET_assert (GNUNET_OK ==
     711             :                    TALER_amount_get_zero (deposit_total.currency,
     712             :                                           &withdraw_total));
     713             :   }
     714           0 :   if (GNUNET_SYSERR ==
     715           0 :       TALER_amount_subtract (balance,
     716             :                              &deposit_total,
     717             :                              &withdraw_total))
     718             :   {
     719           0 :     GNUNET_break (0);
     720           0 :     json_decref (json_history);
     721           0 :     return NULL;
     722             :   }
     723             : 
     724           0 :   return json_history;
     725             : }
     726             : 
     727             : 
     728             : /* end of taler-exchange-httpd_responses.c */

Generated by: LCOV version 1.14