merchant

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

taler-merchant-kyccheck.c (61203B)


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