merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-kyccheck.c (47222B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024 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 General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file src/backend/taler-merchant-kyccheck.c
     18  * @brief Process that check the KYC status of our bank accounts at all exchanges
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include "microhttpd.h"
     23 #include <gnunet/gnunet_util_lib.h>
     24 #include <jansson.h>
     25 #include <pthread.h>
     26 #include <regex.h>
     27 #include <taler/taler_dbevents.h>
     28 #include <taler/taler_json_lib.h>
     29 #include <taler/taler_exchange_service.h>
     30 #include "taler/taler_merchant_util.h"
     31 #include "taler/taler_merchant_bank_lib.h"
     32 #include "merchantdb_lib.h"
     33 #include "merchantdb_lib.h"
     34 #include "merchant-database/account_kyc_get_outdated.h"
     35 #include "merchant-database/account_kyc_set_status.h"
     36 #include "merchant-database/get_kyc_status.h"
     37 #include "merchant-database/select_accounts.h"
     38 #include "merchant-database/select_exchange_keys.h"
     39 #include "merchant-database/event_listen.h"
     40 #include "merchant-database/preflight.h"
     41 #include "merchant-database/start.h"
     42 
     43 
     44 /**
     45  * Timeout for the exchange interaction.  Rather long as we should do
     46  * long-polling and do not want to wake up too often.
     47  */
     48 #define EXCHANGE_TIMEOUT GNUNET_TIME_relative_multiply ( \
     49           GNUNET_TIME_UNIT_MINUTES, \
     50           30)
     51 
     52 /**
     53  * How long do we wait between requests if all we wait
     54  * for is a change in the AML investigation status?
     55  * Default value.
     56  */
     57 #define AML_FREQ GNUNET_TIME_relative_multiply ( \
     58           GNUNET_TIME_UNIT_HOURS, \
     59           6)
     60 
     61 /**
     62  * How long do we wait between requests if all we wait
     63  * for is a change in the AML investigation status?
     64  */
     65 static struct GNUNET_TIME_Relative aml_freq;
     66 
     67 /**
     68  * How frequently do we check for updates to our KYC status
     69  * if there is no actual reason to check? Set to a very low
     70  * frequency, just to ensure we eventually notice.
     71  * Default value.
     72  */
     73 #define AML_LOW_FREQ GNUNET_TIME_relative_multiply ( \
     74           GNUNET_TIME_UNIT_DAYS, \
     75           7)
     76 
     77 /**
     78  * How frequently do we check for updates to our KYC status
     79  * if there is no actual reason to check? Set to a very low
     80  * frequency, just to ensure we eventually notice.
     81  */
     82 static struct GNUNET_TIME_Relative aml_low_freq;
     83 
     84 
     85 /**
     86  * How many inquiries do we process concurrently at most.
     87  */
     88 #define OPEN_INQUIRY_LIMIT 1024
     89 
     90 
     91 /**
     92  * Information about an exchange.
     93  */
     94 struct Exchange
     95 {
     96   /**
     97    * Kept in a DLL.
     98    */
     99   struct Exchange *next;
    100 
    101   /**
    102    * Kept in a DLL.
    103    */
    104   struct Exchange *prev;
    105 
    106   /**
    107    * The keys of this exchange
    108    */
    109   struct TALER_EXCHANGE_Keys *keys;
    110 
    111 };
    112 
    113 
    114 /**
    115  * Information about an Account.
    116  */
    117 struct Account
    118 {
    119   /**
    120    * Kept in a DLL.
    121    */
    122   struct Account *next;
    123 
    124   /**
    125    * Kept in a DLL.
    126    */
    127   struct Account *prev;
    128 
    129   /**
    130    * Head of inquiries for this account.
    131    */
    132   struct Inquiry *i_head;
    133 
    134   /**
    135    * Tail of inquiries for this account.
    136    */
    137   struct Inquiry *i_tail;
    138 
    139   /**
    140    * Merchant instance this account belongs to.
    141    */
    142   char *instance_id;
    143 
    144   /**
    145    * The payto-URI of this account.
    146    */
    147   struct TALER_FullPayto merchant_account_uri;
    148 
    149   /**
    150    * Wire hash of the merchant bank account (with the
    151    * respective salt).
    152    */
    153   struct TALER_MerchantWireHashP h_wire;
    154 
    155   /**
    156    * Private key of the instance.
    157    */
    158   union TALER_AccountPrivateKeyP ap;
    159 
    160   /**
    161    * Hash of the @e merchant_account_uri.
    162    */
    163   struct TALER_NormalizedPaytoHashP h_payto;
    164 
    165   /**
    166    * Database generation when this account
    167    * was last active.
    168    */
    169   uint64_t account_gen;
    170 
    171 };
    172 
    173 
    174 /**
    175  * Information about an inquiry job.
    176  */
    177 struct Inquiry
    178 {
    179   /**
    180    * Kept in a DLL.
    181    */
    182   struct Inquiry *next;
    183 
    184   /**
    185    * Kept in a DLL.
    186    */
    187   struct Inquiry *prev;
    188 
    189   /**
    190    * Main task for this inquiry.
    191    */
    192   struct GNUNET_SCHEDULER_Task *task;
    193 
    194   /**
    195    * Which exchange is this inquiry about.
    196    */
    197   struct Exchange *e;
    198 
    199   /**
    200    * Which account is this inquiry about.
    201    */
    202   struct Account *a;
    203 
    204   /**
    205    * AccountLimits that apply to the account, NULL
    206    * if unknown.
    207    */
    208   json_t *jlimits;
    209 
    210   /**
    211    * Handle for the actual HTTP request to the exchange.
    212    */
    213   struct TALER_EXCHANGE_GetKycCheckHandle *kyc;
    214 
    215   /**
    216    * Access token for the /kyc-info API.
    217    */
    218   struct TALER_AccountAccessTokenP access_token;
    219 
    220   /**
    221    * Last time we called the /kyc-check endpoint.
    222    */
    223   struct GNUNET_TIME_Timestamp last_kyc_check;
    224 
    225   /**
    226    * When is the next KYC check due?
    227    */
    228   struct GNUNET_TIME_Absolute due;
    229 
    230   /**
    231    * When should the current KYC time out?
    232    */
    233   struct GNUNET_TIME_Absolute timeout;
    234 
    235   /**
    236    * Current exponential backoff.
    237    */
    238   struct GNUNET_TIME_Relative backoff;
    239 
    240   /**
    241    * Rule generation known to the client, 0 for none.
    242    * Corresponds to the decision row in the exchange.
    243    */
    244   uint64_t rule_gen;
    245 
    246   /**
    247    * Last HTTP status returned by the exchange from
    248    * the /kyc-check endpoint.
    249    */
    250   unsigned int last_http_status;
    251 
    252   /**
    253    * Last Taler error code returned by the exchange from
    254    * the /kyc-check endpoint.
    255    */
    256   enum TALER_ErrorCode last_ec;
    257 
    258   /**
    259    * True if this is not our first time we make this request.
    260    */
    261   bool not_first_time;
    262 
    263   /**
    264    * Do soft limits on transactions apply to this merchant for operations
    265    * merchants care about? If so, we should increase our request frequency
    266    * and ask more often to see if they were lifted.
    267    */
    268   bool zero_limited;
    269 
    270   /**
    271    * Did we not run this inquiry due to limits?
    272    */
    273   bool limited;
    274 
    275   /**
    276    * Do we believe this account's KYC is in good shape?
    277    */
    278   bool kyc_ok;
    279 
    280   /**
    281    * True if merchant did perform this account's KYC AUTH transfer and @e access_token is set.
    282    */
    283   bool auth_ok;
    284 
    285   /**
    286    * True if the account is known to be currently under
    287    * investigation by AML staff.
    288    */
    289   bool aml_review;
    290 
    291 };
    292 
    293 
    294 /**
    295  * Head of known exchanges.
    296  */
    297 static struct Exchange *e_head;
    298 
    299 /**
    300  * Tail of known exchanges.
    301  */
    302 static struct Exchange *e_tail;
    303 
    304 /**
    305  * Head of accounts.
    306  */
    307 static struct Account *a_head;
    308 
    309 /**
    310  * Tail of accounts.
    311  */
    312 static struct Account *a_tail;
    313 
    314 /**
    315  * The merchant's configuration.
    316  */
    317 static const struct GNUNET_CONFIGURATION_Handle *cfg;
    318 
    319 /**
    320  * Our database connection.
    321  */
    322 static struct TALER_MERCHANTDB_PostgresContext *pg;
    323 
    324 /**
    325  * Handle to the context for interacting with the bank.
    326  */
    327 static struct GNUNET_CURL_Context *ctx;
    328 
    329 /**
    330  * Scheduler context for running the @e ctx.
    331  */
    332 static struct GNUNET_CURL_RescheduleContext *rc;
    333 
    334 /**
    335  * Event handler to learn that there may be new bank
    336  * accounts to check.
    337  */
    338 static struct GNUNET_DB_EventHandler *eh_accounts;
    339 
    340 /**
    341  * Event handler to learn that there may be new exchange
    342  * keys to check.
    343  */
    344 static struct GNUNET_DB_EventHandler *eh_keys;
    345 
    346 /**
    347  * Event handler to learn that there was a KYC
    348  * rule triggered and we need to check the KYC
    349  * status for an account.
    350  */
    351 static struct GNUNET_DB_EventHandler *eh_rule;
    352 
    353 /**
    354  * Event handler to learn that higher-frequency KYC
    355  * checks were forced by an application actively inspecting
    356  * some KYC status values.
    357  */
    358 static struct GNUNET_DB_EventHandler *eh_update_forced;
    359 
    360 /**
    361  * Event handler to learn that we got new /keys
    362  * from an exchange and should reconsider eligibility.
    363  */
    364 static struct GNUNET_DB_EventHandler *keys_rule;
    365 
    366 /**
    367  * Main task to discover (new) accounts.
    368  */
    369 static struct GNUNET_SCHEDULER_Task *account_task;
    370 
    371 /**
    372  * Counter determining how often we have called
    373  * "select_accounts" on the database.
    374  */
    375 static uint64_t database_gen;
    376 
    377 /**
    378  * How many active inquiries do we have right now.
    379  */
    380 static unsigned int active_inquiries;
    381 
    382 /**
    383  * Value to return from main(). 0 on success, non-zero on errors.
    384  */
    385 static int global_ret;
    386 
    387 /**
    388  * #GNUNET_YES if we are in test mode and should exit when idle.
    389  */
    390 static int test_mode;
    391 
    392 /**
    393  * True if the last DB query was limited by the
    394  * #OPEN_INQUIRY_LIMIT and we thus should check again
    395  * as soon as we are substantially below that limit,
    396  * and not only when we get a DB notification.
    397  */
    398 static bool at_limit;
    399 
    400 
    401 /**
    402  * Check about performing a /kyc-check request with the
    403  * exchange for the given inquiry.
    404  *
    405  * @param cls a `struct Inquiry` to process
    406  */
    407 static void
    408 inquiry_work (void *cls);
    409 
    410 
    411 /**
    412  * An inquiry finished, check if we should resume others.
    413  */
    414 static void
    415 end_inquiry (void)
    416 {
    417   GNUNET_assert (active_inquiries > 0);
    418   active_inquiries--;
    419   if ( (active_inquiries < OPEN_INQUIRY_LIMIT / 2) &&
    420        (at_limit) )
    421   {
    422     at_limit = false;
    423     for (struct Account *a = a_head;
    424          NULL != a;
    425          a = a->next)
    426     {
    427       for (struct Inquiry *i = a->i_head;
    428            NULL != i;
    429            i = i->next)
    430       {
    431         if (! i->limited)
    432           continue;
    433         GNUNET_assert (NULL == i->task);
    434         /* done synchronously so that the active_inquiries
    435            is updated immediately */
    436         inquiry_work (i);
    437         if (at_limit)
    438           break;
    439       }
    440       if (at_limit)
    441         break;
    442     }
    443   }
    444   if ( (! at_limit) &&
    445        (0 == active_inquiries) &&
    446        (test_mode) )
    447   {
    448     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    449                 "No more open inquiries and in test mode. Existing.\n");
    450     GNUNET_SCHEDULER_shutdown ();
    451     return;
    452   }
    453 }
    454 
    455 
    456 /**
    457  * Pack the given @a limit into the JSON @a limits array.
    458  *
    459  * @param limit account limit to pack
    460  * @param[in,out] limits JSON array to extend
    461  */
    462 static void
    463 pack_limit (const struct TALER_EXCHANGE_AccountLimit *limit,
    464             json_t *limits)
    465 {
    466   json_t *jl;
    467 
    468   jl = GNUNET_JSON_PACK (
    469     TALER_JSON_pack_kycte ("operation_type",
    470                            limit->operation_type),
    471     GNUNET_JSON_pack_time_rel ("timeframe",
    472                                limit->timeframe),
    473     TALER_JSON_pack_amount ("threshold",
    474                             &limit->threshold),
    475     GNUNET_JSON_pack_bool ("soft_limit",
    476                            limit->soft_limit)
    477     );
    478   GNUNET_assert (0 ==
    479                  json_array_append_new (limits,
    480                                         jl));
    481 }
    482 
    483 
    484 /**
    485  * Update KYC status for @a i based on
    486  * @a account_kyc_status
    487  *
    488  * @param[in,out] i inquiry context, jlimits is updated
    489  * @param account_kyc_status account KYC status details
    490  */
    491 static void
    492 store_kyc_status (
    493   struct Inquiry *i,
    494   const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status)
    495 {
    496   json_t *jlimits;
    497 
    498   json_decref (i->jlimits);
    499   jlimits = json_array ();
    500   GNUNET_assert (NULL != jlimits);
    501   i->zero_limited = false;
    502   for (unsigned int j = 0; j<account_kyc_status->limits_length; j++)
    503   {
    504     const struct TALER_EXCHANGE_AccountLimit *limit
    505       = &account_kyc_status->limits[j];
    506 
    507     pack_limit (limit,
    508                 jlimits);
    509     if (TALER_amount_is_zero (&limit->threshold) &&
    510         limit->soft_limit &&
    511         ( (TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT == limit->operation_type) ||
    512           (TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE == limit->operation_type) ||
    513           (TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION == limit->operation_type) ) )
    514     {
    515       i->zero_limited = true;
    516     }
    517   }
    518   i->jlimits = jlimits;
    519   GNUNET_break (! GNUNET_is_zero (&account_kyc_status->access_token));
    520   i->access_token = account_kyc_status->access_token;
    521   i->aml_review = account_kyc_status->aml_review;
    522   i->kyc_ok = (MHD_HTTP_OK == i->last_http_status);
    523 }
    524 
    525 
    526 /**
    527  * Function called with the result of a KYC check.
    528  *
    529  * @param cls a `struct Inquiry *`
    530  * @param ks the account's KYC status details
    531  */
    532 static void
    533 exchange_check_cb (
    534   void *cls,
    535   const struct TALER_EXCHANGE_GetKycCheckResponse *ks)
    536 {
    537   struct Inquiry *i = cls;
    538   bool progress = false;
    539 
    540   i->kyc = NULL;
    541   if (! i->not_first_time)
    542     progress = true;
    543   if ( (i->last_http_status != ks->hr.http_status) &&
    544        (0 != ks->hr.http_status) )
    545     progress = true;
    546   if (0 != ks->hr.http_status)
    547   {
    548     i->last_http_status = ks->hr.http_status;
    549     i->last_ec = ks->hr.ec;
    550   }
    551   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    552               "KYC status of `%s' / %s at `%s' is %u\n",
    553               i->a->merchant_account_uri.full_payto,
    554               i->a->instance_id,
    555               i->e->keys->exchange_url,
    556               ks->hr.http_status);
    557   switch (ks->hr.http_status)
    558   {
    559   case 0:
    560     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    561                 "Exchange did not responded to /kyc-check request!\n");
    562     i->backoff
    563       = GNUNET_TIME_randomized_backoff (i->backoff,
    564                                         EXCHANGE_TIMEOUT);
    565     i->due = GNUNET_TIME_relative_to_absolute (i->backoff);
    566     break;
    567   case MHD_HTTP_OK:
    568     if (i->rule_gen != ks->details.ok.rule_gen)
    569       progress = true;
    570     i->rule_gen = ks->details.ok.rule_gen;
    571     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    572     /* exchange says KYC is OK, gives status information */
    573     i->auth_ok = true;
    574     store_kyc_status (i,
    575                       &ks->details.ok);
    576     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    577     if (i->aml_review || i->zero_limited)
    578     {
    579       if (! progress)
    580         i->due = GNUNET_TIME_relative_to_absolute (
    581           GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_freq,
    582                                                            i->backoff)));
    583     }
    584     else
    585     {
    586       /* KYC is OK, only check again if triggered */
    587       if (! progress)
    588         i->due = GNUNET_TIME_relative_to_absolute (
    589           GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_low_freq,
    590                                                            i->backoff)));
    591     }
    592     break;
    593   case MHD_HTTP_ACCEPTED:
    594     if (i->rule_gen != ks->details.accepted.rule_gen)
    595       progress = true;
    596     i->rule_gen = ks->details.accepted.rule_gen;
    597     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    598 
    599     /* exchange says KYC is required */
    600     i->auth_ok = true;
    601     store_kyc_status (i,
    602                       &ks->details.accepted);
    603     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    604     /* Start immediately with long-polling */
    605     if (! progress)
    606       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
    607                                          i->timeout);
    608     break;
    609   case MHD_HTTP_NO_CONTENT:
    610     i->rule_gen = 0;
    611     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    612     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    613     /* exchange claims KYC is off! */
    614     i->kyc_ok = true;
    615     i->aml_review = false;
    616     /* Clear limits, in case exchange had KYC on previously */
    617     json_decref (i->jlimits);
    618     i->jlimits = NULL;
    619     /* KYC is OK, only check again if triggered */
    620     i->due = GNUNET_TIME_relative_to_absolute (
    621       GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_low_freq,
    622                                                        i->backoff)));
    623     break;
    624   case MHD_HTTP_FORBIDDEN: /* bad signature */
    625     i->rule_gen = 0;
    626     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    627     /* Forbidden => KYC auth must be wrong */
    628     i->auth_ok = false;
    629     /* Start with long-polling */
    630     if (! progress)
    631       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
    632                                          i->timeout);
    633     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    634     break;
    635   case MHD_HTTP_NOT_FOUND: /* account unknown */
    636     i->rule_gen = 0;
    637     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    638     /* Account unknown => no KYC auth yet */
    639     i->auth_ok = false;
    640     /* unknown account => wire transfer required! */
    641     i->kyc_ok = false;
    642     /* There should not be any limits yet, but clear them
    643        just in case the exchange has amnesia */
    644     json_decref (i->jlimits);
    645     i->jlimits = NULL;
    646     /* Start immediately with Long-polling */
    647     if (! progress)
    648       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
    649                                          i->timeout);
    650     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    651     break;
    652   case MHD_HTTP_CONFLICT: /* no account_pub known */
    653     i->rule_gen = 0;
    654     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    655     /* Conflict => KYC auth wire transfer missing! */
    656     i->auth_ok = false;
    657     /* Start immediately with Long-polling */
    658     if (! progress)
    659       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
    660                                          i->timeout);
    661     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    662     break;
    663   default:
    664     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    665                 "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n",
    666                 ks->hr.http_status,
    667                 ks->hr.ec);
    668     i->backoff
    669       = GNUNET_TIME_randomized_backoff (i->backoff,
    670                                         EXCHANGE_TIMEOUT);
    671     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    672     i->due = GNUNET_TIME_relative_to_absolute (i->backoff);
    673     i->auth_ok = false;
    674     break;
    675   }
    676 
    677   {
    678     enum GNUNET_DB_QueryStatus qs;
    679 
    680     qs = TALER_MERCHANTDB_account_kyc_set_status (
    681       pg,
    682       i->a->instance_id,
    683       &i->a->h_wire,
    684       i->e->keys->exchange_url,
    685       i->last_kyc_check,
    686       i->due,
    687       i->backoff,
    688       i->last_http_status,
    689       i->last_ec,
    690       i->rule_gen,
    691       (i->auth_ok)
    692       ? &i->access_token
    693       : NULL,
    694       i->jlimits,
    695       i->aml_review,
    696       i->kyc_ok);
    697     if (qs < 0)
    698     {
    699       GNUNET_break (0);
    700       global_ret = EXIT_FAILURE;
    701       GNUNET_SCHEDULER_shutdown ();
    702       return;
    703     }
    704     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    705                 "account_kyc_set_status (%s, %s, %u, %s, %s) returned %d\n",
    706                 i->a->instance_id,
    707                 i->e->keys->exchange_url,
    708                 i->last_http_status,
    709                 i->auth_ok ? "auth OK" : "auth needed",
    710                 NULL == i->jlimits ? "default limits" : "custom limits",
    711                 (int) qs);
    712     i->not_first_time = true;
    713   }
    714   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    715               "Will repeat inquiry in %s\n",
    716               GNUNET_TIME_relative2s (
    717                 GNUNET_TIME_absolute_get_remaining (i->due),
    718                 true));
    719   if (! GNUNET_TIME_absolute_is_never (i->due))
    720     i->task = GNUNET_SCHEDULER_add_at (i->due,
    721                                        &inquiry_work,
    722                                        i);
    723   end_inquiry ();
    724 }
    725 
    726 
    727 static void
    728 inquiry_work (void *cls)
    729 {
    730   struct Inquiry *i = cls;
    731   enum TALER_EXCHANGE_KycLongPollTarget lpt;
    732 
    733   i->task = NULL;
    734   if (! GNUNET_TIME_absolute_is_past (i->due))
    735   {
    736     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    737                 "Will start inquiry on %s for %s in %s\n",
    738                 i->a->merchant_account_uri.full_payto,
    739                 i->e->keys->exchange_url,
    740                 GNUNET_TIME_relative2s (
    741                   GNUNET_TIME_absolute_get_remaining (i->due),
    742                   true));
    743     i->task
    744       = GNUNET_SCHEDULER_add_at (i->due,
    745                                  &inquiry_work,
    746                                  i);
    747     goto finish;
    748   }
    749 
    750   GNUNET_assert (OPEN_INQUIRY_LIMIT >= active_inquiries);
    751   if (OPEN_INQUIRY_LIMIT <= active_inquiries)
    752   {
    753     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    754                 "Not looking for work: at limit\n");
    755     i->limited = true;
    756     at_limit = true;
    757     return;
    758   }
    759   at_limit = false;
    760   i->timeout
    761     = GNUNET_TIME_relative_to_absolute (EXCHANGE_TIMEOUT);
    762   lpt = TALER_EXCHANGE_KLPT_NONE;
    763   if (! i->auth_ok)
    764     lpt = TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER;
    765   else if (! i->kyc_ok)
    766     lpt = TALER_EXCHANGE_KLPT_KYC_OK;
    767   else if (i->aml_review)
    768     lpt = TALER_EXCHANGE_KLPT_INVESTIGATION_DONE;
    769   if (! i->not_first_time)
    770     lpt = TALER_EXCHANGE_KLPT_NONE; /* no long polling on 1st call */
    771   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    772               "Starting KYC status of `%s' for %s at `%s' (%d, %d, %d) using LPT %d\n",
    773               i->a->merchant_account_uri.full_payto,
    774               i->a->instance_id,
    775               i->e->keys->exchange_url,
    776               i->not_first_time,
    777               i->auth_ok,
    778               i->kyc_ok,
    779               lpt);
    780   i->kyc = TALER_EXCHANGE_get_kyc_check_create (
    781     ctx,
    782     i->e->keys->exchange_url,
    783     &i->a->h_payto,
    784     &i->a->ap);
    785   if (NULL == i->kyc)
    786   {
    787     GNUNET_break (0);
    788     i->due = i->timeout;
    789     i->task
    790       = GNUNET_SCHEDULER_add_at (i->due,
    791                                  &inquiry_work,
    792                                  i);
    793     goto finish;
    794   }
    795   GNUNET_assert (GNUNET_OK ==
    796                  TALER_EXCHANGE_get_kyc_check_set_options (
    797                    i->kyc,
    798                    TALER_EXCHANGE_get_kyc_check_option_known_rule_gen (
    799                      i->rule_gen),
    800                    TALER_EXCHANGE_get_kyc_check_option_lpt (lpt),
    801                    TALER_EXCHANGE_get_kyc_check_option_timeout (
    802                      i->not_first_time && (! test_mode)
    803                      ? EXCHANGE_TIMEOUT
    804                      : GNUNET_TIME_UNIT_ZERO)));
    805   GNUNET_assert (TALER_EC_NONE ==
    806                  TALER_EXCHANGE_get_kyc_check_start (i->kyc,
    807                                                      &exchange_check_cb,
    808                                                      i));
    809   active_inquiries++;
    810 finish:
    811   if ( (0 == active_inquiries) &&
    812        (test_mode) )
    813   {
    814     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    815                 "No more open inquiries and in test mode. Existing.\n");
    816     GNUNET_SCHEDULER_shutdown ();
    817     return;
    818   }
    819 }
    820 
    821 
    822 /**
    823  * Check if the account @a could work with exchange that
    824  * has keys @a keys.
    825  *
    826  * @param keys the keys of an exchange
    827  * @param a an account
    828  */
    829 static bool
    830 is_eligible (const struct TALER_EXCHANGE_Keys *keys,
    831              const struct Account *a)
    832 {
    833   struct TALER_NormalizedPayto np;
    834   bool ret;
    835 
    836   np = TALER_payto_normalize (a->merchant_account_uri);
    837   ret = TALER_EXCHANGE_keys_test_account_allowed (keys,
    838                                                   true,
    839                                                   np);
    840   GNUNET_free (np.normalized_payto);
    841   return ret;
    842 }
    843 
    844 
    845 /**
    846  * Start the KYC checking for account @a at exchange @a e.
    847  *
    848  * @param e an exchange
    849  * @param a an account
    850  */
    851 static void
    852 start_inquiry (struct Exchange *e,
    853                struct Account *a)
    854 {
    855   struct Inquiry *i;
    856   enum GNUNET_DB_QueryStatus qs;
    857 
    858   i = GNUNET_new (struct Inquiry);
    859   i->e = e;
    860   i->a = a;
    861   GNUNET_CONTAINER_DLL_insert (a->i_head,
    862                                a->i_tail,
    863                                i);
    864   qs = TALER_MERCHANTDB_get_kyc_status (pg,
    865                                         a->merchant_account_uri,
    866                                         a->instance_id,
    867                                         e->keys->exchange_url,
    868                                         &i->auth_ok,
    869                                         &i->access_token,
    870                                         &i->kyc_ok,
    871                                         &i->last_http_status,
    872                                         &i->last_ec,
    873                                         &i->rule_gen,
    874                                         &i->last_kyc_check,
    875                                         &i->due,
    876                                         &i->backoff,
    877                                         &i->aml_review,
    878                                         &i->jlimits);
    879   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    880               "account_kyc_get_status (%s, %s, %s) returned %d (%u, #%llu)\n",
    881               i->a->instance_id,
    882               e->keys->exchange_url,
    883               a->merchant_account_uri.full_payto,
    884               (int) qs,
    885               i->last_http_status,
    886               (unsigned long long) i->rule_gen);
    887   if (qs < 0)
    888   {
    889     GNUNET_break (0);
    890     global_ret = EXIT_FAILURE;
    891     GNUNET_SCHEDULER_shutdown ();
    892     return;
    893   }
    894   if (qs > 0)
    895     i->not_first_time = true;
    896   if (GNUNET_YES == test_mode)
    897     i->due = GNUNET_TIME_UNIT_ZERO_ABS; /* immediately */
    898   inquiry_work (i);
    899 }
    900 
    901 
    902 /**
    903  * Stop KYC inquiry @a i.
    904  *
    905  * @param[in] i the inquiry to stop
    906  */
    907 static void
    908 stop_inquiry (struct Inquiry *i)
    909 {
    910   struct Account *a = i->a;
    911 
    912   GNUNET_CONTAINER_DLL_remove (a->i_head,
    913                                a->i_tail,
    914                                i);
    915   if (NULL != i->task)
    916   {
    917     GNUNET_SCHEDULER_cancel (i->task);
    918     i->task = NULL;
    919   }
    920   if (NULL != i->kyc)
    921   {
    922     TALER_EXCHANGE_get_kyc_check_cancel (i->kyc);
    923     i->kyc = NULL;
    924   }
    925   if (NULL != i->jlimits)
    926   {
    927     json_decref (i->jlimits);
    928     i->jlimits = NULL;
    929   }
    930   GNUNET_free (i);
    931 }
    932 
    933 
    934 /**
    935  * Stop KYC inquiry for account @a at exchange @a e.
    936  *
    937  * @param e an exchange
    938  * @param a an account
    939  */
    940 static void
    941 stop_inquiry_at (struct Exchange *e,
    942                  struct Account *a)
    943 {
    944   for (struct Inquiry *i = a->i_head;
    945        NULL != i;
    946        i = i->next)
    947   {
    948     if (e == i->e)
    949     {
    950       stop_inquiry (i);
    951       return;
    952     }
    953   }
    954   /* strange, there should have been a match! */
    955   GNUNET_break (0);
    956 }
    957 
    958 
    959 /**
    960  * Set the account @a h_wire of @a instance_id to be ineligible
    961  * for the exchange at @a exchange_url and thus no need to do KYC checks.
    962  *
    963  * @param instance_id instance that has the account
    964  * @param exchange_url base URL of the exchange
    965  * @param h_wire hash of the merchant bank account that is ineligible
    966  */
    967 static void
    968 flag_ineligible (const char *instance_id,
    969                  const char *exchange_url,
    970                  const struct TALER_MerchantWireHashP *h_wire)
    971 {
    972   enum GNUNET_DB_QueryStatus qs;
    973 
    974   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    975               "Account %s not eligible at exchange %s\n",
    976               TALER_B2S (h_wire),
    977               exchange_url);
    978   qs = TALER_MERCHANTDB_account_kyc_set_status (
    979     pg,
    980     instance_id,
    981     h_wire,
    982     exchange_url,
    983     GNUNET_TIME_timestamp_get (),
    984     GNUNET_TIME_UNIT_FOREVER_ABS,
    985     GNUNET_TIME_UNIT_FOREVER_REL,
    986     0,
    987     TALER_EC_MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE,
    988     0,
    989     NULL,
    990     NULL,
    991     false,
    992     false);
    993   if (qs < 0)
    994   {
    995     GNUNET_break (0);
    996     global_ret = EXIT_FAILURE;
    997     GNUNET_SCHEDULER_shutdown ();
    998     return;
    999   }
   1000   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1001               "account_kyc_set_status (%s) returned %d\n",
   1002               exchange_url,
   1003               (int) qs);
   1004 }
   1005 
   1006 
   1007 /**
   1008  * Start inquries for all exchanges on account @a a.
   1009  *
   1010  * @param a an account
   1011  */
   1012 static void
   1013 start_inquiries (struct Account *a)
   1014 {
   1015   for (struct Exchange *e = e_head;
   1016        NULL != e;
   1017        e = e->next)
   1018   {
   1019     if (is_eligible (e->keys,
   1020                      a))
   1021     {
   1022       start_inquiry (e,
   1023                      a);
   1024     }
   1025     else
   1026     {
   1027       flag_ineligible (a->instance_id,
   1028                        e->keys->exchange_url,
   1029                        &a->h_wire);
   1030     }
   1031   }
   1032 }
   1033 
   1034 
   1035 /**
   1036  * Stop all inquries involving account @a a.
   1037  *
   1038  * @param a an account
   1039  */
   1040 static void
   1041 stop_inquiries (struct Account *a)
   1042 {
   1043   struct Inquiry *i;
   1044 
   1045   while (NULL != (i = a->i_head))
   1046     stop_inquiry (i);
   1047 }
   1048 
   1049 
   1050 /**
   1051  * Callback invoked with information about a bank account.
   1052  *
   1053  * @param cls closure
   1054  * @param merchant_priv private key of the merchant instance
   1055  * @param ad details about the account
   1056  */
   1057 static void
   1058 account_cb (
   1059   void *cls,
   1060   const struct TALER_MerchantPrivateKeyP *merchant_priv,
   1061   const struct TALER_MERCHANTDB_AccountDetails *ad)
   1062 {
   1063   struct TALER_FullPayto payto_uri = ad->payto_uri;
   1064 
   1065   if (! ad->active)
   1066     return;
   1067   if (NULL == merchant_priv)
   1068     return; /* instance was deleted */
   1069   for (struct Account *a = a_head;
   1070        NULL != a;
   1071        a = a->next)
   1072   {
   1073     if ( (0 ==
   1074           TALER_full_payto_cmp (payto_uri,
   1075                                 a->merchant_account_uri)) &&
   1076          (0 ==
   1077           GNUNET_memcmp (&a->h_wire,
   1078                          &ad->h_wire)) &&
   1079          (0 ==
   1080           strcmp (ad->instance_id,
   1081                   a->instance_id)) )
   1082     {
   1083       a->account_gen = database_gen;
   1084       return;
   1085     }
   1086   }
   1087   {
   1088     struct Account *a = GNUNET_new (struct Account);
   1089 
   1090     a->account_gen = database_gen;
   1091     a->merchant_account_uri.full_payto
   1092       = GNUNET_strdup (ad->payto_uri.full_payto);
   1093     a->instance_id
   1094       = GNUNET_strdup (ad->instance_id);
   1095     a->h_wire
   1096       = ad->h_wire;
   1097     a->ap.merchant_priv
   1098       = *merchant_priv;
   1099     TALER_full_payto_normalize_and_hash (a->merchant_account_uri,
   1100                                          &a->h_payto);
   1101     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1102                 "Found account %s of instance %s with H_PAYTO %s\n",
   1103                 ad->payto_uri.full_payto,
   1104                 ad->instance_id,
   1105                 GNUNET_sh2s (&a->h_payto.hash));
   1106     GNUNET_CONTAINER_DLL_insert (a_head,
   1107                                  a_tail,
   1108                                  a);
   1109     start_inquiries (a);
   1110   }
   1111 }
   1112 
   1113 
   1114 /**
   1115  * The set of bank accounts has changed, update our
   1116  * list of active inquiries.
   1117  *
   1118  * @param cls unused
   1119  */
   1120 static void
   1121 find_accounts (void *cls)
   1122 {
   1123   enum GNUNET_DB_QueryStatus qs;
   1124 
   1125   (void) cls;
   1126   account_task = NULL;
   1127   database_gen++;
   1128   qs = TALER_MERCHANTDB_select_accounts (pg,
   1129                                          NULL, /* all instances */
   1130                                          &account_cb,
   1131                                          NULL);
   1132   if (qs < 0)
   1133   {
   1134     GNUNET_break (0);
   1135     global_ret = EXIT_FAILURE;
   1136     GNUNET_SCHEDULER_shutdown ();
   1137     return;
   1138   }
   1139   for (struct Account *a = a_head;
   1140        NULL != a;
   1141        a = a->next)
   1142   {
   1143     if (a->account_gen < database_gen)
   1144       stop_inquiries (a);
   1145   }
   1146   if ( (! at_limit) &&
   1147        (0 == active_inquiries) &&
   1148        (test_mode) )
   1149   {
   1150     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1151                 "No more open inquiries and in test mode. Existing.\n");
   1152     GNUNET_SCHEDULER_shutdown ();
   1153     return;
   1154   }
   1155 }
   1156 
   1157 
   1158 /**
   1159  * Function called when transfers are added to the merchant database.  We look
   1160  * for more work.
   1161  *
   1162  * @param cls closure (NULL)
   1163  * @param extra additional event data provided
   1164  * @param extra_size number of bytes in @a extra
   1165  */
   1166 static void
   1167 account_changed (void *cls,
   1168                  const void *extra,
   1169                  size_t extra_size)
   1170 {
   1171   (void) cls;
   1172   (void) extra;
   1173   (void) extra_size;
   1174   if (NULL != account_task)
   1175     return;
   1176   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1177               "Received account change notification: reloading accounts\n");
   1178   account_task
   1179     = GNUNET_SCHEDULER_add_now (&find_accounts,
   1180                                 NULL);
   1181 }
   1182 
   1183 
   1184 /**
   1185  * Interact with the database to get the current set
   1186  * of exchange keys known to us.
   1187  *
   1188  * @param exchange_url the exchange URL to check
   1189  */
   1190 static void
   1191 find_keys (const char *exchange_url)
   1192 {
   1193   enum GNUNET_DB_QueryStatus qs;
   1194   struct TALER_EXCHANGE_Keys *keys;
   1195   struct Exchange *e;
   1196   struct GNUNET_TIME_Absolute first_retry;
   1197 
   1198   qs = TALER_MERCHANTDB_select_exchange_keys (pg,
   1199                                               exchange_url,
   1200                                               &first_retry,
   1201                                               &keys);
   1202   if (qs < 0)
   1203   {
   1204     GNUNET_break (0);
   1205     global_ret = EXIT_FAILURE;
   1206     GNUNET_SCHEDULER_shutdown ();
   1207     return;
   1208   }
   1209   if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
   1210        (NULL == keys) )
   1211   {
   1212     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1213                 "No %s/keys yet!\n",
   1214                 exchange_url);
   1215     return;
   1216   }
   1217   for (e = e_head; NULL != e; e = e->next)
   1218   {
   1219     if (0 == strcmp (e->keys->exchange_url,
   1220                      keys->exchange_url))
   1221     {
   1222       struct TALER_EXCHANGE_Keys *old_keys = e->keys;
   1223 
   1224       e->keys = keys;
   1225       for (struct Account *a = a_head;
   1226            NULL != a;
   1227            a = a->next)
   1228       {
   1229         bool was_eligible = is_eligible (old_keys,
   1230                                          a);
   1231         bool now_eligible = is_eligible (keys,
   1232                                          a);
   1233 
   1234         if (was_eligible == now_eligible)
   1235           continue; /* no change, do nothing */
   1236         if (was_eligible)
   1237           stop_inquiry_at (e,
   1238                            a);
   1239         else /* is_eligible */
   1240           start_inquiry (e,
   1241                          a);
   1242       }
   1243       TALER_EXCHANGE_keys_decref (old_keys);
   1244       return;
   1245     }
   1246   }
   1247   e = GNUNET_new (struct Exchange);
   1248   e->keys = keys;
   1249   GNUNET_CONTAINER_DLL_insert (e_head,
   1250                                e_tail,
   1251                                e);
   1252   for (struct Account *a = a_head;
   1253        NULL != a;
   1254        a = a->next)
   1255   {
   1256     if ( (a->account_gen == database_gen) &&
   1257          (is_eligible (e->keys,
   1258                        a)) )
   1259       start_inquiry (e,
   1260                      a);
   1261   }
   1262 }
   1263 
   1264 
   1265 /**
   1266  * Function called when keys were changed in the
   1267  * merchant database. Updates ours.
   1268  *
   1269  * @param cls closure (NULL)
   1270  * @param extra additional event data provided
   1271  * @param extra_size number of bytes in @a extra
   1272  */
   1273 static void
   1274 keys_changed (void *cls,
   1275               const void *extra,
   1276               size_t extra_size)
   1277 {
   1278   const char *url = extra;
   1279 
   1280   (void) cls;
   1281   if ( (NULL == extra) ||
   1282        (0 == extra_size) )
   1283   {
   1284     GNUNET_break (0);
   1285     global_ret = EXIT_FAILURE;
   1286     GNUNET_SCHEDULER_shutdown ();
   1287     return;
   1288   }
   1289   if ('\0' != url[extra_size - 1])
   1290   {
   1291     GNUNET_break (0);
   1292     global_ret = EXIT_FAILURE;
   1293     GNUNET_SCHEDULER_shutdown ();
   1294     return;
   1295   }
   1296   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1297               "Received keys change notification: reload `%s'\n",
   1298               url);
   1299   find_keys (url);
   1300 }
   1301 
   1302 
   1303 /**
   1304  * Function called when a KYC rule was triggered by
   1305  * a transaction and we need to get the latest KYC
   1306  * status immediately.
   1307  *
   1308  * @param cls closure (NULL)
   1309  * @param extra additional event data provided
   1310  * @param extra_size number of bytes in @a extra
   1311  */
   1312 static void
   1313 rule_triggered (void *cls,
   1314                 const void *extra,
   1315                 size_t extra_size)
   1316 {
   1317   const char *text = extra;
   1318   const char *space;
   1319   struct TALER_MerchantWireHashP h_wire;
   1320   const char *exchange_url;
   1321 
   1322   (void) cls;
   1323   if ( (NULL == extra) ||
   1324        (0 == extra_size) )
   1325   {
   1326     GNUNET_break (0);
   1327     global_ret = EXIT_FAILURE;
   1328     GNUNET_SCHEDULER_shutdown ();
   1329     return;
   1330   }
   1331   if ('\0' != text[extra_size - 1])
   1332   {
   1333     GNUNET_break (0);
   1334     global_ret = EXIT_FAILURE;
   1335     GNUNET_SCHEDULER_shutdown ();
   1336     return;
   1337   }
   1338   space = memchr (extra,
   1339                   ' ',
   1340                   extra_size);
   1341   if (NULL == space)
   1342   {
   1343     GNUNET_break (0);
   1344     global_ret = EXIT_FAILURE;
   1345     GNUNET_SCHEDULER_shutdown ();
   1346     return;
   1347   }
   1348   if (GNUNET_OK !=
   1349       GNUNET_STRINGS_string_to_data (extra,
   1350                                      space - text,
   1351                                      &h_wire,
   1352                                      sizeof (h_wire)))
   1353   {
   1354     GNUNET_break (0);
   1355     global_ret = EXIT_FAILURE;
   1356     GNUNET_SCHEDULER_shutdown ();
   1357     return;
   1358   }
   1359   exchange_url = &space[1];
   1360   if (! TALER_is_web_url (exchange_url))
   1361   {
   1362     GNUNET_break (0);
   1363     global_ret = EXIT_FAILURE;
   1364     GNUNET_SCHEDULER_shutdown ();
   1365     return;
   1366   }
   1367 
   1368   for (struct Account *a = a_head;
   1369        NULL != a;
   1370        a = a->next)
   1371   {
   1372     if (0 !=
   1373         GNUNET_memcmp (&h_wire,
   1374                        &a->h_wire))
   1375       continue;
   1376     for (struct Inquiry *i = a->i_head;
   1377          NULL != i;
   1378          i = i->next)
   1379     {
   1380       if (0 != strcmp (exchange_url,
   1381                        i->e->keys->exchange_url))
   1382         continue;
   1383       i->kyc_ok = false;
   1384       i->due = GNUNET_TIME_UNIT_ZERO_ABS;
   1385       if (NULL != i->task)
   1386       {
   1387         GNUNET_SCHEDULER_cancel (i->task);
   1388         i->task = NULL;
   1389       }
   1390       if (NULL != i->kyc)
   1391       {
   1392         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1393                     "/kyc-check already running for %s\n",
   1394                     text);
   1395         return;
   1396       }
   1397       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1398                   "Starting %skyc-check for `%s' due to KYC rule trigger\n",
   1399                   exchange_url,
   1400                   i->a->merchant_account_uri.full_payto);
   1401       i->task = GNUNET_SCHEDULER_add_at (i->due,
   1402                                          &inquiry_work,
   1403                                          i);
   1404       return;
   1405     }
   1406   }
   1407   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1408               "KYC rule trigger notification `%s' matches none of our accounts\n",
   1409               text);
   1410 }
   1411 
   1412 
   1413 /**
   1414  * Function called on each configuration section. Finds sections
   1415  * about exchanges, parses the entries.
   1416  *
   1417  * @param cls NULL
   1418  * @param section name of the section
   1419  */
   1420 static void
   1421 accept_exchanges (void *cls,
   1422                   const char *section)
   1423 {
   1424   char *url;
   1425 
   1426   (void) cls;
   1427   if (0 !=
   1428       strncasecmp (section,
   1429                    "merchant-exchange-",
   1430                    strlen ("merchant-exchange-")))
   1431     return;
   1432   if (GNUNET_YES ==
   1433       GNUNET_CONFIGURATION_get_value_yesno (cfg,
   1434                                             section,
   1435                                             "DISABLED"))
   1436     return;
   1437   if (GNUNET_OK !=
   1438       GNUNET_CONFIGURATION_get_value_string (cfg,
   1439                                              section,
   1440                                              "EXCHANGE_BASE_URL",
   1441                                              &url))
   1442   {
   1443     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1444                                section,
   1445                                "EXCHANGE_BASE_URL");
   1446     global_ret = EXIT_NOTCONFIGURED;
   1447     GNUNET_SCHEDULER_shutdown ();
   1448     return;
   1449   }
   1450   find_keys (url);
   1451   GNUNET_free (url);
   1452 }
   1453 
   1454 
   1455 /**
   1456  * We're being aborted with CTRL-C (or SIGTERM). Shut down.
   1457  *
   1458  * @param cls closure (NULL)
   1459  */
   1460 static void
   1461 shutdown_task (void *cls)
   1462 {
   1463   (void) cls;
   1464   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1465               "Running shutdown\n");
   1466   while (NULL != e_head)
   1467   {
   1468     struct Exchange *e = e_head;
   1469 
   1470     if (NULL != e->keys)
   1471     {
   1472       TALER_EXCHANGE_keys_decref (e->keys);
   1473       e->keys = NULL;
   1474     }
   1475     GNUNET_CONTAINER_DLL_remove (e_head,
   1476                                  e_tail,
   1477                                  e);
   1478     GNUNET_free (e);
   1479   }
   1480   while (NULL != a_head)
   1481   {
   1482     struct Account *a = a_head;
   1483 
   1484     stop_inquiries (a);
   1485     GNUNET_CONTAINER_DLL_remove (a_head,
   1486                                  a_tail,
   1487                                  a);
   1488     GNUNET_free (a->merchant_account_uri.full_payto);
   1489     GNUNET_free (a->instance_id);
   1490     GNUNET_free (a);
   1491   }
   1492   if (NULL != eh_accounts)
   1493   {
   1494     TALER_MERCHANTDB_event_listen_cancel (eh_accounts);
   1495     eh_accounts = NULL;
   1496   }
   1497   if (NULL != account_task)
   1498   {
   1499     GNUNET_SCHEDULER_cancel (account_task);
   1500     account_task = NULL;
   1501   }
   1502   if (NULL != eh_keys)
   1503   {
   1504     TALER_MERCHANTDB_event_listen_cancel (eh_keys);
   1505     eh_keys = NULL;
   1506   }
   1507   if (NULL != eh_rule)
   1508   {
   1509     TALER_MERCHANTDB_event_listen_cancel (eh_rule);
   1510     eh_rule = NULL;
   1511   }
   1512   if (NULL != eh_update_forced)
   1513   {
   1514     TALER_MERCHANTDB_event_listen_cancel (eh_update_forced);
   1515     eh_update_forced = NULL;
   1516   }
   1517   if (NULL != keys_rule)
   1518   {
   1519     TALER_MERCHANTDB_event_listen_cancel (keys_rule);
   1520     keys_rule = NULL;
   1521   }
   1522   if (NULL != pg)
   1523   {
   1524     TALER_MERCHANTDB_disconnect (pg);
   1525     pg = NULL;
   1526   }
   1527   cfg = NULL;
   1528   if (NULL != ctx)
   1529   {
   1530     GNUNET_CURL_fini (ctx);
   1531     ctx = NULL;
   1532   }
   1533   if (NULL != rc)
   1534   {
   1535     GNUNET_CURL_gnunet_rc_destroy (rc);
   1536     rc = NULL;
   1537   }
   1538 }
   1539 
   1540 
   1541 /**
   1542  * Function called when we urgently need to re-check the KYC status
   1543  * of some account. Finds the respective inquiry and re-launches
   1544  * the check, unless we are already doing it.
   1545  *
   1546  * @param cls NULL
   1547  * @param instance_id instance for which to force the check
   1548  * @param exchange_url base URL of the exchange to check
   1549  * @param h_wire hash of the wire account to check KYC status for
   1550  */
   1551 static void
   1552 force_check_now (void *cls,
   1553                  const char *instance_id,
   1554                  const char *exchange_url,
   1555                  const struct TALER_MerchantWireHashP *h_wire)
   1556 {
   1557   for (struct Account *a = a_head;
   1558        NULL != a;
   1559        a = a->next)
   1560   {
   1561     if (0 !=
   1562         strcmp (instance_id,
   1563                 a->instance_id))
   1564       continue;
   1565     if (0 !=
   1566         GNUNET_memcmp (h_wire,
   1567                        &a->h_wire))
   1568       continue;
   1569     for (struct Inquiry *i = a->i_head;
   1570          NULL != i;
   1571          i = i->next)
   1572     {
   1573       if (0 !=
   1574           strcmp (i->e->keys->exchange_url,
   1575                   exchange_url))
   1576         continue;
   1577       /* If we are not actively checking with the exchange, do start
   1578          to check immediately */
   1579       if (NULL != i->kyc)
   1580       {
   1581         i->due = GNUNET_TIME_absolute_get (); /* now! */
   1582         if (NULL != i->task)
   1583           GNUNET_SCHEDULER_cancel (i->task);
   1584         i->task = GNUNET_SCHEDULER_add_at (i->due,
   1585                                            &inquiry_work,
   1586                                            i);
   1587       }
   1588       return;
   1589     }
   1590   }
   1591   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1592               "No inquiry at `%s' for exchange `%s' and h_wire `%s'. Likely the account is not eligible.\n",
   1593               instance_id,
   1594               exchange_url,
   1595               TALER_B2S (h_wire));
   1596   /* In this case, set the due date back to FOREVER */
   1597   flag_ineligible (instance_id,
   1598                    exchange_url,
   1599                    h_wire);
   1600 }
   1601 
   1602 
   1603 /**
   1604  * Function called when a KYC status update was forced by an
   1605  * application checking the KYC status of an account.
   1606  *
   1607  * @param cls closure (NULL)
   1608  * @param extra additional event data provided
   1609  * @param extra_size number of bytes in @a extra
   1610  */
   1611 static void
   1612 update_forced (void *cls,
   1613                const void *extra,
   1614                size_t extra_size)
   1615 {
   1616   enum GNUNET_DB_QueryStatus qs;
   1617 
   1618   (void) cls;
   1619   (void) extra;
   1620   (void) extra_size;
   1621   qs = TALER_MERCHANTDB_account_kyc_get_outdated (
   1622     pg,
   1623     &force_check_now,
   1624     NULL);
   1625   if (qs < 0)
   1626   {
   1627     GNUNET_break (0);
   1628     global_ret = EXIT_FAILURE;
   1629     GNUNET_SCHEDULER_shutdown ();
   1630     return;
   1631   }
   1632 }
   1633 
   1634 
   1635 /**
   1636  * First task.
   1637  *
   1638  * @param cls closure, NULL
   1639  * @param args remaining command-line arguments
   1640  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
   1641  * @param c configuration
   1642  */
   1643 static void
   1644 run (void *cls,
   1645      char *const *args,
   1646      const char *cfgfile,
   1647      const struct GNUNET_CONFIGURATION_Handle *c)
   1648 {
   1649   (void) args;
   1650   (void) cfgfile;
   1651 
   1652   cfg = c;
   1653   if (GNUNET_OK !=
   1654       GNUNET_CONFIGURATION_get_value_time (cfg,
   1655                                            "merchant-kyccheck",
   1656                                            "AML_FREQ",
   1657                                            &aml_freq))
   1658   {
   1659     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
   1660                                "merchant-kyccheck",
   1661                                "AML_FREQ");
   1662     /* use default */
   1663     aml_freq = AML_FREQ;
   1664   }
   1665   if (GNUNET_OK !=
   1666       GNUNET_CONFIGURATION_get_value_time (cfg,
   1667                                            "merchant-kyccheck",
   1668                                            "AML_LOW_FREQ",
   1669                                            &aml_low_freq))
   1670   {
   1671     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
   1672                                "merchant-kyccheck",
   1673                                "AML_LOW_FREQ");
   1674     /* use default */
   1675     aml_low_freq = AML_LOW_FREQ;
   1676   }
   1677   if (GNUNET_TIME_relative_cmp (aml_low_freq,
   1678                                 <,
   1679                                 aml_freq))
   1680   {
   1681     aml_low_freq = GNUNET_TIME_relative_multiply (aml_freq,
   1682                                                   10);
   1683     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1684                 "AML_LOW_FREQ was set to less than AML_FREQ. Using %s instead\n",
   1685                 GNUNET_TIME_relative2s (aml_low_freq,
   1686                                         true));
   1687   }
   1688   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
   1689                                  NULL);
   1690   ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
   1691                           &rc);
   1692   rc = GNUNET_CURL_gnunet_rc_create (ctx);
   1693   if (NULL == ctx)
   1694   {
   1695     GNUNET_break (0);
   1696     GNUNET_SCHEDULER_shutdown ();
   1697     global_ret = EXIT_FAILURE;
   1698     return;
   1699   }
   1700   if (NULL ==
   1701       (pg = TALER_MERCHANTDB_connect (cfg)))
   1702   {
   1703     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1704                 "Failed to initialize DB subsystem. Consider running taler-merchant-dbconfig.\n");
   1705     GNUNET_SCHEDULER_shutdown ();
   1706     global_ret = EXIT_FAILURE;
   1707     return;
   1708   }
   1709   {
   1710     struct GNUNET_DB_EventHeaderP es = {
   1711       .size = htons (sizeof (es)),
   1712       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KEYS)
   1713     };
   1714 
   1715     eh_keys
   1716       = TALER_MERCHANTDB_event_listen (pg,
   1717                                        &es,
   1718                                        GNUNET_TIME_UNIT_FOREVER_REL,
   1719                                        &keys_changed,
   1720                                        NULL);
   1721   }
   1722   {
   1723     struct GNUNET_DB_EventHeaderP es = {
   1724       .size = htons (sizeof (es)),
   1725       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_UPDATE_FORCED)
   1726     };
   1727 
   1728     eh_update_forced
   1729       = TALER_MERCHANTDB_event_listen (pg,
   1730                                        &es,
   1731                                        GNUNET_TIME_UNIT_FOREVER_REL,
   1732                                        &update_forced,
   1733                                        NULL);
   1734   }
   1735   {
   1736     struct GNUNET_DB_EventHeaderP es = {
   1737       .size = htons (sizeof (es)),
   1738       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_RULE_TRIGGERED)
   1739     };
   1740 
   1741     eh_rule
   1742       = TALER_MERCHANTDB_event_listen (pg,
   1743                                        &es,
   1744                                        GNUNET_TIME_UNIT_FOREVER_REL,
   1745                                        &rule_triggered,
   1746                                        NULL);
   1747   }
   1748   GNUNET_CONFIGURATION_iterate_sections (cfg,
   1749                                          &accept_exchanges,
   1750                                          NULL);
   1751   {
   1752     struct GNUNET_DB_EventHeaderP es = {
   1753       .size = htons (sizeof (es)),
   1754       .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
   1755     };
   1756 
   1757     eh_accounts
   1758       = TALER_MERCHANTDB_event_listen (pg,
   1759                                        &es,
   1760                                        GNUNET_TIME_UNIT_FOREVER_REL,
   1761                                        &account_changed,
   1762                                        NULL);
   1763   }
   1764   GNUNET_assert (NULL == account_task);
   1765   account_task
   1766     = GNUNET_SCHEDULER_add_now (&find_accounts,
   1767                                 NULL);
   1768 }
   1769 
   1770 
   1771 /**
   1772  * The main function of taler-merchant-kyccheck
   1773  *
   1774  * @param argc number of arguments from the command line
   1775  * @param argv command line arguments
   1776  * @return 0 ok, 1 on error
   1777  */
   1778 int
   1779 main (int argc,
   1780       char *const *argv)
   1781 {
   1782   struct GNUNET_GETOPT_CommandLineOption options[] = {
   1783     GNUNET_GETOPT_option_timetravel ('T',
   1784                                      "timetravel"),
   1785     GNUNET_GETOPT_option_flag ('t',
   1786                                "test",
   1787                                "run in test mode and exit when idle",
   1788                                &test_mode),
   1789     GNUNET_GETOPT_option_version (VERSION "-" VCS_VERSION),
   1790     GNUNET_GETOPT_OPTION_END
   1791   };
   1792   enum GNUNET_GenericReturnValue ret;
   1793 
   1794   ret = GNUNET_PROGRAM_run (
   1795     TALER_MERCHANT_project_data (),
   1796     argc, argv,
   1797     "taler-merchant-kyccheck",
   1798     gettext_noop (
   1799       "background process that checks the KYC state of our bank accounts at various exchanges"),
   1800     options,
   1801     &run, NULL);
   1802   if (GNUNET_SYSERR == ret)
   1803     return EXIT_INVALIDARGUMENT;
   1804   if (GNUNET_NO == ret)
   1805     return EXIT_SUCCESS;
   1806   return global_ret;
   1807 }
   1808 
   1809 
   1810 /* end of taler-merchant-kyccheck.c */