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

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2017, 2021 Taler Systems SA
       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_deposits_get.c
      18             :  * @brief Handle wire deposit tracking-related requests
      19             :  * @author Christian Grothoff
      20             :  */
      21             : #include "platform.h"
      22             : #include <gnunet/gnunet_util_lib.h>
      23             : #include <jansson.h>
      24             : #include <microhttpd.h>
      25             : #include <pthread.h>
      26             : #include "taler_json_lib.h"
      27             : #include "taler_mhd_lib.h"
      28             : #include "taler_signatures.h"
      29             : #include "taler-exchange-httpd_keys.h"
      30             : #include "taler-exchange-httpd_deposits_get.h"
      31             : #include "taler-exchange-httpd_responses.h"
      32             : 
      33             : 
      34             : /**
      35             :  * Closure for #handle_wtid_data.
      36             :  */
      37             : struct DepositWtidContext
      38             : {
      39             : 
      40             :   /**
      41             :    * Hash over the proposal data of the contract for which this deposit is made.
      42             :    */
      43             :   struct TALER_PrivateContractHashP h_contract_terms;
      44             : 
      45             :   /**
      46             :    * Hash over the wiring information of the merchant.
      47             :    */
      48             :   struct TALER_MerchantWireHashP h_wire;
      49             : 
      50             :   /**
      51             :    * The Merchant's public key.  The deposit inquiry request is to be
      52             :    * signed by the corresponding private key (using EdDSA).
      53             :    */
      54             :   struct TALER_MerchantPublicKeyP merchant;
      55             : 
      56             :   /**
      57             :    * The coin's public key.  This is the value that must have been
      58             :    * signed (blindly) by the Exchange.
      59             :    */
      60             :   struct TALER_CoinSpendPublicKeyP coin_pub;
      61             : 
      62             :   /**
      63             :    * Set by #handle_wtid data to the wire transfer ID.
      64             :    */
      65             :   struct TALER_WireTransferIdentifierRawP wtid;
      66             : 
      67             :   /**
      68             :    * Set by #handle_wtid data to the coin's contribution to the wire transfer.
      69             :    */
      70             :   struct TALER_Amount coin_contribution;
      71             : 
      72             :   /**
      73             :    * Set by #handle_wtid data to the fee charged to the coin.
      74             :    */
      75             :   struct TALER_Amount coin_fee;
      76             : 
      77             :   /**
      78             :    * Set by #handle_wtid data to the wire transfer execution time.
      79             :    */
      80             :   struct GNUNET_TIME_Timestamp execution_time;
      81             : 
      82             :   /**
      83             :    * Set by #handle_wtid to the coin contribution to the transaction
      84             :    * (that is, @e coin_contribution minus @e coin_fee).
      85             :    */
      86             :   struct TALER_Amount coin_delta;
      87             : 
      88             :   /**
      89             :    * KYC status information for the receiving account.
      90             :    */
      91             :   struct TALER_EXCHANGEDB_KycStatus kyc;
      92             : 
      93             :   /**
      94             :    * Set to #GNUNET_YES by #handle_wtid if the wire transfer is still pending
      95             :    * (and the above were not set).
      96             :    * Set to #GNUNET_SYSERR if there was a serious error.
      97             :    */
      98             :   enum GNUNET_GenericReturnValue pending;
      99             : };
     100             : 
     101             : 
     102             : /**
     103             :  * A merchant asked for details about a deposit.  Provide
     104             :  * them. Generates the 200 reply.
     105             :  *
     106             :  * @param connection connection to the client
     107             :  * @param ctx details to respond with
     108             :  * @return MHD result code
     109             :  */
     110             : static MHD_RESULT
     111           0 : reply_deposit_details (
     112             :   struct MHD_Connection *connection,
     113             :   const struct DepositWtidContext *ctx)
     114             : {
     115             :   struct TALER_ExchangePublicKeyP pub;
     116             :   struct TALER_ExchangeSignatureP sig;
     117             :   enum TALER_ErrorCode ec;
     118             : 
     119           0 :   if (TALER_EC_NONE !=
     120           0 :       (ec = TALER_exchange_online_confirm_wire_sign (
     121             :          &TEH_keys_exchange_sign_,
     122             :          &ctx->h_wire,
     123             :          &ctx->h_contract_terms,
     124             :          &ctx->wtid,
     125             :          &ctx->coin_pub,
     126             :          ctx->execution_time,
     127             :          &ctx->coin_delta,
     128             :          &pub,
     129             :          &sig)))
     130             :   {
     131           0 :     return TALER_MHD_reply_with_ec (connection,
     132             :                                     ec,
     133             :                                     NULL);
     134             :   }
     135           0 :   return TALER_MHD_REPLY_JSON_PACK (
     136             :     connection,
     137             :     MHD_HTTP_OK,
     138             :     GNUNET_JSON_pack_data_auto ("wtid",
     139             :                                 &ctx->wtid),
     140             :     GNUNET_JSON_pack_timestamp ("execution_time",
     141             :                                 ctx->execution_time),
     142             :     TALER_JSON_pack_amount ("coin_contribution",
     143             :                             &ctx->coin_delta),
     144             :     GNUNET_JSON_pack_data_auto ("exchange_sig",
     145             :                                 &sig),
     146             :     GNUNET_JSON_pack_data_auto ("exchange_pub",
     147             :                                 &pub));
     148             : }
     149             : 
     150             : 
     151             : /**
     152             :  * Execute a "deposits" GET.  Returns the transfer information
     153             :  * associated with the given deposit.
     154             :  *
     155             :  * If it returns a non-error code, the transaction logic MUST
     156             :  * NOT queue a MHD response.  IF it returns an hard error, the
     157             :  * transaction logic MUST queue a MHD response and set @a mhd_ret.  IF
     158             :  * it returns the soft error code, the function MAY be called again to
     159             :  * retry and MUST NOT queue a MHD response.
     160             :  *
     161             :  * @param cls closure of type `struct DepositWtidContext *`
     162             :  * @param connection MHD request which triggered the transaction
     163             :  * @param[out] mhd_ret set to MHD response status for @a connection,
     164             :  *             if transaction failed (!)
     165             :  * @return transaction status
     166             :  */
     167             : static enum GNUNET_DB_QueryStatus
     168           0 : deposits_get_transaction (void *cls,
     169             :                           struct MHD_Connection *connection,
     170             :                           MHD_RESULT *mhd_ret)
     171             : {
     172           0 :   struct DepositWtidContext *ctx = cls;
     173             :   enum GNUNET_DB_QueryStatus qs;
     174             :   bool pending;
     175             :   struct TALER_Amount fee;
     176             : 
     177           0 :   qs = TEH_plugin->lookup_transfer_by_deposit (TEH_plugin->cls,
     178           0 :                                                &ctx->h_contract_terms,
     179           0 :                                                &ctx->h_wire,
     180           0 :                                                &ctx->coin_pub,
     181           0 :                                                &ctx->merchant,
     182             :                                                &pending,
     183             :                                                &ctx->wtid,
     184             :                                                &ctx->execution_time,
     185             :                                                &ctx->coin_contribution,
     186             :                                                &fee,
     187             :                                                &ctx->kyc);
     188           0 :   if (0 > qs)
     189             :   {
     190           0 :     if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     191             :     {
     192           0 :       GNUNET_break (0);
     193           0 :       *mhd_ret = TALER_MHD_reply_with_error (connection,
     194             :                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
     195             :                                              TALER_EC_GENERIC_DB_FETCH_FAILED,
     196             :                                              NULL);
     197             :     }
     198           0 :     return qs;
     199             :   }
     200           0 :   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     201             :   {
     202           0 :     *mhd_ret = TALER_MHD_reply_with_error (connection,
     203             :                                            MHD_HTTP_NOT_FOUND,
     204             :                                            TALER_EC_EXCHANGE_DEPOSITS_GET_NOT_FOUND,
     205             :                                            NULL);
     206           0 :     return GNUNET_DB_STATUS_HARD_ERROR;
     207             :   }
     208             : 
     209           0 :   if (0 >
     210           0 :       TALER_amount_subtract (&ctx->coin_delta,
     211           0 :                              &ctx->coin_contribution,
     212             :                              &fee))
     213             :   {
     214           0 :     GNUNET_break (0);
     215           0 :     ctx->pending = GNUNET_SYSERR;
     216           0 :     return qs;
     217             :   }
     218           0 :   ctx->pending = (pending) ? GNUNET_YES : GNUNET_NO;
     219           0 :   return qs;
     220             : }
     221             : 
     222             : 
     223             : /**
     224             :  * Lookup and return the wire transfer identifier.
     225             :  *
     226             :  * @param connection the MHD connection to handle
     227             :  * @param ctx context of the signed request to execute
     228             :  * @return MHD result code
     229             :  */
     230             : static MHD_RESULT
     231           0 : handle_track_transaction_request (
     232             :   struct MHD_Connection *connection,
     233             :   struct DepositWtidContext *ctx)
     234             : {
     235             :   MHD_RESULT mhd_ret;
     236             : 
     237           0 :   if (GNUNET_OK !=
     238           0 :       TEH_DB_run_transaction (connection,
     239             :                               "handle deposits GET",
     240             :                               TEH_MT_REQUEST_OTHER,
     241             :                               &mhd_ret,
     242             :                               &deposits_get_transaction,
     243             :                               ctx))
     244           0 :     return mhd_ret;
     245           0 :   if (GNUNET_SYSERR == ctx->pending)
     246           0 :     return TALER_MHD_reply_with_error (connection,
     247             :                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
     248             :                                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
     249             :                                        "wire fees exceed aggregate in database");
     250           0 :   if (ctx->pending)
     251           0 :     return TALER_MHD_REPLY_JSON_PACK (
     252             :       connection,
     253             :       MHD_HTTP_ACCEPTED,
     254             :       GNUNET_JSON_pack_allow_null (
     255             :         (0 == ctx->kyc.requirement_row)
     256             :         ? GNUNET_JSON_pack_string ("requirement_row",
     257             :                                    NULL)
     258             :         : GNUNET_JSON_pack_uint64 ("requirement_row",
     259             :                                    ctx->kyc.requirement_row)),
     260             :       GNUNET_JSON_pack_bool ("kyc_ok",
     261             :                              ctx->kyc.ok),
     262             :       GNUNET_JSON_pack_timestamp ("execution_time",
     263             :                                   ctx->execution_time));
     264           0 :   return reply_deposit_details (connection,
     265             :                                 ctx);
     266             : }
     267             : 
     268             : 
     269             : MHD_RESULT
     270           0 : TEH_handler_deposits_get (struct TEH_RequestContext *rc,
     271             :                           const char *const args[4])
     272             : {
     273             :   enum GNUNET_GenericReturnValue res;
     274             :   struct TALER_MerchantSignatureP merchant_sig;
     275             :   struct DepositWtidContext ctx;
     276             : 
     277           0 :   if (GNUNET_OK !=
     278           0 :       GNUNET_STRINGS_string_to_data (args[0],
     279             :                                      strlen (args[0]),
     280             :                                      &ctx.h_wire,
     281             :                                      sizeof (ctx.h_wire)))
     282             :   {
     283           0 :     GNUNET_break_op (0);
     284           0 :     return TALER_MHD_reply_with_error (rc->connection,
     285             :                                        MHD_HTTP_BAD_REQUEST,
     286             :                                        TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE,
     287             :                                        args[0]);
     288             :   }
     289           0 :   if (GNUNET_OK !=
     290           0 :       GNUNET_STRINGS_string_to_data (args[1],
     291           0 :                                      strlen (args[1]),
     292             :                                      &ctx.merchant,
     293             :                                      sizeof (ctx.merchant)))
     294             :   {
     295           0 :     GNUNET_break_op (0);
     296           0 :     return TALER_MHD_reply_with_error (rc->connection,
     297             :                                        MHD_HTTP_BAD_REQUEST,
     298             :                                        TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB,
     299           0 :                                        args[1]);
     300             :   }
     301           0 :   if (GNUNET_OK !=
     302           0 :       GNUNET_STRINGS_string_to_data (args[2],
     303           0 :                                      strlen (args[2]),
     304             :                                      &ctx.h_contract_terms,
     305             :                                      sizeof (ctx.h_contract_terms)))
     306             :   {
     307           0 :     GNUNET_break_op (0);
     308           0 :     return TALER_MHD_reply_with_error (rc->connection,
     309             :                                        MHD_HTTP_BAD_REQUEST,
     310             :                                        TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS,
     311           0 :                                        args[2]);
     312             :   }
     313           0 :   if (GNUNET_OK !=
     314           0 :       GNUNET_STRINGS_string_to_data (args[3],
     315           0 :                                      strlen (args[3]),
     316             :                                      &ctx.coin_pub,
     317             :                                      sizeof (ctx.coin_pub)))
     318             :   {
     319           0 :     GNUNET_break_op (0);
     320           0 :     return TALER_MHD_reply_with_error (rc->connection,
     321             :                                        MHD_HTTP_BAD_REQUEST,
     322             :                                        TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB,
     323           0 :                                        args[3]);
     324             :   }
     325           0 :   res = TALER_MHD_parse_request_arg_data (rc->connection,
     326             :                                           "merchant_sig",
     327             :                                           &merchant_sig,
     328             :                                           sizeof (merchant_sig));
     329           0 :   if (GNUNET_SYSERR == res)
     330           0 :     return MHD_NO; /* internal error */
     331           0 :   if (GNUNET_NO == res)
     332           0 :     return MHD_YES; /* parse error */
     333           0 :   TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
     334             :   {
     335           0 :     if (GNUNET_OK !=
     336           0 :         TALER_merchant_deposit_verify (&ctx.merchant,
     337             :                                        &ctx.coin_pub,
     338             :                                        &ctx.h_contract_terms,
     339             :                                        &ctx.h_wire,
     340             :                                        &merchant_sig))
     341             :     {
     342           0 :       GNUNET_break_op (0);
     343           0 :       return TALER_MHD_reply_with_error (rc->connection,
     344             :                                          MHD_HTTP_FORBIDDEN,
     345             :                                          TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID,
     346             :                                          NULL);
     347             :     }
     348             :   }
     349             : 
     350           0 :   return handle_track_transaction_request (rc->connection,
     351             :                                            &ctx);
     352             : }
     353             : 
     354             : 
     355             : /* end of taler-exchange-httpd_deposits_get.c */

Generated by: LCOV version 1.14