merchant

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

taler-merchant-kyccheck.c (47286B)


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