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

Generated by: LCOV version 2.0-1