LCOV - code coverage report
Current view: top level - auditor - report-lib.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 28.9 % 280 81
Test Date: 2026-09-09 15:11:34 Functions: 33.3 % 12 4

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2016-2020 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 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 Public License for more details.
      12              : 
      13              :   You should have received a copy of the GNU Affero Public License along with
      14              :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15              : */
      16              : /**
      17              :  * @file auditor/report-lib.c
      18              :  * @brief helper library to facilitate generation of audit reports
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "platform.h"
      22              : #include "report-lib.h"
      23              : #include "auditor-database/preflight.h"
      24              : #include "auditor-database/start.h"
      25              : #include "exchange-database/commit.h"
      26              : #include "exchange-database/get_denomination_by_serial.h"
      27              : #include "exchange-database/get_denomination_info.h"
      28              : #include "exchange-database/iterate_denomination_info.h"
      29              : #include "exchange-database/preflight.h"
      30              : #include "exchange-database/rollback.h"
      31              : #include "exchange-database/start.h"
      32              : 
      33              : /**
      34              :  * Handle to access the exchange's database.
      35              :  */
      36              : struct TALER_EXCHANGEDB_PostgresContext *TALER_ARL_edb;
      37              : 
      38              : /**
      39              :  * Which currency are we doing the audit for?
      40              :  */
      41              : char *TALER_ARL_currency;
      42              : 
      43              : /**
      44              :  * How many fractional digits does the currency use?
      45              :  */
      46              : struct TALER_Amount TALER_ARL_currency_round_unit;
      47              : 
      48              : /**
      49              :  * Our configuration.
      50              :  */
      51              : const struct GNUNET_CONFIGURATION_Handle *TALER_ARL_cfg;
      52              : 
      53              : /**
      54              :  * Handle to access the auditor's database.
      55              :  */
      56              : struct TALER_AUDITORDB_PostgresContext *TALER_ARL_adb;
      57              : 
      58              : /**
      59              :  * Master public key of the exchange to audit.
      60              :  */
      61              : struct TALER_MasterPublicKeyP TALER_ARL_master_pub;
      62              : 
      63              : /**
      64              :  * Public key of the auditor.
      65              :  */
      66              : struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
      67              : 
      68              : /**
      69              :  * REST API endpoint of the auditor.
      70              :  */
      71              : char *TALER_ARL_auditor_url;
      72              : 
      73              : /**
      74              :  * REST API endpoint of the exchange.
      75              :  */
      76              : char *TALER_ARL_exchange_url;
      77              : 
      78              : /**
      79              :  * At what time did the auditor process start?
      80              :  */
      81              : struct GNUNET_TIME_Absolute start_time;
      82              : 
      83              : /**
      84              :  * Results about denominations, cached per-transaction, maps denomination pub hashes
      85              :  * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
      86              :  */
      87              : static struct GNUNET_CONTAINER_MultiHashMap *denominations;
      88              : 
      89              : /**
      90              :  * Results about denominations, cached per-transaction, maps row/serial ID's
      91              :  * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
      92              :  */
      93              : static struct GNUNET_CONTAINER_MultiUuidmap *denominations_by_serial;
      94              : 
      95              : /**
      96              :  * Helper to convert a serial/row id to a uuid for the lookup
      97              :  * in a uuid hash table.
      98              :  *
      99              :  * @param serial serial id of entry
     100              :  * @param[out] uuid uuid to write
     101              :  */
     102              : static void
     103            0 : serial_to_uuid (
     104              :   uint64_t serial,
     105              :   struct GNUNET_Uuid *uuid)
     106              : {
     107            0 :   uuid->value[0] = serial;
     108            0 :   uuid->value[1] = serial >> 32;
     109            0 :   uuid->value[2] = 0;
     110            0 :   uuid->value[3] = 0;
     111            0 : }
     112              : 
     113              : 
     114              : /**
     115              :  * Function called with the results of iterate_denomination_info(),
     116              :  * or directly (!).  Used to check and add the respective denomination
     117              :  * to our hash table.
     118              :  *
     119              :  * @param cls closure, NULL
     120              :  * @param denom_serial table row of the denomaination
     121              :  * @param denom_pub public key, sometimes NULL (!)
     122              :  * @param issue issuing information with value, fees and other info about the denomination.
     123              :  */
     124              : static void
     125            0 : add_denomination (
     126              :   void *cls,
     127              :   uint64_t denom_serial,
     128              :   const struct TALER_DenominationPublicKey *denom_pub,
     129              :   const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
     130              : {
     131              :   (void) cls;
     132              :   (void) denom_pub;
     133            0 :   if (NULL !=
     134            0 :       GNUNET_CONTAINER_multihashmap_get (denominations,
     135              :                                          &issue->denom_hash.hash))
     136            0 :     return; /* value already known */
     137              : #if GNUNET_EXTRA_LOGGING >= 1
     138              :   {
     139            0 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     140              :                 "Tracking denomination `%s' (%s)\n",
     141              :                 GNUNET_h2s (&issue->denom_hash.hash),
     142              :                 TALER_amount2s (&issue->value));
     143            0 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     144              :                 "Withdraw fee is %s\n",
     145              :                 TALER_amount2s (&issue->fees.withdraw));
     146            0 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     147              :                 "Start time is %s\n",
     148              :                 GNUNET_TIME_timestamp2s (issue->start));
     149            0 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     150              :                 "Expire deposit time is %s\n",
     151              :                 GNUNET_TIME_timestamp2s (issue->expire_deposit));
     152              :   }
     153              : #endif
     154              :   {
     155              :     struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
     156              :     struct GNUNET_Uuid uuid;
     157              : 
     158            0 :     i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation);
     159            0 :     *i = *issue;
     160            0 :     GNUNET_assert (GNUNET_OK ==
     161              :                    GNUNET_CONTAINER_multihashmap_put (denominations,
     162              :                                                       &issue->denom_hash.hash,
     163              :                                                       i,
     164              :                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     165            0 :     serial_to_uuid (denom_serial, &uuid);
     166            0 :     GNUNET_assert (GNUNET_OK ==
     167              :                    GNUNET_CONTAINER_multiuuidmap_put (denominations_by_serial,
     168              :                                                       &uuid,
     169              :                                                       i,
     170              :                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     171              :   }
     172              : }
     173              : 
     174              : 
     175              : enum GNUNET_DB_QueryStatus
     176            0 : TALER_ARL_get_denomination_info_by_hash (
     177              :   const struct TALER_DenominationHashP *dh,
     178              :   const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep)
     179              : {
     180              :   enum GNUNET_DB_QueryStatus qs;
     181              : 
     182            0 :   *issuep = NULL;
     183            0 :   if (NULL == denominations)
     184              :   {
     185            0 :     denominations = GNUNET_CONTAINER_multihashmap_create (256,
     186              :                                                           GNUNET_NO);
     187            0 :     if (NULL  == denominations_by_serial)
     188            0 :       denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
     189              :                                                                       GNUNET_NO)
     190              :       ;
     191              : 
     192            0 :     qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb,
     193              :                                                      &add_denomination,
     194              :                                                      NULL);
     195            0 :     if (0 > qs)
     196              :     {
     197            0 :       GNUNET_break (0);
     198            0 :       *issuep = NULL;
     199            0 :       return qs;
     200              :     }
     201              :   }
     202              :   {
     203              :     const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
     204              : 
     205            0 :     i = GNUNET_CONTAINER_multihashmap_get (denominations,
     206              :                                            &dh->hash);
     207            0 :     if (NULL != i)
     208              :     {
     209              :       /* cache hit */
     210            0 :       *issuep = i;
     211            0 :       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     212              :     }
     213              :   }
     214              :   /* maybe database changed since we last iterated, give it one more shot */
     215              :   {
     216              :     struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
     217              :     uint64_t denom_serial;
     218              : 
     219            0 :     qs = TALER_EXCHANGEDB_get_denomination_info (TALER_ARL_edb,
     220              :                                                  dh,
     221              :                                                  &denom_serial,
     222              :                                                  &issue);
     223            0 :     if (qs <= 0)
     224              :     {
     225            0 :       GNUNET_break (qs >= 0);
     226            0 :       if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     227            0 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     228              :                     "Denomination %s not found\n",
     229              :                     TALER_B2S (dh));
     230            0 :       return qs;
     231              :     }
     232              : 
     233            0 :     add_denomination (NULL,
     234              :                       denom_serial,
     235              :                       NULL,
     236              :                       &issue);
     237              :   }
     238              :   {
     239              :     const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
     240              : 
     241            0 :     i = GNUNET_CONTAINER_multihashmap_get (denominations,
     242              :                                            &dh->hash);
     243            0 :     if (NULL != i)
     244              :     {
     245              :       /* cache hit */
     246            0 :       *issuep = i;
     247            0 :       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     248              :     }
     249              :   }
     250              :   /* We found more keys, but not the denomination we are looking for :-( */
     251            0 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     252              :               "Denomination %s not found\n",
     253              :               TALER_B2S (dh));
     254            0 :   return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
     255              : }
     256              : 
     257              : 
     258              : enum GNUNET_DB_QueryStatus
     259            0 : TALER_ARL_get_denomination_info_by_serial (
     260              :   uint64_t denom_serial,
     261              :   const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep)
     262              : {
     263              :   enum GNUNET_DB_QueryStatus qs;
     264              :   struct GNUNET_Uuid uuid;
     265              : 
     266            0 :   *issuep = NULL;
     267            0 :   serial_to_uuid (denom_serial,
     268              :                   &uuid);
     269            0 :   if (NULL == denominations_by_serial)
     270              :   {
     271            0 :     denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
     272              :                                                                     GNUNET_NO);
     273            0 :     if (NULL == denominations)
     274            0 :       denominations = GNUNET_CONTAINER_multihashmap_create (256,
     275              :                                                             GNUNET_NO);
     276              : 
     277            0 :     qs = TALER_EXCHANGEDB_iterate_denomination_info (TALER_ARL_edb,
     278              :                                                      &add_denomination,
     279              :                                                      NULL);
     280            0 :     if (0 > qs)
     281              :     {
     282            0 :       GNUNET_break (0);
     283            0 :       *issuep = NULL;
     284            0 :       return qs;
     285              :     }
     286              :   }
     287              :   {
     288              :     const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
     289              : 
     290            0 :     i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
     291              :                                            &uuid);
     292            0 :     if (NULL != i)
     293              :     {
     294              :       /* cache hit */
     295            0 :       *issuep = i;
     296            0 :       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     297              :     }
     298              :   }
     299              :   /* maybe database changed since we last iterated, give it one more shot */
     300              :   {
     301              :     struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
     302              : 
     303            0 :     qs = TALER_EXCHANGEDB_get_denomination_by_serial (TALER_ARL_edb,
     304              :                                                       denom_serial,
     305              :                                                       &issue);
     306            0 :     if (qs <= 0)
     307              :     {
     308            0 :       GNUNET_break (qs >= 0);
     309            0 :       if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     310            0 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     311              :                     "Denomination with serial %lu not found\n",
     312              :                     denom_serial);
     313            0 :       return qs;
     314              :     }
     315              : 
     316            0 :     add_denomination (NULL,
     317              :                       denom_serial,
     318              :                       NULL,
     319              :                       &issue);
     320              :   }
     321              : 
     322              :   {
     323              :     const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
     324              : 
     325            0 :     i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
     326              :                                            &uuid);
     327            0 :     if (NULL != i)
     328              :     {
     329              :       /* cache hit */
     330            0 :       *issuep = i;
     331            0 :       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     332              :     }
     333              :   }
     334              :   /* We found more keys, but not the denomination we are looking for :-( */
     335            0 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     336              :               "Denomination with serial %lu not found\n",
     337              :               denom_serial);
     338            0 :   return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
     339              : }
     340              : 
     341              : 
     342              : enum GNUNET_DB_QueryStatus
     343            0 : TALER_ARL_get_denomination_info (
     344              :   const struct TALER_DenominationPublicKey *denom_pub,
     345              :   const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue,
     346              :   struct TALER_DenominationHashP *dh)
     347              : {
     348              :   struct TALER_DenominationHashP hc;
     349              : 
     350            0 :   if (NULL == dh)
     351            0 :     dh = &hc;
     352            0 :   TALER_denom_pub_hash (denom_pub,
     353              :                         dh);
     354            0 :   return TALER_ARL_get_denomination_info_by_hash (dh,
     355              :                                                   issue);
     356              : }
     357              : 
     358              : 
     359              : /**
     360              :  * Perform the given @a analysis within a transaction scope.
     361              :  * Commit on success.
     362              :  *
     363              :  * @param analysis analysis to run
     364              :  * @param analysis_cls closure for @a analysis
     365              :  * @return #GNUNET_OK if @a analysis successfully committed,
     366              :  *         #GNUNET_NO if we had an error on commit (retry may help)
     367              :  *         #GNUNET_SYSERR on hard errors
     368              :  */
     369              : static enum GNUNET_GenericReturnValue
     370           27 : transact (TALER_ARL_Analysis analysis,
     371              :           void *analysis_cls)
     372              : {
     373              :   int ret;
     374              :   enum GNUNET_DB_QueryStatus qs;
     375              : 
     376           27 :   ret = TALER_AUDITORDB_start (TALER_ARL_adb,
     377              :                                "auditor-analysis");
     378           27 :   if (GNUNET_OK != ret)
     379              :   {
     380            0 :     GNUNET_break (0);
     381            0 :     return GNUNET_SYSERR;
     382              :   }
     383           27 :   if (GNUNET_OK !=
     384           27 :       TALER_EXCHANGEDB_preflight (TALER_ARL_edb))
     385              :   {
     386            0 :     GNUNET_break (0);
     387            0 :     return GNUNET_SYSERR;
     388              :   }
     389           27 :   ret = TALER_EXCHANGEDB_start (TALER_ARL_edb,
     390              :                                 "auditor");
     391           27 :   if (GNUNET_OK != ret)
     392              :   {
     393            0 :     GNUNET_break (0);
     394            0 :     TALER_EXCHANGEDB_rollback (TALER_ARL_edb);
     395            0 :     return GNUNET_SYSERR;
     396              :   }
     397           27 :   qs = analysis (analysis_cls);
     398           27 :   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
     399              :   {
     400           16 :     qs = TALER_EXCHANGEDB_commit (TALER_ARL_edb);
     401           16 :     if (0 > qs)
     402              :     {
     403            0 :       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     404            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     405              :                   "Exchange DB commit failed, rolling back transaction\n");
     406            0 :       TALER_AUDITORDB_rollback (TALER_ARL_adb);
     407              :     }
     408              :     else
     409              :     {
     410           16 :       qs = TALER_AUDITORDB_commit (TALER_ARL_adb);
     411           16 :       if (0 > qs)
     412              :       {
     413            0 :         GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     414            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     415              :                     "Auditor DB commit failed!\n");
     416              :       }
     417              :     }
     418              :   }
     419              :   else
     420              :   {
     421           11 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     422              :                 "Processing failed; rolling back transaction\n");
     423           11 :     TALER_AUDITORDB_rollback (TALER_ARL_adb);
     424           11 :     TALER_EXCHANGEDB_rollback (TALER_ARL_edb);
     425              :   }
     426           27 :   switch (qs)
     427              :   {
     428            0 :   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     429            0 :     return GNUNET_OK;
     430           20 :   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     431           20 :     return GNUNET_OK;
     432            7 :   case GNUNET_DB_STATUS_SOFT_ERROR:
     433            7 :     return GNUNET_NO;
     434            0 :   case GNUNET_DB_STATUS_HARD_ERROR:
     435            0 :     return GNUNET_SYSERR;
     436              :   }
     437            0 :   return GNUNET_OK;
     438              : }
     439              : 
     440              : 
     441              : enum GNUNET_GenericReturnValue
     442           20 : TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana,
     443              :                                   void *ana_cls)
     444              : {
     445              :   enum GNUNET_GenericReturnValue ret;
     446              : 
     447           20 :   if (GNUNET_SYSERR ==
     448           20 :       TALER_EXCHANGEDB_preflight (TALER_ARL_edb))
     449              :   {
     450            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     451              :                 "Failed to initialize exchange connection.\n");
     452            0 :     return GNUNET_SYSERR;
     453              :   }
     454           20 :   if (GNUNET_SYSERR ==
     455           20 :       TALER_AUDITORDB_preflight (TALER_ARL_adb))
     456              :   {
     457            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     458              :                 "Failed to initialize auditor session.\n");
     459            0 :     return GNUNET_SYSERR;
     460              :   }
     461              : 
     462           27 :   for (unsigned int retries = 0; retries<3; retries++)
     463              :   {
     464           27 :     ret = transact (ana,
     465              :                     ana_cls);
     466           27 :     if (GNUNET_NO != ret)
     467           20 :       break;
     468            7 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     469              :                 "Serialization issue, trying again\n");
     470              :   }
     471           20 :   if (GNUNET_OK != ret)
     472              :   {
     473              :     /* Includes the retries running out: the analysis was rolled back every
     474              :        time, so there is nothing committed to report success about. */
     475            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     476              :                 "Analysis failed, not recording progress\n");
     477            0 :     return GNUNET_SYSERR;
     478              :   }
     479           20 :   return GNUNET_OK;
     480              : }
     481              : 
     482              : 
     483              : void
     484            0 : TALER_ARL_amount_add_ (struct TALER_Amount *sum,
     485              :                        const struct TALER_Amount *a1,
     486              :                        const struct TALER_Amount *a2,
     487              :                        const char *filename,
     488              :                        const char *functionname,
     489              :                        unsigned int line)
     490              : {
     491              :   enum TALER_AmountArithmeticResult aar;
     492              :   const char *msg;
     493              :   char *a2s;
     494              : 
     495            0 :   aar = TALER_amount_add (sum,
     496              :                           a1,
     497              :                           a2);
     498            0 :   if (aar >= 0)
     499            0 :     return;
     500            0 :   switch (aar)
     501              :   {
     502            0 :   case TALER_AAR_INVALID_RESULT_OVERFLOW:
     503            0 :     msg =
     504              :       "arithmetic overflow in amount addition (likely the database is corrupt, see manual)";
     505            0 :     break;
     506            0 :   case TALER_AAR_INVALID_NORMALIZATION_FAILED:
     507            0 :     msg =
     508              :       "normalization failed in amount addition (likely the database is corrupt, see manual)";
     509            0 :     break;
     510            0 :   case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
     511            0 :     msg =
     512              :       "incompatible currencies in amount addition (likely bad configuration and auditor code missing a sanity check, see manual)";
     513            0 :     break;
     514            0 :   default:
     515            0 :     GNUNET_assert (0); /* should be impossible */
     516              :   }
     517            0 :   a2s = TALER_amount_to_string (a2);
     518            0 :   fprintf (stderr,
     519              :            "Aborting audit due to fatal error in function %s at %s:%d trying to add %s to %s: %s\n",
     520              :            functionname,
     521              :            filename,
     522              :            line,
     523              :            TALER_amount2s (a1),
     524              :            a2s,
     525              :            msg);
     526            0 :   GNUNET_free (a2s);
     527            0 :   exit (42);
     528              : }
     529              : 
     530              : 
     531              : void
     532            0 : TALER_ARL_amount_subtract_ (struct TALER_Amount *diff,
     533              :                             const struct TALER_Amount *a1,
     534              :                             const struct TALER_Amount *a2,
     535              :                             const char *filename,
     536              :                             const char *functionname,
     537              :                             unsigned int line)
     538              : {
     539              :   enum TALER_AmountArithmeticResult aar;
     540              :   const char *msg;
     541              :   char *a2s;
     542              : 
     543            0 :   aar = TALER_amount_subtract (diff,
     544              :                                a1,
     545              :                                a2);
     546            0 :   if (aar >= 0)
     547            0 :     return;
     548            0 :   switch (aar)
     549              :   {
     550            0 :   case TALER_AAR_INVALID_NEGATIVE_RESULT:
     551            0 :     msg =
     552              :       "negative result in amount subtraction (likely the database is corrupt, see manual)";
     553            0 :     break;
     554            0 :   case TALER_AAR_INVALID_NORMALIZATION_FAILED:
     555            0 :     msg =
     556              :       "normalization failed in amount subtraction (likely the database is corrupt, see manual)";
     557            0 :     break;
     558            0 :   case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
     559            0 :     msg =
     560              :       "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)";
     561            0 :     break;
     562            0 :   default:
     563            0 :     GNUNET_assert (0); /* should be impossible */
     564              :   }
     565            0 :   a2s = TALER_amount_to_string (a2);
     566            0 :   fprintf (stderr,
     567              :            "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n",
     568              :            functionname,
     569              :            filename,
     570              :            line,
     571              :            a2s,
     572              :            TALER_amount2s (a1),
     573              :            msg);
     574            0 :   GNUNET_free (a2s);
     575            0 :   exit (42);
     576              : }
     577              : 
     578              : 
     579              : enum TALER_ARL_SubtractionResult
     580            0 : TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff,
     581              :                                 const struct TALER_Amount *a1,
     582              :                                 const struct TALER_Amount *a2,
     583              :                                 const char *filename,
     584              :                                 const char *functionname,
     585              :                                 unsigned int line)
     586              : {
     587              :   enum TALER_AmountArithmeticResult aar;
     588              :   const char *msg;
     589              :   char *a2s;
     590              : 
     591            0 :   aar = TALER_amount_subtract (diff,
     592              :                                a1,
     593              :                                a2);
     594            0 :   switch (aar)
     595              :   {
     596            0 :   case TALER_AAR_RESULT_POSITIVE:
     597            0 :     return TALER_ARL_SR_POSITIVE;
     598            0 :   case TALER_AAR_RESULT_ZERO:
     599            0 :     return TALER_ARL_SR_ZERO;
     600            0 :   case TALER_AAR_INVALID_NEGATIVE_RESULT:
     601            0 :     return TALER_ARL_SR_INVALID_NEGATIVE;
     602            0 :   case TALER_AAR_INVALID_NORMALIZATION_FAILED:
     603            0 :     msg =
     604              :       "normalization failed in amount subtraction (likely the database is corrupt, see manual)";
     605            0 :     break;
     606            0 :   case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
     607            0 :     msg =
     608              :       "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)";
     609            0 :     break;
     610            0 :   default:
     611            0 :     GNUNET_assert (0); /* should be impossible */
     612              :   }
     613            0 :   a2s = TALER_amount_to_string (a2);
     614            0 :   fprintf (stderr,
     615              :            "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n",
     616              :            functionname,
     617              :            filename,
     618              :            line,
     619              :            a2s,
     620              :            TALER_amount2s (a1),
     621              :            msg);
     622            0 :   GNUNET_free (a2s);
     623            0 :   exit (42);
     624              : }
     625              : 
     626              : 
     627              : int
     628           20 : TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c)
     629              : {
     630           20 :   TALER_ARL_cfg = c;
     631           20 :   start_time = GNUNET_TIME_absolute_get ();
     632              : 
     633           20 :   if (GNUNET_OK !=
     634           20 :       GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
     635              :                                              "auditor",
     636              :                                              "BASE_URL",
     637              :                                              &TALER_ARL_auditor_url))
     638              :   {
     639            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     640              :                                "auditor",
     641              :                                "BASE_URL");
     642            0 :     return EXIT_NOTCONFIGURED;
     643              :   }
     644           20 :   if (GNUNET_OK !=
     645           20 :       GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
     646              :                                              "exchange",
     647              :                                              "BASE_URL",
     648              :                                              &TALER_ARL_exchange_url))
     649              :   {
     650            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     651              :                                "exchange",
     652              :                                "BASE_URL");
     653            0 :     return EXIT_NOTCONFIGURED;
     654              :   }
     655              : 
     656           20 :   if (GNUNET_is_zero (&TALER_ARL_master_pub))
     657              :   {
     658              :     /* -m option not given, try configuration */
     659              :     char *master_public_key_str;
     660              : 
     661           20 :     if (GNUNET_OK !=
     662           20 :         GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
     663              :                                                "exchange",
     664              :                                                "MASTER_PUBLIC_KEY",
     665              :                                                &master_public_key_str))
     666              :     {
     667            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     668              :                   "Pass option -m or set MASTER_PUBLIC_KEY in the configuration!\n");
     669            0 :       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     670              :                                  "exchange",
     671              :                                  "MASTER_PUBLIC_KEY");
     672            0 :       return EXIT_NOTCONFIGURED;
     673              :     }
     674           20 :     if (GNUNET_OK !=
     675           20 :         GNUNET_CRYPTO_eddsa_public_key_from_string (
     676              :           master_public_key_str,
     677              :           strlen (master_public_key_str),
     678              :           &TALER_ARL_master_pub.eddsa_pub))
     679              :     {
     680            0 :       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     681              :                                  "exchange",
     682              :                                  "MASTER_PUBLIC_KEY",
     683              :                                  "invalid key");
     684            0 :       GNUNET_free (master_public_key_str);
     685            0 :       return EXIT_NOTCONFIGURED;
     686              :     }
     687           20 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     688              :                 "Running auditor against exchange master public key `%s'\n",
     689              :                 master_public_key_str);
     690           20 :     GNUNET_free (master_public_key_str);
     691              :   } /* end of -m not given */
     692              : 
     693           20 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     694              :               "Taler auditor running for exchange master public key %s\n",
     695              :               TALER_B2S (&TALER_ARL_master_pub));
     696              : 
     697           20 :   if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
     698              :   {
     699              :     char *auditor_public_key_str;
     700              : 
     701           20 :     if (GNUNET_OK ==
     702           20 :         GNUNET_CONFIGURATION_get_value_string (c,
     703              :                                                "auditor",
     704              :                                                "PUBLIC_KEY",
     705              :                                                &auditor_public_key_str))
     706              :     {
     707           20 :       if (GNUNET_OK !=
     708           20 :           GNUNET_CRYPTO_eddsa_public_key_from_string (
     709              :             auditor_public_key_str,
     710              :             strlen (auditor_public_key_str),
     711              :             &TALER_ARL_auditor_pub.eddsa_pub))
     712              :       {
     713            0 :         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     714              :                                    "auditor",
     715              :                                    "PUBLIC_KEY",
     716              :                                    "invalid key");
     717            0 :         GNUNET_free (auditor_public_key_str);
     718            0 :         return EXIT_NOTCONFIGURED;
     719              :       }
     720           20 :       GNUNET_free (auditor_public_key_str);
     721              :     }
     722              :   }
     723              : 
     724           20 :   if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
     725              :   {
     726              :     /* public key not configured */
     727              :     /* try loading private key and deriving public key */
     728              :     char *fn;
     729              : 
     730            0 :     if (GNUNET_OK ==
     731            0 :         GNUNET_CONFIGURATION_get_value_filename (c,
     732              :                                                  "auditor",
     733              :                                                  "AUDITOR_PRIV_FILE",
     734              :                                                  &fn))
     735              :     {
     736              :       struct TALER_AuditorPrivateKeyP auditor_priv;
     737              : 
     738            0 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     739              :                   "Loading offline private key from `%s' to get auditor public key\n",
     740              :                   fn);
     741            0 :       if (GNUNET_OK ==
     742            0 :           GNUNET_CRYPTO_eddsa_key_from_file (fn,
     743              :                                              GNUNET_NO, /* do NOT create it! */
     744              :                                              &auditor_priv.eddsa_priv))
     745              :       {
     746            0 :         GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv,
     747              :                                             &TALER_ARL_auditor_pub.eddsa_pub);
     748              :       }
     749            0 :       GNUNET_free (fn);
     750              :     }
     751              :   }
     752              : 
     753           20 :   if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
     754              :   {
     755            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     756              :                                "auditor",
     757              :                                "PUBLIC_KEY/AUDITOR_PRIV_FILE");
     758            0 :     return EXIT_NOTCONFIGURED;
     759              :   }
     760              : 
     761           20 :   if (GNUNET_OK !=
     762           20 :       TALER_config_get_currency (TALER_ARL_cfg,
     763              :                                  "exchange",
     764              :                                  &TALER_ARL_currency))
     765              :   {
     766            0 :     return EXIT_NOTCONFIGURED;
     767              :   }
     768              :   {
     769           20 :     if ( (GNUNET_OK !=
     770           20 :           TALER_config_get_amount (TALER_ARL_cfg,
     771              :                                    "exchange",
     772              :                                    "CURRENCY_ROUND_UNIT",
     773           20 :                                    &TALER_ARL_currency_round_unit)) ||
     774           20 :          ( (0 != TALER_ARL_currency_round_unit.fraction) &&
     775           20 :            (0 != TALER_ARL_currency_round_unit.value) ) )
     776              :     {
     777            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     778              :                   "Need non-zero value in section `exchange' under `CURRENCY_ROUND_UNIT'\n");
     779            0 :       return EXIT_NOTCONFIGURED;
     780              :     }
     781              :   }
     782           20 :   if (NULL ==
     783           20 :       (TALER_ARL_edb = TALER_EXCHANGEDB_connect (TALER_ARL_cfg)))
     784              :   {
     785            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     786              :                 "Failed to initialize exchange database plugin.\n");
     787            0 :     TALER_ARL_done ();
     788            0 :     return EXIT_FAILURE;
     789              :   }
     790           20 :   if (NULL ==
     791           20 :       (TALER_ARL_adb = TALER_AUDITORDB_connect (TALER_ARL_cfg)))
     792              :   {
     793            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     794              :                 "Failed to initialize auditor database plugin.\n");
     795            0 :     TALER_ARL_done ();
     796            0 :     return EXIT_FAILURE;
     797              :   }
     798           20 :   if (GNUNET_SYSERR ==
     799           20 :       TALER_AUDITORDB_preflight (TALER_ARL_adb))
     800              :   {
     801            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     802              :                 "Failed to start session with auditor database.\n");
     803            0 :     TALER_ARL_done ();
     804            0 :     return EXIT_FAILURE;
     805              :   }
     806           20 :   return EXIT_SUCCESS;
     807              : }
     808              : 
     809              : 
     810              : void
     811           20 : TALER_ARL_done ()
     812              : {
     813           20 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     814              :               "Audit complete\n");
     815           20 :   if (NULL != TALER_ARL_adb)
     816              :   {
     817           20 :     TALER_AUDITORDB_disconnect (TALER_ARL_adb);
     818           20 :     TALER_ARL_adb = NULL;
     819              :   }
     820           20 :   if (NULL != TALER_ARL_edb)
     821              :   {
     822           20 :     TALER_EXCHANGEDB_disconnect (TALER_ARL_edb);
     823           20 :     TALER_ARL_edb = NULL;
     824              :   }
     825           20 :   GNUNET_free (TALER_ARL_exchange_url);
     826           20 :   GNUNET_free (TALER_ARL_auditor_url);
     827           20 : }
     828              : 
     829              : 
     830              : /* end of report-lib.c */
        

Generated by: LCOV version 2.0-1