LCOV - code coverage report
Current view: top level - exchange - taler-exchange-httpd_db.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 38 70 54.3 %
Date: 2025-06-22 12:09:43 Functions: 2 2 100.0 %

          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 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 <http://www.gnu.org/licenses/>
      15             : */
      16             : /**
      17             :  * @file taler-exchange-httpd_db.c
      18             :  * @brief Generic database operations for the exchange.
      19             :  * @author Christian Grothoff
      20             :  */
      21             : #include "taler/platform.h"
      22             : #include <gnunet/gnunet_db_lib.h>
      23             : #include <pthread.h>
      24             : #include <jansson.h>
      25             : #include <gnunet/gnunet_json_lib.h>
      26             : #include "taler/taler_error_codes.h"
      27             : #include "taler/taler_exchangedb_plugin.h"
      28             : #include "taler/taler_json_lib.h"
      29             : #include "taler/taler_mhd_lib.h"
      30             : #include "taler/taler_exchangedb_lib.h"
      31             : #include "taler-exchange-httpd_db.h"
      32             : #include "taler-exchange-httpd_responses.h"
      33             : 
      34             : 
      35             : enum GNUNET_DB_QueryStatus
      36         159 : TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
      37             :                      struct MHD_Connection *connection,
      38             :                      uint64_t *known_coin_id,
      39             :                      MHD_RESULT *mhd_ret)
      40             : {
      41             :   enum TALER_EXCHANGEDB_CoinKnownStatus cks;
      42             :   struct TALER_DenominationHashP h_denom_pub;
      43         159 :   struct TALER_AgeCommitmentHashP h_age_commitment = {{{0}}};
      44             : 
      45             :   /* make sure coin is 'known' in database */
      46         159 :   cks = TEH_plugin->ensure_coin_known (TEH_plugin->cls,
      47             :                                        coin,
      48             :                                        known_coin_id,
      49             :                                        &h_denom_pub,
      50             :                                        &h_age_commitment);
      51         159 :   switch (cks)
      52             :   {
      53          79 :   case TALER_EXCHANGEDB_CKS_ADDED:
      54          79 :     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
      55          78 :   case TALER_EXCHANGEDB_CKS_PRESENT:
      56          78 :     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
      57           0 :   case TALER_EXCHANGEDB_CKS_SOFT_FAIL:
      58           0 :     return GNUNET_DB_STATUS_SOFT_ERROR;
      59           0 :   case TALER_EXCHANGEDB_CKS_HARD_FAIL:
      60             :     *mhd_ret
      61           0 :       = TALER_MHD_reply_with_error (connection,
      62             :                                     MHD_HTTP_INTERNAL_SERVER_ERROR,
      63             :                                     TALER_EC_GENERIC_DB_STORE_FAILED,
      64             :                                     NULL);
      65           0 :     return GNUNET_DB_STATUS_HARD_ERROR;
      66           2 :   case TALER_EXCHANGEDB_CKS_DENOM_CONFLICT:
      67             :     /* The exchange has a seen this coin before, but with a different denomination.
      68             :      * Get the corresponding signature and sent it to the client as proof */
      69             :     {
      70             :       struct
      71             :       {
      72             :         struct TALER_DenominationPublicKey pub;
      73             :         struct TALER_DenominationSignature sig;
      74           2 :       } prev_denom = {0};
      75             : 
      76           2 :       if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
      77           2 :           TEH_plugin->get_signature_for_known_coin (TEH_plugin->cls,
      78             :                                                     &coin->coin_pub,
      79             :                                                     &prev_denom.pub,
      80             :                                                     &prev_denom.sig))
      81             :       {
      82             :         /* There _should_ have been a result, because
      83             :          * we ended here due to a conflict! */
      84           0 :         GNUNET_break (0);
      85           0 :         *mhd_ret = TALER_MHD_reply_with_error (connection,
      86             :                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
      87             :                                                TALER_EC_GENERIC_DB_FETCH_FAILED,
      88             :                                                NULL);
      89           0 :         return GNUNET_DB_STATUS_HARD_ERROR;
      90             :       }
      91             : 
      92           2 :       *mhd_ret = TEH_RESPONSE_reply_coin_denomination_conflict (
      93             :         connection,
      94             :         TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY,
      95             :         &coin->coin_pub,
      96             :         &prev_denom.pub,
      97             :         &prev_denom.sig);
      98           2 :       TALER_denom_pub_free (&prev_denom.pub);
      99           2 :       TALER_denom_sig_free (&prev_denom.sig);
     100           2 :       return GNUNET_DB_STATUS_HARD_ERROR;
     101             :     }
     102           0 :   case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL:
     103             :   case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL:
     104             :   case TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS:
     105           0 :     *mhd_ret = TEH_RESPONSE_reply_coin_age_commitment_conflict (
     106             :       connection,
     107             :       TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
     108             :       cks,
     109             :       &h_denom_pub,
     110             :       &coin->coin_pub,
     111             :       &h_age_commitment);
     112           0 :     return GNUNET_DB_STATUS_HARD_ERROR;
     113             :   }
     114           0 :   GNUNET_assert (0);
     115             :   return GNUNET_DB_STATUS_HARD_ERROR;
     116             : }
     117             : 
     118             : 
     119             : enum GNUNET_GenericReturnValue
     120        4423 : TEH_DB_run_transaction (struct MHD_Connection *connection,
     121             :                         const char *name,
     122             :                         enum TEH_MetricTypeRequest mt,
     123             :                         MHD_RESULT *mhd_ret,
     124             :                         TEH_DB_TransactionCallback cb,
     125             :                         void *cb_cls)
     126             : {
     127        4423 :   if (NULL != mhd_ret)
     128        4423 :     *mhd_ret = -1; /* set to invalid value, to help detect bugs */
     129        4423 :   if (GNUNET_OK !=
     130        4423 :       TEH_plugin->preflight (TEH_plugin->cls))
     131             :   {
     132           0 :     GNUNET_break (0);
     133           0 :     if (NULL != mhd_ret)
     134           0 :       *mhd_ret = TALER_MHD_reply_with_error (connection,
     135             :                                              MHD_HTTP_INTERNAL_SERVER_ERROR,
     136             :                                              TALER_EC_GENERIC_DB_SETUP_FAILED,
     137             :                                              NULL);
     138           0 :     return GNUNET_SYSERR;
     139             :   }
     140        4423 :   GNUNET_assert (mt < TEH_MT_REQUEST_COUNT);
     141        4423 :   TEH_METRICS_num_requests[mt]++;
     142        4423 :   for (unsigned int retries = 0;
     143        4423 :        retries < MAX_TRANSACTION_COMMIT_RETRIES;
     144           0 :        retries++)
     145             :   {
     146             :     enum GNUNET_DB_QueryStatus qs;
     147             : 
     148        4423 :     if (GNUNET_OK !=
     149        4423 :         TEH_plugin->start (TEH_plugin->cls,
     150             :                            name))
     151             :     {
     152           0 :       GNUNET_break (0);
     153           0 :       if (NULL != mhd_ret)
     154           0 :         *mhd_ret = TALER_MHD_reply_with_error (connection,
     155             :                                                MHD_HTTP_INTERNAL_SERVER_ERROR,
     156             :                                                TALER_EC_GENERIC_DB_START_FAILED,
     157             :                                                NULL);
     158           0 :       return GNUNET_SYSERR;
     159             :     }
     160        4423 :     qs = cb (cb_cls,
     161             :              connection,
     162             :              mhd_ret);
     163        4423 :     if (0 > qs)
     164             :     {
     165          47 :       TEH_plugin->rollback (TEH_plugin->cls);
     166          47 :       if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     167          47 :         return GNUNET_SYSERR;
     168             :     }
     169             :     else
     170             :     {
     171        4376 :       qs = TEH_plugin->commit (TEH_plugin->cls);
     172        4376 :       if (GNUNET_DB_STATUS_HARD_ERROR == qs)
     173             :       {
     174           0 :         TEH_plugin->rollback (TEH_plugin->cls);
     175           0 :         if (NULL != mhd_ret)
     176           0 :           *mhd_ret = TALER_MHD_reply_with_error (connection,
     177             :                                                  MHD_HTTP_INTERNAL_SERVER_ERROR,
     178             :                                                  TALER_EC_GENERIC_DB_COMMIT_FAILED,
     179             :                                                  NULL);
     180           0 :         return GNUNET_SYSERR;
     181             :       }
     182        4376 :       if (0 > qs)
     183           0 :         TEH_plugin->rollback (TEH_plugin->cls);
     184             :     }
     185             :     /* make sure callback did not violate invariants! */
     186        4376 :     GNUNET_assert ( (NULL == mhd_ret) ||
     187             :                     (-1 == (int) *mhd_ret) );
     188        4376 :     if (0 <= qs)
     189        4376 :       return GNUNET_OK;
     190           0 :     TEH_METRICS_num_conflict[mt]++;
     191             :   }
     192           0 :   TEH_plugin->rollback (TEH_plugin->cls);
     193           0 :   TALER_LOG_ERROR ("Transaction `%s' commit failed %u times\n",
     194             :                    name,
     195             :                    MAX_TRANSACTION_COMMIT_RETRIES);
     196           0 :   if (NULL != mhd_ret)
     197           0 :     *mhd_ret = TALER_MHD_reply_with_error (connection,
     198             :                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
     199             :                                            TALER_EC_GENERIC_DB_SOFT_FAILURE,
     200             :                                            NULL);
     201           0 :   return GNUNET_SYSERR;
     202             : }
     203             : 
     204             : 
     205             : /* end of taler-exchange-httpd_db.c */

Generated by: LCOV version 1.16