merchant

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

taler-merchant-kyccheck.c (46944B)


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