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

Generated by: LCOV version 2.0-1