LCOV - code coverage report
Current view: top level - auditor - report-lib.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 143 276 51.8 %
Date: 2025-06-05 21:03:14 Functions: 12 12 100.0 %

          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             : 
      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       37556 : serial_to_uuid (
      95             :   uint64_t serial,
      96             :   struct GNUNET_Uuid *uuid)
      97             : {
      98       37556 :   uuid->value[0] = serial;
      99       37556 :   uuid->value[1] = serial >> 32;
     100       37556 :   uuid->value[2] = 0;
     101       37556 :   uuid->value[3] = 0;
     102       37556 : }
     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       34344 : 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       34344 :   if (NULL !=
     125       34344 :       GNUNET_CONTAINER_multihashmap_get (denominations,
     126             :                                          &issue->denom_hash.hash))
     127           0 :     return; /* value already known */
     128             : #if GNUNET_EXTRA_LOGGING >= 1
     129             :   {
     130       34344 :     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       34344 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     135             :                 "Withdraw fee is %s\n",
     136             :                 TALER_amount2s (&issue->fees.withdraw));
     137       34344 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     138             :                 "Start time is %s\n",
     139             :                 GNUNET_TIME_timestamp2s (issue->start));
     140       34344 :     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       34344 :     i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation);
     150       34344 :     *i = *issue;
     151       34344 :     GNUNET_assert (GNUNET_OK ==
     152             :                    GNUNET_CONTAINER_multihashmap_put (denominations,
     153             :                                                       &issue->denom_hash.hash,
     154             :                                                       i,
     155             :                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     156       34344 :     serial_to_uuid (denom_serial, &uuid);
     157       34344 :     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         309 : 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         309 :   if (NULL == denominations)
     174             :   {
     175          15 :     denominations = GNUNET_CONTAINER_multihashmap_create (256,
     176             :                                                           GNUNET_NO);
     177          15 :     if (NULL  == denominations_by_serial)
     178          15 :       denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
     179             :                                                                       GNUNET_NO)
     180             :       ;
     181             : 
     182          15 :     qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
     183             :                                                    &add_denomination,
     184             :                                                    NULL);
     185          15 :     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         309 :     i = GNUNET_CONTAINER_multihashmap_get (denominations,
     196             :                                            &dh->hash);
     197         309 :     if (NULL != i)
     198             :     {
     199             :       /* cache hit */
     200         309 :       *issuep = i;
     201         309 :       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        3212 : 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        3212 :   serial_to_uuid (denom_serial,
     257             :                   &uuid);
     258        3212 :   if (NULL == denominations_by_serial)
     259             :   {
     260          66 :     denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
     261             :                                                                     GNUNET_NO);
     262          66 :     if (NULL == denominations)
     263          66 :       denominations = GNUNET_CONTAINER_multihashmap_create (256,
     264             :                                                             GNUNET_NO);
     265             : 
     266          66 :     qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
     267             :                                                    &add_denomination,
     268             :                                                    NULL);
     269          66 :     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        3212 :     i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
     280             :                                            &uuid);
     281        3212 :     if (NULL != i)
     282             :     {
     283             :       /* cache hit */
     284        3212 :       *issuep = i;
     285        3212 :       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         267 : 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         267 :   if (NULL == dh)
     340         131 :     dh = &hc;
     341         267 :   TALER_denom_pub_hash (denom_pub,
     342             :                         dh);
     343         267 :   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         370 : transact (TALER_ARL_Analysis analysis,
     360             :           void *analysis_cls)
     361             : {
     362             :   int ret;
     363             :   enum GNUNET_DB_QueryStatus qs;
     364             : 
     365         370 :   ret = TALER_ARL_adb->start (TALER_ARL_adb->cls);
     366         370 :   if (GNUNET_OK != ret)
     367             :   {
     368           0 :     GNUNET_break (0);
     369           0 :     return GNUNET_SYSERR;
     370             :   }
     371         370 :   if (GNUNET_OK !=
     372         370 :       TALER_ARL_edb->preflight (TALER_ARL_edb->cls))
     373             :   {
     374           0 :     GNUNET_break (0);
     375           0 :     return GNUNET_SYSERR;
     376             :   }
     377         370 :   ret = TALER_ARL_edb->start (TALER_ARL_edb->cls,
     378             :                               "auditor");
     379         370 :   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         370 :   qs = analysis (analysis_cls);
     386         370 :   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
     387             :   {
     388         304 :     qs = TALER_ARL_edb->commit (TALER_ARL_edb->cls);
     389         304 :     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         304 :       qs = TALER_ARL_adb->commit (TALER_ARL_adb->cls);
     399         304 :       if (0 > qs)
     400             :       {
     401           0 :         GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     402           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     403             :                     "Auditor DB commit failed!\n");
     404             :       }
     405             :     }
     406             :   }
     407             :   else
     408             :   {
     409          66 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     410             :                 "Processing failed; rolling back transaction\n");
     411          66 :     TALER_ARL_adb->rollback (TALER_ARL_adb->cls);
     412          66 :     TALER_ARL_edb->rollback (TALER_ARL_edb->cls);
     413             :   }
     414         370 :   switch (qs)
     415             :   {
     416           0 :   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     417           0 :     return GNUNET_OK;
     418         364 :   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     419         364 :     return GNUNET_OK;
     420           6 :   case GNUNET_DB_STATUS_SOFT_ERROR:
     421           6 :     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         370 : TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana,
     431             :                                   void *ana_cls)
     432             : {
     433             :   enum GNUNET_DB_QueryStatus qs;
     434             : 
     435         370 :   if (GNUNET_SYSERR ==
     436         370 :       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         370 :   if (GNUNET_SYSERR ==
     443         370 :       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         370 :   for (unsigned int retries=0; retries<3; retries++)
     451             :   {
     452         370 :     qs = transact (ana,
     453             :                    ana_cls);
     454         370 :     if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
     455         370 :       break;
     456             :   }
     457         370 :   if (qs < 0)
     458           0 :     return GNUNET_SYSERR;
     459         370 :   return GNUNET_OK;
     460             : }
     461             : 
     462             : 
     463             : void
     464       18037 : 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       18037 :   aar = TALER_amount_add (sum,
     476             :                           a1,
     477             :                           a2);
     478       18037 :   if (aar >= 0)
     479       18037 :     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         351 : 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         351 :   aar = TALER_amount_subtract (diff,
     524             :                                a1,
     525             :                                a2);
     526         351 :   if (aar >= 0)
     527         351 :     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         676 : 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         676 :   aar = TALER_amount_subtract (diff,
     572             :                                a1,
     573             :                                a2);
     574         676 :   switch (aar)
     575             :   {
     576         663 :   case TALER_AAR_RESULT_POSITIVE:
     577         663 :     return TALER_ARL_SR_POSITIVE;
     578           5 :   case TALER_AAR_RESULT_ZERO:
     579           5 :     return TALER_ARL_SR_ZERO;
     580           8 :   case TALER_AAR_INVALID_NEGATIVE_RESULT:
     581           8 :     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         574 : TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c)
     609             : {
     610         574 :   TALER_ARL_cfg = c;
     611         574 :   start_time = GNUNET_TIME_absolute_get ();
     612             : 
     613         574 :   if (GNUNET_OK !=
     614         574 :       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         574 :   if (GNUNET_OK !=
     625         574 :       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         574 :   if (GNUNET_is_zero (&TALER_ARL_master_pub))
     637             :   {
     638             :     /* -m option not given, try configuration */
     639             :     char *master_public_key_str;
     640             : 
     641         574 :     if (GNUNET_OK !=
     642         574 :         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         574 :     if (GNUNET_OK !=
     655         574 :         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         574 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     668             :                 "Running auditor against exchange master public key `%s'\n",
     669             :                 master_public_key_str);
     670         574 :     GNUNET_free (master_public_key_str);
     671             :   } /* end of -m not given */
     672             : 
     673         574 :   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         574 :   if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
     678             :   {
     679             :     char *auditor_public_key_str;
     680             : 
     681         574 :     if (GNUNET_OK ==
     682         574 :         GNUNET_CONFIGURATION_get_value_string (c,
     683             :                                                "auditor",
     684             :                                                "PUBLIC_KEY",
     685             :                                                &auditor_public_key_str))
     686             :     {
     687         574 :       if (GNUNET_OK !=
     688         574 :           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         574 :       GNUNET_free (auditor_public_key_str);
     701             :     }
     702             :   }
     703             : 
     704         574 :   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         574 :   if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
     734             :   {
     735           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
     736             :                                "auditor",
     737             :                                "PUBLIC_KEY/AUDITOR_PRIV_FILE");
     738           0 :     return GNUNET_SYSERR;
     739             :   }
     740             : 
     741         574 :   if (GNUNET_OK !=
     742         574 :       TALER_config_get_currency (TALER_ARL_cfg,
     743             :                                  "exchange",
     744             :                                  &TALER_ARL_currency))
     745             :   {
     746           0 :     return GNUNET_SYSERR;
     747             :   }
     748             :   {
     749         574 :     if ( (GNUNET_OK !=
     750         574 :           TALER_config_get_amount (TALER_ARL_cfg,
     751             :                                    "exchange",
     752             :                                    "CURRENCY_ROUND_UNIT",
     753         574 :                                    &TALER_ARL_currency_round_unit)) ||
     754         574 :          ( (0 != TALER_ARL_currency_round_unit.fraction) &&
     755         574 :            (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         574 :   if (NULL ==
     763         574 :       (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         574 :   if (NULL ==
     772         574 :       (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         574 :   if (GNUNET_SYSERR ==
     781         574 :       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         574 :   return GNUNET_OK;
     789             : }
     790             : 
     791             : 
     792             : void
     793         574 : TALER_ARL_done ()
     794             : {
     795         574 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     796             :               "Audit complete\n");
     797         574 :   if (NULL != TALER_ARL_adb)
     798             :   {
     799         574 :     TALER_AUDITORDB_plugin_unload (TALER_ARL_adb);
     800         574 :     TALER_ARL_adb = NULL;
     801             :   }
     802         574 :   if (NULL != TALER_ARL_edb)
     803             :   {
     804         574 :     TALER_EXCHANGEDB_plugin_unload (TALER_ARL_edb);
     805         574 :     TALER_ARL_edb = NULL;
     806             :   }
     807         574 :   GNUNET_free (TALER_ARL_exchange_url);
     808         574 :   GNUNET_free (TALER_ARL_auditor_url);
     809         574 : }
     810             : 
     811             : 
     812             : /* end of report-lib.c */

Generated by: LCOV version 1.16